From b46bdef429c53abb7dff74049e135bf4d5615502 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 22 Mar 2013 15:00:06 +0100 Subject: [PATCH] Added the possibility to handle the enteres_the_battlefield event according to rule 614.12 (issue #164). --- .../abilities/effects/ContinuousEffects.java | 6 +++-- .../abilities/effects/ReplacementEffect.java | 2 ++ .../effects/ReplacementEffectImpl.java | 23 +++++++++++++++++++ Mage/src/mage/cards/CardImpl.java | 4 ++++ Mage/src/mage/game/Game.java | 4 ++++ Mage/src/mage/game/GameImpl.java | 21 +++++++++++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index 69a7c3bd0a7..3d537405f29 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -261,8 +261,10 @@ public class ContinuousEffects implements Serializable { Ability ability = replacementEffects.getAbility(effect.getId()); if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { - if (effect.applies(event, ability, game)) { - replaceEffects.add(effect); + if (!game.getScopeRelevant() || effect.hasSelfScope() || !event.getTargetId().equals(this.replacementEffects.getAbility(effect.getId()).getSourceId())) { + if (effect.applies(event, ability, game)) { + replaceEffects.add(effect); + } } } } diff --git a/Mage/src/mage/abilities/effects/ReplacementEffect.java b/Mage/src/mage/abilities/effects/ReplacementEffect.java index 3e8d31985cd..873a7365bbe 100644 --- a/Mage/src/mage/abilities/effects/ReplacementEffect.java +++ b/Mage/src/mage/abilities/effects/ReplacementEffect.java @@ -41,4 +41,6 @@ public interface ReplacementEffect> extends Conti boolean replaceEvent(GameEvent event, Ability source, Game game); boolean applies(GameEvent event, Ability source, Game game); + boolean hasSelfScope(); + } diff --git a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java index 573fdf54dab..f0283d4818f 100644 --- a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java @@ -38,13 +38,36 @@ import mage.Constants.Outcome; */ public abstract class ReplacementEffectImpl> extends ContinuousEffectImpl implements ReplacementEffect { + // 614.12 + // Some replacement effects modify how a permanent enters the battlefield. (See rules 614.1c-d.) + // Such effects may come from the permanent itself if they affect only that permanent (as opposed + // to a general subset of permanents that includes it). They may also come from other sources. To + // determine which replacement effects apply and how they apply, check the characteristics of the + // permanent as it would exist on the battlefield, taking into account replacement effects that have + // already modified how it enters the battlefield (see rule 616.1), continuous effects generated by + // the resolution of spells or abilities that changed the permanent's characteristics on the stack + // (see rule 400.7a), and continuous effects from the permanent's own static abilities, but ignoring + // continuous effects from any other source that would affect it. + + protected boolean selfScope; + public ReplacementEffectImpl(Duration duration, Outcome outcome) { + this(duration, outcome, true); + } + + public ReplacementEffectImpl(Duration duration, Outcome outcome, boolean selfScope) { super(duration, outcome); this.effectType = EffectType.REPLACEMENT; + this.selfScope = selfScope; } public ReplacementEffectImpl(final ReplacementEffectImpl effect) { super(effect); + this.selfScope = effect.selfScope; } + @Override + public boolean hasSelfScope() { + return selfScope; + } } diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 777c7da7e63..12ffdce2b9b 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -317,8 +317,10 @@ public abstract class CardImpl> extends MageObjectImpl game.resetForSourceId(permanent.getId()); game.addPermanent(permanent); game.setZone(objectId, Zone.BATTLEFIELD); + game.setScopeRelevant(true); game.applyEffects(); permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); + game.setScopeRelevant(false); game.applyEffects(); if (flag) { permanent.setTapped(true); @@ -446,8 +448,10 @@ public abstract class CardImpl> extends MageObjectImpl game.resetForSourceId(permanent.getId()); game.addPermanent(permanent); game.setZone(objectId, Zone.BATTLEFIELD); + game.setScopeRelevant(true); game.applyEffects(); // magenoxx: this causes bugs - LevelX2: but it's neccessary for casting e.g. Kird Ape which must trigger evolve permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); + game.setScopeRelevant(false); game.applyEffects(); game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); return true; diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 58e7cdf3071..5cdfd28c19f 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -206,4 +206,8 @@ public interface Game extends MageItem, Serializable { // game cheats (for tests only) void cheat(UUID ownerId, Map commands); void cheat(UUID ownerId, List library, List hand, List battlefield, List graveyard); + + // controlling the behaviour of replacement effects + void setScopeRelevant(boolean scopeRelevant); + public boolean getScopeRelevant(); } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 0794b07f64b..df39baf8038 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -145,6 +145,9 @@ public abstract class GameImpl> implements Game, Serializa private Player losingPlayer; private boolean stateCheckRequired = false; + // used to indicate that currently applied replacement effects have to check for scope relevance (614.12 13/01/18) + private boolean scopeRelevant = false; + @Override public abstract T copy(); @@ -184,6 +187,7 @@ public abstract class GameImpl> implements Game, Serializa this.actions = new LinkedList(); this.stateCheckRequired = game.stateCheckRequired; this.scorePlayer = game.scorePlayer; + this.scopeRelevant = game.scopeRelevant; } @Override @@ -1721,4 +1725,21 @@ public abstract class GameImpl> implements Game, Serializa stateCheckRequired = true; } + /** + * If true, only self scope replacement effects are applied + * + * @param scopeRelevant + */ + @Override + public void setScopeRelevant(boolean scopeRelevant) { + this.scopeRelevant = scopeRelevant; + } + + /** + * @return - true if only self scope replacement effects have to be applied + */ + @Override + public boolean getScopeRelevant() { + return this.scopeRelevant; + } }