mirror of
https://github.com/magefree/mage.git
synced 2026-01-09 12:22:10 -08:00
changes to the way abilities are added to cards
This commit is contained in:
parent
65390e09a6
commit
72ff6f27b3
91 changed files with 2003 additions and 217 deletions
|
|
@ -361,6 +361,19 @@ public interface Ability extends Controllable, Serializable {
|
|||
|
||||
boolean canChooseTarget(Game game);
|
||||
|
||||
/**
|
||||
* Gets the list of sub-abilities associated with this ability.
|
||||
* @return
|
||||
*/
|
||||
List<Ability> getSubAbilities();
|
||||
|
||||
/**
|
||||
* Adds a sub-ability to this ability.
|
||||
*
|
||||
* @param ability The {@link Ability} to add.
|
||||
*/
|
||||
void addSubAbility(Ability ability);
|
||||
|
||||
List<Watcher> getWatchers();
|
||||
void addWatcher(Watcher watcher);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
|
||||
private static final transient Logger logger = Logger.getLogger(AbilityImpl.class);
|
||||
private static final List<Watcher> emptyWatchers = new ArrayList<>();
|
||||
private static final List<Ability> emptyAbilities = new ArrayList<>();
|
||||
|
||||
protected UUID id;
|
||||
protected UUID originalId;
|
||||
|
|
@ -110,6 +111,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
protected boolean worksFaceDown = false;
|
||||
protected MageObject sourceObject;
|
||||
protected List<Watcher> watchers = null;
|
||||
protected List<Ability> subAbilities = null;
|
||||
|
||||
public AbilityImpl(AbilityType abilityType, Zone zone) {
|
||||
this.id = UUID.randomUUID();
|
||||
|
|
@ -145,6 +147,12 @@ public abstract class AbilityImpl implements Ability {
|
|||
watchers.add(watcher.copy());
|
||||
}
|
||||
}
|
||||
if (ability.subAbilities != null) {
|
||||
this.subAbilities = new ArrayList<>();
|
||||
for (Ability subAbility: ability.subAbilities) {
|
||||
subAbilities.add(subAbility.copy());
|
||||
}
|
||||
}
|
||||
this.modes = ability.modes.copy();
|
||||
this.ruleAtTheTop = ability.ruleAtTheTop;
|
||||
this.ruleVisible = ability.ruleVisible;
|
||||
|
|
@ -562,6 +570,11 @@ public abstract class AbilityImpl implements Ability {
|
|||
watcher.setControllerId(controllerId);
|
||||
}
|
||||
}
|
||||
if (subAbilities != null) {
|
||||
for (Ability subAbility: subAbilities) {
|
||||
subAbility.setControllerId(controllerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -579,6 +592,11 @@ public abstract class AbilityImpl implements Ability {
|
|||
this.sourceId = sourceId;
|
||||
}
|
||||
}
|
||||
if (subAbilities != null) {
|
||||
for (Ability subAbility: subAbilities) {
|
||||
subAbility.setSourceId(sourceId);
|
||||
}
|
||||
}
|
||||
if (watchers != null) {
|
||||
for (Watcher watcher: watchers) {
|
||||
watcher.setSourceId(sourceId);
|
||||
|
|
@ -660,6 +678,23 @@ public abstract class AbilityImpl implements Ability {
|
|||
watchers.add(watcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Ability> getSubAbilities() {
|
||||
if (subAbilities != null)
|
||||
return subAbilities;
|
||||
else
|
||||
return emptyAbilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSubAbility(Ability ability) {
|
||||
if (subAbilities == null)
|
||||
subAbilities = new ArrayList<>();
|
||||
ability.setSourceId(this.sourceId);
|
||||
ability.setControllerId(this.controllerId);
|
||||
subAbilities.add(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsesStack() {
|
||||
return usesStack;
|
||||
|
|
|
|||
|
|
@ -107,8 +107,7 @@ public class GainAbilitySourceEffect extends ContinuousEffectImpl implements Sou
|
|||
}
|
||||
if (card != null) {
|
||||
// add ability to card only once
|
||||
card.addAbility(ability);
|
||||
discard();
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl {
|
|||
for (UUID cardId : targetPointer.getTargets(game, source)) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null) {
|
||||
card.addAbility(ability);
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
affectedTargets++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ public class BestowAbility extends SpellAbility {
|
|||
this.addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BestowTypeChangingEffect());
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
}
|
||||
|
||||
public BestowAbility(final BestowAbility ability) {
|
||||
|
|
|
|||
|
|
@ -105,12 +105,12 @@ public class ChampionAbility extends StaticAbility {
|
|||
Ability ability1 = new EntersBattlefieldTriggeredAbility(
|
||||
new SacrificeSourceUnlessPaysEffect(new ChampionExileCost(filter, new StringBuilder(card.getName()).append(" championed permanents").toString())),false);
|
||||
ability1.setRuleVisible(false);
|
||||
card.addAbility(ability1);
|
||||
addSubAbility(ability1);
|
||||
|
||||
// When this permanent leaves the battlefield, return the exiled card to the battlefield under its owner's control.
|
||||
Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false);
|
||||
ability2.setRuleVisible(false);
|
||||
card.addAbility(ability2);
|
||||
addSubAbility(ability2);
|
||||
}
|
||||
|
||||
public ChampionAbility(final ChampionAbility ability) {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
|||
public ConspireAbility(Card card) {
|
||||
super(Zone.STACK, null);
|
||||
setRuleAtTheTop(false);
|
||||
card.addAbility(new ConspireTriggeredAbility());
|
||||
addSubAbility(new ConspireTriggeredAbility());
|
||||
}
|
||||
|
||||
public ConspireAbility(final ConspireAbility ability) {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
|
|||
Effect effect = new ReturnToHandTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId()));
|
||||
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), false));
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public class EvokeAbility extends StaticAbility implements AlternativeSourceCost
|
|||
this.addEvokeCost(manaString);
|
||||
Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect()), EvokedCondition.getInstance(), "Sacrifice {this} when it enters the battlefield and was evoked.");
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public class FadingAbility extends EntersBattlefieldAbility {
|
|||
super(new AddCountersSourceEffect(CounterType.FADE.createInstance(fadeCounter)), "with");
|
||||
Ability ability = new BeginningOfUpkeepTriggeredAbility(new FadingEffect(), TargetController.YOU, false);
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
StringBuilder sb = new StringBuilder("Fading ");
|
||||
sb.append(fadeCounter);
|
||||
sb.append(" <i>(This permanent enters the battlefield with ")
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class GraftAbility extends TriggeredAbilityImpl {
|
|||
sb.append(theCardtype.toString().toLowerCase(Locale.ENGLISH)).append(" ");
|
||||
}
|
||||
this.cardtype = sb.toString().trim();
|
||||
card.addAbility(new GraftStaticAbility(amount));
|
||||
addSubAbility(new GraftStaticAbility(amount));
|
||||
}
|
||||
|
||||
public GraftAbility(GraftAbility ability) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public class HauntAbility extends TriggeredAbilityImpl {
|
|||
|
||||
public HauntAbility(Card card, Effect effect) {
|
||||
super(Zone.ALL, effect , false);
|
||||
card.addAbility(new HauntExileAbility());
|
||||
addSubAbility(new HauntExileAbility());
|
||||
}
|
||||
|
||||
public HauntAbility(final HauntAbility ability) {
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ public class HideawayAbility extends StaticAbility {
|
|||
super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new TapSourceEffect(true)));
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new HideawayExileEffect(), false);
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
// Allow controller to look at face down card
|
||||
ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new HideawayLookAtFaceDownCardEffect());
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
}
|
||||
|
||||
public HideawayAbility(final HideawayAbility ability) {
|
||||
|
|
|
|||
|
|
@ -134,9 +134,11 @@ public class LevelerCardBuilder {
|
|||
*
|
||||
* @param card
|
||||
* @param levelAbilities
|
||||
* @return list of levelAbilities to add to card
|
||||
*/
|
||||
public static void construct(Card card, LevelAbility... levelAbilities) {
|
||||
public static List<Ability> construct(LevelAbility... levelAbilities) {
|
||||
LevelerCardBuilder builder = new LevelerCardBuilder();
|
||||
List<Ability> abilities = new ArrayList<>();
|
||||
|
||||
for (LevelAbility levelAbility : levelAbilities) {
|
||||
// set main params
|
||||
|
|
@ -153,22 +155,11 @@ public class LevelerCardBuilder {
|
|||
builder.addAbility(addedAbility);
|
||||
}
|
||||
|
||||
// build static abilities and add them to card
|
||||
for (Ability simpleStaticAbility : builder.build()) {
|
||||
card.addAbility(simpleStaticAbility);
|
||||
}
|
||||
// build static abilities and add them to list
|
||||
abilities.addAll(builder.build());
|
||||
}
|
||||
|
||||
// set max level counters (for ai)
|
||||
if (card instanceof LevelerCard) {
|
||||
int maxValue = 0;
|
||||
for (LevelAbility levelAbility : levelAbilities) {
|
||||
if (levelAbility.getLevel1() > maxValue) {
|
||||
maxValue = levelAbility.getLevel1();
|
||||
}
|
||||
}
|
||||
((LevelerCard) card).setMaxLevelCounters(maxValue);
|
||||
}
|
||||
return abilities;
|
||||
}
|
||||
|
||||
public static class LevelAbility {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class MadnessAbility extends StaticAbility {
|
|||
@SuppressWarnings("unchecked")
|
||||
public MadnessAbility(Card card, ManaCosts madnessCost) {
|
||||
super(Zone.HAND, new MadnessReplacementEffect((ManaCosts<ManaCost>)madnessCost));
|
||||
card.addAbility(new MadnessTriggeredAbility((ManaCosts<ManaCost>)madnessCost));
|
||||
addSubAbility(new MadnessTriggeredAbility((ManaCosts<ManaCost>)madnessCost));
|
||||
rule = "Madness " + madnessCost.getText() + " <i>(If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)<i/>";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@ public class ModularAbility extends DiesTriggeredAbility {
|
|||
if (sunburst) {
|
||||
Ability ability = new SunburstAbility(card);
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
} else {
|
||||
card.addAbility(new ModularStaticAbility(amount));
|
||||
addSubAbility(new ModularStaticAbility(amount));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
|
|||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesFaceDownCreatureEffect(morphCosts, (megamorph ? FaceDownType.MEGAMORPHED :FaceDownType.MORPHED)));
|
||||
ability.setWorksFaceDown(true);
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
addSubAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public class ReboundAbility extends TriggeredAbilityImpl {
|
|||
((ZoneChangeEvent) event).getToZone() == Zone.STACK) {
|
||||
Card card = (Card) game.getObject(event.getTargetId());
|
||||
|
||||
if (card.getAbilities().contains(this)) {
|
||||
if (card.getAbilities(game).contains(this)) {
|
||||
this.installReboundEffect = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public class ReplicateAbility extends StaticAbility implements OptionalAdditiona
|
|||
this.additionalCost = new OptionalAdditionalCostImpl(keywordText, reminderTextMana, new ManaCostsImpl(manaString));
|
||||
this.additionalCost.setRepeatable(true);
|
||||
setRuleAtTheTop(true);
|
||||
card.addAbility(new ReplicateTriggeredAbility());
|
||||
addSubAbility(new ReplicateTriggeredAbility());
|
||||
}
|
||||
|
||||
public ReplicateAbility(final ReplicateAbility ability) {
|
||||
|
|
|
|||
|
|
@ -179,8 +179,8 @@ public class SuspendAbility extends ActivatedAbilityImpl {
|
|||
if (card.getManaCost().isEmpty()) {
|
||||
setRuleAtTheTop(true);
|
||||
}
|
||||
card.addAbility(new SuspendBeginningOfUpkeepTriggeredAbility());
|
||||
card.addAbility(new SuspendPlayCardAbility(card.getCardType().contains(CardType.CREATURE)));
|
||||
addSubAbility(new SuspendBeginningOfUpkeepTriggeredAbility());
|
||||
addSubAbility(new SuspendPlayCardAbility(card.getCardType().contains(CardType.CREATURE)));
|
||||
}
|
||||
ruleText = sb.toString();
|
||||
}
|
||||
|
|
@ -196,18 +196,18 @@ public class SuspendAbility extends ActivatedAbilityImpl {
|
|||
SuspendAbility ability = new SuspendAbility(0, null, card, false);
|
||||
ability.setSourceId(card.getId());
|
||||
ability.setControllerId(card.getOwnerId());
|
||||
game.getState().addOtherAbility(card.getId(), ability);
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
|
||||
SuspendBeginningOfUpkeepTriggeredAbility ability1 = new SuspendBeginningOfUpkeepTriggeredAbility();
|
||||
ability1.setSourceId(card.getId());
|
||||
ability1.setControllerId(card.getOwnerId());
|
||||
game.getState().addOtherAbility(card.getId(), ability1);
|
||||
game.getState().addOtherAbility(card, ability1);
|
||||
game.getState().addAbility(ability1, source.getSourceId(), card);
|
||||
|
||||
SuspendPlayCardAbility ability2 = new SuspendPlayCardAbility(card.getCardType().contains(CardType.CREATURE));
|
||||
ability2.setSourceId(card.getId());
|
||||
ability2.setControllerId(card.getOwnerId());
|
||||
game.getState().addOtherAbility(card.getId(), ability2);
|
||||
game.getState().addOtherAbility(card, ability2);
|
||||
game.getState().addAbility(ability2, source.getSourceId(), card);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.Rarity;
|
||||
|
|
@ -47,7 +48,7 @@ public interface Card extends MageObject {
|
|||
int getCardNumber();
|
||||
Rarity getRarity();
|
||||
void setOwnerId(UUID ownerId);
|
||||
void addAbility(Ability ability);
|
||||
public Abilities<Ability> getAbilities(Game game);
|
||||
void setSpellAbility(SpellAbility ability);
|
||||
SpellAbility getSpellAbility();
|
||||
List<String> getRules(); // gets base card rules
|
||||
|
|
|
|||
|
|
@ -36,10 +36,11 @@ import java.util.UUID;
|
|||
import mage.MageObject;
|
||||
import mage.MageObjectImpl;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.PlayLandAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.abilities.mana.ManaAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
|
|
@ -226,11 +227,11 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
for (String data : cardState.getInfo().values()) {
|
||||
rules.add(data);
|
||||
}
|
||||
for (Ability ability: cardState.getAbilities()) {
|
||||
rules.add(ability.getRule());
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (Ability ability: state.getAbilities()) {
|
||||
// rules.add(ability.getRule());
|
||||
// }
|
||||
return rules;
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception in rules generation for card: " + this.getName(), e);
|
||||
|
|
@ -238,12 +239,48 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
return rulesError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all base abilities - does not include additional abilities added by
|
||||
* other cards or effects
|
||||
* @return A list of {@link Ability} - this collection is modifiable
|
||||
*/
|
||||
@Override
|
||||
public void addAbility(Ability ability) {
|
||||
ability.setSourceId(this.getId());
|
||||
abilities.add(ability);
|
||||
public Abilities<Ability> getAbilities() {
|
||||
return super.getAbilities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all current abilities - includes additional abilities added by
|
||||
* other cards or effects
|
||||
* @param game
|
||||
* @return A list of {@link Ability} - this collection is not modifiable
|
||||
*/
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(objectId);
|
||||
if (otherAbilities == null) {
|
||||
return abilities;
|
||||
}
|
||||
Abilities<Ability> all = new AbilitiesImpl<>();
|
||||
all.addAll(abilities);
|
||||
all.addAll(otherAbilities);
|
||||
return all;
|
||||
}
|
||||
|
||||
protected void addAbility(Ability ability) {
|
||||
ability.setSourceId(this.getId());
|
||||
abilities.add(ability);
|
||||
for (Ability subAbility: ability.getSubAbilities()) {
|
||||
abilities.add(subAbility);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addAbilities(List<Ability> abilities) {
|
||||
for (Ability ability: abilities) {
|
||||
addAbility(ability);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addAbility(Ability ability, Watcher watcher) {
|
||||
addAbility(ability);
|
||||
ability.addWatcher(watcher);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public abstract class LevelerCard extends CardImpl {
|
|||
return maxLevelCounters;
|
||||
}
|
||||
|
||||
public void setMaxLevelCounters(int maxLevelCounters) {
|
||||
protected void setMaxLevelCounters(int maxLevelCounters) {
|
||||
this.maxLevelCounters = maxLevelCounters;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,19 @@ public abstract class SplitCard extends CardImpl {
|
|||
return allAbilites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
Abilities<Ability> allAbilites = new AbilitiesImpl<>();
|
||||
for (Ability ability : super.getAbilities(game)) {
|
||||
if (ability instanceof SpellAbility && !((SpellAbility)ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT)) {
|
||||
allAbilites.add(ability);
|
||||
}
|
||||
}
|
||||
allAbilites.addAll(leftHalfCard.getAbilities(game));
|
||||
allAbilites.addAll(rightHalfCard.getAbilities(game));
|
||||
return allAbilites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
List<String> rules = new ArrayList<>();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ package mage.game;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.counters.Counters;
|
||||
/**
|
||||
*
|
||||
|
|
@ -12,8 +15,10 @@ public class CardState {
|
|||
protected boolean faceDown;
|
||||
protected Map<String, String> info;
|
||||
protected Counters counters;
|
||||
protected Abilities<Ability> abilities;
|
||||
|
||||
private static final Map<String, String> emptyInfo = new HashMap<>();
|
||||
private static final Abilities<Ability> emptyAbilities = new AbilitiesImpl<>();
|
||||
|
||||
public CardState() {
|
||||
counters = new Counters();
|
||||
|
|
@ -26,6 +31,12 @@ public class CardState {
|
|||
info.putAll(state.info);
|
||||
}
|
||||
counters = state.counters.copy();
|
||||
if (state.abilities != null) {
|
||||
abilities = new AbilitiesImpl<>();
|
||||
for (Ability ability: state.abilities) {
|
||||
abilities.add(ability.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CardState copy() {
|
||||
|
|
@ -62,10 +73,37 @@ public class CardState {
|
|||
return info;
|
||||
}
|
||||
|
||||
public Abilities<Ability> getAbilities() {
|
||||
if (abilities == null) {
|
||||
return emptyAbilities;
|
||||
}
|
||||
return abilities;
|
||||
}
|
||||
|
||||
public void addAbility(Ability ability) {
|
||||
if (abilities == null) {
|
||||
abilities = new AbilitiesImpl<>();
|
||||
}
|
||||
abilities.add(ability);
|
||||
for (Ability sub: ability.getSubAbilities()) {
|
||||
abilities.add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAbilities() {
|
||||
if (abilities != null) {
|
||||
for (Ability ability: abilities) {
|
||||
ability.setSourceId(null);
|
||||
ability.setControllerId(null);
|
||||
}
|
||||
abilities = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
counters.clear();
|
||||
info = null;
|
||||
clearAbilities();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ import mage.watchers.Watchers;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -80,7 +79,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
private final Map<UUID, LookedAt> lookedAt = new HashMap<>();
|
||||
private final DelayedTriggeredAbilities delayed;
|
||||
private final SpecialActions specialActions;
|
||||
private final Map<UUID, Abilities<Ability>> otherAbilities = new HashMap<>();
|
||||
private final TurnMods turnMods;
|
||||
private final Watchers watchers;
|
||||
|
||||
|
|
@ -156,9 +154,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
this.zones.putAll(state.zones);
|
||||
for (Map.Entry<UUID, Abilities<Ability>> entry: state.otherAbilities.entrySet()) {
|
||||
otherAbilities.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
this.paused = state.paused;
|
||||
this.simultaneousEvents.addAll(state.simultaneousEvents);
|
||||
for (Map.Entry<UUID, CardState> entry: state.cardState.entrySet()) {
|
||||
|
|
@ -601,6 +596,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
watcher.setSourceId(attachedTo.getId());
|
||||
watchers.add(watcher);
|
||||
}
|
||||
for (Ability sub: ability.getSubAbilities()) {
|
||||
addAbility(sub, sourceId, attachedTo);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCommandObject(CommandObject commandObject) {
|
||||
|
|
@ -678,41 +676,32 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
* @return
|
||||
*/
|
||||
public Abilities<ActivatedAbility> getActivatedOtherAbilities(UUID objectId, Zone zone) {
|
||||
if (otherAbilities.containsKey(objectId)) {
|
||||
return otherAbilities.get(objectId).getActivatedAbilities(zone);
|
||||
if (cardState.containsKey(objectId)) {
|
||||
return cardState.get(objectId).getAbilities().getActivatedAbilities(zone);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Abilities<Ability> getAllOtherAbilities(UUID objectId) {
|
||||
if (otherAbilities.containsKey(objectId)) {
|
||||
return otherAbilities.get(objectId);
|
||||
if (cardState.containsKey(objectId)) {
|
||||
return cardState.get(objectId).getAbilities();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addOtherAbility(UUID objectId, Ability ability) {
|
||||
if (!otherAbilities.containsKey(objectId)) {
|
||||
otherAbilities.put(objectId, new AbilitiesImpl(ability));
|
||||
} else {
|
||||
otherAbilities.get(objectId).add(ability);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the ability to continuous or triggered abilities
|
||||
* @param ability
|
||||
* @param card
|
||||
*/
|
||||
public void addOtherAbility(Ability ability, Card card) {
|
||||
addOtherAbility(card.getId(), ability);
|
||||
addAbility(ability, card.getId(), card);
|
||||
}
|
||||
|
||||
private void resetOtherAbilities() {
|
||||
otherAbilities.clear();
|
||||
public void addOtherAbility(Card attachedTo, Ability ability) {
|
||||
ability.setSourceId(attachedTo.getId());
|
||||
ability.setControllerId(attachedTo.getOwnerId());
|
||||
if (!cardState.containsKey(attachedTo.getId())) {
|
||||
cardState.put(attachedTo.getId(), new CardState());
|
||||
}
|
||||
cardState.get(attachedTo.getId()).addAbility(ability);
|
||||
addAbility(ability, attachedTo.getId(), attachedTo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -734,7 +723,9 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
triggers.removeAllGainedAbilities();
|
||||
getContinuousEffects().removeAllTemporaryEffects();
|
||||
this.setLegendaryRuleActive(true);
|
||||
this.resetOtherAbilities();
|
||||
for (CardState state: cardState.values()) {
|
||||
state.clearAbilities();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
|
@ -754,7 +745,6 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
legendaryRuleActive = true;
|
||||
gameOver = false;
|
||||
specialActions.clear();
|
||||
otherAbilities.clear();
|
||||
cardState.clear();
|
||||
combat.clear();
|
||||
turnMods.clear();
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ public interface Permanent extends Card, Controllable {
|
|||
String getValue();
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
void addAbility(Ability ability);
|
||||
@Deprecated
|
||||
void addAbility(Ability ability, Game game);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ import java.util.Map;
|
|||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
|
@ -244,6 +246,16 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
return abilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
return abilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void addAbility(Ability ability) {
|
||||
|
|
|
|||
|
|
@ -601,6 +601,11 @@ public class Spell implements StackObject, Card {
|
|||
return card.getAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
return card.getAbilities(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAbility(UUID abilityId, Game game) {
|
||||
return card.hasAbility(abilityId, game);
|
||||
|
|
@ -674,7 +679,6 @@ public class Spell implements StackObject, Card {
|
|||
spellAbilities.add(spellAbility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAbility(Ability ability) {}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -487,6 +487,16 @@ public class StackAbility implements StackObject, Ability {
|
|||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Ability> getSubAbilities() {
|
||||
return this.ability.getSubAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSubAbility(Ability ability) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageObject getSourceObject(Game game) {
|
||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue