Shared zcc init code

This commit is contained in:
Steven Knipe 2025-06-01 13:01:20 -07:00 committed by Failure
parent b3d721c16b
commit bd996b2dac
6 changed files with 48 additions and 13 deletions

View file

@ -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.
* <p>
* 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();

View file

@ -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;

View file

@ -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();

View file

@ -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);
}

View file

@ -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();

View file

@ -1306,7 +1306,7 @@ public abstract class PlayerImpl implements Player, Serializable {
SpellAbility ability = originalAbility.copy();
Set<MageIdentifier> 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