refactor: improved EachOpponentPermanentTargetsAdjuster and few card fixes (#12102)

* Wreck and Rebuild: Return a land, not a creature
* Sinister Concierge should still gain suspend with 0 targets
* Fixed Tolarian Contempt
This commit is contained in:
ssk97 2024-04-09 19:59:21 -07:00 committed by GitHub
parent fd0da67e46
commit 124d60e2b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 65 additions and 38 deletions

View file

@ -23,7 +23,8 @@ public final class BlatantThievery extends CardImpl {
this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true) this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true)
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, gain control of target permanent that player controls")); .setText("for each opponent, gain control of target permanent that player controls"));
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent())); this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
this.getSpellAbility().addTarget(new TargetPermanent());
} }
private BlatantThievery(final BlatantThievery card) { private BlatantThievery(final BlatantThievery card) {

View file

@ -46,7 +46,8 @@ public final class BronzebeakForagers extends CardImpl {
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield") .setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield")
); );
etbAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0, 1))); etbAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
etbAbility.addTarget(new TargetNonlandPermanent(0, 1));
this.addAbility(etbAbility); this.addAbility(etbAbility);
// {X}{W}: Put target card with mana value X exiled with Bronzebeak Foragers into its owner's graveyard. // {X}{W}: Put target card with mana value X exiled with Bronzebeak Foragers into its owner's graveyard.

View file

@ -33,7 +33,8 @@ public final class DecoyGambit extends CardImpl {
// For each opponent, choose up to one target creature that player controls, // For each opponent, choose up to one target creature that player controls,
// then return that creature to its owner's hand unless its controller has you draw a card. // then return that creature to its owner's hand unless its controller has you draw a card.
this.getSpellAbility().addEffect(new DecoyGambitEffect()); this.getSpellAbility().addEffect(new DecoyGambitEffect());
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0,1));
} }
private DecoyGambit(final DecoyGambit card) { private DecoyGambit(final DecoyGambit card) {

View file

@ -44,7 +44,8 @@ public final class DesecrateReality extends CardImpl {
this.getSpellAbility().addEffect(new ExileTargetEffect() this.getSpellAbility().addEffect(new ExileTargetEffect()
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, exile up to one target permanent that player controls with an even mana value.")); .setText("for each opponent, exile up to one target permanent that player controls with an even mana value."));
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, evenFilter))); this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
this.getSpellAbility().addTarget(new TargetPermanent(0, 1, evenFilter));
// Adamant -- If at least three colorless mana was spent to cast this spell, return a permanent card with an odd mana value from your graveyard to the battlefield. // Adamant -- If at least three colorless mana was spent to cast this spell, return a permanent card with an odd mana value from your graveyard to the battlefield.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect( this.getSpellAbility().addEffect(new ConditionalOneShotEffect(

View file

@ -27,8 +27,8 @@ public final class DismantlingWave extends CardImpl {
this.getSpellAbility().addEffect(new DestroyTargetEffect() this.getSpellAbility().addEffect(new DestroyTargetEffect()
.setTargetPointer(new EachTargetPointer()) .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(new EachOpponentPermanentTargetsAdjuster( this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT))); this.getSpellAbility().addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
// Cycling {6}{W}{W} // Cycling {6}{W}{W}
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{6}{W}{W}"))); this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{6}{W}{W}")));

View file

@ -25,7 +25,8 @@ public final class ElminstersSimulacrum extends CardImpl {
// For each opponent, you create a token that's a copy of up to one target creature that player controls. // For each opponent, you create a token that's a copy of up to one target creature that player controls.
this.getSpellAbility().addEffect(new ElminstersSimulacrumAdjusterEffect()); this.getSpellAbility().addEffect(new ElminstersSimulacrumAdjusterEffect());
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0,1));
} }
private ElminstersSimulacrum(final ElminstersSimulacrum card) { private ElminstersSimulacrum(final ElminstersSimulacrum card) {

View file

@ -39,7 +39,8 @@ public final class EnigmaThief extends CardImpl {
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect() Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, return up to one target nonland permanent that player controls to its owner's hand")); .setText("for each opponent, return up to one target nonland permanent that player controls to its owner's hand"));
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetNonlandPermanent(0,1));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -25,7 +25,8 @@ public final class GraspOfFate extends CardImpl {
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield") .setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield")
); );
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetNonlandPermanent(0,1));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,6 +1,7 @@
package mage.cards.h; package mage.cards.h;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.keyword.MyriadAbility; import mage.abilities.keyword.MyriadAbility;
@ -31,11 +32,14 @@ public final class HammersOfMoradin extends CardImpl {
this.addAbility(new MyriadAbility()); this.addAbility(new MyriadAbility());
// Whenever Hammers of Moradin attacks, for each opponent, tap up to one target creature that player controls. // Whenever Hammers of Moradin attacks, for each opponent, tap up to one target creature that player controls.
this.addAbility(new AttacksTriggeredAbility( Ability ability = new AttacksTriggeredAbility(
new TapTargetEffect() new TapTargetEffect()
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, tap up to one target creature that player controls") .setText("for each opponent, tap up to one target creature that player controls")
).setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1)))); );
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreaturePermanent(0,1));
this.addAbility(ability);
} }
private HammersOfMoradin(final HammersOfMoradin card) { private HammersOfMoradin(final HammersOfMoradin card) {

View file

@ -57,7 +57,8 @@ public final class InTheDarknessBindThem extends CardImpl {
ability.addEffect(new TheRingTemptsYouEffect()); ability.addEffect(new TheRingTemptsYouEffect());
ability.getEffects().setTargetPointer(new EachTargetPointer()); ability.getEffects().setTargetPointer(new EachTargetPointer());
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreaturePermanent(0,1));
} }
); );

