diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index 4621d104feb..31dee95d241 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -504,6 +504,17 @@ public interface Ability extends Controllable, Serializable { MageObject getSourceObject(Game game); void setSourceObjectZoneChangeCounter(int zoneChangeCounter); + /** + * Initializes the internally stored Source Object ZCC value + * to be equal to the source object's current ZCC. + *

+ * If the source is an entering permanent, then + * the ZCC is set as if the permanent had already entered the battlefield. + * + * @param game + * @param force Update only occurs if stored ZCC is zero or if force is true. + */ + void initSourceObjectZoneChangeCounter(Game game, boolean force); int getSourceObjectZoneChangeCounter(); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 65198348e02..ad735b98e74 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -272,9 +272,7 @@ public abstract class AbilityImpl implements Ability { game.applyEffects(); MageObject sourceObject = getSourceObject(game); - if (getSourceObjectZoneChangeCounter() == 0) { - setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(getSourceId())); - } + initSourceObjectZoneChangeCounter(game, false); setSourcePermanentTransformCount(game); // if ability can be cast for no mana, clear the mana costs now, because additional mana costs must be paid. @@ -1664,7 +1662,7 @@ public abstract class AbilityImpl implements Ability { @Override public MageObject getSourceObjectIfItStillExists(Game game) { if (getSourceObjectZoneChangeCounter() == 0 - || getSourceObjectZoneChangeCounter() == game.getState().getZoneChangeCounter(getSourceId())) { + || getSourceObjectZoneChangeCounter() == getCurrentSourceObjectZoneChangeCounter(game)) { // exists or lki from battlefield return game.getObject(getSourceId()); } @@ -1703,6 +1701,27 @@ public abstract class AbilityImpl implements Ability { this.sourceObjectZoneChangeCounter = sourceObjectZoneChangeCounter; } + @Override + public void initSourceObjectZoneChangeCounter(Game game, boolean force) { + if (!(this instanceof MageSingleton) && (force || sourceObjectZoneChangeCounter == 0 )) { + setSourceObjectZoneChangeCounter(getCurrentSourceObjectZoneChangeCounter(game)); + } + } + + private int getCurrentSourceObjectZoneChangeCounter(Game game){ + int zcc = game.getState().getZoneChangeCounter(getSourceId()); + // TODO: Enable this, #13710 + /*if (game.getPermanentEntering(getSourceId()) != null){ + // If the triggered ability triggered while the permanent is entering the battlefield + // then add 1 zcc so that it triggers as if the permanent was already on the battlefield + // So "Enters with counters" causes "Whenever counters are placed" to trigger with battlefield zcc + // Particularly relevant for Sagas, which always involve both + // Note that this does NOT apply to "As ~ ETB" effects, those still use the stack zcc + zcc += 1; + }*/ + return zcc; + } + @Override public int getSourceObjectZoneChangeCounter() { return sourceObjectZoneChangeCounter; diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java index 67d2f1cce87..f975727ef27 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java @@ -131,6 +131,11 @@ public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityIm ability.setSourceObjectZoneChangeCounter(sourceObjectZoneChangeCounter); } + @Override + public void initSourceObjectZoneChangeCounter(Game game, boolean force) { + ability.initSourceObjectZoneChangeCounter(game, force); + } + @Override public int getSourceObjectZoneChangeCounter() { return ability.getSourceObjectZoneChangeCounter(); diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 63147190c01..4b80538a332 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1960,7 +1960,7 @@ public abstract class GameImpl implements Game { @Override public void addEffect(ContinuousEffect continuousEffect, Ability source) { Ability newAbility = source.copy(); - newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId())); + newAbility.initSourceObjectZoneChangeCounter(this, true); ContinuousEffect newEffect = continuousEffect.copy(); newEffect.newId(); @@ -2159,18 +2159,14 @@ public abstract class GameImpl implements Game { // countered, or otherwise responded to. Rather, it resolves immediately after the mana // ability that triggered it, without waiting for priority. Ability manaAbility = ability.copy(); - if (manaAbility.getSourceObjectZoneChangeCounter() == 0) { - manaAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId())); - } + manaAbility.initSourceObjectZoneChangeCounter(this, false); if (manaAbility.activate(this, false)) { manaAbility.resolve(this); } } else { TriggeredAbility newAbility = ability.copy(); newAbility.newId(); - if (newAbility.getSourceObjectZoneChangeCounter() == 0) { - newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId())); - } + newAbility.initSourceObjectZoneChangeCounter(this, false); if (!(newAbility instanceof DelayedTriggeredAbility)) { newAbility.setSourcePermanentTransformCount(this); } diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index a880c666afa..f83a90a5697 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -673,6 +673,10 @@ public class StackAbility extends StackObjectImpl implements Ability { ability.setSourceObjectZoneChangeCounter(zoneChangeCounter); } + @Override + public void initSourceObjectZoneChangeCounter(Game game, boolean force) { + ability.initSourceObjectZoneChangeCounter(game, force); + } @Override public int getSourceObjectZoneChangeCounter() { return ability.getSourceObjectZoneChangeCounter(); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 73ec0e6b91e..80127259644 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1306,7 +1306,7 @@ public abstract class PlayerImpl implements Player, Serializable { SpellAbility ability = originalAbility.copy(); Set allowedIdentifiers = originalAbility.spellCanBeActivatedNow(getId(), game); ability.setControllerId(getId()); - ability.setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(ability.getSourceId())); + ability.initSourceObjectZoneChangeCounter(game, true); //20091005 - 601.2a if (ability.getSourceId() == null) { @@ -1332,7 +1332,7 @@ public abstract class PlayerImpl implements Player, Serializable { spell.setCopy(true, null); } // Update the zcc to the stack - ability.setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(ability.getSourceId())); + ability.initSourceObjectZoneChangeCounter(game, true); // ALTERNATIVE COST from dynamic effects // some effects set sourceId to cast without paying mana costs or other costs