Remove custom multitarget handling from DestroyTargetEffect (use EachTargetPointer instead)

This commit is contained in:
Alex W. Jackson 2022-09-04 07:04:46 -04:00
parent addfd5166e
commit e3b8a813e5
24 changed files with 124 additions and 217 deletions

View file

@ -1,8 +1,6 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -13,6 +11,7 @@ import mage.constants.TargetController;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterLandPermanent; import mage.filter.common.FilterLandPermanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetpointer.EachTargetPointer;
public final class BoomBust extends SplitCard { public final class BoomBust extends SplitCard {
@ -29,9 +28,7 @@ public final class BoomBust extends SplitCard {
// Boom // Boom
// Destroy target land you control and target land you don't control. // Destroy target land you control and target land you don't control.
Effect effect = new DestroyTargetEffect(false, true); getLeftHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
effect.setText("Destroy target land you control and target land you don't control");
getLeftHalfCard().getSpellAbility().addEffect(effect);
getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter1)); getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter1));
getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter2)); getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter2));

View file

@ -2,7 +2,6 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -11,6 +10,7 @@ import mage.target.common.TargetArtifactPermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetEnchantmentPermanent; import mage.target.common.TargetEnchantmentPermanent;
import mage.target.common.TargetLandPermanent; 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}"); super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}{G}");
// Destroy target artifact, target creature, target enchantment, and target land. // Destroy target artifact, target creature, target enchantment, and target land.
Effect effect = new DestroyTargetEffect(false, true); this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
effect.setText("Destroy target artifact, target creature, target enchantment, and target land.");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addTarget(new TargetArtifactPermanent());
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addTarget(new TargetEnchantmentPermanent()); this.getSpellAbility().addTarget(new TargetEnchantmentPermanent());

View file

@ -15,6 +15,7 @@ import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game; import mage.game.Game;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetadjustment.TargetAdjuster;
import mage.target.targetpointer.EachTargetPointer;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
@ -31,7 +32,8 @@ public final class DismantlingWave extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}");
// For each opponent, destroy up to one target artifact or enchantment that player controls. // 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.")); .setText("For each opponent, destroy up to one target artifact or enchantment that player controls."));
this.getSpellAbility().setTargetAdjuster(DismantlingWaveAdjuster.instance); this.getSpellAbility().setTargetAdjuster(DismantlingWaveAdjuster.instance);

View file

@ -29,6 +29,7 @@ public final class FinaleOfEternity extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); 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. // 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().addEffect(new FinaleOfEternityEffect());
this.getSpellAbility().setTargetAdjuster(FinaleOfEternityAdjuster.instance); this.getSpellAbility().setTargetAdjuster(FinaleOfEternityAdjuster.instance);
} }
@ -59,9 +60,8 @@ enum FinaleOfEternityAdjuster implements TargetAdjuster {
class FinaleOfEternityEffect extends OneShotEffect { class FinaleOfEternityEffect extends OneShotEffect {
FinaleOfEternityEffect() { FinaleOfEternityEffect() {
super(Outcome.Benefit); super(Outcome.PutCreatureInPlay);
staticText = "Destroy up to three target creatures with toughness X or less. " + staticText = "If X is 10 or more, return all creature cards from your graveyard to the battlefield.";
"If X is 10 or more, return all creature cards from your graveyard to the battlefield.";
} }
private FinaleOfEternityEffect(final FinaleOfEternityEffect effect) { private FinaleOfEternityEffect(final FinaleOfEternityEffect effect) {
@ -75,7 +75,6 @@ class FinaleOfEternityEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
new DestroyTargetEffect(false, true).apply(game, source);
if (source.getManaCostsToPay().getX() < 10) { if (source.getManaCostsToPay().getX() < 10) {
return true; return true;
} }

View file

@ -1,4 +1,3 @@
package mage.cards.f; package mage.cards.f;
import java.util.UUID; import java.util.UUID;
@ -10,6 +9,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetLandPermanent; 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. // As an additional cost to cast Fumarole, pay 3 life.
this.getSpellAbility().addCost(new PayLifeCost(3)); this.getSpellAbility().addCost(new PayLifeCost(3));
// Destroy target creature and target land. // Destroy target creature and target land.
Effect effect = new DestroyTargetEffect(false, true); this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
effect.setText("Destroy target creature and target land");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addTarget(new TargetLandPermanent()); this.getSpellAbility().addTarget(new TargetLandPermanent());
} }

View file

@ -1,4 +1,3 @@
package mage.cards.g; package mage.cards.g;
import java.util.UUID; import java.util.UUID;
@ -15,6 +14,7 @@ import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetLandPermanent; 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); 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. // 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"); effect.setText("you may sacrifice it. If you do, destroy target creature and target land");
Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect); Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect);
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());