View file

@ -42,7 +42,8 @@ public final class JuvenileMistDragon extends CardImpl {
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("Each of those creatures doesn't untap during its controller's next untap step") .setText("Each of those creatures doesn't untap during its controller's next untap step")
); );
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreaturePermanent(0,1));
this.addAbility(ability.withFlavorWord("Confounding Clouds")); this.addAbility(ability.withFlavorWord("Confounding Clouds"));
} }

View file

@ -40,7 +40,8 @@ public final class LuminatePrimordial extends CardImpl {
// When Luminate Primordial enters the battlefield, for each opponent, exile up to one target creature // When Luminate Primordial enters the battlefield, for each opponent, exile up to one target creature
// that player controls and that player gains life equal to its power. // that player controls and that player gains life equal to its power.
Ability ability = new EntersBattlefieldTriggeredAbility(new LuminatePrimordialEffect(), false); Ability ability = new EntersBattlefieldTriggeredAbility(new LuminatePrimordialEffect(), false);
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreaturePermanent(0,1));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -31,7 +31,8 @@ public final class MassMutiny extends CardImpl {
// For each opponent, gain control of up to one target creature that player controls until end of turn. Untap those creatures. They gain haste until end of turn. // For each opponent, gain control of up to one target creature that player controls until end of turn. Untap those creatures. They gain haste until end of turn.
this.getSpellAbility().addEffect(new MassMutinyEffect()); this.getSpellAbility().addEffect(new MassMutinyEffect());
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0,1));
} }
private MassMutiny(final MassMutiny card) { private MassMutiny(final MassMutiny card) {

View file

@ -41,7 +41,8 @@ public final class MoltenPrimordial extends CardImpl {
// When Molten Primordial enters the battlefield, for each opponent, take control of up to one target creature that player controls until end of turn. Untap those creatures. They have haste until end of turn. // When Molten Primordial enters the battlefield, for each opponent, take control of up to one target creature that player controls until end of turn. Untap those creatures. They have haste until end of turn.
Ability ability = new EntersBattlefieldTriggeredAbility(new MoltenPrimordialEffect(), false); Ability ability = new EntersBattlefieldTriggeredAbility(new MoltenPrimordialEffect(), false);
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreaturePermanent(0,1));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -84,8 +84,7 @@ class SinisterConciergeEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Card card = game.getCard(source.getSourceId()); Card card = game.getCard(source.getSourceId());
Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (controller == null || card == null) {
if (controller == null || card == null || targetCreature == null) {
return false; return false;
} }
@ -99,6 +98,11 @@ class SinisterConciergeEffect extends OneShotEffect {
} }
} }
Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (targetCreature == null){
return false;
}
// Exile, put time counters, and give suspend for target // Exile, put time counters, and give suspend for target
Effect exileTarget = new ExileTargetEffect(); Effect exileTarget = new ExileTargetEffect();
exileTarget.setTargetPointer(this.getTargetPointer().copy()); exileTarget.setTargetPointer(this.getTargetPointer().copy());

View file

