From e3b8a813e53146d0e0890ed64e68d961f65f1c57 Mon Sep 17 00:00:00 2001 From: "Alex W. Jackson" Date: Sun, 4 Sep 2022 07:04:46 -0400 Subject: [PATCH] Remove custom multitarget handling from DestroyTargetEffect (use EachTargetPointer instead) --- Mage.Sets/src/mage/cards/b/BoomBust.java | 7 +- Mage.Sets/src/mage/cards/d/Decimate.java | 6 +- .../src/mage/cards/d/DismantlingWave.java | 6 +- .../src/mage/cards/f/FinaleOfEternity.java | 9 +-- Mage.Sets/src/mage/cards/f/Fumarole.java | 6 +- .../src/mage/cards/g/GoblinGrenadiers.java | 5 +- Mage.Sets/src/mage/cards/h/HullBreach.java | 15 +--- .../src/mage/cards/p/PhyrexianPurge.java | 9 +-- Mage.Sets/src/mage/cards/p/PlagueSpores.java | 6 +- Mage.Sets/src/mage/cards/r/ReignOfChaos.java | 28 +++---- Mage.Sets/src/mage/cards/r/RelicCrush.java | 19 +++-- Mage.Sets/src/mage/cards/s/SeismicShift.java | 2 +- Mage.Sets/src/mage/cards/s/SpitefulBlow.java | 7 +- Mage.Sets/src/mage/cards/s/StompAndHowl.java | 11 +-- .../mage/cards/s/SwordOfSinewAndSteel.java | 6 +- .../src/mage/cards/w/WindgracesJudgment.java | 11 ++- .../common/DestroyMultiTargetEffect.java | 73 ------------------ .../effects/common/DestroyTargetEffect.java | 74 ++++--------------- .../AttachedOrShareCreatureTypePredicate.java | 4 + .../targetpointer/EachTargetPointer.java | 15 ++++ .../targetpointer/FirstTargetPointer.java | 5 ++ .../targetpointer/SecondTargetPointer.java | 5 ++ .../target/targetpointer/TargetPointer.java | 7 +- .../targetpointer/ThirdTargetPointer.java | 5 ++ 24 files changed, 124 insertions(+), 217 deletions(-) delete mode 100644 Mage/src/main/java/mage/abilities/effects/common/DestroyMultiTargetEffect.java diff --git a/Mage.Sets/src/mage/cards/b/BoomBust.java b/Mage.Sets/src/mage/cards/b/BoomBust.java index 2f4644a010..c41288711c 100644 --- a/Mage.Sets/src/mage/cards/b/BoomBust.java +++ b/Mage.Sets/src/mage/cards/b/BoomBust.java @@ -1,8 +1,6 @@ - package mage.cards.b; import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardSetInfo; @@ -13,6 +11,7 @@ import mage.constants.TargetController; import mage.filter.StaticFilters; import mage.filter.common.FilterLandPermanent; import mage.target.TargetPermanent; +import mage.target.targetpointer.EachTargetPointer; public final class BoomBust extends SplitCard { @@ -29,9 +28,7 @@ public final class BoomBust extends SplitCard { // Boom // Destroy target land you control and target land you don't control. - Effect effect = new DestroyTargetEffect(false, true); - effect.setText("Destroy target land you control and target land you don't control"); - getLeftHalfCard().getSpellAbility().addEffect(effect); + getLeftHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter1)); getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter2)); diff --git a/Mage.Sets/src/mage/cards/d/Decimate.java b/Mage.Sets/src/mage/cards/d/Decimate.java index 31bb8019a2..b1d901eff0 100644 --- a/Mage.Sets/src/mage/cards/d/Decimate.java +++ b/Mage.Sets/src/mage/cards/d/Decimate.java @@ -2,7 +2,6 @@ package mage.cards.d; import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,6 +10,7 @@ import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetEnchantmentPermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -22,9 +22,7 @@ public final class Decimate extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}{G}"); // Destroy target artifact, target creature, target enchantment, and target land. - Effect effect = new DestroyTargetEffect(false, true); - effect.setText("Destroy target artifact, target creature, target enchantment, and target land."); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetEnchantmentPermanent()); diff --git a/Mage.Sets/src/mage/cards/d/DismantlingWave.java b/Mage.Sets/src/mage/cards/d/DismantlingWave.java index 1f3b0c05ad..15a8aa2c71 100644 --- a/Mage.Sets/src/mage/cards/d/DismantlingWave.java +++ b/Mage.Sets/src/mage/cards/d/DismantlingWave.java @@ -15,6 +15,7 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.target.TargetPermanent; import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.EachTargetPointer; import java.util.Objects; import java.util.UUID; @@ -31,7 +32,8 @@ public final class DismantlingWave extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); // For each opponent, destroy up to one target artifact or enchantment that player controls. - this.getSpellAbility().addEffect(new DestroyTargetEffect(false, true) + this.getSpellAbility().addEffect(new DestroyTargetEffect() + .setTargetPointer(new EachTargetPointer()) .setText("For each opponent, destroy up to one target artifact or enchantment that player controls.")); this.getSpellAbility().setTargetAdjuster(DismantlingWaveAdjuster.instance); @@ -70,4 +72,4 @@ enum DismantlingWaveAdjuster implements TargetAdjuster { ability.addTarget(new TargetPermanent(0, 1, filter, false)); }); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/f/FinaleOfEternity.java b/Mage.Sets/src/mage/cards/f/FinaleOfEternity.java index b753855442..e0df5c3173 100644 --- a/Mage.Sets/src/mage/cards/f/FinaleOfEternity.java +++ b/Mage.Sets/src/mage/cards/f/FinaleOfEternity.java @@ -29,6 +29,7 @@ public final class FinaleOfEternity extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); // Destroy up to three target creatures with toughness X or less. If X is 10 or more, return all creature cards from your graveyard to the battlefield. + this.getSpellAbility().addEffect(new DestroyTargetEffect().setText("destroy up to three target creatures with toughness X or less")); this.getSpellAbility().addEffect(new FinaleOfEternityEffect()); this.getSpellAbility().setTargetAdjuster(FinaleOfEternityAdjuster.instance); } @@ -59,9 +60,8 @@ enum FinaleOfEternityAdjuster implements TargetAdjuster { class FinaleOfEternityEffect extends OneShotEffect { FinaleOfEternityEffect() { - super(Outcome.Benefit); - staticText = "Destroy up to three target creatures with toughness X or less. " + - "If X is 10 or more, return all creature cards from your graveyard to the battlefield."; + super(Outcome.PutCreatureInPlay); + staticText = "If X is 10 or more, return all creature cards from your graveyard to the battlefield."; } private FinaleOfEternityEffect(final FinaleOfEternityEffect effect) { @@ -75,7 +75,6 @@ class FinaleOfEternityEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - new DestroyTargetEffect(false, true).apply(game, source); if (source.getManaCostsToPay().getX() < 10) { return true; } @@ -89,4 +88,4 @@ class FinaleOfEternityEffect extends OneShotEffect { ), Zone.BATTLEFIELD, source, game ); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/f/Fumarole.java b/Mage.Sets/src/mage/cards/f/Fumarole.java index 993769d9fd..5b615ff621 100644 --- a/Mage.Sets/src/mage/cards/f/Fumarole.java +++ b/Mage.Sets/src/mage/cards/f/Fumarole.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.UUID; @@ -10,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -23,9 +23,7 @@ public final class Fumarole extends CardImpl { // As an additional cost to cast Fumarole, pay 3 life. this.getSpellAbility().addCost(new PayLifeCost(3)); // Destroy target creature and target land. - Effect effect = new DestroyTargetEffect(false, true); - effect.setText("Destroy target creature and target land"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetLandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinGrenadiers.java b/Mage.Sets/src/mage/cards/g/GoblinGrenadiers.java index 7ccf73b875..1e626de509 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinGrenadiers.java +++ b/Mage.Sets/src/mage/cards/g/GoblinGrenadiers.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.UUID; @@ -15,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -29,7 +29,8 @@ public final class GoblinGrenadiers extends CardImpl { this.toughness = new MageInt(2); // Whenever Goblin Grenadiers attacks and isn't blocked, you may sacrifice it. If you do, destroy target creature and target land. - Effect effect = new DoIfCostPaid(new DestroyTargetEffect(false, true), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature and target land?"); + Effect effect = new DoIfCostPaid(new DestroyTargetEffect(), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature and target land?"); + effect.setTargetPointer(new EachTargetPointer()); effect.setText("you may sacrifice it. If you do, destroy target creature and target land"); Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/h/HullBreach.java b/Mage.Sets/src/mage/cards/h/HullBreach.java index d8f0706a6e..f3a56deec5 100644 --- a/Mage.Sets/src/mage/cards/h/HullBreach.java +++ b/Mage.Sets/src/mage/cards/h/HullBreach.java @@ -1,16 +1,14 @@ - package mage.cards.h; import java.util.UUID; import mage.abilities.Mode; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.target.Target; import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetEnchantmentPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -23,21 +21,16 @@ public final class HullBreach extends CardImpl { // Choose one - Destroy target artifact; this.getSpellAbility().addEffect(new DestroyTargetEffect()); - Target target = new TargetArtifactPermanent(); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addTarget(new TargetArtifactPermanent()); // or destroy target enchantment; Mode mode = new Mode(new DestroyTargetEffect()); - target = new TargetEnchantmentPermanent(); - mode.addTarget(target); + mode.addTarget(new TargetEnchantmentPermanent()); this.getSpellAbility().addMode(mode); // or destroy target artifact and target enchantment. - Effect effect = new DestroyTargetEffect(false, true); - effect.setText("destroy target artifact and target enchantment"); - mode = new Mode(effect); + mode = new Mode(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); mode.addTarget(new TargetArtifactPermanent()); mode.addTarget(new TargetEnchantmentPermanent()); this.getSpellAbility().addMode(mode); - } private HullBreach(final HullBreach card) { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java b/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java index b73602680d..0f09c5bf07 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java @@ -1,10 +1,9 @@ - package mage.cards.p; import mage.abilities.Ability; import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.PayLifeCost; -import mage.abilities.effects.common.DestroyMultiTargetEffect; +import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,7 +16,7 @@ import mage.target.targetadjustment.TargetAdjuster; import java.util.UUID; /** - * @author escplan9 - Derek Monturo + * @author awjackson */ public final class PhyrexianPurge extends CardImpl { @@ -28,7 +27,7 @@ public final class PhyrexianPurge extends CardImpl { // Phyrexian Purge costs 3 life more to cast for each target. this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); this.getSpellAbility().addEffect(new InfoEffect("this spell costs 3 life more to cast for each target")); - this.getSpellAbility().addEffect(new DestroyMultiTargetEffect().concatBy("
")); + this.getSpellAbility().addEffect(new DestroyTargetEffect().concatBy("
").setText("destroy any number of target creatures")); this.getSpellAbility().setTargetAdjuster(PhyrexianPurgeTargetAdjuster.instance); this.getSpellAbility().setCostAdjuster(PhyrexianPurgeCostAdjuster.instance); } @@ -65,4 +64,4 @@ enum PhyrexianPurgeTargetAdjuster implements TargetAdjuster { int maxTargets = you.getLife() / 3; ability.addTarget(new TargetCreaturePermanent(0, maxTargets)); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/p/PlagueSpores.java b/Mage.Sets/src/mage/cards/p/PlagueSpores.java index bda4db4a9c..9e3162505c 100644 --- a/Mage.Sets/src/mage/cards/p/PlagueSpores.java +++ b/Mage.Sets/src/mage/cards/p/PlagueSpores.java @@ -1,7 +1,6 @@ package mage.cards.p; import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -9,6 +8,7 @@ import mage.constants.CardType; import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -21,9 +21,7 @@ public final class PlagueSpores extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{R}"); // Destroy target nonblack creature and target land. They can't be regenerated. - Effect effect = new DestroyTargetEffect(true, true); - effect.setText("Destroy target nonblack creature and target land. They can't be regenerated."); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DestroyTargetEffect(true).setTargetPointer(new EachTargetPointer())); this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addTarget(new TargetLandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/r/ReignOfChaos.java b/Mage.Sets/src/mage/cards/r/ReignOfChaos.java index eb57bd91e4..7ca8ac2b34 100644 --- a/Mage.Sets/src/mage/cards/r/ReignOfChaos.java +++ b/Mage.Sets/src/mage/cards/r/ReignOfChaos.java @@ -11,8 +11,10 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.TargetPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -20,28 +22,26 @@ import mage.target.TargetPermanent; */ public final class ReignOfChaos extends CardImpl { - private static final FilterPermanent filter1 = new FilterPermanent("Plains"); - private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("white creature"); - private static final FilterPermanent filter3 = new FilterPermanent("Island"); - private static final FilterCreaturePermanent filter4 = new FilterCreaturePermanent("blue creature"); + private static final FilterPermanent filterPlains = new FilterLandPermanent(SubType.PLAINS, "Plains"); + private static final FilterPermanent filterWhite = new FilterCreaturePermanent("white creature"); + private static final FilterPermanent filterIsland = new FilterLandPermanent(SubType.ISLAND, "Island"); + private static final FilterPermanent filterBlue = new FilterCreaturePermanent("blue creature"); static { - filter1.add(SubType.PLAINS.getPredicate()); - filter2.add(new ColorPredicate(ObjectColor.WHITE)); - filter3.add(SubType.ISLAND.getPredicate()); - filter4.add(new ColorPredicate(ObjectColor.BLUE)); + filterWhite.add(new ColorPredicate(ObjectColor.WHITE)); + filterBlue.add(new ColorPredicate(ObjectColor.BLUE)); } public ReignOfChaos(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{R}"); // Choose one - Destroy target Plains and target white creature; or destroy target Island and target blue creature. - this.getSpellAbility().addEffect(new DestroyTargetEffect(false, true)); - this.getSpellAbility().addTarget(new TargetPermanent(filter1)); - this.getSpellAbility().addTarget(new TargetPermanent(filter2)); - Mode mode = new Mode(new DestroyTargetEffect(false, true)); - mode.addTarget(new TargetPermanent(filter3)); - mode.addTarget(new TargetPermanent(filter4)); + this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); + this.getSpellAbility().addTarget(new TargetPermanent(filterPlains)); + this.getSpellAbility().addTarget(new TargetPermanent(filterWhite)); + Mode mode = new Mode(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); + mode.addTarget(new TargetPermanent(filterIsland)); + mode.addTarget(new TargetPermanent(filterBlue)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/r/RelicCrush.java b/Mage.Sets/src/mage/cards/r/RelicCrush.java index 4add92087a..171b122a4b 100644 --- a/Mage.Sets/src/mage/cards/r/RelicCrush.java +++ b/Mage.Sets/src/mage/cards/r/RelicCrush.java @@ -1,13 +1,16 @@ package mage.cards.r; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterArtifactOrEnchantmentPermanent; +import mage.filter.predicate.other.AnotherTargetPredicate; import mage.target.TargetPermanent; +import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -17,15 +20,19 @@ import java.util.UUID; */ public final class RelicCrush extends CardImpl { + private static final FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent("other target artifact or enchantment"); + + static { + filter.add(new AnotherTargetPredicate(2)); + } + public RelicCrush(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{G}"); // Destroy target artifact or enchantment and up to one other target artifact or enchantment. - Effect effect = new DestroyTargetEffect(false, true); - effect.setText("Destroy target artifact or enchantment and up to one other target artifact or enchantment"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); - this.getSpellAbility().addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT, false)); + this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT).setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter).setTargetTag(2)); } private RelicCrush(final RelicCrush card) { diff --git a/Mage.Sets/src/mage/cards/s/SeismicShift.java b/Mage.Sets/src/mage/cards/s/SeismicShift.java index 51bf400d35..be1b13ab3b 100644 --- a/Mage.Sets/src/mage/cards/s/SeismicShift.java +++ b/Mage.Sets/src/mage/cards/s/SeismicShift.java @@ -23,7 +23,7 @@ public final class SeismicShift extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Destroy target land. Up to two target creatures can't block this turn. - this.getSpellAbility().addEffect(new DestroyTargetEffect(false, false)); + this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetLandPermanent()); this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn) .setText("Up to two target creatures can't block this turn") diff --git a/Mage.Sets/src/mage/cards/s/SpitefulBlow.java b/Mage.Sets/src/mage/cards/s/SpitefulBlow.java index deb43f3860..ab5b4fb305 100644 --- a/Mage.Sets/src/mage/cards/s/SpitefulBlow.java +++ b/Mage.Sets/src/mage/cards/s/SpitefulBlow.java @@ -1,14 +1,13 @@ - package mage.cards.s; import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.EachTargetPointer; /** * @@ -20,9 +19,7 @@ public final class SpitefulBlow extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{B}"); // Destroy target creature and target land. - Effect effect = new DestroyTargetEffect(false, true); - effect.setText("Destroy target creature and target land"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetLandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/s/StompAndHowl.java b/Mage.Sets/src/mage/cards/s/StompAndHowl.java index 4e047e1b56..4fa22e3197 100644 --- a/Mage.Sets/src/mage/cards/s/StompAndHowl.java +++ b/Mage.Sets/src/mage/cards/s/StompAndHowl.java @@ -1,26 +1,27 @@ - package mage.cards.s; import java.util.UUID; -import mage.abilities.effects.common.DestroyMultiTargetEffect; +import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetEnchantmentPermanent; +import mage.target.targetpointer.EachTargetPointer; + /** * - * @author vereena42 + * @author awjackson */ public final class StompAndHowl extends CardImpl { public StompAndHowl(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); - + // Destroy target artifact and target enchantment. + this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())); this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addTarget(new TargetEnchantmentPermanent()); - this.getSpellAbility().addEffect(new DestroyMultiTargetEffect()); } private StompAndHowl(final StompAndHowl card) { diff --git a/Mage.Sets/src/mage/cards/s/SwordOfSinewAndSteel.java b/Mage.Sets/src/mage/cards/s/SwordOfSinewAndSteel.java index 007aea7db5..fd551e0fc6 100644 --- a/Mage.Sets/src/mage/cards/s/SwordOfSinewAndSteel.java +++ b/Mage.Sets/src/mage/cards/s/SwordOfSinewAndSteel.java @@ -17,10 +17,11 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.target.common.TargetArtifactPermanent; +import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetPlaneswalkerPermanent; +import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; -import mage.target.common.TargetControlledCreaturePermanent; /** * @author TheElk801 @@ -41,8 +42,7 @@ public final class SwordOfSinewAndSteel extends CardImpl { // Whenever equipped creature deals combat damage to a player, destroy up to one target planeswalker and up to one target artifact. ability = new DealsDamageToAPlayerAttachedTriggeredAbility( - new DestroyTargetEffect(false, true) - .setText("destroy up to one target planeswalker and up to one target artifact."), + new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()), "equipped creature", false ); ability.addTarget(new TargetPlaneswalkerPermanent(0, 1)); diff --git a/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java b/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java index e7e1659dd2..849be55796 100644 --- a/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java +++ b/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java @@ -11,6 +11,7 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -23,11 +24,9 @@ public final class WindgracesJudgment extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{G}"); // For any number of opponents, destroy target nonland permanent that player controls. - this.getSpellAbility().addEffect( - new DestroyTargetEffect(false, true). - setText("For any number of opponents, " - + "destroy target nonland permanent " - + "that player controls") + this.getSpellAbility().addEffect(new DestroyTargetEffect() + .setTargetPointer(new EachTargetPointer()) + .setText("For any number of opponents, destroy target nonland permanent that player controls") ); this.getSpellAbility().setTargetAdjuster(WindgracesJudgmentAdjuster.instance); } @@ -60,4 +59,4 @@ enum WindgracesJudgmentAdjuster implements TargetAdjuster { } }); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/DestroyMultiTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DestroyMultiTargetEffect.java deleted file mode 100644 index e4b6acf2f7..0000000000 --- a/Mage/src/main/java/mage/abilities/effects/common/DestroyMultiTargetEffect.java +++ /dev/null @@ -1,73 +0,0 @@ - -package mage.abilities.effects.common; - -import java.util.Iterator; -import java.util.UUID; -import mage.constants.Outcome; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.OneShotEffect; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.Target; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class DestroyMultiTargetEffect extends OneShotEffect { - protected boolean noRegen; - - public DestroyMultiTargetEffect() { - this(false); - } - - public DestroyMultiTargetEffect(boolean noRegen) { - super(Outcome.DestroyPermanent); - this.noRegen = noRegen; - } - - public DestroyMultiTargetEffect(final DestroyMultiTargetEffect effect) { - super(effect); - this.noRegen = effect.noRegen; - } - - @Override - public DestroyMultiTargetEffect copy() { - return new DestroyMultiTargetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int affectedTargets = 0; - for (Target target: source.getTargets()) { - for (UUID permanentId: target.getTargets()) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - permanent.destroy(source, game, noRegen); - affectedTargets++; - } - } - } - return affectedTargets > 0; - } - - @Override - public String getText(Mode mode) { - StringBuilder sb = new StringBuilder(); - sb.append("Destroy "); - - Iterator iterator = mode.getTargets().iterator(); - while (iterator.hasNext()) { - Target target = iterator.next(); - if (target.getNumberOfTargets() > 1) { - sb.append(target.getNumberOfTargets()).append(' '); - } - sb.append("target ").append(target.getTargetName()); - if (iterator.hasNext()) { - sb.append(" and "); - } - } - return sb.toString(); - } -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java index 481cdcaebb..42774b5190 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java @@ -19,7 +19,6 @@ import java.util.UUID; public class DestroyTargetEffect extends OneShotEffect { protected boolean noRegen; - protected boolean multitargetHandling; public DestroyTargetEffect() { this(false); @@ -30,24 +29,18 @@ public class DestroyTargetEffect extends OneShotEffect { } public DestroyTargetEffect(boolean noRegen) { - this(noRegen, false); + super(Outcome.DestroyPermanent); + this.noRegen = noRegen; } public DestroyTargetEffect(String ruleText, boolean noRegen) { - this(noRegen, false); + this(noRegen); staticText = ruleText; } - public DestroyTargetEffect(boolean noRegen, boolean multitargetHandling) { - super(Outcome.Detriment); - this.noRegen = noRegen; - this.multitargetHandling = multitargetHandling; - } - public DestroyTargetEffect(final DestroyTargetEffect effect) { super(effect); this.noRegen = effect.noRegen; - this.multitargetHandling = effect.multitargetHandling; } @Override @@ -58,29 +51,13 @@ public class DestroyTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int affectedTargets = 0; - if (multitargetHandling - && source.getTargets().size() > 1 - && targetPointer instanceof FirstTargetPointer) { // Decimate - for (Target target : source.getTargets()) { - for (UUID permanentId : target.getTargets()) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null - && permanent.isPhasedIn() - && !permanent.isPhasedOutIndirectly()) { - permanent.destroy(source, game, noRegen); - affectedTargets++; - } - } - } - } else { - for (UUID permanentId : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null - && permanent.isPhasedIn() - && !permanent.isPhasedOutIndirectly()) { - permanent.destroy(source, game, noRegen); - affectedTargets++; - } + for (UUID permanentId : targetPointer.getTargets(game, source)) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent != null + && permanent.isPhasedIn() + && !permanent.isPhasedOutIndirectly()) { + permanent.destroy(source, game, noRegen); + affectedTargets++; } } return affectedTargets > 0; @@ -91,36 +68,11 @@ public class DestroyTargetEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - StringBuilder sb = new StringBuilder(); - if (mode.getTargets().isEmpty()) { - sb.append("destroy that creature"); //TODO add possibility to specify text with targetPointer usage - } else { - Target target; - if (targetPointer instanceof SecondTargetPointer && mode.getTargets().size() > 1) { - target = mode.getTargets().get(1); - } else { - target = mode.getTargets().get(0); - } - if (target.getNumberOfTargets() == 1) { - String targetName = target.getTargetName(); - sb.append("destroy "); - if (!targetName.startsWith("another")) { - sb.append("target "); - } - sb.append(targetName); - } else { - if (target.getMaxNumberOfTargets() == target.getMinNumberOfTargets()) { - sb.append("destroy ").append(CardUtil.numberToText(target.getNumberOfTargets())); - } else { - sb.append("destroy up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets())); - } - sb.append(" target ").append(target.getTargetName()); - } - } + StringBuilder sb = new StringBuilder("destroy " + getTargetPointer().describeTargets(mode.getTargets(), "that creature")); if (noRegen) { - sb.append(". It can't be regenerated"); + sb.append(getTargetPointer().isPlural(mode.getTargets()) ? ". They" : ". It"); + sb.append(" can't be regenerated"); } return sb.toString(); } - } diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/AttachedOrShareCreatureTypePredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/AttachedOrShareCreatureTypePredicate.java index 7e095d7aec..5046ee1742 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/AttachedOrShareCreatureTypePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/AttachedOrShareCreatureTypePredicate.java @@ -7,6 +7,10 @@ import mage.game.permanent.Permanent; import java.util.UUID; +/** + * + * @author awjackson + */ public enum AttachedOrShareCreatureTypePredicate implements ObjectSourcePlayerPredicate { instance; diff --git a/Mage/src/main/java/mage/target/targetpointer/EachTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/EachTargetPointer.java index 2ae5cdc6ab..fcd28722a2 100644 --- a/Mage/src/main/java/mage/target/targetpointer/EachTargetPointer.java +++ b/Mage/src/main/java/mage/target/targetpointer/EachTargetPointer.java @@ -7,6 +7,8 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; +import mage.target.Targets; +import mage.util.CardUtil; import java.util.*; import java.util.stream.Collectors; @@ -129,4 +131,17 @@ public class EachTargetPointer extends TargetPointerImpl { } return permanent; } + + @Override + public String describeTargets(Targets targets, String defaultDescription) { + if (targets.isEmpty()) { + return defaultDescription; + } + return CardUtil.concatWithAnd(targets.stream().map(Target::getDescription).collect(Collectors.toList())); + } + + @Override + public boolean isPlural(Targets targets) { + return true; + } } diff --git a/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java index 7442e05053..021142cbeb 100644 --- a/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java +++ b/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java @@ -123,4 +123,9 @@ public class FirstTargetPointer extends TargetPointerImpl { public String describeTargets(Targets targets, String defaultDescription) { return targets.isEmpty() ? defaultDescription : targets.get(0).getDescription(); } + + @Override + public boolean isPlural(Targets targets) { + return !targets.isEmpty() && targets.get(0).getMaxNumberOfTargets() > 1; + } } diff --git a/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java index 56f57c5215..7fa4a5b4d9 100644 --- a/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java +++ b/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java @@ -120,4 +120,9 @@ public class SecondTargetPointer extends TargetPointerImpl { public String describeTargets(Targets targets, String defaultDescription) { return targets.size() < 2 ? defaultDescription : targets.get(1).getDescription(); } + + @Override + public boolean isPlural(Targets targets) { + return targets.size() > 1 && targets.get(1).getMaxNumberOfTargets() > 1; + } } diff --git a/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java index f0d44081c8..52609e4b82 100644 --- a/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java +++ b/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java @@ -39,15 +39,20 @@ public interface TargetPointer extends Serializable, Copyable { Permanent getFirstTargetPermanentOrLKI(Game game, Ability source); /** - * Returns description of targets for ability text + * Describes the appropriate subset of targets for ability text. * * @param targets * @param defaultText + * @return */ default String describeTargets(Targets targets, String defaultDescription) { return defaultDescription; } + default boolean isPlural(Targets targets) { + return false; + } + /** * Store text to target pointer (usefull to keep data for specific trigger, e.g. selected target name for rules) * diff --git a/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java index 7206d1b41f..17891a0358 100644 --- a/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java +++ b/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java @@ -124,4 +124,9 @@ public class ThirdTargetPointer extends TargetPointerImpl { public String describeTargets(Targets targets, String defaultDescription) { return targets.size() < 3 ? defaultDescription : targets.get(2).getDescription(); } + + @Override + public boolean isPlural(Targets targets) { + return targets.size() > 2 && targets.get(2).getMaxNumberOfTargets() > 1; + } }