View file

@ -1,16 +1,14 @@
package mage.cards.h; package mage.cards.h;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.target.Target;
import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetArtifactPermanent;
import mage.target.common.TargetEnchantmentPermanent; 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; // Choose one - Destroy target artifact;
this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new DestroyTargetEffect());
Target target = new TargetArtifactPermanent(); this.getSpellAbility().addTarget(new TargetArtifactPermanent());
this.getSpellAbility().addTarget(target);
// or destroy target enchantment; // or destroy target enchantment;
Mode mode = new Mode(new DestroyTargetEffect()); Mode mode = new Mode(new DestroyTargetEffect());
target = new TargetEnchantmentPermanent(); mode.addTarget(new TargetEnchantmentPermanent());
mode.addTarget(target);
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
// or destroy target artifact and target enchantment. // or destroy target artifact and target enchantment.
Effect effect = new DestroyTargetEffect(false, true); mode = new Mode(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
effect.setText("destroy target artifact and target enchantment");
mode = new Mode(effect);
mode.addTarget(new TargetArtifactPermanent()); mode.addTarget(new TargetArtifactPermanent());
mode.addTarget(new TargetEnchantmentPermanent()); mode.addTarget(new TargetEnchantmentPermanent());
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }
private HullBreach(final HullBreach card) { private HullBreach(final HullBreach card) {

View file

@ -1,10 +1,9 @@
package mage.cards.p; package mage.cards.p;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.common.PayLifeCost; 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.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -17,7 +16,7 @@ import mage.target.targetadjustment.TargetAdjuster;
import java.util.UUID; import java.util.UUID;
/** /**
* @author escplan9 - Derek Monturo * @author awjackson
*/ */
public final class PhyrexianPurge extends CardImpl { 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. // Phyrexian Purge costs 3 life more to cast for each target.
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); 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 InfoEffect("this spell costs 3 life more to cast for each target"));
this.getSpellAbility().addEffect(new DestroyMultiTargetEffect().concatBy("<br>")); this.getSpellAbility().addEffect(new DestroyTargetEffect().concatBy("<br>").setText("destroy any number of target creatures"));
this.getSpellAbility().setTargetAdjuster(PhyrexianPurgeTargetAdjuster.instance); this.getSpellAbility().setTargetAdjuster(PhyrexianPurgeTargetAdjuster.instance);
this.getSpellAbility().setCostAdjuster(PhyrexianPurgeCostAdjuster.instance); this.getSpellAbility().setCostAdjuster(PhyrexianPurgeCostAdjuster.instance);
} }

View file

@ -1,7 +1,6 @@
package mage.cards.p; package mage.cards.p;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -9,6 +8,7 @@ import mage.constants.CardType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetLandPermanent; 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}"); super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{R}");
// Destroy target nonblack creature and target land. They can't be regenerated. // Destroy target nonblack creature and target land. They can't be regenerated.
Effect effect = new DestroyTargetEffect(true, true); this.getSpellAbility().addEffect(new DestroyTargetEffect(true).setTargetPointer(new EachTargetPointer()));
effect.setText("Destroy target nonblack creature and target land. They can't be regenerated.");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK));
this.getSpellAbility().addTarget(new TargetLandPermanent()); this.getSpellAbility().addTarget(new TargetLandPermanent());
} }

View file