@ -42,7 +42,8 @@ public final class SontaranGeneral extends CardImpl {
.setText("for each opponent, goad up to one target creature that player controls.")); .setText("for each opponent, goad up to one target creature that player controls."));
ability.addEffect(new CantBlockTargetEffect(Duration.EndOfTurn) ability.addEffect(new CantBlockTargetEffect(Duration.EndOfTurn)
.setText("Those creatures can't block this turn.")); .setText("Those creatures can't block this turn."));
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0, 1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreaturePermanent(0, 1));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -46,7 +46,8 @@ public final class SylvanPrimordial extends CardImpl {
// When Sylvan Primordial enters the battlefield, for each opponent, destroy target noncreature permanent that player controls. For each permanent destroyed this way, search your library for a Forest card and put that card onto the battlefield tapped. Then shuffle your library. // When Sylvan Primordial enters the battlefield, for each opponent, destroy target noncreature permanent that player controls. For each permanent destroyed this way, search your library for a Forest card and put that card onto the battlefield tapped. Then shuffle your library.
Ability ability = new EntersBattlefieldTriggeredAbility(new SylvanPrimordialEffect(), false); Ability ability = new EntersBattlefieldTriggeredAbility(new SylvanPrimordialEffect(), false);
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(filter))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -31,7 +31,8 @@ public final class TemptedByTheOriq extends CardImpl {
.setTargetPointer(new EachTargetPointer()) .setTargetPointer(new EachTargetPointer())
.setText("for each opponent, gain control of up to one target creature " + .setText("for each opponent, gain control of up to one target creature " +
"or planeswalker that player controls with mana value 3 or less")); "or planeswalker that player controls with mana value 3 or less"));
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, filter))); this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter));
} }
private TemptedByTheOriq(final TemptedByTheOriq card) { private TemptedByTheOriq(final TemptedByTheOriq card) {

View file

@ -51,7 +51,8 @@ public final class TheBalrogOfMoria extends CardImpl {
.setText("for each opponent, exile up to one target creature that player controls."), .setText("for each opponent, exile up to one target creature that player controls."),
false false
); );
reflexiveAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); reflexiveAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
reflexiveAbility.addTarget(new TargetCreaturePermanent(0,1));
this.addAbility(new DiesSourceTriggeredAbility( this.addAbility(new DiesSourceTriggeredAbility(
new DoWhenCostPaid( new DoWhenCostPaid(

View file

@ -57,7 +57,8 @@ public final class TheHorusHeresy extends CardImpl {
// I -- For each opponent, gain control of up to one target nonlegendary creature that player controls for as long as The Horus Heresy remains on the battlefield. // I -- For each opponent, gain control of up to one target nonlegendary creature that player controls for as long as The Horus Heresy remains on the battlefield.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, ability -> { sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, ability -> {
ability.addEffect(new TheHorusHeresyControlEffect()); ability.addEffect(new TheHorusHeresyControlEffect());
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, filterNonlegendary))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetPermanent(0, 1, filterNonlegendary));
}); });
// II -- Draw a card for each creature you control but don't own. // II -- Draw a card for each creature you control but don't own.

View file

@ -46,7 +46,8 @@ public final class TheTrueScriptures extends CardImpl {
ability -> { ability -> {
ability.addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()) ability.addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer())
.setText("for each opponent, destroy up to one target creature or planeswalker that player controls")); .setText("for each opponent, destroy up to one target creature or planeswalker that player controls"));
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreatureOrPlaneswalker(0,1))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetCreatureOrPlaneswalker(0,1));
} }
); );

View file

@ -46,9 +46,10 @@ public final class TolarianContempt extends CardImpl {
)); ));
// At the beginning of your end step, for each opponent, choose up to one target creature they control with a rejection counter on it. That creature's owner puts it on the top or bottom of their library. // At the beginning of your end step, for each opponent, choose up to one target creature they control with a rejection counter on it. That creature's owner puts it on the top or bottom of their library.
this.addAbility(new BeginningOfEndStepTriggeredAbility( Ability ability = new BeginningOfEndStepTriggeredAbility(new TolarianContemptEffect(), TargetController.YOU, false);
new TolarianContemptEffect(), TargetController.YOU, false ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
).setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0,1, filterRejection)))); ability.addTarget(new TargetPermanent(0,1, filterRejection));
this.addAbility(ability);
} }
private TolarianContempt(final TolarianContempt card) { private TolarianContempt(final TolarianContempt card) {

View file

@ -56,7 +56,8 @@ public final class VronosMaskedInquisitor extends CardImpl {
// 2: For each opponent, return up to one target nonland permanent that player controls to its owner's hand. // 2: For each opponent, return up to one target nonland permanent that player controls to its owner's hand.
LoyaltyAbility ability2 = new LoyaltyAbility(new ReturnToHandTargetEffect().setTargetPointer(new EachTargetPointer()) LoyaltyAbility ability2 = new LoyaltyAbility(new ReturnToHandTargetEffect().setTargetPointer(new EachTargetPointer())
.setText("for each opponent, return up to one target nonland permanent that player controls to its owner's hand"), -2); .setText("for each opponent, return up to one target nonland permanent that player controls to its owner's hand"), -2);
ability2.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0,1))); ability2.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability2.addTarget(new TargetNonlandPermanent(0,1));
this.addAbility(ability2); this.addAbility(ability2);
// 7: Target artifact you control becomes a 9/9 Construct artifact creature and gains vigilance, indestructible, and "This creature can't be blocked." // 7: Target artifact you control becomes a 9/9 Construct artifact creature and gains vigilance, indestructible, and "This creature can't be blocked."

