diff --git a/Mage.Sets/src/mage/cards/a/AssertAuthority.java b/Mage.Sets/src/mage/cards/a/AssertAuthority.java index 7f1c2cdea45..e449168bafa 100644 --- a/Mage.Sets/src/mage/cards/a/AssertAuthority.java +++ b/Mage.Sets/src/mage/cards/a/AssertAuthority.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -7,7 +6,7 @@ import mage.abilities.keyword.AffinityForArtifactsAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -23,7 +22,7 @@ public final class AssertAuthority extends CardImpl { // Affinity for artifacts this.addAbility(new AffinityForArtifactsAbility()); // Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/d/Delay.java b/Mage.Sets/src/mage/cards/d/Delay.java index 0c21ae549a0..f5473de4097 100644 --- a/Mage.Sets/src/mage/cards/d/Delay.java +++ b/Mage.Sets/src/mage/cards/d/Delay.java @@ -13,6 +13,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.PutCards; import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; @@ -65,7 +66,7 @@ class DelayEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); if (controller != null && spell != null) { - Effect effect = new CounterTargetWithReplacementEffect(Zone.EXILED); + Effect effect = new CounterTargetWithReplacementEffect(PutCards.EXILED); effect.setTargetPointer(targetPointer); Card card = game.getCard(spell.getSourceId()); if (card != null && effect.apply(game, source) && game.getState().getZone(card.getId()) == Zone.EXILED) { diff --git a/Mage.Sets/src/mage/cards/d/DenyExistence.java b/Mage.Sets/src/mage/cards/d/DenyExistence.java index 06aff882f3e..20261eb5411 100644 --- a/Mage.Sets/src/mage/cards/d/DenyExistence.java +++ b/Mage.Sets/src/mage/cards/d/DenyExistence.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -6,7 +5,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.common.FilterCreatureSpell; import mage.target.TargetSpell; @@ -20,7 +19,7 @@ public final class DenyExistence extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}"); // Counter target creature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(new FilterCreatureSpell())); } diff --git a/Mage.Sets/src/mage/cards/d/DenyTheDivine.java b/Mage.Sets/src/mage/cards/d/DenyTheDivine.java index 0b999258d68..608466e395a 100644 --- a/Mage.Sets/src/mage/cards/d/DenyTheDivine.java +++ b/Mage.Sets/src/mage/cards/d/DenyTheDivine.java @@ -4,7 +4,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; import mage.target.TargetSpell; @@ -29,7 +29,7 @@ public final class DenyTheDivine extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Counter target creature or enchantment spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(filter)); } diff --git a/Mage.Sets/src/mage/cards/d/Desertion.java b/Mage.Sets/src/mage/cards/d/Desertion.java index 329fd89eb3a..e1289cfb2a2 100644 --- a/Mage.Sets/src/mage/cards/d/Desertion.java +++ b/Mage.Sets/src/mage/cards/d/Desertion.java @@ -1,38 +1,30 @@ package mage.cards.d; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; -import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; +import mage.game.stack.StackObject; import mage.target.TargetSpell; -import java.util.Objects; import java.util.UUID; /** - * @author Quercitron + * @author awjackson */ public final class Desertion extends CardImpl { public Desertion(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}"); - // Counter target spell. - this.getSpellAbility().addEffect(new CounterTargetEffect()); + // Counter target spell. If an artifact or creature spell is countered this way, + // put that card onto the battlefield under your control instead of into its owner's graveyard. + this.getSpellAbility().addEffect(new DesertionEffect()); this.getSpellAbility().addTarget(new TargetSpell()); - - // If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard. - this.addAbility(new SimpleStaticAbility(Zone.STACK, new DesertionReplacementEffect())); } private Desertion(final Desertion card) { @@ -45,48 +37,30 @@ public final class Desertion extends CardImpl { } } -class DesertionReplacementEffect extends ReplacementEffectImpl { +class DesertionEffect extends OneShotEffect { - DesertionReplacementEffect() { - super(Duration.WhileOnStack, Outcome.PutCardInPlay); - staticText = "If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard"; + public DesertionEffect() { + super(Outcome.Detriment); + staticText = "counter target spell. If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard"; } - private DesertionReplacementEffect(final DesertionReplacementEffect effect) { + private DesertionEffect(final DesertionEffect effect) { super(effect); } @Override - public DesertionReplacementEffect copy() { - return new DesertionReplacementEffect(this); + public DesertionEffect copy() { + return new DesertionEffect(this); } @Override public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - ZoneChangeEvent zce = (ZoneChangeEvent) event; - zce.setToZone(Zone.BATTLEFIELD); - zce.setPlayerId(source.getControllerId()); - return false; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (!Objects.equals(event.getSourceId(), source.getSourceId()) - || !(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD)) { + StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source)); + if (spell == null) { return false; } - MageObject mageObject = game.getObject(event.getTargetId()); - return mageObject != null - && (mageObject.isArtifact(game) || mageObject.isCreature(game)); + return game.getStack().counter(spell.getId(), source, game, + spell.isArtifact() || spell.isCreature() ? PutCards.BATTLEFIELD : PutCards.GRAVEYARD + ); } } diff --git a/Mage.Sets/src/mage/cards/d/DeviousCoverUp.java b/Mage.Sets/src/mage/cards/d/DeviousCoverUp.java index ca67e1561ea..166ef4b86cc 100644 --- a/Mage.Sets/src/mage/cards/d/DeviousCoverUp.java +++ b/Mage.Sets/src/mage/cards/d/DeviousCoverUp.java @@ -12,7 +12,7 @@ import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.game.Game; import mage.players.Player; import mage.target.TargetSpell; @@ -29,7 +29,7 @@ public final class DeviousCoverUp extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); // Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell()); // You may shuffle up to four target cards from your graveyard into your library. diff --git a/Mage.Sets/src/mage/cards/d/Dissipate.java b/Mage.Sets/src/mage/cards/d/Dissipate.java index 8e7b21daaf8..d27f9ca7e68 100644 --- a/Mage.Sets/src/mage/cards/d/Dissipate.java +++ b/Mage.Sets/src/mage/cards/d/Dissipate.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -6,7 +5,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -19,7 +18,7 @@ public final class Dissipate extends CardImpl { // Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/f/FaerieTrickery.java b/Mage.Sets/src/mage/cards/f/FaerieTrickery.java index 4fac0ea5840..102b43e67a9 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieTrickery.java +++ b/Mage.Sets/src/mage/cards/f/FaerieTrickery.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.UUID; @@ -7,7 +6,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; import mage.target.TargetSpell; @@ -30,7 +29,7 @@ public final class FaerieTrickery extends CardImpl { // Counter target non-Faerie spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(filter)); } diff --git a/Mage.Sets/src/mage/cards/f/ForceOfNegation.java b/Mage.Sets/src/mage/cards/f/ForceOfNegation.java index f9ad6d4c910..39dd59e8028 100644 --- a/Mage.Sets/src/mage/cards/f/ForceOfNegation.java +++ b/Mage.Sets/src/mage/cards/f/ForceOfNegation.java @@ -9,7 +9,7 @@ import mage.abilities.hint.common.NotMyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.StaticFilters; import mage.filter.common.FilterOwnedCard; import mage.filter.predicate.mageobject.ColorPredicate; @@ -40,7 +40,7 @@ public final class ForceOfNegation extends CardImpl { ).addHint(NotMyTurnHint.instance)); // Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_NON_CREATURE)); } diff --git a/Mage.Sets/src/mage/cards/h/Hinder.java b/Mage.Sets/src/mage/cards/h/Hinder.java index 5de37fc763b..a2e09877dfd 100644 --- a/Mage.Sets/src/mage/cards/h/Hinder.java +++ b/Mage.Sets/src/mage/cards/h/Hinder.java @@ -1,4 +1,3 @@ - package mage.cards.h; import java.util.UUID; @@ -6,8 +5,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -20,7 +18,7 @@ public final class Hinder extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}"); // Counter target spell. If that spell is countered this way, put that card on the top or bottom of its owner's library instead of into that player's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.LIBRARY, ZoneDetail.CHOOSE)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.TOP_OR_BOTTOM)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/h/HorriblyAwry.java b/Mage.Sets/src/mage/cards/h/HorriblyAwry.java index 80c556dd4ab..6d7628f6841 100644 --- a/Mage.Sets/src/mage/cards/h/HorriblyAwry.java +++ b/Mage.Sets/src/mage/cards/h/HorriblyAwry.java @@ -8,7 +8,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.common.FilterCreatureSpell; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.target.TargetSpell; @@ -32,7 +32,7 @@ public final class HorriblyAwry extends CardImpl { this.addAbility(new DevoidAbility(this.color)); // Counter target creature spell with converted mana cost 4 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(filter)); } diff --git a/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java b/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java index af63724b798..5e21fd87ff2 100644 --- a/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java +++ b/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java @@ -73,7 +73,7 @@ class KheruSpellsnatcherEffect extends OneShotEffect { MageObject sourceObject = source.getSourceObject(game); StackObject stackObject = game.getStack().getStackObject(targetPointer.getFirst(game, source)); if (stackObject != null && sourceObject != null - && game.getStack().counter(targetPointer.getFirst(game, source), source, game, Zone.EXILED, false, ZoneDetail.NONE)) { + && game.getStack().counter(targetPointer.getFirst(game, source), source, game, PutCards.EXILED)) { if (!stackObject.isCopy()) { MageObject card = game.getObject(stackObject.getSourceId()); if (card instanceof Card) { diff --git a/Mage.Sets/src/mage/cards/l/LapseOfCertainty.java b/Mage.Sets/src/mage/cards/l/LapseOfCertainty.java index 6b1434eae0a..da5519d8f22 100644 --- a/Mage.Sets/src/mage/cards/l/LapseOfCertainty.java +++ b/Mage.Sets/src/mage/cards/l/LapseOfCertainty.java @@ -6,8 +6,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -20,7 +19,7 @@ public final class LapseOfCertainty extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}"); // Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.LIBRARY, ZoneDetail.TOP)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.TOP_ANY)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/l/Liquify.java b/Mage.Sets/src/mage/cards/l/Liquify.java index 0a342aeda8c..c9d1f386240 100644 --- a/Mage.Sets/src/mage/cards/l/Liquify.java +++ b/Mage.Sets/src/mage/cards/l/Liquify.java @@ -7,7 +7,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.target.TargetSpell; @@ -28,7 +28,7 @@ public final class Liquify extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}"); // Counter target spell with converted mana cost 3 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(filter)); } diff --git a/Mage.Sets/src/mage/cards/m/MemoryLapse.java b/Mage.Sets/src/mage/cards/m/MemoryLapse.java index 46c82140d7b..a25c05c8bbe 100644 --- a/Mage.Sets/src/mage/cards/m/MemoryLapse.java +++ b/Mage.Sets/src/mage/cards/m/MemoryLapse.java @@ -6,8 +6,7 @@ import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -20,7 +19,7 @@ public final class MemoryLapse extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); // Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.LIBRARY, ZoneDetail.TOP)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.TOP_ANY)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/n/NoEscape.java b/Mage.Sets/src/mage/cards/n/NoEscape.java index e43ba896da4..9b128b9469b 100644 --- a/Mage.Sets/src/mage/cards/n/NoEscape.java +++ b/Mage.Sets/src/mage/cards/n/NoEscape.java @@ -5,7 +5,7 @@ import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; import mage.target.TargetSpell; @@ -30,7 +30,7 @@ public final class NoEscape extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Counter target creature or planeswalker spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell(filter)); // Scry 1. diff --git a/Mage.Sets/src/mage/cards/r/Remand.java b/Mage.Sets/src/mage/cards/r/Remand.java index e1da9c643e4..60795292843 100644 --- a/Mage.Sets/src/mage/cards/r/Remand.java +++ b/Mage.Sets/src/mage/cards/r/Remand.java @@ -1,4 +1,3 @@ - package mage.cards.r; import java.util.UUID; @@ -7,7 +6,7 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -19,12 +18,11 @@ public final class Remand extends CardImpl { public Remand(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); - // Counter target spell. If that spell is countered this way, put it into its owner's hand instead of into that player's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.HAND)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.HAND)); this.getSpellAbility().addTarget(new TargetSpell()); // Draw a card. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } private Remand(final Remand card) { diff --git a/Mage.Sets/src/mage/cards/s/SpellCrumple.java b/Mage.Sets/src/mage/cards/s/SpellCrumple.java index 7da1f705e86..687d87fe63a 100644 --- a/Mage.Sets/src/mage/cards/s/SpellCrumple.java +++ b/Mage.Sets/src/mage/cards/s/SpellCrumple.java @@ -1,18 +1,12 @@ - package mage.cards.s; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterTargetWithReplacementEffect; import mage.abilities.effects.common.ReturnToLibrarySpellEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.constants.ZoneDetail; -import mage.game.Game; -import mage.players.Player; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -24,9 +18,11 @@ public final class SpellCrumple extends CardImpl { public SpellCrumple(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}"); - // Counter target spell. If that spell is countered this way, put it on the bottom of its owner's library instead of into that player's graveyard. Put Spell Crumple on the bottom of its owner's library. + // Counter target spell. If that spell is countered this way, put it on the + // bottom of its owner's library instead of into that player's graveyard. + // Put Spell Crumple on the bottom of its owner's library. this.getSpellAbility().addTarget(new TargetSpell()); - this.getSpellAbility().addEffect(new SpellCrumpleCounterEffect()); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.BOTTOM_ANY)); this.getSpellAbility().addEffect(new ReturnToLibrarySpellEffect(false)); } @@ -39,29 +35,3 @@ public final class SpellCrumple extends CardImpl { return new SpellCrumple(this); } } - -class SpellCrumpleCounterEffect extends OneShotEffect { - - public SpellCrumpleCounterEffect() { - super(Outcome.Benefit); - this.staticText = "Counter target spell. If that spell is countered this way, put it on the bottom of its owner's library instead of into that player's graveyard"; - } - - public SpellCrumpleCounterEffect(final SpellCrumpleCounterEffect effect) { - super(effect); - } - - @Override - public SpellCrumpleCounterEffect copy() { - return new SpellCrumpleCounterEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return game.getStack().counter(targetPointer.getFirst(game, source), source, game, Zone.LIBRARY, false, ZoneDetail.BOTTOM); - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/s/Spelljack.java b/Mage.Sets/src/mage/cards/s/Spelljack.java index 19559ab21dc..0fe3c212415 100644 --- a/Mage.Sets/src/mage/cards/s/Spelljack.java +++ b/Mage.Sets/src/mage/cards/s/Spelljack.java @@ -9,12 +9,7 @@ import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffec import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.*; import mage.game.Game; import mage.game.stack.Spell; import mage.game.stack.StackObject; @@ -68,7 +63,7 @@ class SpelljackEffect extends OneShotEffect { if (controller != null) { UUID targetId = targetPointer.getFirst(game, source); StackObject stackObject = game.getStack().getStackObject(targetId); - if (stackObject != null && game.getStack().counter(targetId, source, game, Zone.EXILED, false, ZoneDetail.NONE)) { + if (stackObject != null && game.getStack().counter(targetId, source, game, PutCards.EXILED)) { Card card = ((Spell) stackObject).getCard(); if (card != null) { ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.Custom, true); diff --git a/Mage.Sets/src/mage/cards/v/VoidShatter.java b/Mage.Sets/src/mage/cards/v/VoidShatter.java index 95683dc21db..8ad3b860229 100644 --- a/Mage.Sets/src/mage/cards/v/VoidShatter.java +++ b/Mage.Sets/src/mage/cards/v/VoidShatter.java @@ -7,7 +7,7 @@ import mage.abilities.keyword.DevoidAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PutCards; import mage.target.TargetSpell; /** @@ -23,7 +23,7 @@ public final class VoidShatter extends CardImpl { this.addAbility(new DevoidAbility(this.color)); // Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(Zone.EXILED)); + this.getSpellAbility().addEffect(new CounterTargetWithReplacementEffect(PutCards.EXILED)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java index 5f3a9e030e4..dfe6ceac810 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java @@ -1,12 +1,10 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.game.Game; import mage.players.Player; @@ -15,29 +13,20 @@ import mage.players.Player; */ public class CounterTargetWithReplacementEffect extends OneShotEffect { - private Zone targetZone; - private ZoneDetail zoneDetail; - - public CounterTargetWithReplacementEffect(Zone targetZone) { - this(targetZone, ZoneDetail.NONE); - } + private final PutCards putIt; /** * - * @param targetZone - * @param zoneDetail use to specify when moving card to library + * @param putIt */ - public CounterTargetWithReplacementEffect(Zone targetZone, ZoneDetail zoneDetail) { + public CounterTargetWithReplacementEffect(PutCards putIt) { super(Outcome.Detriment); - this.targetZone = targetZone; - this.zoneDetail = zoneDetail; + this.putIt = putIt; } public CounterTargetWithReplacementEffect(final CounterTargetWithReplacementEffect effect) { super(effect); - this.targetZone = effect.targetZone; - this.zoneDetail = effect.zoneDetail; + this.putIt = effect.putIt; } @Override @@ -49,41 +38,26 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - return game.getStack().counter(targetPointer.getFirst(game, source), source, game, targetZone, false, zoneDetail); + return game.getStack().counter(getTargetPointer().getFirst(game, source), source, game, putIt); } return false; } @Override public String getText(Mode mode) { - StringBuilder sb = new StringBuilder("Counter target "); - sb.append(mode.getTargets().get(0).getTargetName()); + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + StringBuilder sb = new StringBuilder("counter "); + sb.append(getTargetPointer().describeTargets(mode.getTargets(), "it")); sb.append(". If that spell is countered this way, "); - if (targetZone == Zone.EXILED) { + if (putIt == PutCards.EXILED) { sb.append("exile it instead of putting it into its owner's graveyard"); + } else { + sb.append(putIt == PutCards.TOP_OR_BOTTOM ? "put that card " : "put it "); + sb.append(putIt.getMessage(true, false)); + sb.append(" instead of into that player's graveyard"); } - if (targetZone == Zone.HAND) { - sb.append("put it into its owner's hand instead of into that player's graveyard"); - } - if (targetZone == Zone.LIBRARY) { - sb.append("put it on "); - switch (zoneDetail) { - case BOTTOM: - sb.append("the bottom"); - break; - case TOP: - sb.append("top"); - break; - case CHOOSE: - sb.append("top or bottom"); - break; - case NONE: - sb.append(""); - break; - } - sb.append(" of its owner's library instead of into that player's graveyard"); - } - return sb.toString(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java index d8534377cff..83a0edf42fa 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java @@ -7,8 +7,7 @@ import mage.abilities.costs.mana.ManaCost; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.game.Game; import mage.game.stack.StackObject; import mage.players.Player; @@ -88,11 +87,7 @@ public class CounterUnlessPaysEffect extends OneShotEffect { if (!(player.chooseUse(Outcome.Benefit, message, source, game) && costToPay.pay(source, game, source, spell.getControllerId(), false, null))) { game.informPlayers(player.getLogName() + " chooses not to pay " + costValueMessage + " to prevent the counter effect"); - if (exile) { - game.getStack().counter(spell.getId(), source, game, Zone.EXILED, false, ZoneDetail.NONE); - } else { - return game.getStack().counter(spell.getId(), source, game); - } + game.getStack().counter(spell.getId(), source, game, exile ? PutCards.EXILED : PutCards.GRAVEYARD); } game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect"); return true; @@ -103,13 +98,8 @@ public class CounterUnlessPaysEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - - StringBuilder sb = new StringBuilder(); - if (mode.getTargets().isEmpty()) { - sb.append("counter it"); - } else { - sb.append("counter target ").append(mode.getTargets().get(0).getTargetName()); - } + StringBuilder sb = new StringBuilder("counter "); + sb.append(getTargetPointer().describeTargets(mode.getTargets(), "it")); sb.append(" unless its controller pays "); if (cost != null) { sb.append(cost.getText()); @@ -121,9 +111,8 @@ public class CounterUnlessPaysEffect extends OneShotEffect { sb.append(genericMana.getMessage()); } if (exile) { - sb.append(". If that spell is countered this way, exile it instead of putting it into its owner's graveyard."); + sb.append(". If that spell is countered this way, exile it instead of putting it into its owner's graveyard"); } return sb.toString(); } - } diff --git a/Mage/src/main/java/mage/constants/ZoneDetail.java b/Mage/src/main/java/mage/constants/ZoneDetail.java deleted file mode 100644 index fd2b95b88e2..00000000000 --- a/Mage/src/main/java/mage/constants/ZoneDetail.java +++ /dev/null @@ -1,14 +0,0 @@ - -package mage.constants; - -/** - * - * @author LevelX2 - */ -public enum ZoneDetail { - - NONE, - TOP, - BOTTOM, - CHOOSE -} diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 9a11e8dc021..a4271243533 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -413,47 +413,46 @@ public class Spell extends StackObjectImpl implements Card { @Override public void counter(Ability source, Game game) { - this.counter(source, game, Zone.GRAVEYARD, false, ZoneDetail.NONE); + this.counter(source, game, PutCards.GRAVEYARD); } @Override - public void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) { + public void counter(Ability source, Game game, PutCards zone) { // source can be null for fizzled spells, don't use that code in your ZONE_CHANGE watchers/triggers: // event.getSourceId().equals - // TODO: so later it must be replaced to another technics with non null source - UUID counteringSourceId = (source == null ? null : source.getSourceId()); + // TODO: fizzled spells are no longer considered "countered" as of current rules; may need refactor this.countered = true; - if (!isCopy()) { - Player player = game.getPlayer(game.getControllerId(counteringSourceId)); - if (player == null) { - player = game.getPlayer(getControllerId()); - } - if (player != null) { - Ability counteringAbility = null; - MageObject counteringObject = game.getObject(counteringSourceId); - if (counteringObject instanceof StackObject) { - counteringAbility = ((StackObject) counteringObject).getStackAbility(); - } - if (zone == Zone.LIBRARY) { - if (zoneDetail == ZoneDetail.CHOOSE) { - if (player.chooseUse(Outcome.Detriment, "Move countered spell to the top of the library? (otherwise it goes to the bottom)", counteringAbility, game)) { - zoneDetail = ZoneDetail.TOP; - } else { - zoneDetail = ZoneDetail.BOTTOM; - } - } - if (zoneDetail == ZoneDetail.TOP) { - player.putCardsOnTopOfLibrary(new CardsImpl(card), game, counteringAbility, false); - } else { - player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, counteringAbility, false); - } - } else { - player.moveCards(card, zone, counteringAbility, game, false, false, owner, null); - } - } - } else { + if (isCopy()) { // copied spell, only remove from stack game.getStack().remove(this, game); + return; + } + Player player = game.getPlayer(source == null ? getControllerId() : source.getControllerId()); + if (player != null) { + switch (zone) { + case TOP_OR_BOTTOM: + if (player.chooseUse(Outcome.Detriment, + "Put the countered spell on the top or bottom of its owner's library?", + null, "Top", "Bottom", source, game + )) { + player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, false); + } else { + player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false); + } + break; + case TOP_ANY: + player.putCardsOnTopOfLibrary(new CardsImpl(card), game, source, false); + break; + case BOTTOM_ANY: + case BOTTOM_RANDOM: + player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false); + break; + case BATTLEFIELD_TAPPED: + player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); + break; + default: + player.moveCards(card, zone.getZone(), source, game); + } } } diff --git a/Mage/src/main/java/mage/game/stack/SpellStack.java b/Mage/src/main/java/mage/game/stack/SpellStack.java index 473bb29b3e0..853622efd7d 100644 --- a/Mage/src/main/java/mage/game/stack/SpellStack.java +++ b/Mage/src/main/java/mage/game/stack/SpellStack.java @@ -6,8 +6,7 @@ import java.util.Date; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.game.Game; import mage.game.events.GameEvent; import org.apache.log4j.Logger; @@ -60,13 +59,10 @@ public class SpellStack extends ArrayDeque { } public boolean counter(UUID objectId, Ability source, Game game) { - return counter(objectId, source, game, Zone.GRAVEYARD, false, ZoneDetail.TOP); + return counter(objectId, source, game, PutCards.GRAVEYARD); } - public boolean counter(UUID objectId, Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) { - // the counter logic is copied by some spells to handle replacement effects of the countered spell - // so if logic is changed here check those spells for needed changes too - // Concerned cards to check: Hinder, Spell Crumple + public boolean counter(UUID objectId, Ability source, Game game, PutCards zone) { StackObject stackObject = getStackObject(objectId); MageObject sourceObject = game.getObject(source); if (stackObject != null && sourceObject != null) { @@ -86,7 +82,7 @@ public class SpellStack extends ArrayDeque { if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement this.remove(stackObject, game); } - stackObject.counter(source, game, zone, owner, zoneDetail); + stackObject.counter(source, game, zone); if (!game.isSimulation()) { game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName()); } diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index c44b31ba44c..451fcdbf08b 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -104,12 +104,12 @@ public class StackAbility extends StackObjectImpl implements Ability { @Override public void counter(Ability source, Game game) { - // zone, owner, top ignored - this.counter(source, game, Zone.GRAVEYARD, true, ZoneDetail.TOP); + // zone ignored + this.counter(source, game, PutCards.GRAVEYARD); } @Override - public void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) { + public void counter(Ability source, Game game, PutCards zone) { //20100716 - 603.8 if (ability instanceof StateTriggeredAbility) { ((StateTriggeredAbility) ability).counter(game); diff --git a/Mage/src/main/java/mage/game/stack/StackObject.java b/Mage/src/main/java/mage/game/stack/StackObject.java index e48cda583d6..4a9228b1a04 100644 --- a/Mage/src/main/java/mage/game/stack/StackObject.java +++ b/Mage/src/main/java/mage/game/stack/StackObject.java @@ -3,8 +3,7 @@ package mage.game.stack; import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; -import mage.constants.Zone; -import mage.constants.ZoneDetail; +import mage.constants.PutCards; import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.game.Controllable; @@ -25,7 +24,7 @@ public interface StackObject extends MageObject, Controllable { */ void counter(Ability source, Game game); - void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail); + void counter(Ability source, Game game, PutCards zone); Ability getStackAbility();