@ -11,8 +11,10 @@ import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetpointer.EachTargetPointer;
/** /**
* *
@ -20,28 +22,26 @@ import mage.target.TargetPermanent;
*/ */
public final class ReignOfChaos extends CardImpl { public final class ReignOfChaos extends CardImpl {
private static final FilterPermanent filter1 = new FilterPermanent("Plains"); private static final FilterPermanent filterPlains = new FilterLandPermanent(SubType.PLAINS, "Plains");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("white creature"); private static final FilterPermanent filterWhite = new FilterCreaturePermanent("white creature");
private static final FilterPermanent filter3 = new FilterPermanent("Island"); private static final FilterPermanent filterIsland = new FilterLandPermanent(SubType.ISLAND, "Island");
private static final FilterCreaturePermanent filter4 = new FilterCreaturePermanent("blue creature"); private static final FilterPermanent filterBlue = new FilterCreaturePermanent("blue creature");
static { static {
filter1.add(SubType.PLAINS.getPredicate()); filterWhite.add(new ColorPredicate(ObjectColor.WHITE));
filter2.add(new ColorPredicate(ObjectColor.WHITE)); filterBlue.add(new ColorPredicate(ObjectColor.BLUE));
filter3.add(SubType.ISLAND.getPredicate());
filter4.add(new ColorPredicate(ObjectColor.BLUE));
} }
public ReignOfChaos(UUID ownerId, CardSetInfo setInfo) { public ReignOfChaos(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{R}"); 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. // 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().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
this.getSpellAbility().addTarget(new TargetPermanent(filter1)); this.getSpellAbility().addTarget(new TargetPermanent(filterPlains));
this.getSpellAbility().addTarget(new TargetPermanent(filter2)); this.getSpellAbility().addTarget(new TargetPermanent(filterWhite));
Mode mode = new Mode(new DestroyTargetEffect(false, true)); Mode mode = new Mode(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
mode.addTarget(new TargetPermanent(filter3)); mode.addTarget(new TargetPermanent(filterIsland));
mode.addTarget(new TargetPermanent(filter4)); mode.addTarget(new TargetPermanent(filterBlue));
this.getSpellAbility().addMode(mode); this.getSpellAbility().addMode(mode);
} }

View file

@ -1,13 +1,16 @@
package mage.cards.r; package mage.cards.r;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterArtifactOrEnchantmentPermanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetpointer.EachTargetPointer;
import java.util.UUID; import java.util.UUID;
@ -17,15 +20,19 @@ import java.util.UUID;
*/ */
public final class RelicCrush extends CardImpl { 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) { public RelicCrush(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{G}"); super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{G}");
// Destroy target artifact or enchantment and up to one other target artifact or enchantment. // Destroy target artifact or enchantment and up to one other target artifact or enchantment.
Effect effect = new DestroyTargetEffect(false, true); this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
effect.setText("Destroy target artifact or enchantment and up to one other target artifact or enchantment"); this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT).setTargetTag(1));
this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter).setTargetTag(2));
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));
} }
private RelicCrush(final RelicCrush card) { private RelicCrush(final RelicCrush card) {

View file

@ -23,7 +23,7 @@ public final class SeismicShift extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// Destroy target land. Up to two target creatures can't block this turn. // 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().addTarget(new TargetLandPermanent());
this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn) this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn)
.setText("Up to two target creatures can't block this turn") .setText("Up to two target creatures can't block this turn")

View file

@ -1,14 +1,13 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetLandPermanent; 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}"); super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{B}");
// Destroy target creature and target land. // Destroy target creature and target land.
Effect effect = new DestroyTargetEffect(false, true); this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
effect.setText("Destroy target creature and target land");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addTarget(new TargetLandPermanent()); this.getSpellAbility().addTarget(new TargetLandPermanent());
} }

View file

