From 2e196fc41b54dcfc00e43657339739cdd8e7ec75 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Sat, 10 Feb 2018 18:50:22 +0100 Subject: [PATCH 1/2] CardTaits: make cardtraits inside LKI has the same id's as the in the original object\nReplaceMoved now works with Blood Moon and Blood Sun --- .../java/forge/ai/ComputerUtilCombat.java | 2 +- .../forge/ai/ability/ChooseCardNameAi.java | 4 +- .../java/forge/ai/ability/SetStateAi.java | 2 +- .../java/forge/ai/simulation/GameCopier.java | 10 +- .../main/java/forge/game/GameActionUtil.java | 2 +- .../forge/game/TriggerReplacementBase.java | 2 +- .../forge/game/ability/AbilityApiBased.java | 12 --- .../game/ability/effects/CharmEffect.java | 2 +- .../game/ability/effects/PumpEffect.java | 4 + .../src/main/java/forge/game/card/Card.java | 24 +++-- .../java/forge/game/card/CardFactory.java | 41 ++++----- .../main/java/forge/game/card/CardState.java | 41 ++++++--- .../main/java/forge/game/card/CardUtil.java | 12 ++- .../forge/game/keyword/KeywordCollection.java | 11 +++ .../forge/game/keyword/KeywordInstance.java | 19 ++-- .../forge/game/keyword/KeywordInterface.java | 2 +- .../forge/game/replacement/ReplaceMoved.java | 31 +++++-- .../game/replacement/ReplacementEffect.java | 92 ++++++++++++++----- .../game/replacement/ReplacementHandler.java | 21 ++--- .../game/replacement/ReplacementType.java | 10 -- .../game/spellability/AbilityActivated.java | 4 - .../forge/game/spellability/AbilitySub.java | 11 --- .../forge/game/spellability/SpellAbility.java | 34 ++++--- .../StaticAbilityContinuous.java | 5 +- .../main/java/forge/game/trigger/Trigger.java | 86 ++++++++--------- .../java/forge/game/trigger/TriggerType.java | 12 --- 26 files changed, 270 insertions(+), 226 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index c699e3eec7f..5f26065df22 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -2466,7 +2466,7 @@ public class ComputerUtilCombat { for (SpellAbility sa : original.getSpellAbilities()) { if (sa.getApi() == ApiType.SetState && ComputerUtilCost.canPayCost(sa, original.getController())) { Card transformed = CardUtil.getLKICopy(original); - transformed.getCurrentState().copyFrom(original, original.getAlternateState()); + transformed.getCurrentState().copyFrom(original.getAlternateState(), true); transformed.updateStateForView(); return transformed; } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseCardNameAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseCardNameAi.java index 822500b4665..6148e60fdb5 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseCardNameAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseCardNameAi.java @@ -88,9 +88,9 @@ public class ChooseCardNameAi extends SpellAbilityAi { Card copy = CardUtil.getLKICopy(card); // for calcing i need only one split side if (isOther) { - copy.getCurrentState().copyFrom(card, card.getState(CardStateName.RightSplit)); + copy.getCurrentState().copyFrom(card.getState(CardStateName.RightSplit), true); } else { - copy.getCurrentState().copyFrom(card, card.getState(CardStateName.LeftSplit)); + copy.getCurrentState().copyFrom(card.getState(CardStateName.LeftSplit), true); } copy.updateStateForView(); diff --git a/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java b/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java index 73647c7bfaf..350f368a817 100644 --- a/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java @@ -167,7 +167,7 @@ public class SetStateAi extends SpellAbilityAi { // need a copy for evaluation Card transformed = CardUtil.getLKICopy(card); - transformed.getCurrentState().copyFrom(card, card.getAlternateState()); + transformed.getCurrentState().copyFrom(card.getAlternateState(), true); transformed.updateStateForView(); // TODO: compareCards assumes that a creature will transform into a creature. Need to improve this diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index f79d0c263b1..636a509c35f 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -29,7 +29,6 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.RegisteredPlayer; -import forge.game.spellability.AbilityActivated; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityRestriction; import forge.game.spellability.SpellAbilityStackInstance; @@ -263,15 +262,8 @@ public class GameCopier { newCard.addStaticAbility(stAb); } for (SpellAbility sa : c.getSpellAbilities()) { - SpellAbility saCopy; - - if (sa instanceof AbilityActivated) { - saCopy = ((AbilityActivated)sa).getCopy(); - } else { - saCopy = sa.copy(); - } + SpellAbility saCopy = sa.copy(newCard, true); if (saCopy != null) { - saCopy.setHostCard(newCard); newCard.addSpellAbility(saCopy); } else { System.err.println(sa.toString()); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 0d090796141..9b1851c0767 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -233,7 +233,7 @@ public final class GameActionUtil { alternatives.add(newSA); } if (sa.hasParam("Equip") && sa instanceof AbilityActivated && keyword.equals("EquipInstantSpeed")) { - final SpellAbility newSA = ((AbilityActivated) sa).getCopy(); + final SpellAbility newSA = sa.copy(); SpellAbilityRestriction sar = newSA.getRestrictions(); sar.setSorcerySpeed(false); sar.setInstantSpeed(true); diff --git a/forge-game/src/main/java/forge/game/TriggerReplacementBase.java b/forge-game/src/main/java/forge/game/TriggerReplacementBase.java index b4b79798642..8552db9f0ff 100644 --- a/forge-game/src/main/java/forge/game/TriggerReplacementBase.java +++ b/forge-game/src/main/java/forge/game/TriggerReplacementBase.java @@ -11,7 +11,7 @@ import forge.game.zone.ZoneType; /** * Created by Hellfish on 2014-02-09. */ -public abstract class TriggerReplacementBase extends CardTraitBase { +public abstract class TriggerReplacementBase extends CardTraitBase implements IIdentifiable, Cloneable { protected EnumSet validHostZones; /** The overriding ability. */ diff --git a/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java b/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java index 9f8236f64ba..a471e78703a 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityApiBased.java @@ -5,7 +5,6 @@ import forge.game.ability.effects.ChangeZoneEffect; import forge.game.ability.effects.ManaEffect; import forge.game.ability.effects.ManaReflectedEffect; import forge.game.card.Card; -import forge.game.card.CardFactory; import forge.game.cost.Cost; import forge.game.spellability.AbilityActivated; import forge.game.spellability.AbilityManaPart; @@ -41,17 +40,6 @@ public class AbilityApiBased extends AbilityActivated { return effect.getStackDescriptionWithSubs(mapParams, this); } - /* (non-Javadoc) - * @see forge.card.spellability.AbilityActivated#getCopy() - */ - @Override - public AbilityActivated getCopy() { - TargetRestrictions tgt = getTargetRestrictions() == null ? null : new TargetRestrictions(getTargetRestrictions()); - AbilityActivated res = new AbilityApiBased(api, getHostCard(), getPayCosts(), tgt, mapParams); - CardFactory.copySpellAbility(this, res, getHostCard()); - return res; - } - /* (non-Javadoc) * @see forge.card.spellability.SpellAbility#resolve() */ diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index c54ae208e0e..3652fa9ee08 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -195,7 +195,7 @@ public class CharmEffect extends SpellAbilityEffect { for (AbilitySub sub : chosen) { // Clone the chosen, just in case the some subAb gets chosen multiple times - AbilitySub clone = (AbilitySub)sub.getCopy(); + AbilitySub clone = (AbilitySub)sub.copy(); // update ActivatingPlayer clone.setActivatingPlayer(sa.getActivatingPlayer()); diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java index 1305dc1dc8e..02a0dd7016f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java @@ -141,6 +141,10 @@ public class PumpEffect extends SpellAbilityEffect { } } + /* + * (non-Javadoc) + * @see forge.game.ability.SpellAbilityEffect#getStackDescription(forge.game.spellability.SpellAbility) + */ @Override protected String getStackDescription(final SpellAbility sa) { 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 d75badf6f1c..54370bf834a 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -822,17 +822,18 @@ public class Card extends GameEntity implements Comparable { public final FCollectionView getTriggers() { return currentState.getTriggers(); } + // only used for LKI public final void setTriggers(final Iterable trigs, boolean intrinsicOnly) { final FCollection copyList = new FCollection<>(); for (final Trigger t : trigs) { if (!intrinsicOnly || t.isIntrinsic()) { - copyList.add(t.getCopyForHostCard(this)); + copyList.add(t.copy(this, true)); } } currentState.setTriggers(copyList); } public final Trigger addTrigger(final Trigger t) { - final Trigger newtrig = t.getCopyForHostCard(this); + final Trigger newtrig = t.copy(this, false); currentState.addTrigger(newtrig); return newtrig; } @@ -5171,16 +5172,14 @@ public class Card extends GameEntity implements Comparable { currentState.clearReplacementEffects(); for (final ReplacementEffect replacementEffect : res) { if (replacementEffect.isIntrinsic()) { - addReplacementEffect(replacementEffect); + addReplacementEffect(replacementEffect.copy(this, false)); } } } public ReplacementEffect addReplacementEffect(final ReplacementEffect replacementEffect) { - final ReplacementEffect replacementEffectCopy = replacementEffect.getCopy(); // doubtful - every caller provides a newly parsed instance, why copy? - replacementEffectCopy.setHostCard(this); - currentState.addReplacementEffect(replacementEffectCopy); - return replacementEffectCopy; + currentState.addReplacementEffect(replacementEffect); + return replacementEffect; } public void removeReplacementEffect(ReplacementEffect replacementEffect) { currentState.removeReplacementEffect(replacementEffect); @@ -5192,6 +5191,17 @@ public class Card extends GameEntity implements Comparable { } } + public boolean hasReplacementEffect(final ReplacementEffect re) { + return currentState.hasReplacementEffect(re); + } + public boolean hasReplacementEffect(final int id) { + return currentState.hasReplacementEffect(id); + } + + public ReplacementEffect getReplacementEffect(final int id) { + return currentState.getReplacementEffect(id); + } + /** * Returns what zone this card was cast from (from what zone it was moved to the stack). */ 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 d0976e3d2ab..66fc64cfcbd 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -184,21 +184,10 @@ public class CardFactory { c.setCopiedSpell(true); final SpellAbility copySA; - if (sa instanceof AbilityActivated) { - copySA = ((AbilityActivated)sa).getCopy(); - copySA.setHostCard(original); - } - else if (sa.isTrigger()) { + if (sa.isTrigger()) { copySA = getCopiedTriggeredAbility(sa); - } - else { - copySA = sa.copy(); - AbilitySub subSA = copySA.getSubAbility(); - while (subSA != null) { - subSA.setCopied(true); - subSA = subSA.getSubAbility(); - } - copySA.setHostCard(c); + } else { + copySA = sa.copy(c, false); } c.getCurrentState().setNonManaAbilities(copySA); copySA.setCopied(true); @@ -577,27 +566,28 @@ public class CardFactory { to.addAlternateState(toState, updateView); } final CardState toCharacteristics = to.getState(toState), fromCharacteristics = from.getState(fromState); - toCharacteristics.copyFrom(from, fromCharacteristics); + toCharacteristics.copyFrom(fromCharacteristics, false); } - - public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host) { - if (from.getActivatingPlayer() != null) { - to.setActivatingPlayer(from.getActivatingPlayer()); + + public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host, final boolean lki) { + + if (from.getTargetRestrictions() != null) { + to.setTargetRestrictions(from.getTargetRestrictions()); } to.setDescription(from.getOriginalDescription()); to.setStackDescription(from.getOriginalStackDescription()); if (from.getSubAbility() != null) { - to.setSubAbility(from.getSubAbility().getCopy(host)); + to.setSubAbility((AbilitySub) from.getSubAbility().copy(host, lki)); } for (Map.Entry e : from.getAdditionalAbilities().entrySet()) { - to.setAdditionalAbility(e.getKey(), e.getValue().getCopy(host)); + to.setAdditionalAbility(e.getKey(), (AbilitySub) e.getValue().copy(host, lki)); } for (Map.Entry> e : from.getAdditionalAbilityLists().entrySet()) { to.setAdditionalAbilityList(e.getKey(), Lists.transform(e.getValue(), new Function() { @Override public AbilitySub apply(AbilitySub input) { - return input.getCopy(host); + return (AbilitySub) input.copy(host, lki); } })); } @@ -607,7 +597,12 @@ public class CardFactory { if (from.getConditions() != null) { to.setConditions((SpellAbilityCondition) from.getConditions().copy()); } - + + // do this after other abilties are copied + if (from.getActivatingPlayer() != null) { + to.setActivatingPlayer(from.getActivatingPlayer(), lki); + } + for (String sVar : from.getSVars()) { to.setSVar(sVar, from.getSVar(sVar)); } 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 a82ce1897b5..b7ce1d11f8a 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -170,10 +170,10 @@ public class CardState extends GameObject { public final boolean hasIntrinsicKeyword(String k) { return intrinsicKeywords.contains(k); } - public final void setIntrinsicKeywords(final Iterable intrinsicKeyword0) { + public final void setIntrinsicKeywords(final Iterable intrinsicKeyword0, final boolean lki) { intrinsicKeywords.clear(); for (KeywordInterface k : intrinsicKeyword0) { - intrinsicKeywords.insert(k.copy(card)); + intrinsicKeywords.insert(k.copy(card, lki)); } } @@ -367,6 +367,24 @@ public class CardState extends GameObject { return getReplacementEffects().contains(re); } + public final boolean hasReplacementEffect(final int id) { + for (final ReplacementEffect r : getReplacementEffects()) { + if (id == r.getId()) { + return true; + } + } + return false; + } + + public final ReplacementEffect getReplacementEffect(final int id) { + for (final ReplacementEffect r : getReplacementEffects()) { + if (id == r.getId()) { + return r; + } + } + return null; + } + public final Map getSVars() { return sVars; } @@ -406,7 +424,7 @@ public class CardState extends GameObject { return 0; } - public final void copyFrom(final Card c, final CardState source) { + public final void copyFrom(final CardState source, final boolean lki) { // Makes a "deeper" copy of a CardState object setName(source.getName()); setType(source.type); @@ -419,36 +437,30 @@ public class CardState extends GameObject { manaAbilities.clear(); for (SpellAbility sa : source.manaAbilities) { if (sa.isIntrinsic()) { - SpellAbility saCopy = sa.copy(); - saCopy.setHostCard(card); // update HostCard - manaAbilities.add(saCopy); + manaAbilities.add(sa.copy(card, lki)); } } nonManaAbilities.clear(); for (SpellAbility sa : source.nonManaAbilities) { if (sa.isIntrinsic()) { - SpellAbility saCopy = sa.copy(); - saCopy.setHostCard(card); // update HostCard - nonManaAbilities.add(saCopy); + nonManaAbilities.add(sa.copy(card, lki)); } } - setIntrinsicKeywords(source.intrinsicKeywords.getValues()); + setIntrinsicKeywords(source.intrinsicKeywords.getValues(), lki); setImageKey(source.getImageKey()); setRarity(source.rarity); setSetCode(source.setCode); triggers.clear(); for (Trigger tr : source.triggers) { - triggers.add(tr.getCopyForHostCard(card)); + triggers.add(tr.copy(card, lki)); } replacementEffects.clear(); for (ReplacementEffect re : source.replacementEffects) { - ReplacementEffect reCopy = re.getCopy(); - reCopy.setHostCard(card); - replacementEffects.add(reCopy); + replacementEffects.add(re.copy(card, lki)); } staticAbilities.clear(); @@ -456,7 +468,6 @@ public class CardState extends GameObject { StaticAbility saCopy = new StaticAbility(sa, this.card); staticAbilities.add(saCopy); } - view.updateKeywords(c, this); } diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index 626b45eb08c..864d6214400 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -211,19 +211,18 @@ public final class CardUtil { // used for the purpose of cards that care about the zone the card was known to be in last newCopy.setLastKnownZone(in.getLastKnownZone()); - newCopy.getCurrentState().copyFrom(in, in.getState(in.getCurrentStateName())); + newCopy.getCurrentState().copyFrom(in.getState(in.getCurrentStateName()), true); if (in.isCloned()) { newCopy.addAlternateState(CardStateName.Cloner, false); - newCopy.getState(CardStateName.Cloner).copyFrom(in, in.getState(CardStateName.Cloner)); + newCopy.getState(CardStateName.Cloner).copyFrom(in.getState(CardStateName.Cloner), true); } newCopy.setType(new CardType(in.getType())); newCopy.setToken(in.isToken()); newCopy.setTriggers(in.getTriggers(), false); for (SpellAbility sa : in.getSpellAbilities()) { - newCopy.addSpellAbility(sa); - sa.setHostCard(in); + newCopy.addSpellAbility(sa.copy(newCopy, true)); } // lock in the current P/T without bonus from counters @@ -263,6 +262,11 @@ public final class CardUtil { newCopy.setMeldedWith(in.getMeldedWith()); + // update keyword cache on all states + for (CardStateName s : newCopy.getStates()) { + newCopy.updateKeywordsCache(newCopy.getState(s)); + } + return newCopy; } diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java b/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java index 398174c8fe5..a0d545fabc5 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java @@ -167,6 +167,17 @@ public class KeywordCollection implements Iterable, Serializable { }; } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(map.values()); + return sb.toString(); + } + public KeywordCollectionView getView() { if (view == null) { view = new KeywordCollectionView(); 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 aff0cb035f5..7329dc81c9b 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java @@ -180,26 +180,23 @@ public abstract class KeywordInstance> implements K * (non-Javadoc) * @see forge.game.keyword.KeywordInterface#copy() */ - public KeywordInterface copy(final Card host) { + public KeywordInterface copy(final Card host, final boolean lki) { try { KeywordInstance result = (KeywordInstance) super.clone(); result.abilities = Lists.newArrayList(); for (SpellAbility sa : this.abilities) { - SpellAbility saCopy = sa.copy(host); - result.abilities.add(saCopy); + result.abilities.add(sa.copy(host, lki)); } result.triggers = Lists.newArrayList(); for (Trigger tr : this.triggers) { - result.triggers.add(tr.getCopyForHostCard(host)); + result.triggers.add(tr.copy(host, lki)); } result.replacements = Lists.newArrayList(); for (ReplacementEffect re : this.replacements) { - ReplacementEffect reCopy = re.getCopy(); - reCopy.setHostCard(host); - result.replacements.add(reCopy); + result.replacements.add(re.copy(host, lki)); } result.staticAbilities = Lists.newArrayList(); @@ -212,4 +209,12 @@ public abstract class KeywordInstance> implements K throw new RuntimeException("KeywordInstance : clone() error, " + ex); } } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return this.getOriginal(); + } } diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java b/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java index a25de537e09..9fbde89f4af 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java @@ -49,5 +49,5 @@ public interface KeywordInterface extends Cloneable { */ public Collection getStaticAbilities(); - public KeywordInterface copy(final Card host); + public KeywordInterface copy(final Card host, final boolean lki); } \ No newline at end of file diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java b/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java index 77767a91f55..1ee3ef08f98 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java @@ -1,12 +1,16 @@ package forge.game.replacement; import forge.game.card.Card; +import forge.game.card.CardCollection; +import forge.game.card.CardUtil; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import java.util.Map; +import com.google.common.collect.Sets; + /** * TODO: Write javadoc for this type. * @@ -32,7 +36,7 @@ public class ReplaceMoved extends ReplacementEffect { return false; } final Player controller = getHostCard().getController(); - + if (hasParam("ValidCard")) { if (!matchesValid(runParams.get("Affected"), getParam("ValidCard").split(","), getHostCard())) { return false; @@ -44,31 +48,46 @@ public class ReplaceMoved extends ReplacementEffect { return false; } } - + boolean matchedZone = false; if (hasParam("Origin")) { for(ZoneType z : ZoneType.listValueOf(getParam("Origin"))) { if(z == (ZoneType) runParams.get("Origin")) matchedZone = true; } - + if(!matchedZone) { return false; } } - + if (hasParam("Destination")) { matchedZone = false; + ZoneType zt = (ZoneType) runParams.get("Destination"); for(ZoneType z : ZoneType.listValueOf(getParam("Destination"))) { - if(z == (ZoneType) runParams.get("Destination")) + if(z == zt) matchedZone = true; } - + if(!matchedZone) { return false; } + + if (zt.equals(ZoneType.Battlefield)) { + // would be an etb replacement effect that enters the battlefield + Card lki = CardUtil.getLKICopy((Card) runParams.get("Affected")); + lki.setLastKnownZone(lki.getController().getZone(zt)); + + CardCollection preList = new CardCollection(lki); + getHostCard().getGame().getAction().checkStaticAbilities(false, Sets.newHashSet(lki), preList); + + // check if when entering the battlefield would still has this RE or is suppressed + if (!lki.hasReplacementEffect(this) || lki.getReplacementEffect(getId()).isSuppressed()) { + return false; + } + } } if (hasParam("ExcludeDestination")) { diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java index b613b8ac1a8..8800168fe1e 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java @@ -19,11 +19,9 @@ package forge.game.replacement; import forge.game.Game; import forge.game.TriggerReplacementBase; -import forge.game.ability.AbilityApiBased; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.phase.PhaseType; -import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; import forge.util.TextUtil; @@ -35,12 +33,37 @@ import java.util.Map; * */ public abstract class ReplacementEffect extends TriggerReplacementBase { + private static int maxId = 0; + private static int nextId() { return ++maxId; } + + /** The ID. */ + private int id; private ReplacementLayer layer = ReplacementLayer.None; /** The has run. */ private boolean hasRun = false; + /** + * Gets the id. + * + * @return the id + */ + public int getId() { + return this.id; + } + + /** + *

