diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index cbdce2b6ab2..205d9d5fc9a 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1396,6 +1396,7 @@ public class AiController { final List abilities = Lists.newArrayList(); LandAbility la = new LandAbility(land, player, null); + la.setCardState(land.getCurrentState()); if (la.canPlay()) { abilities.add(la); } @@ -1403,6 +1404,7 @@ public class AiController { // add mayPlay option for (CardPlayOption o : land.mayPlay(player)) { la = new LandAbility(land, player, o.getAbility()); + la.setCardState(land.getCurrentState()); if (la.canPlay()) { abilities.add(la); } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 109c5dfc423..efd78ccad60 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -5,6 +5,8 @@ import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; + +import forge.card.CardStateName; import forge.card.CardType; import forge.card.ColorSet; import forge.card.MagicColor; @@ -1837,7 +1839,7 @@ public class ComputerUtilCard { public static AiPlayDecision checkNeedsToPlayReqs(final Card card, final SpellAbility sa) { Game game = card.getGame(); - boolean isRightSplit = sa != null && sa.getCardState() != null; + boolean isRightSplit = sa != null && sa.getCardState().getStateName() == CardStateName.RightSplit; String needsToPlayName = isRightSplit ? "SplitNeedsToPlay" : "NeedsToPlay"; String needsToPlayVarName = isRightSplit ? "SplitNeedsToPlayVar" : "NeedsToPlayVar"; diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index fa59e04c78a..c795bcac0b9 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -1,11 +1,13 @@ package forge.game; +import forge.card.CardStateName; import forge.card.MagicColor; import forge.card.mana.ManaAtom; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardLists; +import forge.game.card.CardState; import forge.game.card.CardUtil; import forge.game.card.CardView; import forge.game.card.IHasCardView; @@ -29,8 +31,7 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView, /** The host card. */ protected Card hostCard; - - private Card grantorCard = null; // card which grants the ability (equipment or owner of static ability that gave this one) + protected CardState cardState = null; /** The map params. */ protected Map originalMapParams = Maps.newHashMap(), @@ -468,9 +469,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView, } protected IHasSVars getSVarFallback() { - if (getOriginalHost() != null) { - return getOriginalHost(); - } + if (getCardState() != null) + return getCardState(); return getHostCard(); } @@ -520,11 +520,30 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView, sVars.remove(var); } - public Card getOriginalHost() { - return grantorCard; + public CardState getCardState() { + return cardState; } - public void setOriginalHost(final Card c) { - grantorCard = c; + public void setCardState(CardState state) { + this.cardState = state; + } + public CardStateName getCardStateName() { + if (this.getCardState() == null) { + return null; + } + return getCardState().getView().getState(); + } + + public Card getOriginalHost() { + if (getCardState() != null) + return getCardState().getCard(); + return null; + } + + public boolean isCopiedTrait() { + if (this.getCardState() == null) { + return false; + } + return !getHostCard().equals(getCardState().getCard()); } public Map getChangedTextColors() { @@ -580,6 +599,7 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView, copy.originalMapParams = Maps.newHashMap(originalMapParams); copy.mapParams = Maps.newHashMap(originalMapParams); copy.setSVars(sVars); + copy.setCardState(cardState); // dont use setHostCard to not trigger the not copied parts yet copy.hostCard = host; } diff --git a/forge-game/src/main/java/forge/game/TriggerReplacementBase.java b/forge-game/src/main/java/forge/game/TriggerReplacementBase.java index 0764bd7b2fc..3e636eb4968 100644 --- a/forge-game/src/main/java/forge/game/TriggerReplacementBase.java +++ b/forge-game/src/main/java/forge/game/TriggerReplacementBase.java @@ -4,6 +4,7 @@ import java.util.EnumSet; import java.util.Set; import forge.game.card.Card; +import forge.game.card.CardState; import forge.game.spellability.SpellAbility; import forge.game.zone.Zone; import forge.game.zone.ZoneType; @@ -27,15 +28,13 @@ public abstract class TriggerReplacementBase extends CardTraitBase implements II } @Override - public void setOriginalHost(Card c) { - super.setOriginalHost(c); + public void setCardState(CardState state) { + super.setCardState(state); if (overridingAbility != null) { - overridingAbility.setOriginalHost(c); + overridingAbility.setCardState(state); } } - - public Set getActiveZone() { return validHostZones; } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index e252a1d131d..7452ebdf6ad 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -226,6 +226,7 @@ public final class AbilityFactory { msg.append(". Looking for API: ").append(api); throw new RuntimeException(msg.toString()); } + spellAbility.setCardState(state); if (mapParams.containsKey("Forecast")) { spellAbility.putParam("ActivationZone", "Hand"); diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 593c57c1012..2897adb5c25 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1614,7 +1614,7 @@ public class AbilityUtils { // If the chosen creature has X in its mana cost, that X is considered to be 0. // The value of X in Altered Ego’s last ability will be whatever value was chosen for X while casting Altered Ego. - if (sa.getOriginalHost() != null || !sa.getHostCard().equals(c)) { + if (sa.isCopiedTrait() || !sa.getHostCard().equals(c)) { return CardFactoryUtil.doXMath(0, expr, c); } @@ -2063,7 +2063,6 @@ public class AbilityUtils { subAbility.setActivatingPlayer(sa.getActivatingPlayer()); subAbility.setHostCard(sa.getHostCard()); - subAbility.setOriginalHost(c); //add the spliced ability to the end of the chain sa.appendSubAbility(subAbility); diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index c5efe07fc58..b529d37077b 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -431,7 +431,7 @@ public abstract class SpellAbilityEffect { + " exile it instead of putting it anywhere else."; String effect = "DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Battlefield | Destination$ " + zone; - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true, null); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true); re.setLayer(ReplacementLayer.Other); re.setOverridingAbility(AbilityFactory.getAbility(effect, eff)); diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java index 86ad24f6249..7115bcf00e7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java @@ -152,7 +152,6 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { final List addedAbilities = Lists.newArrayList(); for (final String s : abilities) { SpellAbility sSA = AbilityFactory.getAbility(c, s, sa); - sSA.setOriginalHost(source); addedAbilities.add(sSA); } @@ -160,7 +159,6 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { final List addedTriggers = Lists.newArrayList(); for (final String s : triggers) { final Trigger parsedTrigger = TriggerHandler.parseTrigger(AbilityUtils.getSVar(sa, s), c, false, sa); - parsedTrigger.setOriginalHost(source); addedTriggers.add(parsedTrigger); } @@ -174,7 +172,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { // itself a static ability) final List addedStaticAbilities = Lists.newArrayList(); for (final String s : stAbs) { - addedStaticAbilities.add(new StaticAbility(AbilityUtils.getSVar(sa, s), c)); + addedStaticAbilities.add(new StaticAbility(AbilityUtils.getSVar(sa, s), c, sa.getCardState())); } final GameCommand unanimate = new GameCommand() { diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java index a76b1013c53..8ffd2c9fd7c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java @@ -251,7 +251,7 @@ public class PlayEffect extends SpellAbilityEffect { tgtSA = sa.getActivatingPlayer().getController().getAbilityToPlay(tgtCard, sas); } else { // For Illusionary Mask effect - tgtSA = CardFactoryUtil.abilityMorphDown(tgtCard); + tgtSA = CardFactoryUtil.abilityMorphDown(tgtCard.getCurrentState()); } // in case player canceled from choice dialog if (tgtSA == null) { diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 912a935e435..4b86b9b8951 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2227,7 +2227,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { String sAbility = formatSpellAbility(sa); // add Adventure to AbilityText - if (sa.isAdventure() && state.getView().getState().equals(CardStateName.Original)) { + if (sa.isAdventure() && state.getStateName().equals(CardStateName.Original)) { CardState advState = getState(CardStateName.Adventure); StringBuilder sbSA = new StringBuilder(); sbSA.append(Localizer.getInstance().getMessage("lblAdventure")); @@ -4388,7 +4388,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final StaticAbility addStaticAbility(final String s) { if (!s.trim().isEmpty()) { - final StaticAbility stAb = new StaticAbility(s, this); + final StaticAbility stAb = new StaticAbility(s, this, currentState); stAb.setIntrinsic(true); currentState.addStaticAbility(stAb); return stAb; @@ -6326,11 +6326,14 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public void setSplitStateToPlayAbility(final SpellAbility sa) { + if (isFaceDown()) { + return; + } if (sa.isBestow()) { animateBestow(); } - CardStateName stateName = sa.getCardState(); - if (hasState(stateName)) { + CardStateName stateName = sa.getCardStateName(); + if (stateName != null && hasState(stateName) && this.getCurrentStateName() != stateName) { setState(stateName, true); // need to set backSide value according to the SplitType if (hasBackSide()) { @@ -6356,6 +6359,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public List getAllPossibleAbilities(final Player player, final boolean removeUnplayable) { + CardState oState = getState(CardStateName.Original); // this can only be called by the Human final List abilities = Lists.newArrayList(); for (SpellAbility sa : getSpellAbilities()) { @@ -6382,7 +6386,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } if (isInPlay() && isFaceDown() && isManifested()) { - CardState oState = getState(CardStateName.Original); ManaCost cost = oState.getManaCost(); if (oState.getType().isCreature()) { abilities.add(CardFactoryUtil.abilityManifestFaceUp(this, cost)); @@ -6409,6 +6412,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } if (getState(CardStateName.Original).getType().isLand()) { LandAbility la = new LandAbility(this, player, null); + la.setCardState(oState); if (la.canPlay()) { abilities.add(la); } @@ -6433,6 +6437,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // extra for MayPlay for (CardPlayOption o : source.mayPlay(player)) { la = new LandAbility(this, player, o.getAbility()); + la.setCardState(oState); if (la.canPlay()) { abilities.add(la); } @@ -6449,9 +6454,10 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } if (isModal() && hasState(CardStateName.Modal)) { - if (getState(CardStateName.Modal).getType().isLand()) { + CardState modal = getState(CardStateName.Modal); + if (modal.getType().isLand()) { LandAbility la = new LandAbility(this, player, null); - la.setCardState(CardStateName.Modal); + la.setCardState(modal); Card source = CardUtil.getLKICopy(this); boolean lkicheck = true; @@ -6483,7 +6489,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // extra for MayPlay for (CardPlayOption o : source.mayPlay(player)) { la = new LandAbility(this, player, o.getAbility()); - la.setCardState(CardStateName.Modal); + la.setCardState(modal); if (la.canPlay(source)) { abilities.add(la); } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 9d24e6d34e0..e2106e04b07 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -29,7 +29,6 @@ import forge.game.Game; import forge.game.ability.AbilityFactory; import forge.game.cost.Cost; import forge.game.player.Player; -import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementHandler; import forge.game.spellability.*; import forge.game.staticability.StaticAbility; @@ -258,7 +257,7 @@ public class CardFactory { // ************** Link to different CardFactories ******************* if (state == CardStateName.LeftSplit || state == CardStateName.RightSplit) { for (final SpellAbility sa : card.getSpellAbilities()) { - sa.setCardState(state); + sa.setCardState(card.getState(state)); } CardFactoryUtil.setupKeywordedAbilities(card); final CardState original = card.getState(CardStateName.Original); @@ -366,9 +365,9 @@ public class CardFactory { for (Entry v : face.getVariables()) c.setSVar(v.getKey(), v.getValue()); - for (String r : face.getReplacements()) c.addReplacementEffect(ReplacementHandler.parseReplacement(r, c, true)); + for (String r : face.getReplacements()) c.addReplacementEffect(ReplacementHandler.parseReplacement(r, c, true, c.getCurrentState())); for (String s : face.getStaticAbilities()) c.addStaticAbility(s); - for (String t : face.getTriggers()) c.addTrigger(TriggerHandler.parseTrigger(t, c, true)); + for (String t : face.getTriggers()) c.addTrigger(TriggerHandler.parseTrigger(t, c, true, c.getCurrentState())); // keywords not before variables c.addIntrinsicKeywords(face.getKeywords(), false); @@ -401,9 +400,9 @@ public class CardFactory { SpellAbility sa = new SpellPermanent(c); // Currently only for Modal, might react different when state is always set - if (c.getCurrentStateName() == CardStateName.Modal) { - sa.setCardState(c.getCurrentStateName()); - } + //if (c.getCurrentStateName() == CardStateName.Modal) { + sa.setCardState(c.getCurrentState()); + //} c.addSpellAbility(sa); } // TODO add LandAbility there when refactor MayPlay @@ -678,7 +677,6 @@ public class CardFactory { if (origSVars.containsKey(s)) { final String actualTrigger = origSVars.get(s); final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, out, true); - parsedTrigger.setOriginalHost(host); state.addTrigger(parsedTrigger); } } @@ -702,7 +700,6 @@ public class CardFactory { if (origSVars.containsKey(s)) { final String actualAbility = origSVars.get(s); final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, out); - grantedAbility.setOriginalHost(host); grantedAbility.setIntrinsic(true); state.addSpellAbility(grantedAbility); } @@ -715,8 +712,7 @@ public class CardFactory { for (final String s : str.split(",")) { if (origSVars.containsKey(s)) { final String actualStatic = origSVars.get(s); - final StaticAbility grantedStatic = new StaticAbility(actualStatic, out); - grantedStatic.setOriginalHost(host); + final StaticAbility grantedStatic = new StaticAbility(actualStatic, out, sa.getCardState()); grantedStatic.setIntrinsic(true); state.addStaticAbility(grantedStatic); } @@ -765,26 +761,6 @@ public class CardFactory { // set the host card for copied replacement effects // needed for copied xPaid ETB effects (for the copy, xPaid = 0) - for (final ReplacementEffect rep : state.getReplacementEffects()) { - final SpellAbility newSa = rep.getOverridingAbility(); - if (newSa != null && newSa.getOriginalHost() == null) { - newSa.setOriginalHost(in); - } - } - - // set the host card for copied spellabilities, if they are not set yet - for (final SpellAbility newSa : state.getSpellAbilities()) { - if (newSa.getOriginalHost() == null) { - newSa.setOriginalHost(in); - } - } - - for (final Trigger trigger : state.getTriggers()) { - final SpellAbility newSa = trigger.getOverridingAbility(); - if (newSa != null && newSa.getOriginalHost() == null) { - newSa.setOriginalHost(in); - } - } if (sa.hasParam("GainTextOf") && originalState != null) { state.setSetCode(originalState.getSetCode()); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index ece30c88987..f8a17467c06 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -94,8 +94,8 @@ public class CardFactoryUtil { * a {@link forge.game.card.Card} object. * @return a {@link forge.game.spellability.SpellAbility} object. */ - public static SpellAbility abilityMorphDown(final Card sourceCard) { - final Spell morphDown = new Spell(sourceCard, new Cost(ManaCost.THREE, false)) { + public static SpellAbility abilityMorphDown(final CardState cardState) { + final Spell morphDown = new Spell(cardState.getCard(), new Cost(ManaCost.THREE, false)) { private static final long serialVersionUID = -1438810964807867610L; @Override @@ -119,6 +119,8 @@ public class CardFactoryUtil { } }; + morphDown.setCardState(cardState); + morphDown.setDescription("(You may cast this card face down as a 2/2 creature for {3}.)"); morphDown.setStackDescription("Morph - Creature 2/2"); morphDown.setCastFaceDown(true); @@ -136,7 +138,7 @@ public class CardFactoryUtil { * a {@link forge.game.card.Card} object. * @return a {@link forge.game.spellability.AbilityActivated} object. */ - public static SpellAbility abilityMorphUp(final Card sourceCard, final String costStr, final boolean mega) { + public static SpellAbility abilityMorphUp(final CardState cardState, final String costStr, final boolean mega) { Cost cost = new Cost(costStr, true); String costDesc = cost.toString(); StringBuilder sbCost = new StringBuilder(mega ? "Megamorph" : "Morph"); @@ -156,15 +158,15 @@ public class CardFactoryUtil { sb.append(" | Mode$ TurnFace | SpellDescription$ (Turn this face up any time for its morph cost.)"); - final SpellAbility morphUp = AbilityFactory.getAbility(sb.toString(), sourceCard); + final SpellAbility morphUp = AbilityFactory.getAbility(sb.toString(), cardState); // if Cost has X in cost, need to check source for an SVar for this - if (cost.hasXInAnyCostPart() && sourceCard.hasSVar("X")) { - morphUp.setSVar("X", sourceCard.getSVar("X")); + if (cost.hasXInAnyCostPart() && cardState.hasSVar("X")) { + morphUp.setSVar("X", cardState.getSVar("X")); } final StringBuilder sbStack = new StringBuilder(); - sbStack.append(sourceCard.getName()).append(" - turn this card face up."); + sbStack.append(cardState.getName()).append(" - turn this card face up."); morphUp.setStackDescription(sbStack.toString()); return morphUp; @@ -2098,6 +2100,7 @@ public class CardFactoryUtil { final SpellAbility intrinsicAbility = AbilityFactory.getAbility(rawAbility, card); card.addSpellAbility(intrinsicAbility); intrinsicAbility.setIntrinsic(true); + intrinsicAbility.setCardState(card.getCurrentState()); } catch (Exception e) { String msg = "CardFactoryUtil:addAbilityFactoryAbilities: crash in raw Ability"; Sentry.getContext().recordBreadcrumb( @@ -2139,16 +2142,17 @@ public class CardFactoryUtil { } } - private static ReplacementEffect createETBReplacement(final Card card, ReplacementLayer layer, + private static ReplacementEffect createETBReplacement(final CardState card, ReplacementLayer layer, final String effect, final boolean optional, final boolean secondary, final boolean intrinsic, final String valid, final String zone) { SpellAbility repAb = AbilityFactory.getAbility(effect, card); return createETBReplacement(card, layer, repAb, optional, secondary, intrinsic, valid, zone); } - private static ReplacementEffect createETBReplacement(final Card card, ReplacementLayer layer, + private static ReplacementEffect createETBReplacement(final CardState card, ReplacementLayer layer, final SpellAbility repAb, final boolean optional, final boolean secondary, final boolean intrinsic, final String valid, final String zone) { + Card host = card.getCard(); String desc = repAb.getDescription(); setupETBReplacementAbility(repAb); if (!intrinsic) { @@ -2169,14 +2173,14 @@ public class CardFactoryUtil { repEffsb.append(" | ActiveZones$ ").append(zone); } - ReplacementEffect re = ReplacementHandler.parseReplacement(repEffsb.toString(), card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repEffsb.toString(), host, intrinsic, card); re.setLayer(layer); re.setOverridingAbility(repAb); return re; } - public static ReplacementEffect makeEtbCounter(final String kw, final Card card, final boolean intrinsic) + public static ReplacementEffect makeEtbCounter(final String kw, final CardState card, final boolean intrinsic) { String parse = kw; @@ -2212,7 +2216,7 @@ public class CardFactoryUtil { String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield " + "| Secondary$ True | Description$ " + desc + (!extraparams.equals("") ? " | " + extraparams : ""); - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card.getCard(), intrinsic, card); re.setOverridingAbility(sa); @@ -3342,10 +3346,11 @@ public class CardFactoryUtil { } } - public static void addReplacementEffect(final KeywordInterface inst, final Card card, final boolean intrinsic) { + public static void addReplacementEffect(final KeywordInterface inst, final CardState card, final boolean intrinsic) { + Card host = card.getCard(); String keyword = inst.getOriginal(); - if (keyword.equals("Aftermath") && card.getCurrentStateName().equals(CardStateName.RightSplit)) { + if (keyword.equals("Aftermath") && card.getStateName().equals(CardStateName.RightSplit)) { StringBuilder sb = new StringBuilder(); sb.append("Event$ Moved | ValidCard$ Card.Self | Origin$ Stack | ExcludeDestination$ Exile "); sb.append("| ValidStackSa$ Spell.Aftermath | Description$ Aftermath"); @@ -3362,7 +3367,7 @@ public class CardFactoryUtil { saExile.setIntrinsic(intrinsic); - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); re.setOverridingAbility(saExile); @@ -3408,7 +3413,7 @@ public class CardFactoryUtil { saReveal.setIntrinsic(intrinsic); - ReplacementEffect re = ReplacementHandler.parseReplacement(actualRep, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(actualRep, host, intrinsic, card); re.setOverridingAbility(saReveal); @@ -3460,7 +3465,7 @@ public class CardFactoryUtil { saReturn.setIntrinsic(intrinsic); - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); re.setOverridingAbility(saReturn); @@ -3483,7 +3488,7 @@ public class CardFactoryUtil { saMill.setIntrinsic(intrinsic); - ReplacementEffect re = ReplacementHandler.parseReplacement(actualRep, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(actualRep, host, intrinsic, card); re.setOverridingAbility(saMill); re.setSVar("DredgeCheckLib", "Count$ValidLibrary Card.YouOwn"); @@ -3513,7 +3518,7 @@ public class CardFactoryUtil { String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | Secondary$ True | Description$ Devour " + magnitude + " ("+ inst.getReminderText() + ")"; - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); setupETBReplacementAbility(cleanupSA); re.setOverridingAbility(sacrificeSA); @@ -3563,7 +3568,7 @@ public class CardFactoryUtil { saExile.setIntrinsic(false); } - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); re.setOverridingAbility(saExile); @@ -3598,7 +3603,7 @@ public class CardFactoryUtil { saExile.setIntrinsic(false); } - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); re.setOverridingAbility(saExile); @@ -3607,7 +3612,7 @@ public class CardFactoryUtil { // Set Madness Replacement effects String repeffstr = "Event$ Discard | ActiveZones$ Hand | ValidCard$ Card.Self | Secondary$ True " + " | Description$ Madness: If you discard this card, discard it into exile."; - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); String sVarMadness = "DB$ Discard | Defined$ ReplacedPlayer | Mode$ Defined | DefinedCards$ ReplacedCard | Madness$ True"; re.setOverridingAbility(AbilityFactory.getAbility(sVarMadness, card)); @@ -3657,7 +3662,7 @@ public class CardFactoryUtil { saExile.setIntrinsic(false); } - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); re.setOverridingAbility(saExile); @@ -3704,7 +3709,7 @@ public class CardFactoryUtil { } else if (keyword.equals("Sunburst")) { // Rule 702.43a If this object is entering the battlefield as a creature, // ignoring any type-changing effects that would affect it - CounterType t = CounterType.get(card.isCreature() ? CounterEnumType.P1P1 : CounterEnumType.CHARGE); + CounterType t = CounterType.get(host.isCreature() ? CounterEnumType.P1P1 : CounterEnumType.CHARGE); StringBuilder sb = new StringBuilder("etbCounter:"); sb.append(t).append(":Sunburst:no Condition:"); @@ -3732,7 +3737,7 @@ public class CardFactoryUtil { sa.setIntrinsic(false); } - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); re.setOverridingAbility(sa); @@ -3773,7 +3778,7 @@ public class CardFactoryUtil { String repeffstr = "Event$ Destroy | ActiveZones$ Battlefield | ValidCard$ Card.Self" + " | Secondary$ True | Regeneration$ True | Description$ " + keyword; String effect = "DB$ Regeneration | Defined$ ReplacedCard"; - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card); SpellAbility sa = AbilityFactory.getAbility(effect, card); re.setOverridingAbility(sa); @@ -3810,13 +3815,13 @@ public class CardFactoryUtil { if (from) { String fromRep = rep + " | ValidSource$ Card.Self"; - ReplacementEffect re = ReplacementHandler.parseReplacement(fromRep, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(fromRep, host, intrinsic, card); inst.addReplacement(re); } if (to) { String toRep = rep + " | ValidTarget$ Card.Self"; - ReplacementEffect re = ReplacementHandler.parseReplacement(toRep, card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(toRep, host, intrinsic, card); inst.addReplacement(re); } @@ -3828,7 +3833,7 @@ public class CardFactoryUtil { StringBuilder sb = new StringBuilder("Event$ Moved | Destination$ Graveyard | ValidCard$ Card.Self "); // to show it on Nexus - if (card.isPermanent()) { + if (host.isPermanent()) { sb.append("| Secondary$ True"); } sb.append("| Description$ ").append(keyword); @@ -3841,7 +3846,7 @@ public class CardFactoryUtil { sa.setIntrinsic(false); } - ReplacementEffect re = ReplacementHandler.parseReplacement(sb.toString(), card, intrinsic); + ReplacementEffect re = ReplacementHandler.parseReplacement(sb.toString(), host, intrinsic, card); re.setOverridingAbility(sa); @@ -3878,16 +3883,17 @@ public class CardFactoryUtil { } } - public static void addSpellAbility(final KeywordInterface inst, final Card card, final boolean intrinsic) { + public static void addSpellAbility(final KeywordInterface inst, final CardState card, final boolean intrinsic) { String keyword = inst.getOriginal(); - if (keyword.startsWith("Alternative Cost") && !card.isLand()) { + Card host = card.getCard(); + if (keyword.startsWith("Alternative Cost") && !host.isLand()) { final String[] kw = keyword.split(":"); String costStr = kw[1]; - for (SpellAbility sa: card.getBasicSpells()) { + for (SpellAbility sa: host.getBasicSpells()) { final SpellAbility newSA = sa.copy(); newSA.setBasicSpell(false); if (costStr.equals("ConvertedManaCost")) { - costStr = Integer.toString(card.getCMC()); + costStr = Integer.toString(host.getCMC()); } final Cost cost = new Cost(costStr, false).add(sa.getPayCosts().copyWithNoMana()); newSA.putParam("Secondary", "True"); @@ -3925,7 +3931,7 @@ public class CardFactoryUtil { final SpellAbility sa = AbilityFactory.getAbility(effect, card); sa.setIntrinsic(intrinsic); inst.addSpellAbility(sa); - } else if (keyword.equals("Aftermath") && card.getCurrentStateName().equals(CardStateName.RightSplit)) { + } else if (keyword.equals("Aftermath") && card.getStateName().equals(CardStateName.RightSplit)) { // Aftermath does modify existing SA, and does not add new one // only target RightSplit of it @@ -4135,7 +4141,7 @@ public class CardFactoryUtil { inst.addSpellAbility(newSA); } else if (keyword.startsWith("Foretell")) { - final SpellAbility foretell = new AbilityStatic(card, new Cost(ManaCost.TWO, false), null) { + final SpellAbility foretell = new AbilityStatic(card.getCard(), new Cost(ManaCost.TWO, false), null) { @Override public boolean canPlay() { if (!getRestrictions().canPlay(getHostCard(), this)) { @@ -4183,6 +4189,8 @@ public class CardFactoryUtil { foretell.setDescription(sbDesc.toString()); foretell.putParam("Secondary", "True"); + foretell.setCardState(card); + foretell.getRestrictions().setZone(ZoneType.Hand); foretell.setIntrinsic(intrinsic); inst.addSpellAbility(foretell); @@ -4207,12 +4215,12 @@ public class CardFactoryUtil { // instantiate attach ability final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card); inst.addSpellAbility(sa); - } else if (keyword.startsWith("Fuse") && card.getCurrentStateName().equals(CardStateName.Original)) { - final SpellAbility sa = AbilityFactory.buildFusedAbility(card); + } else if (keyword.startsWith("Fuse") && card.getStateName().equals(CardStateName.Original)) { + final SpellAbility sa = AbilityFactory.buildFusedAbility(card.getCard()); card.addSpellAbility(sa); inst.addSpellAbility(sa); } else if (keyword.startsWith("Haunt")) { - if (!card.isCreature() && intrinsic) { + if (!host.isCreature() && intrinsic) { final String[] k = keyword.split(":"); final String hauntSVarName = k[1]; @@ -4377,7 +4385,7 @@ public class CardFactoryUtil { final Cost prowlCost = new Cost(k[1], false); final SpellAbility newSA = card.getFirstSpellAbility().copyWithDefinedCost(prowlCost); - if (card.isInstant() || card.isSorcery()) { + if (host.isInstant() || host.isSorcery()) { newSA.putParam("Secondary", "True"); } newSA.putParam("PrecostDesc", "Prowl"); @@ -4509,7 +4517,7 @@ public class CardFactoryUtil { // be careful with Suspend ability, it will not hit the stack Cost cost = new Cost(k[2], true); - final SpellAbility suspend = new AbilityStatic(card, cost, null) { + final SpellAbility suspend = new AbilityStatic(host, cost, null) { @Override public boolean canPlay() { if (!(this.getRestrictions().canPlay(this.getHostCard(), this))) { @@ -4525,7 +4533,7 @@ public class CardFactoryUtil { @Override public void resolve() { - final Game game = card.getGame(); + final Game game = this.getHostCard().getGame(); final Card c = game.getAction().exile(this.getHostCard(), this); int counters = AbilityUtils.calculateAmount(c, k[1], this); @@ -4546,6 +4554,7 @@ public class CardFactoryUtil { String svar = "X"; // emulate "References X" here suspend.setSVar(svar, card.getSVar(svar)); + suspend.setCardState(card); final StringBuilder sbStack = new StringBuilder(); sbStack.append(card.getName()).append(" suspending for "); @@ -4673,7 +4682,7 @@ public class CardFactoryUtil { } } - public static void addStaticAbility(final KeywordInterface inst, final Card card, final boolean intrinsic) { + public static void addStaticAbility(final KeywordInterface inst, final CardState state, final boolean intrinsic) { String keyword = inst.getOriginal(); String effect = null; Map svars = Maps.newHashMap(); @@ -4716,7 +4725,7 @@ public class CardFactoryUtil { sb.append("Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ PlayEncoded"); sb.append(" | CombatDamage$ True | OptionalDecider$ You | TriggerDescription$ "); sb.append("Whenever CARDNAME deals combat damage to a player, its controller may cast a copy of "); - sb.append(card.getName()).append(" without paying its mana cost."); + sb.append(state.getName()).append(" without paying its mana cost."); String trig = sb.toString(); @@ -4786,7 +4795,7 @@ public class CardFactoryUtil { } if (effect != null) { - StaticAbility st = new StaticAbility(effect, card); + StaticAbility st = new StaticAbility(effect, state.getCard(), state); st.setIntrinsic(intrinsic); for (Map.Entry e : svars.entrySet()) { st.setSVar(e.getKey(), e.getValue()); @@ -4964,7 +4973,7 @@ public class CardFactoryUtil { if (sa == null) { return; } - sa.setCardState(CardStateName.Adventure); + sa.setCardState(card.getCurrentState()); StringBuilder sb = new StringBuilder(); sb.append("Event$ Moved | ValidCard$ Card.Self | Origin$ Stack | ExcludeDestination$ Exile "); diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index 799740e332e..c3212eb7754 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -104,6 +104,10 @@ public class CardState extends GameObject implements IHasSVars { view.updateName(this); } + public CardStateName getStateName() { + return this.getView().getState(); + } + @Override public String toString() { return name + " (" + view.getState() + ")"; @@ -303,6 +307,11 @@ public class CardState extends GameObject implements IHasSVars { return Iterables.filter(getSpellAbilities(), SpellAbilityPredicates.isIntrinsic()); } + + public final SpellAbility getFirstSpellAbility() { + return Iterables.getFirst(getNonManaAbilities(), null); + } + public final boolean hasSpellAbility(final SpellAbility sa) { return getSpellAbilities().contains(sa); } @@ -431,7 +440,7 @@ public class CardState extends GameObject implements IHasSVars { if (getTypeWithChanges().isPlaneswalker()) { if (loyaltyRep == null) { - loyaltyRep = CardFactoryUtil.makeEtbCounter("etbCounter:LOYALTY:" + this.baseLoyalty, card, true); + loyaltyRep = CardFactoryUtil.makeEtbCounter("etbCounter:LOYALTY:" + this.baseLoyalty, this, true); } result.add(loyaltyRep); } diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java index 0ef5b3ffcd7..b54207e8dcd 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java @@ -109,9 +109,9 @@ public abstract class KeywordInstance> implements K Sentry.getContext().addExtra("Keyword", this.original); CardFactoryUtil.addTriggerAbility(this, host, intrinsic); - CardFactoryUtil.addReplacementEffect(this, host, intrinsic); - CardFactoryUtil.addSpellAbility(this, host, intrinsic); - CardFactoryUtil.addStaticAbility(this, host, intrinsic); + CardFactoryUtil.addReplacementEffect(this, host.getCurrentState(), intrinsic); + CardFactoryUtil.addSpellAbility(this, host.getCurrentState(), intrinsic); + CardFactoryUtil.addStaticAbility(this, host.getCurrentState(), intrinsic); } catch (Exception e) { String msg = "KeywordInstance:createTraits: failed Traits for Keyword"; Sentry.getContext().recordBreadcrumb( diff --git a/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java b/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java index fa4cf5fd431..4eb3eeac0c7 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java @@ -29,7 +29,7 @@ public class PlayerFactoryUtil { } if (effect != null) { final Card card = player.getKeywordCard(); - StaticAbility st = new StaticAbility(effect, card); + StaticAbility st = new StaticAbility(effect, card, card.getCurrentState()); st.setIntrinsic(false); inst.addStaticAbility(st); } diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index e042aace629..d23d1f933dc 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -17,6 +17,7 @@ */ package forge.game.replacement; +import forge.game.CardTraitBase; import forge.game.Game; import forge.game.GameLogEntryType; import forge.game.IHasSVars; @@ -25,6 +26,7 @@ import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; +import forge.game.card.CardState; import forge.game.card.CardTraitChanges; import forge.game.card.CardUtil; import forge.game.keyword.KeywordInterface; @@ -405,6 +407,11 @@ public class ReplacementHandler { ret.setOverridingAbility(AbilityFactory.getAbility(host, mapParams.get("ReplaceWith"), sVarHolder)); } + if (sVarHolder instanceof CardState) { + ret.setCardState((CardState)sVarHolder); + } else if (sVarHolder instanceof CardTraitBase) { + ret.setCardState(((CardTraitBase)sVarHolder).getCardState()); + } return ret; } } diff --git a/forge-game/src/main/java/forge/game/spellability/LandAbility.java b/forge-game/src/main/java/forge/game/spellability/LandAbility.java index 77a99dd58b4..0e2bcdde8f4 100644 --- a/forge-game/src/main/java/forge/game/spellability/LandAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/LandAbility.java @@ -49,11 +49,11 @@ public class LandAbility extends Ability { Card land = this.getHostCard(); final Player p = this.getActivatingPlayer(); - if (this.getCardState() != null) { + if (this.getCardState() != null && land.getCurrentStateName() != this.getCardStateName()) { if (!land.isLKI()) { land = CardUtil.getLKICopy(land); } - CardStateName stateName = getCardState(); + CardStateName stateName = getCardStateName(); if (!land.hasState(stateName)) { land.addAlternateState(stateName, false); land.getState(stateName).copyFrom(getHostCard().getState(stateName), true); @@ -87,7 +87,7 @@ public class LandAbility extends Ability { StringBuilder sb = new StringBuilder("Play land"); if (getHostCard().isModal()) { - sb.append(" (").append(getHostCard().getName(ObjectUtils.defaultIfNull(getCardState(), CardStateName.Original))).append(")"); + sb.append(" (").append(getHostCard().getName(ObjectUtils.firstNonNull(getCardStateName(), CardStateName.Original))).append(")"); } StaticAbility sta = getMayPlay(); diff --git a/forge-game/src/main/java/forge/game/spellability/Spell.java b/forge-game/src/main/java/forge/game/spellability/Spell.java index 55f86ddeef6..138a6e74cbd 100644 --- a/forge-game/src/main/java/forge/game/spellability/Spell.java +++ b/forge-game/src/main/java/forge/game/spellability/Spell.java @@ -175,11 +175,11 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable } source.turnFaceDownNoUpdate(); lkicheck = true; - } else if (getCardState() != null) { + } else if (getCardState() != null && source.getCurrentStateName() != getCardStateName()) { if (!source.isLKI()) { source = CardUtil.getLKICopy(source); } - CardStateName stateName = getCardState(); + CardStateName stateName = getCardState().getStateName(); if (!source.hasState(stateName)) { source.addAlternateState(stateName, false); source.getState(stateName).copyFrom(getHostCard().getState(stateName), true); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 0719e906ae2..844164a37b8 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -115,8 +115,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private boolean blessing = false; private Integer chapter = null; - private CardStateName stateName = null; - /** The pay costs. */ private Cost payCosts; private SpellAbilityRestriction restrictions = new SpellAbilityRestriction(); @@ -466,21 +464,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return this.hasParam("Boast"); } - public void setOriginalHost(final Card c) { - super.setOriginalHost(c); - if (subAbility != null) { - subAbility.setOriginalHost(c); - } - for (AbilitySub sa : additionalAbilities.values()) { - sa.setOriginalHost(c); - } - for (List list : additionalAbilityLists.values()) { - for (AbilitySub sa : list) { - sa.setOriginalHost(c); - } - } - } - // If this is not null, then ability was made in a factory public ApiType getApi() { return api; @@ -960,15 +943,8 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit mayPlay = sta; } - public CardStateName getCardState() { - return stateName; - } - public void setCardState(CardStateName stateName0) { - this.stateName = stateName0; - } - public boolean isAdventure() { - return this.stateName == CardStateName.Adventure; + return this.getCardStateName() == CardStateName.Adventure; } public SpellAbility copy() { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index bd709f86c3a..8c637752f9c 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -31,6 +31,7 @@ import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; import forge.game.card.CardLists; +import forge.game.card.CardState; import forge.game.card.CounterType; import forge.game.cost.Cost; import forge.game.phase.PhaseHandler; @@ -236,8 +237,8 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone * @param host * the host */ - public StaticAbility(final String params, final Card host) { - this(parseParams(params, host), host); + public StaticAbility(final String params, final Card host, CardState state) { + this(parseParams(params, host), host, state); } /** @@ -248,13 +249,14 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone * @param host * the host */ - private StaticAbility(final Map params, final Card host) { + private StaticAbility(final Map params, final Card host, CardState state) { this.id = nextId(); this.originalMapParams.putAll(params); this.mapParams.putAll(params); this.layers = this.generateLayer(); this.hostCard = host; buildCommonAttributes(host); + this.setCardState(state); } public final CardCollectionView applyContinuousAbilityBefore(final StaticAbilityLayer layer, final CardCollectionView preList) { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index c0066417085..404aa9ae796 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -736,7 +736,6 @@ public final class StaticAbilityContinuous { if (abilty.startsWith("AB") || abilty.startsWith("ST")) { // grant the ability final SpellAbility sa = AbilityFactory.getAbility(abilty, affectedCard, stAb); sa.setIntrinsic(false); - sa.setOriginalHost(hostCard); addedAbilities.add(sa); } } @@ -766,9 +765,6 @@ public final class StaticAbilityContinuous { newSA.setRestrictions(sa.getRestrictions()); newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn")); } - if (newSA.getOriginalHost() == null) { - newSA.setOriginalHost(c); - } newSA.setOriginalAbility(sa); // need to be set to get the Once Per turn Clause correct newSA.setGrantorStatic(stAb); newSA.setIntrinsic(false); @@ -794,7 +790,6 @@ public final class StaticAbilityContinuous { // turn them into SpellAbility object before adding to card // with that the TargetedCard does not need the Svars added to them anymore // but only do it if the trigger doesn't already have a overriding ability - actualTrigger.setOriginalHost(hostCard); addedTrigger.add(actualTrigger); } } @@ -807,9 +802,8 @@ public final class StaticAbilityContinuous { s = TextUtil.fastReplace(s, "ConvertedManaCost", costcmc); } - StaticAbility stat = new StaticAbility(s, affectedCard); + StaticAbility stat = new StaticAbility(s, affectedCard, stAb.getCardState()); stat.setIntrinsic(false); - stat.setOriginalHost(hostCard); addedStaticAbility.add(stat); } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 66a53b9ff34..07b71db7a04 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -17,6 +17,7 @@ */ package forge.game.trigger; +import forge.game.CardTraitBase; import forge.game.Game; import forge.game.GlobalRuleChange; import forge.game.IHasSVars; @@ -29,6 +30,7 @@ import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardLists; import forge.game.card.CardPredicates; +import forge.game.card.CardState; import forge.game.card.CardZoneTable; import forge.game.keyword.KeywordInterface; import forge.game.player.Player; @@ -151,6 +153,12 @@ public class TriggerHandler { ret = type.createTrigger(mapParams, host, intrinsic); if (sVarHolder != null) { ret.ensureAbility(sVarHolder); + + if (sVarHolder instanceof CardState) { + ret.setCardState((CardState)sVarHolder); + } else if (sVarHolder instanceof CardTraitBase) { + ret.setCardState(((CardTraitBase)sVarHolder).getCardState()); + } } } catch (Exception e) { String msg = "TriggerHandler:parseTrigger failed to parse"; diff --git a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java index 935ae869c4c..b614f346934 100644 --- a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java +++ b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java @@ -6,6 +6,7 @@ import forge.game.ability.AbilityKey; import forge.game.ability.ApiType; import forge.game.card.Card; import forge.game.card.CardCollection; +import forge.game.card.CardState; import forge.game.cost.Cost; import forge.game.player.Player; import forge.game.spellability.*; @@ -515,10 +516,11 @@ public class WrappedAbility extends Ability { sa.setXManaCostPaid(n); } - public Card getOriginalHost() { - return sa.getOriginalHost(); + + public CardState getCardState() { + return sa.getCardState(); } - public void setOriginalHost(final Card c) { - sa.setOriginalHost(c); + public void setCardState(CardState state) { + sa.setCardState(state); } } \ No newline at end of file