@ -1,16 +1,17 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.common.DestroyMultiTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetArtifactPermanent;
import mage.target.common.TargetEnchantmentPermanent; import mage.target.common.TargetEnchantmentPermanent;
import mage.target.targetpointer.EachTargetPointer;
/** /**
* *
* @author vereena42 * @author awjackson
*/ */
public final class StompAndHowl extends CardImpl { public final class StompAndHowl extends CardImpl {
@ -18,9 +19,9 @@ public final class StompAndHowl extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
// Destroy target artifact and target enchantment. // Destroy target artifact and target enchantment.
this.getSpellAbility().addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()));
this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addTarget(new TargetArtifactPermanent());
this.getSpellAbility().addTarget(new TargetEnchantmentPermanent()); this.getSpellAbility().addTarget(new TargetEnchantmentPermanent());
this.getSpellAbility().addEffect(new DestroyMultiTargetEffect());
} }
private StompAndHowl(final StompAndHowl card) { private StompAndHowl(final StompAndHowl card) {

View file

@ -17,10 +17,11 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetArtifactPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetPlaneswalkerPermanent; import mage.target.common.TargetPlaneswalkerPermanent;
import mage.target.targetpointer.EachTargetPointer;
import java.util.UUID; import java.util.UUID;
import mage.target.common.TargetControlledCreaturePermanent;
/** /**
* @author TheElk801 * @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. // Whenever equipped creature deals combat damage to a player, destroy up to one target planeswalker and up to one target artifact.
ability = new DealsDamageToAPlayerAttachedTriggeredAbility( ability = new DealsDamageToAPlayerAttachedTriggeredAbility(
new DestroyTargetEffect(false, true) new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()),
.setText("destroy up to one target planeswalker and up to one target artifact."),
"equipped creature", false "equipped creature", false
); );
ability.addTarget(new TargetPlaneswalkerPermanent(0, 1)); ability.addTarget(new TargetPlaneswalkerPermanent(0, 1));

View file

@ -11,6 +11,7 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetadjustment.TargetAdjuster;
import mage.target.targetpointer.EachTargetPointer;
import java.util.UUID; import java.util.UUID;
@ -23,11 +24,9 @@ public final class WindgracesJudgment extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{G}");
// For any number of opponents, destroy target nonland permanent that player controls. // For any number of opponents, destroy target nonland permanent that player controls.
this.getSpellAbility().addEffect( this.getSpellAbility().addEffect(new DestroyTargetEffect()
new DestroyTargetEffect(false, true). .setTargetPointer(new EachTargetPointer())
setText("For any number of opponents, " .setText("For any number of opponents, destroy target nonland permanent that player controls")
+ "destroy target nonland permanent "
+ "that player controls")
); );
this.getSpellAbility().setTargetAdjuster(WindgracesJudgmentAdjuster.instance); this.getSpellAbility().setTargetAdjuster(WindgracesJudgmentAdjuster.instance);
} }

View file

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

View file

@ -19,7 +19,6 @@ import java.util.UUID;
public class DestroyTargetEffect extends OneShotEffect { public class DestroyTargetEffect extends OneShotEffect {
protected boolean noRegen; protected boolean noRegen;
protected boolean multitargetHandling;
public DestroyTargetEffect() { public DestroyTargetEffect() {
this(false); this(false);
@ -30,24 +29,18 @@ public class DestroyTargetEffect extends OneShotEffect {
} }
public DestroyTargetEffect(boolean noRegen) { public DestroyTargetEffect(boolean noRegen) {
this(noRegen, false); super(Outcome.DestroyPermanent);
this.noRegen = noRegen;
} }
public DestroyTargetEffect(String ruleText, boolean noRegen) { public DestroyTargetEffect(String ruleText, boolean noRegen) {
this(noRegen, false); this(noRegen);
staticText = ruleText; staticText = ruleText;
} }
public DestroyTargetEffect(boolean noRegen, boolean multitargetHandling) {
super(Outcome.Detriment);
this.noRegen = noRegen;
this.multitargetHandling = multitargetHandling;
}
public DestroyTargetEffect(final DestroyTargetEffect effect) { public DestroyTargetEffect(final DestroyTargetEffect effect) {
super(effect); super(effect);
this.noRegen = effect.noRegen; this.noRegen = effect.noRegen;
this.multitargetHandling = effect.multitargetHandling;
} }
@Override @Override
@ -58,29 +51,13 @@ public class DestroyTargetEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
int affectedTargets = 0; int affectedTargets = 0;
if (multitargetHandling for (UUID permanentId : targetPointer.getTargets(game, source)) {
&& source.getTargets().size() > 1 Permanent permanent = game.getPermanent(permanentId);
&& targetPointer instanceof FirstTargetPointer) { // Decimate if (permanent != null
for (Target target : source.getTargets()) { && permanent.isPhasedIn()
for (UUID permanentId : target.getTargets()) { && !permanent.isPhasedOutIndirectly()) {
Permanent permanent = game.getPermanent(permanentId); permanent.destroy(source, game, noRegen);
if (permanent != null affectedTargets++;
&& 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++;
}
} }
} }
return affectedTargets > 0; return affectedTargets > 0;
@ -91,36 +68,11 @@ public class DestroyTargetEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) { if (staticText != null && !staticText.isEmpty()) {
return staticText; return staticText;
} }
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder("destroy " + getTargetPointer().describeTargets(mode.getTargets(), "that creature"));
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());
}
}
if (noRegen) { 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(); return sb.toString();
} }
} }

View file

@ -7,6 +7,10 @@ import mage.game.permanent.Permanent;
import java.util.UUID; import java.util.UUID;
/**
*
* @author awjackson
*/
public enum AttachedOrShareCreatureTypePredicate implements ObjectSourcePlayerPredicate<Permanent> { public enum AttachedOrShareCreatureTypePredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance; instance;

View file

@ -7,6 +7,8 @@ import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.Target; import mage.target.Target;
import mage.target.Targets;
import mage.util.CardUtil;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -129,4 +131,17 @@ public class EachTargetPointer extends TargetPointerImpl {
} }
return permanent; 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;
}
} }