+ * setID. + *

+ * + * @param id + * a int. + */ + public final void setId(final int id) { + this.id = id; + } /** * Checks for run. * @@ -59,6 +82,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { * the host */ public ReplacementEffect(final Map map, final Card host, final boolean intrinsic) { + this.id = nextId(); this.intrinsic = intrinsic; originalMapParams.putAll(map); mapParams.putAll(map); @@ -133,32 +157,27 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { * * @return the copy */ - public final ReplacementEffect getCopy() { - final ReplacementType rt = ReplacementType.getTypeFor(this); - final ReplacementEffect res = rt.createReplacement(mapParams, hostCard, intrinsic); - final SpellAbility overridingAbility = this.getOverridingAbility(); - if (overridingAbility != null) { - final SpellAbility overridingAbilityCopy; - if (overridingAbility instanceof AbilityApiBased) { - overridingAbilityCopy = ((AbilityApiBased) overridingAbility).getCopy(); - } else if (overridingAbility instanceof AbilitySub) { - overridingAbilityCopy = ((AbilitySub) overridingAbility).getCopy(); - } else { - System.err.println("Overriding ability of " + hostCard + " of unexpected type " + overridingAbility.getClass()); - overridingAbilityCopy = null; - } - - if (overridingAbilityCopy != null) { - overridingAbilityCopy.setHostCard(hostCard); - res.setOverridingAbility(overridingAbilityCopy); - } - } - res.setActiveZone(validHostZones); - res.setLayer(getLayer()); - res.setTemporary(isTemporary()); + public final ReplacementEffect copy(final Card host, final boolean lki) { + final ReplacementEffect res = (ReplacementEffect) clone(); for (String key : getSVars()) { res.setSVar(key, getSVar(key)); } + + final SpellAbility sa = this.getOverridingAbility(); + if (sa != null) { + final SpellAbility overridingAbilityCopy = sa.copy(host, lki); + if (overridingAbilityCopy != null) { + res.setOverridingAbility(overridingAbilityCopy); + } + } + + if (!lki) { + res.setId(nextId()); + } + + res.setActiveZone(validHostZones); + res.setLayer(getLayer()); + res.setTemporary(isTemporary()); return res; } @@ -206,6 +225,29 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { } } + /** {@inheritDoc} */ + @Override + public final Object clone() { + try { + return super.clone(); + } catch (final Exception ex) { + throw new RuntimeException("ReplacementEffect : clone() error, " + ex); + } + } + /** {@inheritDoc} */ + @Override + public final boolean equals(final Object o) { + if (!(o instanceof ReplacementEffect)) { + return false; + } + return this.getId() == ((ReplacementEffect) o).getId(); + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return 42 * (42 + this.getId()); + } } 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 b133bafc8be..3c555c28624 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -61,21 +61,12 @@ public class ReplacementHandler { decider = ((Card) affected).getController(); } - ReplacementResult res = run(runParams, ReplacementLayer.Control, decider); - if (res != ReplacementResult.NotReplaced) { - return res; - } - res = run(runParams, ReplacementLayer.Copy, decider); - if (res != ReplacementResult.NotReplaced) { - return res; - } - res = run(runParams, ReplacementLayer.Other, decider); - if (res != ReplacementResult.NotReplaced) { - return res; - } - res = run(runParams, ReplacementLayer.None, decider); - if (res != ReplacementResult.NotReplaced) { - return res; + // try out all layer + for (ReplacementLayer layer : ReplacementLayer.values()) { + ReplacementResult res = run(runParams, layer, decider); + if (res != ReplacementResult.NotReplaced) { + return res; + } } return ReplacementResult.NotReplaced; diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java index bffaf067e3b..35fed6dbc52 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java @@ -32,16 +32,6 @@ public enum ReplacementType { clasz = cls; } - public static ReplacementType getTypeFor(ReplacementEffect e) { - final Class cls = e.getClass(); - for (final ReplacementType v : ReplacementType.values()) { - if (v.clasz.equals(cls)) { - return v; - } - } - return null; - } - public static ReplacementType smartValueOf(String value) { final String valToCompate = value.trim(); for (final ReplacementType v : ReplacementType.values()) { diff --git a/forge-game/src/main/java/forge/game/spellability/AbilityActivated.java b/forge-game/src/main/java/forge/game/spellability/AbilityActivated.java index 77bf6a44374..810676225cd 100644 --- a/forge-game/src/main/java/forge/game/spellability/AbilityActivated.java +++ b/forge-game/src/main/java/forge/game/spellability/AbilityActivated.java @@ -72,10 +72,6 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S } } - public abstract AbilityActivated getCopy(); /* { - return null; - } - /** {@inheritDoc} */ @Override public boolean canPlay() { diff --git a/forge-game/src/main/java/forge/game/spellability/AbilitySub.java b/forge-game/src/main/java/forge/game/spellability/AbilitySub.java index 9dbc1d77e53..a426e23bf9f 100644 --- a/forge-game/src/main/java/forge/game/spellability/AbilitySub.java +++ b/forge-game/src/main/java/forge/game/spellability/AbilitySub.java @@ -25,7 +25,6 @@ import forge.game.ability.effects.ChangeZoneEffect; import forge.game.ability.effects.ManaEffect; import forge.game.ability.effects.ManaReflectedEffect; import forge.game.card.Card; -import forge.game.card.CardFactory; import forge.game.cost.Cost; import java.util.Map; @@ -102,16 +101,6 @@ public final class AbilitySub extends SpellAbility implements java.io.Serializab } } - public AbilitySub getCopy() { - return getCopy(getHostCard()); - } - public AbilitySub getCopy(Card host) { - TargetRestrictions t = getTargetRestrictions() == null ? null : new TargetRestrictions(getTargetRestrictions()); - AbilitySub res = new AbilitySub(api, host, t, mapParams); - CardFactory.copySpellAbility(this, res, host); - return res; - } - @Override public String getStackDescription() { return effect.getStackDescriptionWithSubs(mapParams, this); 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 8fed0f8fa35..0308f34cf46 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -313,24 +313,25 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return activatingPlayer; } public void setActivatingPlayer(final Player player) { + setActivatingPlayer(player, false); + } + public void setActivatingPlayer(final Player player, final boolean lki) { // trickle down activating player activatingPlayer = player; if (subAbility != null) { - subAbility.setActivatingPlayer(player); + subAbility.setActivatingPlayer(player, lki); } for (AbilitySub sa : additionalAbilities.values()) { - if (sa.getActivatingPlayer() != player) { - sa.setActivatingPlayer(player); - } + sa.setActivatingPlayer(player, lki); } for (List list : additionalAbilityLists.values()) { for (AbilitySub sa : list) { - if (sa.getActivatingPlayer() != player) { - sa.setActivatingPlayer(player); - } + sa.setActivatingPlayer(player, lki); } } - view.updateCanPlay(this, false); + if (!lki) { + view.updateCanPlay(this, false); + } } public Player getDeltrigActivatingPlayer() { @@ -789,17 +790,18 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } public SpellAbility copy() { - return copy(hostCard); + return copy(hostCard, false); } - public SpellAbility copy(Card host) { + public SpellAbility copy(Card host, final boolean lki) { SpellAbility clone = null; try { clone = (SpellAbility) clone(); - clone.id = nextId(); + clone.id = lki ? id : nextId(); clone.view = new SpellAbilityView(clone); + // dont use setHostCard to not trigger the not copied parts yet clone.hostCard = host; - if (host != null && host.getGame() != null) { + if (!lki && host != null && host.getGame() != null) { host.getGame().addSpellAbility(clone); } // need to clone the maps too so they can be changed @@ -808,8 +810,11 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit clone.triggeringObjects = Maps.newHashMap(this.triggeringObjects); + if (getPayCosts() != null) { + clone.setPayCosts(getPayCosts().copy()); + } // run special copy Ability to make a deep copy - CardFactory.copySpellAbility(this, clone, host); + CardFactory.copySpellAbility(this, clone, host, lki); } catch (final CloneNotSupportedException e) { System.err.println(e); } @@ -1109,6 +1114,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } public void setCopied(boolean isCopied0) { isCopied = isCopied0; + if (this.getSubAbility() != null) { + this.getSubAbility().setCopied(isCopied0); + } } /** 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 324df8096c0..f4e50436cae 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -369,12 +369,12 @@ public final class StaticAbilityContinuous { cardsIGainedAbilitiesFrom = CardLists.getValidCards(cardsIGainedAbilitiesFrom, valids, hostCard.getController(), hostCard, null); if (cardsIGainedAbilitiesFrom.size() > 0) { - addFullAbs = new ArrayList(); + addFullAbs = Lists.newArrayList(); for (Card c : cardsIGainedAbilitiesFrom) { for (SpellAbility sa : c.getSpellAbilities()) { if (sa instanceof AbilityActivated) { - SpellAbility newSA = ((AbilityActivated) sa).getCopy(); + SpellAbility newSA = sa.copy(hostCard, false); if (params.containsKey("GainsAbilitiesLimitPerTurn")) { newSA.setRestrictions(sa.getRestrictions()); newSA.getRestrictions().setLimitToCheck(params.get("GainsAbilitiesLimitPerTurn")); @@ -382,7 +382,6 @@ public final class StaticAbilityContinuous { newSA.setOriginalHost(c); newSA.setIntrinsic(false); newSA.setTemporary(true); - newSA.setHostCard(hostCard); addFullAbs.add(newSA); } } diff --git a/forge-game/src/main/java/forge/game/trigger/Trigger.java b/forge-game/src/main/java/forge/game/trigger/Trigger.java index e35754e97f9..2835e658c28 100644 --- a/forge-game/src/main/java/forge/game/trigger/Trigger.java +++ b/forge-game/src/main/java/forge/game/trigger/Trigger.java @@ -29,7 +29,6 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.Ability; -import forge.game.spellability.AbilitySub; import forge.game.spellability.OptionalCost; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; @@ -49,9 +48,8 @@ import forge.util.TextUtil; * @version $Id$ */ public abstract class Trigger extends TriggerReplacementBase { - - /** Constant nextID=0. */ - private static int nextID = 0; + private static int maxId = 0; + private static int nextId() { return ++maxId; } /** *

@@ -59,23 +57,12 @@ public abstract class Trigger extends TriggerReplacementBase { *

*/ public static void resetIDs() { - Trigger.nextID = 50000; + Trigger.maxId = 50000; } /** The ID. */ - private int id = Trigger.nextID++; + private int id; - /** - *

- * setID. - *

- * - * @param id - * a int. - */ - public final void setID(final int id) { - this.id = id; - } /** The run params. */ private Map runParams; @@ -131,9 +118,10 @@ public abstract class Trigger extends TriggerReplacementBase { * the intrinsic */ public Trigger(final Map params, final Card host, final boolean intrinsic) { + this.id = nextId(); this.intrinsic = intrinsic; - this.setRunParams(new HashMap()); + this.setRunParams(Maps.newHashMap()); this.originalMapParams.putAll(params); this.mapParams.putAll(params); this.setHostCard(host); @@ -462,13 +450,25 @@ public abstract class Trigger extends TriggerReplacementBase { /** * Gets the id. - * + * * @return the id */ public int getId() { return this.id; } + /** + *

+ * setID. + *

+ * + * @param id + * a int. + */ + public final void setId(final int id) { + this.id = id; + } + private Ability triggeredSA; /** @@ -515,33 +515,25 @@ public abstract class Trigger extends TriggerReplacementBase { void setMode(TriggerType triggerType) { mode = triggerType; } - - public final Trigger getCopyForHostCard(Card newHost) { - final TriggerType tt = TriggerType.getTypeFor(this); - final Trigger copy = tt.createTrigger(originalMapParams, newHost, intrinsic); + public final Trigger copy(Card newHost, boolean lki) { + final Trigger copy = (Trigger) clone(); - if (this.getOverridingAbility() != null) { - SpellAbility old = this.getOverridingAbility(); - SpellAbility sa = old; - // try to copy it if newHost is not the wanted host - final Card oldHost = old.getHostCard(); - if (!newHost.equals(oldHost)) { - if (old instanceof AbilitySub) { - sa = ((AbilitySub)old).getCopy(); - sa.setHostCard(newHost); - } - } else if (newHost != oldHost) { - //host would be the same, but different state? - sa.setHostCard(newHost); - } - copy.setOverridingAbility(sa); + copy.originalMapParams.putAll(originalMapParams); + copy.mapParams.putAll(originalMapParams); + copy.setHostCard(newHost); + + if (getOverridingAbility() != null) { + copy.setOverridingAbility(getOverridingAbility().copy(newHost, lki)); } - // 2015-03-07 Removing the ID copying which makes copied triggers Identical to each other when removing - //copy.setID(this.getId()); - copy.setMode(this.getMode()); - copy.setTriggerPhases(this.validPhases); + if (!lki) { + copy.setId(nextId()); + } + + if (validPhases != null) { + copy.setTriggerPhases(Lists.newArrayList(validPhases)); + } copy.setActiveZone(validHostZones); copy.setTemporary(isTemporary()); return copy; @@ -572,4 +564,14 @@ public abstract class Trigger extends TriggerReplacementBase { { this.numberTurnActivations = 0; } + + /** {@inheritDoc} */ + @Override + public final Object clone() { + try { + return super.clone(); + } catch (final Exception ex) { + throw new RuntimeException("Trigger : clone() error, " + ex); + } + } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java index 837be50f1fd..c0447b620e3 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java @@ -86,11 +86,9 @@ public enum TriggerType { Untaps(TriggerUntaps.class), Vote(TriggerVote.class); - private final Class classTrigger; private final Constructor constructor; private TriggerType(Class clasz) { - classTrigger = clasz; constructor = findConstructor(clasz); } @@ -122,16 +120,6 @@ public enum TriggerType { throw new RuntimeException("Element " + value + " not found in TriggerType enum"); } - - public static TriggerType getTypeFor(Trigger t) { - final Class cls = t.getClass(); - for (final TriggerType v : TriggerType.values()) { - if (v.classTrigger.equals(cls)) { - return v; - } - } - return null; - } /** * TODO: Write javadoc for this method. From da5cb3d90568ce7a67bf6f07ba2da3d1d02b4ae0 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Sun, 11 Feb 2018 12:11:04 +0100 Subject: [PATCH 2/2] check lands: use shorter code for etb replacement --- forge-gui/res/cardsfolder/c/clifftop_retreat.txt | 6 ++---- forge-gui/res/cardsfolder/d/dragonskull_summit.txt | 6 ++---- forge-gui/res/cardsfolder/d/drowned_catacomb.txt | 6 ++---- forge-gui/res/cardsfolder/g/glacial_fortress.txt | 6 ++---- forge-gui/res/cardsfolder/h/hinterland_harbor.txt | 6 ++---- forge-gui/res/cardsfolder/i/isolated_chapel.txt | 6 ++---- forge-gui/res/cardsfolder/r/rootbound_crag.txt | 6 ++---- forge-gui/res/cardsfolder/s/sulfur_falls.txt | 6 ++---- forge-gui/res/cardsfolder/s/sunpetal_grove.txt | 6 ++---- forge-gui/res/cardsfolder/w/woodland_cemetery.txt | 6 ++---- 10 files changed, 20 insertions(+), 40 deletions(-) diff --git a/forge-gui/res/cardsfolder/c/clifftop_retreat.txt b/forge-gui/res/cardsfolder/c/clifftop_retreat.txt index 8fecb3a89b8..287a0c04e57 100644 --- a/forge-gui/res/cardsfolder/c/clifftop_retreat.txt +++ b/forge-gui/res/cardsfolder/c/clifftop_retreat.txt @@ -1,10 +1,8 @@ Name:Clifftop Retreat ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Mountain or a Plains. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Mountain.YouCtrl,Plains.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Mountain.YouCtrl,Plains.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Mountain or a Plains. A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/clifftop_retreat.jpg diff --git a/forge-gui/res/cardsfolder/d/dragonskull_summit.txt b/forge-gui/res/cardsfolder/d/dragonskull_summit.txt index f37c692988c..3ba70a6bd8a 100644 --- a/forge-gui/res/cardsfolder/d/dragonskull_summit.txt +++ b/forge-gui/res/cardsfolder/d/dragonskull_summit.txt @@ -1,10 +1,8 @@ Name:Dragonskull Summit ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Swamp or a Mountain. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Swamp.YouCtrl,Mountain.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Swamp.YouCtrl,Mountain.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Swamp or a Mountain. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/dragonskull_summit.jpg diff --git a/forge-gui/res/cardsfolder/d/drowned_catacomb.txt b/forge-gui/res/cardsfolder/d/drowned_catacomb.txt index e005ccbc8a3..44168a5157e 100644 --- a/forge-gui/res/cardsfolder/d/drowned_catacomb.txt +++ b/forge-gui/res/cardsfolder/d/drowned_catacomb.txt @@ -1,10 +1,8 @@ Name:Drowned Catacomb ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control an Island or a Swamp. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Island.YouCtrl,Swamp.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Island.YouCtrl,Swamp.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control an Island or a Swamp. A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/drowned_catacomb.jpg diff --git a/forge-gui/res/cardsfolder/g/glacial_fortress.txt b/forge-gui/res/cardsfolder/g/glacial_fortress.txt index 3fd63976850..ae33f09887a 100644 --- a/forge-gui/res/cardsfolder/g/glacial_fortress.txt +++ b/forge-gui/res/cardsfolder/g/glacial_fortress.txt @@ -1,10 +1,8 @@ Name:Glacial Fortress ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Plains or an Island. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Island.YouCtrl,Plains.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Plains.YouCtrl,Island.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Plains or an Island. A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/glacial_fortress.jpg diff --git a/forge-gui/res/cardsfolder/h/hinterland_harbor.txt b/forge-gui/res/cardsfolder/h/hinterland_harbor.txt index 2d92328d719..e59433a6580 100644 --- a/forge-gui/res/cardsfolder/h/hinterland_harbor.txt +++ b/forge-gui/res/cardsfolder/h/hinterland_harbor.txt @@ -1,10 +1,8 @@ Name:Hinterland Harbor ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Forest or an Island. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Island.YouCtrl,Forest.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Forest.YouCtrl,Island.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Forest or an Island. A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/hinterland_harbor.jpg diff --git a/forge-gui/res/cardsfolder/i/isolated_chapel.txt b/forge-gui/res/cardsfolder/i/isolated_chapel.txt index 27b05b411cd..340e1224d12 100644 --- a/forge-gui/res/cardsfolder/i/isolated_chapel.txt +++ b/forge-gui/res/cardsfolder/i/isolated_chapel.txt @@ -1,10 +1,8 @@ Name:Isolated Chapel ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Plains or a Swamp. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Plains.YouCtrl,Swamp.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Plains.YouCtrl,Swamp.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Plains or a Swamp. A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/isolated_chapel.jpg diff --git a/forge-gui/res/cardsfolder/r/rootbound_crag.txt b/forge-gui/res/cardsfolder/r/rootbound_crag.txt index e598041f2e2..7e4933a623e 100644 --- a/forge-gui/res/cardsfolder/r/rootbound_crag.txt +++ b/forge-gui/res/cardsfolder/r/rootbound_crag.txt @@ -1,10 +1,8 @@ Name:Rootbound Crag ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Mountain or a Forest. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Mountain.YouCtrl,Forest.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Mountain.YouCtrl,Forest.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Mountain or a Forest. A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/rootbound_crag.jpg diff --git a/forge-gui/res/cardsfolder/s/sulfur_falls.txt b/forge-gui/res/cardsfolder/s/sulfur_falls.txt index 2120464866e..7dd6a4b5e15 100644 --- a/forge-gui/res/cardsfolder/s/sulfur_falls.txt +++ b/forge-gui/res/cardsfolder/s/sulfur_falls.txt @@ -1,10 +1,8 @@ Name:Sulfur Falls ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control an Island or a Mountain. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Mountain.YouCtrl,Island.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Island.YouCtrl,Mountain.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control an Island or a Mountain. A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/sulfur_falls.jpg diff --git a/forge-gui/res/cardsfolder/s/sunpetal_grove.txt b/forge-gui/res/cardsfolder/s/sunpetal_grove.txt index 086888b0651..59757c2524d 100644 --- a/forge-gui/res/cardsfolder/s/sunpetal_grove.txt +++ b/forge-gui/res/cardsfolder/s/sunpetal_grove.txt @@ -1,10 +1,8 @@ Name:Sunpetal Grove ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Forest or a Plains. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Forest.YouCtrl,Plains.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Forest.YouCtrl,Plains.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Forest or a Plains. A:AB$ Mana | Cost$ T | Produced$ W | SpellDescription$ Add {W} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/sunpetal_grove.jpg diff --git a/forge-gui/res/cardsfolder/w/woodland_cemetery.txt b/forge-gui/res/cardsfolder/w/woodland_cemetery.txt index 78aacc5eb90..67aabb80555 100644 --- a/forge-gui/res/cardsfolder/w/woodland_cemetery.txt +++ b/forge-gui/res/cardsfolder/w/woodland_cemetery.txt @@ -1,10 +1,8 @@ Name:Woodland Cemetery ManaCost:no cost Types:Land -R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ LandTapped | Description$ CARDNAME enters the battlefield tapped unless you control a Swamp or a Forest. -SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionCheckSVar$ ETBCheckSVar | ConditionSVarCompare$ EQ0 | References$ ETBCheckSVar | SubAbility$ MoveToPlay -SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard -SVar:ETBCheckSVar:Count$Valid Swamp.YouCtrl,Forest.YouCtrl +K:ETBReplacement:Other:LandTapped +SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Swamp.YouCtrl,Forest.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Swamp or a Forest. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B} to your mana pool. A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G} to your mana pool. SVar:Picture:http://www.wizards.com/global/images/magic/general/woodland_cemetery.jpg