View file

@ -63,7 +63,8 @@ public final class WelcomeTo extends CardImpl {
).setText("For each opponent, up to one target noncreature artifact they control becomes " + ).setText("For each opponent, up to one target noncreature artifact they control becomes " +
"a 0/4 Wall artifact creature with defender for as long as you control this Saga.")); "a 0/4 Wall artifact creature with defender for as long as you control this Saga."));
ability.getEffects().setTargetPointer(new EachTargetPointer()); ability.getEffects().setTargetPointer(new EachTargetPointer());
ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, filterNoncreatureArtifact))); ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster());
ability.addTarget(new TargetPermanent(0, 1, filterNoncreatureArtifact));
}); });
// II -- Create a 3/3 green Dinosaur creature token with trample. It gains haste until end of turn. // II -- Create a 3/3 green Dinosaur creature token with trample. It gains haste until end of turn.

View file

@ -75,7 +75,7 @@ class WreckAndRebuildEffect extends OneShotEffect {
return false; return false;
} }
TargetCard targetCard = new TargetCardInYourGraveyard( TargetCard targetCard = new TargetCardInYourGraveyard(
0, 1, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD, true 0, 1, StaticFilters.FILTER_CARD_LAND, true
); );
player.choose(outcome, targetCard, source, game); player.choose(outcome, targetCard, source, game);
Card card = game.getCard(targetCard.getFirstTarget()); Card card = game.getCard(targetCard.getFirstTarget());

View file

@ -11,25 +11,23 @@ import mage.target.TargetPermanent;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author notgreat * @author notgreat
*/ */
public class EachOpponentPermanentTargetsAdjuster implements TargetAdjuster { public class EachOpponentPermanentTargetsAdjuster implements TargetAdjuster {
private final TargetPermanent blueprintTarget; private TargetPermanent blueprintTarget = null;
/** /**
* Duplicates the permanent target for each opponent. * Duplicates the permanent target for each opponent.
* Filtering of permanent's controllers will be handled inside, so * Filtering of permanent's controllers will be handled inside, so
* do not pass a blueprint target with a controller restriction filter/predicate. * do not pass a blueprint target with a controller restriction filter/predicate.
*
* @param blueprintTarget The target to be duplicated per opponent
*/ */
public EachOpponentPermanentTargetsAdjuster(TargetPermanent blueprintTarget) { public EachOpponentPermanentTargetsAdjuster() {
this.blueprintTarget = blueprintTarget.copy(); //Defensively copy the blueprint to ensure immutability
} }
@Override @Override
public void adjustTargets(Ability ability, Game game) { public void adjustTargets(Ability ability, Game game) {
if (blueprintTarget == null) {
blueprintTarget = (TargetPermanent) ability.getTargets().get(0).copy();
}
ability.getTargets().clear(); ability.getTargets().clear();
for (UUID opponentId : game.getOpponents(ability.getControllerId())) { for (UUID opponentId : game.getOpponents(ability.getControllerId())) {
Player opponent = game.getPlayer(opponentId); Player opponent = game.getPlayer(opponentId);
@ -40,7 +38,7 @@ public class EachOpponentPermanentTargetsAdjuster implements TargetAdjuster {
Filter<Permanent> filter = newTarget.getFilter(); Filter<Permanent> filter = newTarget.getFilter();
filter.add(new ControllerIdPredicate(opponentId)); filter.add(new ControllerIdPredicate(opponentId));
if (newTarget.canChoose(ability.getControllerId(), ability, game)) { if (newTarget.canChoose(ability.getControllerId(), ability, game)) {
filter.setMessage(filter.getMessage()+" controlled by " + opponent.getLogName()); filter.setMessage(filter.getMessage() + " controlled by " + opponent.getLogName());
ability.addTarget(newTarget); ability.addTarget(newTarget);
} }
} }