View file

@ -123,4 +123,9 @@ public class FirstTargetPointer extends TargetPointerImpl {
public String describeTargets(Targets targets, String defaultDescription) { public String describeTargets(Targets targets, String defaultDescription) {
return targets.isEmpty() ? defaultDescription : targets.get(0).getDescription(); return targets.isEmpty() ? defaultDescription : targets.get(0).getDescription();
} }
@Override
public boolean isPlural(Targets targets) {
return !targets.isEmpty() && targets.get(0).getMaxNumberOfTargets() > 1;
}
} }

View file

@ -120,4 +120,9 @@ public class SecondTargetPointer extends TargetPointerImpl {
public String describeTargets(Targets targets, String defaultDescription) { public String describeTargets(Targets targets, String defaultDescription) {
return targets.size() < 2 ? defaultDescription : targets.get(1).getDescription(); return targets.size() < 2 ? defaultDescription : targets.get(1).getDescription();
} }
@Override
public boolean isPlural(Targets targets) {
return targets.size() > 1 && targets.get(1).getMaxNumberOfTargets() > 1;
}
} }

View file

@ -39,15 +39,20 @@ public interface TargetPointer extends Serializable, Copyable<TargetPointer> {
Permanent getFirstTargetPermanentOrLKI(Game game, Ability source); 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 targets
* @param defaultText * @param defaultText
* @return
*/ */
default String describeTargets(Targets targets, String defaultDescription) { default String describeTargets(Targets targets, String defaultDescription) {
return 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) * Store text to target pointer (usefull to keep data for specific trigger, e.g. selected target name for rules)
* *

View file

@ -124,4 +124,9 @@ public class ThirdTargetPointer extends TargetPointerImpl {
public String describeTargets(Targets targets, String defaultDescription) { public String describeTargets(Targets targets, String defaultDescription) {
return targets.size() < 3 ? defaultDescription : targets.get(2).getDescription(); return targets.size() < 3 ? defaultDescription : targets.get(2).getDescription();
} }
@Override
public boolean isPlural(Targets targets) {
return targets.size() > 2 && targets.get(2).getMaxNumberOfTargets() > 1;
}
} }