From d886b3e4501f98991c3f10882ada9c01f0262e44 Mon Sep 17 00:00:00 2001 From: ssk97 Date: Thu, 28 Mar 2024 14:32:38 -0700 Subject: [PATCH] [WHO] Implement 4 cards, create generic EachOpponentPermanentTargetsAdjuster (#11886) * Implement Bigger on the Inside * implement Reverse the Polarity * Implement Sontaran General * Implement Everything Comes to Dust --- .../src/mage/cards/b/BiggerOnTheInside.java | 105 ++++++++++++++++++ .../src/mage/cards/b/BlatantThievery.java | 32 +----- .../src/mage/cards/b/BronzebeakForagers.java | 33 +----- Mage.Sets/src/mage/cards/d/DecoyGambit.java | 29 +---- .../src/mage/cards/d/DesecrateReality.java | 41 ++----- .../src/mage/cards/d/DismantlingWave.java | 31 +----- .../mage/cards/e/ElminstersSimulacrum.java | 28 +---- Mage.Sets/src/mage/cards/e/EnigmaThief.java | 28 +---- .../mage/cards/e/EverythingComesToDust.java | 70 ++++++++++++ Mage.Sets/src/mage/cards/g/GraspOfFate.java | 31 +----- .../src/mage/cards/h/HammersOfMoradin.java | 31 +----- .../mage/cards/i/InTheDarknessBindThem.java | 30 +---- .../src/mage/cards/j/JuvenileMistDragon.java | 30 +---- .../src/mage/cards/l/LuminatePrimordial.java | 24 +--- Mage.Sets/src/mage/cards/m/MassMutiny.java | 28 +---- .../src/mage/cards/m/MoltenPrimordial.java | 25 +---- .../src/mage/cards/r/ReverseThePolarity.java | 80 +++++++++++++ .../src/mage/cards/s/SontaranGeneral.java | 57 ++++++++++ .../src/mage/cards/s/SylvanPrimordial.java | 30 ++--- .../src/mage/cards/t/TemptedByTheOriq.java | 34 +----- .../src/mage/cards/t/TheBalrogOfMoria.java | 30 +---- .../src/mage/cards/t/TheHorusHeresy.java | 26 +---- .../src/mage/cards/t/TheTrueScriptures.java | 32 +----- .../src/mage/cards/t/TolarianContempt.java | 32 ++---- .../mage/cards/v/VronosMaskedInquisitor.java | 29 +---- Mage.Sets/src/mage/cards/w/WelcomeTo.java | 31 +----- Mage.Sets/src/mage/sets/DoctorWho.java | 4 + .../NextSpellCastHasAbilityEffect.java | 34 +++++- .../EachOpponentPermanentTargetsAdjuster.java | 48 ++++++++ .../targetadjustment/TargetAdjuster.java | 1 + 30 files changed, 479 insertions(+), 585 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/b/BiggerOnTheInside.java create mode 100644 Mage.Sets/src/mage/cards/e/EverythingComesToDust.java create mode 100644 Mage.Sets/src/mage/cards/r/ReverseThePolarity.java create mode 100644 Mage.Sets/src/mage/cards/s/SontaranGeneral.java create mode 100644 Mage/src/main/java/mage/target/targetadjustment/EachOpponentPermanentTargetsAdjuster.java diff --git a/Mage.Sets/src/mage/cards/b/BiggerOnTheInside.java b/Mage.Sets/src/mage/cards/b/BiggerOnTheInside.java new file mode 100644 index 00000000000..f85cc74f7a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BiggerOnTheInside.java @@ -0,0 +1,105 @@ +package mage.cards.b; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.common.continuous.NextSpellCastHasAbilityEffect; +import mage.abilities.effects.mana.AddManaOfAnyColorEffect; +import mage.abilities.effects.mana.ManaEffect; +import mage.abilities.keyword.CascadeAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class BiggerOnTheInside extends CardImpl { + + private static final FilterPermanent filter + = new FilterPermanent("artifact or land"); + + static { + filter.add(Predicates.or( + CardType.ARTIFACT.getPredicate(), + CardType.LAND.getPredicate() + )); + } + + public BiggerOnTheInside(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{G}"); + this.subtype.add(SubType.AURA); + + // Enchant artifact or land + TargetPermanent auraTarget = new TargetPermanent(filter); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + this.addAbility(new EnchantAbility(auraTarget)); + + // Enchanted permanent has "{T}: Target player adds two mana of any one color. The next spell they cast this turn has cascade." + Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BiggerOnTheInsideEffect(), new TapSourceCost()); + gainedAbility.addTarget(new TargetPlayer()); + Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + private BiggerOnTheInside(final BiggerOnTheInside card) { + super(card); + } + + @Override + public BiggerOnTheInside copy() { + return new BiggerOnTheInside(this); + } +} + +class BiggerOnTheInsideEffect extends OneShotEffect { //Not a mana ability since it targets + + BiggerOnTheInsideEffect() { + super(Outcome.Benefit); + staticText = "Target player adds two mana of any one color. The next spell they cast this turn has cascade"; + } + + private BiggerOnTheInsideEffect(final BiggerOnTheInsideEffect effect) { + super(effect); + } + + @Override + public BiggerOnTheInsideEffect copy() { + return new BiggerOnTheInsideEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player == null) { + return false; + } + ContinuousEffect cascadeEffect = new NextSpellCastHasAbilityEffect(new CascadeAbility(), TargetController.SOURCE_TARGETS); + game.addEffect(cascadeEffect, source); + + ManaEffect manaEffect = new AddManaOfAnyColorEffect(2); + Mana manaToAdd = manaEffect.produceMana(game, source); + if (manaToAdd != null && manaToAdd.count() > 0) { + player.getManaPool().addMana(manaToAdd, game, source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BlatantThievery.java b/Mage.Sets/src/mage/cards/b/BlatantThievery.java index c619988e8f5..c2b6fe4723b 100644 --- a/Mage.Sets/src/mage/cards/b/BlatantThievery.java +++ b/Mage.Sets/src/mage/cards/b/BlatantThievery.java @@ -1,18 +1,12 @@ package mage.cards.b; -import mage.abilities.Ability; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -29,7 +23,7 @@ public final class BlatantThievery extends CardImpl { this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true) .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, gain control of target permanent that player controls")); - this.getSpellAbility().setTargetAdjuster(BlatantThieveryAdjuster.instance); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent())); } private BlatantThievery(final BlatantThievery card) { @@ -41,25 +35,3 @@ public final class BlatantThievery extends CardImpl { return new BlatantThievery(this); } } - -enum BlatantThieveryAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null || game.getBattlefield().count( - StaticFilters.FILTER_CONTROLLED_PERMANENT, - opponentId, ability, game - ) < 1) { - continue; - } - FilterPermanent filter = new FilterPermanent("Permanent controlled by " + opponent.getName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetPermanent targetPermanent = new TargetPermanent(filter); - ability.addTarget(targetPermanent); - } - } -} diff --git a/Mage.Sets/src/mage/cards/b/BronzebeakForagers.java b/Mage.Sets/src/mage/cards/b/BronzebeakForagers.java index a667d2c72f9..da804113374 100644 --- a/Mage.Sets/src/mage/cards/b/BronzebeakForagers.java +++ b/Mage.Sets/src/mage/cards/b/BronzebeakForagers.java @@ -1,6 +1,5 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -11,22 +10,22 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.Card; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ManaValuePredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.players.Player; -import mage.target.TargetPermanent; import mage.target.common.TargetCardInExile; +import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.EachTargetPointer; import mage.util.CardUtil; +import java.util.UUID; + /** * * @author jimga150 @@ -47,7 +46,7 @@ public final class BronzebeakForagers extends CardImpl { .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield") ); - etbAbility.setTargetAdjuster(BronzebeakForagerExileAdjuster.instance); + etbAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0, 1))); this.addAbility(etbAbility); // {X}{W}: Put target card with mana value X exiled with Bronzebeak Foragers into its owner's graveyard. @@ -72,26 +71,6 @@ public final class BronzebeakForagers extends CardImpl { } } -enum BronzebeakForagerExileAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterPermanent("nonland permanent controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(Predicates.not(CardType.LAND.getPredicate())); - TargetPermanent target = new TargetPermanent(0, 1, filter, false); - ability.addTarget(target); - } - } -} - // Based on Gelatinous Cube enum BronzebeakForagerDissolveAdjuster implements TargetAdjuster { instance; diff --git a/Mage.Sets/src/mage/cards/d/DecoyGambit.java b/Mage.Sets/src/mage/cards/d/DecoyGambit.java index 0736cdccef7..135434fe84d 100644 --- a/Mage.Sets/src/mage/cards/d/DecoyGambit.java +++ b/Mage.Sets/src/mage/cards/d/DecoyGambit.java @@ -9,15 +9,12 @@ import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import java.util.Collection; import java.util.List; @@ -36,7 +33,7 @@ public final class DecoyGambit extends CardImpl { // 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. this.getSpellAbility().addEffect(new DecoyGambitEffect()); - this.getSpellAbility().setTargetAdjuster(DecoyGambitAdjuster.instance); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); } private DecoyGambit(final DecoyGambit card) { @@ -49,26 +46,6 @@ public final class DecoyGambit extends CardImpl { } } -enum DecoyGambitAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - game.getOpponents(ability.getControllerId()) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .forEachOrdered(player -> { - FilterPermanent filter = new FilterCreaturePermanent( - "creature controlled by " + player.getName() - ); - filter.add(new ControllerIdPredicate(player.getId())); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - }); - } -} - class DecoyGambitEffect extends OneShotEffect { DecoyGambitEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DesecrateReality.java b/Mage.Sets/src/mage/cards/d/DesecrateReality.java index 4e5015d26c3..e92fb2e4388 100644 --- a/Mage.Sets/src/mage/cards/d/DesecrateReality.java +++ b/Mage.Sets/src/mage/cards/d/DesecrateReality.java @@ -13,16 +13,14 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.FilterCard; import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.mageobject.ManaValueParityPredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import mage.target.targetpointer.FixedTarget; @@ -33,6 +31,11 @@ import java.util.UUID; */ public final class DesecrateReality extends CardImpl { + private static final FilterPermanent evenFilter = new FilterPermanent("permanent with an even mana value"); + + static { + evenFilter.add(ManaValueParityPredicate.EVEN); + } public DesecrateReality(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{7}"); @@ -41,7 +44,7 @@ public final class DesecrateReality extends CardImpl { this.getSpellAbility().addEffect(new ExileTargetEffect() .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, exile up to one target permanent that player controls with an even mana value.")); - this.getSpellAbility().setTargetAdjuster(DesecrateRealityAdjuster.instance); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(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. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( @@ -62,36 +65,6 @@ public final class DesecrateReality extends CardImpl { } } -enum DesecrateRealityAdjuster implements TargetAdjuster { - instance; - - private static final FilterControlledPermanent filterCount = new FilterControlledPermanent(""); - - static { - filterCount.add(ManaValueParityPredicate.EVEN); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - - if (opponent == null || game.getBattlefield().count( - filterCount, - opponentId, ability, game - ) < 1) { - continue; - } - FilterPermanent filter = new FilterPermanent("permanent controlled by " + opponent.getName() + " with an even mana value."); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(ManaValueParityPredicate.EVEN); - TargetPermanent targetPermanent = new TargetPermanent(0, 1, filter); - ability.addTarget(targetPermanent); - } - } -} - class DesecrateRealityEffect extends OneShotEffect { private static final FilterCard filter diff --git a/Mage.Sets/src/mage/cards/d/DismantlingWave.java b/Mage.Sets/src/mage/cards/d/DismantlingWave.java index 76bfe9f0e73..4625feede73 100644 --- a/Mage.Sets/src/mage/cards/d/DismantlingWave.java +++ b/Mage.Sets/src/mage/cards/d/DismantlingWave.java @@ -1,6 +1,5 @@ package mage.cards.d; -import mage.abilities.Ability; import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DestroyAllEffect; @@ -9,16 +8,11 @@ import mage.abilities.keyword.CyclingAbility; 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.permanent.ControllerIdPredicate; -import mage.game.Game; import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; -import java.util.Objects; import java.util.UUID; /** @@ -33,7 +27,8 @@ public final class DismantlingWave extends CardImpl { 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); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster( + new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT))); // Cycling {6}{W}{W} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{6}{W}{W}"))); @@ -51,23 +46,3 @@ public final class DismantlingWave extends CardImpl { return new DismantlingWave(this); } } - -enum DismantlingWaveAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - game.getOpponents(ability.getControllerId()) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .forEachOrdered(player -> { - FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent( - "artifact or enchantment controlled by " + player.getName() - ); - filter.add(new ControllerIdPredicate(player.getId())); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - }); - } -} diff --git a/Mage.Sets/src/mage/cards/e/ElminstersSimulacrum.java b/Mage.Sets/src/mage/cards/e/ElminstersSimulacrum.java index f4147401d47..791a982ea3f 100644 --- a/Mage.Sets/src/mage/cards/e/ElminstersSimulacrum.java +++ b/Mage.Sets/src/mage/cards/e/ElminstersSimulacrum.java @@ -7,14 +7,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -29,7 +25,7 @@ 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. this.getSpellAbility().addEffect(new ElminstersSimulacrumAdjusterEffect()); - this.getSpellAbility().setTargetAdjuster(ElminstersSimulacrumAdjuster.instance); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); } private ElminstersSimulacrum(final ElminstersSimulacrum card) { @@ -42,24 +38,6 @@ public final class ElminstersSimulacrum extends CardImpl { } } -enum ElminstersSimulacrumAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - } -} - class ElminstersSimulacrumAdjusterEffect extends OneShotEffect { ElminstersSimulacrumAdjusterEffect() { diff --git a/Mage.Sets/src/mage/cards/e/EnigmaThief.java b/Mage.Sets/src/mage/cards/e/EnigmaThief.java index f6f0482af51..d67f142d888 100644 --- a/Mage.Sets/src/mage/cards/e/EnigmaThief.java +++ b/Mage.Sets/src/mage/cards/e/EnigmaThief.java @@ -10,13 +10,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -44,7 +39,7 @@ public final class EnigmaThief extends CardImpl { Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect() .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, return up to one target nonland permanent that player controls to its owner's hand")); - ability.setTargetAdjuster(EnigmaThiefAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0,1))); this.addAbility(ability); } @@ -58,20 +53,3 @@ public final class EnigmaThief extends CardImpl { } } -enum EnigmaThiefAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterNonlandPermanent("nonland permanent controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - } -} diff --git a/Mage.Sets/src/mage/cards/e/EverythingComesToDust.java b/Mage.Sets/src/mage/cards/e/EverythingComesToDust.java new file mode 100644 index 00000000000..85e501262a3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EverythingComesToDust.java @@ -0,0 +1,70 @@ +package mage.cards.e; + +import mage.MageObjectReference; +import mage.abilities.effects.common.ExileAllEffect; +import mage.abilities.keyword.ConvokeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +import java.util.HashSet; +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class EverythingComesToDust extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("creatures except those that share a creature type with a creature that convoked this spell, all artifacts, and all enchantments"); + + static { + filter.add(EverythingComesToDustPredicate.instance); + } + public EverythingComesToDust(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{W}{W}{W}"); + + // Convoke + this.addAbility(new ConvokeAbility()); + + // Exile all creatures except those that share a creature type with a creature that convoked this spell, all artifacts, and all enchantments. + this.getSpellAbility().addEffect(new ExileAllEffect(filter)); + } + + private EverythingComesToDust(final EverythingComesToDust card) { + super(card); + } + + @Override + public EverythingComesToDust copy() { + return new EverythingComesToDust(this); + } +} + +enum EverythingComesToDustPredicate implements ObjectSourcePlayerPredicate { + instance; + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Permanent p = input.getObject(); + if (p.isArtifact(game) || p.isEnchantment(game)){ + return true; + } + if (!p.isCreature(game)){ + return false; + } + HashSet set = CardUtil.getSourceCostsTag(game, input.getSource(), ConvokeAbility.convokingCreaturesKey, new HashSet<>(0)); + for (MageObjectReference mor : set){ + Permanent convoked = game.getPermanentOrLKIBattlefield(mor); + if (convoked.shareCreatureTypes(game, p)){ + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GraspOfFate.java b/Mage.Sets/src/mage/cards/g/GraspOfFate.java index 985edb6b32c..20e3cff70d2 100644 --- a/Mage.Sets/src/mage/cards/g/GraspOfFate.java +++ b/Mage.Sets/src/mage/cards/g/GraspOfFate.java @@ -6,13 +6,8 @@ import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -30,7 +25,7 @@ public final class GraspOfFate extends CardImpl { .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield") ); - ability.setTargetAdjuster(GraspOfFateAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0,1))); this.addAbility(ability); } @@ -43,23 +38,3 @@ public final class GraspOfFate extends CardImpl { return new GraspOfFate(this); } } - -enum GraspOfFateAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterPermanent("nonland permanent from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(Predicates.not(CardType.LAND.getPredicate())); - TargetPermanent target = new TargetPermanent(0, 1, filter, false); - ability.addTarget(target); - } - } -} diff --git a/Mage.Sets/src/mage/cards/h/HammersOfMoradin.java b/Mage.Sets/src/mage/cards/h/HammersOfMoradin.java index d666b42b2d8..ddab9134d70 100644 --- a/Mage.Sets/src/mage/cards/h/HammersOfMoradin.java +++ b/Mage.Sets/src/mage/cards/h/HammersOfMoradin.java @@ -1,7 +1,6 @@ package mage.cards.h; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.MyriadAbility; @@ -9,13 +8,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -41,7 +35,7 @@ public final class HammersOfMoradin extends CardImpl { new TapTargetEffect() .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, tap up to one target creature that player controls") - ).setTargetAdjuster(HammersOfMoradinAdjuster.instance)); + ).setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1)))); } private HammersOfMoradin(final HammersOfMoradin card) { @@ -53,22 +47,3 @@ public final class HammersOfMoradin extends CardImpl { return new HammersOfMoradin(this); } } - -enum HammersOfMoradinAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetPermanent target = new TargetPermanent(0, 1, filter); - ability.addTarget(target); - } - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/InTheDarknessBindThem.java b/Mage.Sets/src/mage/cards/i/InTheDarknessBindThem.java index 361c8081536..c890b6a5139 100644 --- a/Mage.Sets/src/mage/cards/i/InTheDarknessBindThem.java +++ b/Mage.Sets/src/mage/cards/i/InTheDarknessBindThem.java @@ -1,6 +1,5 @@ package mage.cards.i; -import mage.abilities.Ability; import mage.abilities.common.SagaAbility; import mage.abilities.effects.Effects; import mage.abilities.effects.common.CreateTokenEffect; @@ -15,14 +14,9 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SagaChapter; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; import mage.game.permanent.token.WraithToken; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -63,7 +57,7 @@ public final class InTheDarknessBindThem extends CardImpl { ability.addEffect(new TheRingTemptsYouEffect()); ability.getEffects().setTargetPointer(new EachTargetPointer()); - ability.setTargetAdjuster(InTheDarknessBindThemAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); } ); @@ -79,21 +73,3 @@ public final class InTheDarknessBindThem extends CardImpl { return new InTheDarknessBindThem(this); } } - -enum InTheDarknessBindThemAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player player = game.getPlayer(opponentId); - if (player == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + player.getName()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter)); - } - } -} diff --git a/Mage.Sets/src/mage/cards/j/JuvenileMistDragon.java b/Mage.Sets/src/mage/cards/j/JuvenileMistDragon.java index 222fb7207db..be08f005926 100644 --- a/Mage.Sets/src/mage/cards/j/JuvenileMistDragon.java +++ b/Mage.Sets/src/mage/cards/j/JuvenileMistDragon.java @@ -10,13 +10,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -47,7 +42,7 @@ public final class JuvenileMistDragon extends CardImpl { .setTargetPointer(new EachTargetPointer()) .setText("Each of those creatures doesn't untap during its controller's next untap step") ); - ability.setTargetAdjuster(JuvenileMistDragonAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.addAbility(ability.withFlavorWord("Confounding Clouds")); } @@ -60,22 +55,3 @@ public final class JuvenileMistDragon extends CardImpl { return new JuvenileMistDragon(this); } } - -enum JuvenileMistDragonAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetPermanent target = new TargetPermanent(0, 1, filter, false); - ability.addTarget(target); - } - } -} diff --git a/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java b/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java index f0e2304b9cc..3d4d1e50d63 100644 --- a/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java +++ b/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java @@ -11,15 +11,13 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import java.util.*; import java.util.stream.Collectors; @@ -42,7 +40,7 @@ public final class LuminatePrimordial extends CardImpl { // 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. Ability ability = new EntersBattlefieldTriggeredAbility(new LuminatePrimordialEffect(), false); - ability.setTargetAdjuster(LuminatePrimordialAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.addAbility(ability); } @@ -56,24 +54,6 @@ public final class LuminatePrimordial extends CardImpl { } } -enum LuminatePrimordialAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - } -} - class LuminatePrimordialEffect extends OneShotEffect { LuminatePrimordialEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MassMutiny.java b/Mage.Sets/src/mage/cards/m/MassMutiny.java index afad5d93d6a..a686ced3c0e 100644 --- a/Mage.Sets/src/mage/cards/m/MassMutiny.java +++ b/Mage.Sets/src/mage/cards/m/MassMutiny.java @@ -1,6 +1,5 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; @@ -12,16 +11,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** * * @author LevelX2 @@ -33,7 +31,7 @@ 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. this.getSpellAbility().addEffect(new MassMutinyEffect()); - this.getSpellAbility().setTargetAdjuster(MassMutinyAdjuster.instance); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); } private MassMutiny(final MassMutiny card) { @@ -46,24 +44,6 @@ public final class MassMutiny extends CardImpl { } } -enum MassMutinyAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - } -} - class MassMutinyEffect extends OneShotEffect { MassMutinyEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java b/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java index dbd48ca315a..026ec4f17b7 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java +++ b/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java @@ -15,14 +15,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -44,7 +41,7 @@ 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. Ability ability = new EntersBattlefieldTriggeredAbility(new MoltenPrimordialEffect(), false); - ability.setTargetAdjuster(MoltenPrimordialAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.addAbility(ability); } @@ -58,24 +55,6 @@ public final class MoltenPrimordial extends CardImpl { } } -enum MoltenPrimordialAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - } -} - class MoltenPrimordialEffect extends OneShotEffect { MoltenPrimordialEffect() { diff --git a/Mage.Sets/src/mage/cards/r/ReverseThePolarity.java b/Mage.Sets/src/mage/cards/r/ReverseThePolarity.java new file mode 100644 index 00000000000..e26c6857785 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/ReverseThePolarity.java @@ -0,0 +1,80 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.combat.CantBeBlockedAllEffect; +import mage.abilities.effects.common.continuous.SwitchPowerToughnessAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; + +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class ReverseThePolarity extends CardImpl { + + public ReverseThePolarity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); + + // Choose one -- + // * Counter all other spells. + this.getSpellAbility().addEffect(new ReverseThePolarityCounterAllEffect()); + // * Switch each creature's power and toughness until end of turn. + this.getSpellAbility().addMode(new Mode(new SwitchPowerToughnessAllEffect(Duration.EndOfTurn))); + // * Creatures can't be blocked this turn. + this.getSpellAbility().addMode(new Mode(new CantBeBlockedAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES, Duration.EndOfTurn))); + } + + private ReverseThePolarity(final ReverseThePolarity card) { + super(card); + } + + @Override + public ReverseThePolarity copy() { + return new ReverseThePolarity(this); + } +} +//Based on Counterflux/Swift Silence +class ReverseThePolarityCounterAllEffect extends OneShotEffect { + + ReverseThePolarityCounterAllEffect() { + super(Outcome.Detriment); + staticText = "Counter all other spells."; + } + + private ReverseThePolarityCounterAllEffect(final ReverseThePolarityCounterAllEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + List spellsToCounter = new LinkedList<>(); + for (StackObject stackObject : game.getStack()) { + if (stackObject instanceof Spell && !stackObject.getId().equals(source.getSourceObject(game).getId())) { + spellsToCounter.add((Spell) stackObject); + } + } + for (Spell spell : spellsToCounter) { + game.getStack().counter(spell.getId(), source, game); + } + return true; + } + + @Override + public ReverseThePolarityCounterAllEffect copy() { + return new ReverseThePolarityCounterAllEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SontaranGeneral.java b/Mage.Sets/src/mage/cards/s/SontaranGeneral.java new file mode 100644 index 00000000000..7bf0867ba46 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SontaranGeneral.java @@ -0,0 +1,57 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.abilities.effects.common.combat.GoadTargetEffect; +import mage.abilities.keyword.BattalionAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class SontaranGeneral extends CardImpl { + + public SontaranGeneral(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); + this.subtype.add(SubType.ALIEN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Battalion -- Whenever Sontaran General and at least two other creatures attack, for each opponent, + // goad up to one target creature that player controls. Those creatures can't block this turn. + Ability ability = new BattalionAbility(new GoadTargetEffect() + .setText("for each opponent, goad up to one target creature that player controls.")); + ability.addEffect(new CantBlockTargetEffect(Duration.EndOfTurn) + .setText("Those creatures can't block this turn.")); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0, 1))); + this.addAbility(ability); + } + + private SontaranGeneral(final SontaranGeneral card) { + super(card); + } + + @Override + public SontaranGeneral copy() { + return new SontaranGeneral(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java b/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java index 2cdf67038a1..5068a9c92a1 100644 --- a/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java +++ b/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java @@ -15,14 +15,12 @@ import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterLandCard; import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import java.util.UUID; @@ -31,6 +29,11 @@ import java.util.UUID; */ public final class SylvanPrimordial extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("noncreature permanent"); + + static { + filter.add(Predicates.not(CardType.CREATURE.getPredicate())); + } public SylvanPrimordial(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); this.subtype.add(SubType.AVATAR); @@ -43,7 +46,7 @@ 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. Ability ability = new EntersBattlefieldTriggeredAbility(new SylvanPrimordialEffect(), false); - ability.setTargetAdjuster(SylvanPrimordialAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(filter))); this.addAbility(ability); } @@ -57,25 +60,6 @@ public final class SylvanPrimordial extends CardImpl { } } -enum SylvanPrimordialAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterPermanent filter = new FilterPermanent("noncreature permanent from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(Predicates.not(CardType.CREATURE.getPredicate())); - TargetPermanent target = new TargetPermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - } -} - class SylvanPrimordialEffect extends OneShotEffect { private static final FilterLandCard filterForest = new FilterLandCard("Forest"); diff --git a/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java b/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java index 8eff4f25d7c..56429d94364 100644 --- a/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java +++ b/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java @@ -1,20 +1,15 @@ package mage.cards.t; -import mage.abilities.Ability; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Duration; -import mage.filter.FilterPermanent; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -23,7 +18,11 @@ import java.util.UUID; * @author TheElk801 */ public final class TemptedByTheOriq extends CardImpl { + private static final FilterCreatureOrPlaneswalkerPermanent filter = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker with mana value 3 or less"); + static { + filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3)); + } public TemptedByTheOriq(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}{U}"); @@ -32,7 +31,7 @@ public final class TemptedByTheOriq extends CardImpl { .setTargetPointer(new EachTargetPointer()) .setText("for each opponent, gain control of up to one target creature " + "or planeswalker that player controls with mana value 3 or less")); - this.getSpellAbility().setTargetAdjuster(TemptedByTheOriqAdjuster.instance); + this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, filter))); } private TemptedByTheOriq(final TemptedByTheOriq card) { @@ -44,24 +43,3 @@ public final class TemptedByTheOriq extends CardImpl { return new TemptedByTheOriq(this); } } - -enum TemptedByTheOriqAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent( - "creature or planeswalker " + opponent.getName() + " controls with mana value 3 or less" - ); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - } -} diff --git a/Mage.Sets/src/mage/cards/t/TheBalrogOfMoria.java b/Mage.Sets/src/mage/cards/t/TheBalrogOfMoria.java index f977cb1cded..ed6097f131a 100644 --- a/Mage.Sets/src/mage/cards/t/TheBalrogOfMoria.java +++ b/Mage.Sets/src/mage/cards/t/TheBalrogOfMoria.java @@ -1,7 +1,6 @@ package mage.cards.t; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; @@ -18,14 +17,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; import mage.game.permanent.token.TreasureToken; -import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -57,7 +51,7 @@ public final class TheBalrogOfMoria extends CardImpl { .setText("for each opponent, exile up to one target creature that player controls."), false ); - reflexiveAbility.setTargetAdjuster(TheBalrogOfMoriaAdjuster.instance); + reflexiveAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreaturePermanent(0,1))); this.addAbility(new DiesSourceTriggeredAbility( new DoWhenCostPaid( @@ -83,21 +77,3 @@ public final class TheBalrogOfMoria extends CardImpl { return new TheBalrogOfMoria(this); } } - -enum TheBalrogOfMoriaAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - } -} diff --git a/Mage.Sets/src/mage/cards/t/TheHorusHeresy.java b/Mage.Sets/src/mage/cards/t/TheHorusHeresy.java index f8ce4d1471b..cb67f709700 100644 --- a/Mage.Sets/src/mage/cards/t/TheHorusHeresy.java +++ b/Mage.Sets/src/mage/cards/t/TheHorusHeresy.java @@ -17,13 +17,12 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.HashSet; @@ -37,9 +36,11 @@ public final class TheHorusHeresy extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature you control but don't own"); + private static final FilterCreaturePermanent filterNonlegendary = new FilterCreaturePermanent("nonlegendary creature"); static { filter.add(TargetController.NOT_YOU.getOwnerPredicate()); + filterNonlegendary.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); } private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, 1); @@ -56,7 +57,7 @@ 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. sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, ability -> { ability.addEffect(new TheHorusHeresyControlEffect()); - ability.setTargetAdjuster(TheHorusHeresyAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, filterNonlegendary))); }); // II -- Draw a card for each creature you control but don't own. @@ -77,25 +78,6 @@ public final class TheHorusHeresy extends CardImpl { } } -enum TheHorusHeresyAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player player = game.getPlayer(opponentId); - if (player == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent("nonlegendary creature controlled by " + player.getName()); - filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter)); - } - } -} - class TheHorusHeresyControlEffect extends GainControlTargetEffect { TheHorusHeresyControlEffect() { diff --git a/Mage.Sets/src/mage/cards/t/TheTrueScriptures.java b/Mage.Sets/src/mage/cards/t/TheTrueScriptures.java index eee0ca95a36..ba9d9d4d127 100644 --- a/Mage.Sets/src/mage/cards/t/TheTrueScriptures.java +++ b/Mage.Sets/src/mage/cards/t/TheTrueScriptures.java @@ -13,14 +13,11 @@ import mage.cards.CardSetInfo; import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.*; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.players.Player; -import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.Collection; @@ -49,7 +46,7 @@ public final class TheTrueScriptures extends CardImpl { ability -> { ability.addEffect(new DestroyTargetEffect().setTargetPointer(new EachTargetPointer()) .setText("for each opponent, destroy up to one target creature or planeswalker that player controls")); - ability.setTargetAdjuster(TheTrueScripturesAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetCreatureOrPlaneswalker(0,1))); } ); @@ -79,29 +76,6 @@ public final class TheTrueScriptures extends CardImpl { } } -enum TheTrueScripturesAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID playerId : game.getOpponents(ability.getControllerId())) { - Player player = game.getPlayer(playerId); - if (player == null) { - continue; - } - FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent( - "creature or planeswalker controlled by " + player.getName() - ); - filter.add(new ControllerIdPredicate(playerId)); - if (game.getBattlefield().count(filter, ability.getControllerId(), ability, game) == 0) { - continue; - } - ability.addTarget(new TargetPermanent(0, 1, filter)); - } - } -} - class TheTrueScripturesEffect extends OneShotEffect { TheTrueScripturesEffect() { diff --git a/Mage.Sets/src/mage/cards/t/TolarianContempt.java b/Mage.Sets/src/mage/cards/t/TolarianContempt.java index 90f825ad1fe..b54ced1aa85 100644 --- a/Mage.Sets/src/mage/cards/t/TolarianContempt.java +++ b/Mage.Sets/src/mage/cards/t/TolarianContempt.java @@ -14,12 +14,11 @@ import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterOpponentsCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -31,6 +30,12 @@ public final class TolarianContempt extends CardImpl { private static final FilterPermanent filter = new FilterOpponentsCreaturePermanent("creature your opponents control"); + private static final FilterPermanent filterRejection + = new FilterCreaturePermanent("creature with a rejection counter on it"); + + static { + filter.add(CounterType.REJECTION.getPredicate()); + } public TolarianContempt(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}"); @@ -43,7 +48,7 @@ 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. this.addAbility(new BeginningOfEndStepTriggeredAbility( new TolarianContemptEffect(), TargetController.YOU, false - ).setTargetAdjuster(TolarianContemptAdjuster.instance)); + ).setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0,1, filterRejection)))); } private TolarianContempt(final TolarianContempt card) { @@ -56,27 +61,6 @@ public final class TolarianContempt extends CardImpl { } } -enum TolarianContemptAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterCreaturePermanent( - "creature controlled by " + opponent.getName() + " with a rejection counter on it" - ); - filter.add(CounterType.REJECTION.getPredicate()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter)); - } - } -} - class TolarianContemptEffect extends OneShotEffect { TolarianContemptEffect() { diff --git a/Mage.Sets/src/mage/cards/v/VronosMaskedInquisitor.java b/Mage.Sets/src/mage/cards/v/VronosMaskedInquisitor.java index 5ce41e937d5..1eb650eae34 100644 --- a/Mage.Sets/src/mage/cards/v/VronosMaskedInquisitor.java +++ b/Mage.Sets/src/mage/cards/v/VronosMaskedInquisitor.java @@ -1,6 +1,5 @@ package mage.cards.v; -import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; @@ -19,17 +18,13 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPlaneswalkerPermanent; -import mage.filter.common.FilterNonlandPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; import mage.game.permanent.token.custom.CreatureToken; -import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -61,7 +56,7 @@ 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. 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); - ability2.setTargetAdjuster(VronosMaskedInquisitorAdjuster.instance); + ability2.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0,1))); 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." @@ -86,21 +81,3 @@ public final class VronosMaskedInquisitor extends CardImpl { return new VronosMaskedInquisitor(this); } } - -enum VronosMaskedInquisitorAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterNonlandPermanent("nonland permanent controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - } -} diff --git a/Mage.Sets/src/mage/cards/w/WelcomeTo.java b/Mage.Sets/src/mage/cards/w/WelcomeTo.java index 0cefaca1fc2..ac854728ea1 100644 --- a/Mage.Sets/src/mage/cards/w/WelcomeTo.java +++ b/Mage.Sets/src/mage/cards/w/WelcomeTo.java @@ -17,13 +17,11 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.token.DinosaurToken; import mage.game.permanent.token.custom.CreatureToken; -import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster; import mage.target.targetpointer.EachTargetPointer; import mage.target.targetpointer.FixedTarget; @@ -36,9 +34,12 @@ import java.util.UUID; public final class WelcomeTo extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("Walls"); + private static final FilterPermanent filterNoncreatureArtifact = new FilterPermanent("noncreature artifact"); static { filter.add(SubType.WALL.getPredicate()); + filterNoncreatureArtifact.add(Predicates.not(CardType.CREATURE.getPredicate())); + filterNoncreatureArtifact.add(CardType.ARTIFACT.getPredicate()); } // Based on Azusa's Many Journeys // Likeness of the Seeker, Vronos Masked Inquisitor, In the Darkness Bind Then, @@ -62,7 +63,7 @@ public final class WelcomeTo extends CardImpl { ).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.")); ability.getEffects().setTargetPointer(new EachTargetPointer()); - ability.setTargetAdjuster(WelcomeToAdjuster.instance); + ability.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent(0, 1, filterNoncreatureArtifact))); }); // II -- Create a 3/3 green Dinosaur creature token with trample. It gains haste until end of turn. @@ -89,28 +90,6 @@ public final class WelcomeTo extends CardImpl { } } -// Based on Vronos, Masked Inquisitor -enum WelcomeToAdjuster implements TargetAdjuster { - instance; - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent == null) { - continue; - } - FilterPermanent filter = new FilterPermanent( - "noncreature artifact controlled by " + opponent.getLogName()); - filter.add(Predicates.not(CardType.CREATURE.getPredicate())); - filter.add(CardType.ARTIFACT.getPredicate()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - } -} - // Based on Mordor on the March class WelcomeToEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/sets/DoctorWho.java b/Mage.Sets/src/mage/sets/DoctorWho.java index 5abcb0108f7..1086951d4d1 100644 --- a/Mage.Sets/src/mage/sets/DoctorWho.java +++ b/Mage.Sets/src/mage/sets/DoctorWho.java @@ -36,6 +36,7 @@ public final class DoctorWho extends ExpansionSet { cards.add(new SetCardInfo("Beast Within", 228, Rarity.UNCOMMON, mage.cards.b.BeastWithin.class)); cards.add(new SetCardInfo("Become the Pilot", 37, Rarity.RARE, mage.cards.b.BecomeThePilot.class)); cards.add(new SetCardInfo("Bessie, the Doctor's Roadster", 171, Rarity.RARE, mage.cards.b.BessieTheDoctorsRoadster.class)); + cards.add(new SetCardInfo("Bigger on the Inside", 115, Rarity.UNCOMMON, mage.cards.b.BiggerOnTheInside.class)); cards.add(new SetCardInfo("Blasphemous Act", 224, Rarity.RARE, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Canopy Vista", 258, Rarity.RARE, mage.cards.c.CanopyVista.class)); cards.add(new SetCardInfo("Canyon Slough", 259, Rarity.RARE, mage.cards.c.CanyonSlough.class)); @@ -82,6 +83,7 @@ public final class DoctorWho extends ExpansionSet { cards.add(new SetCardInfo("Duggan, Private Detective", 728, Rarity.RARE, mage.cards.d.DugganPrivateDetective.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Duggan, Private Detective", 1000, Rarity.RARE, mage.cards.d.DugganPrivateDetective.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ecstatic Beauty", 83, Rarity.RARE, mage.cards.e.EcstaticBeauty.class)); + cards.add(new SetCardInfo("Everything Comes to Dust", 19, Rarity.RARE, mage.cards.e.EverythingComesToDust.class)); cards.add(new SetCardInfo("Evolving Wilds", 275, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); cards.add(new SetCardInfo("Exotic Orchard", 276, Rarity.RARE, mage.cards.e.ExoticOrchard.class)); cards.add(new SetCardInfo("Explore", 231, Rarity.COMMON, mage.cards.e.Explore.class)); @@ -167,6 +169,7 @@ public final class DoctorWho extends ExpansionSet { cards.add(new SetCardInfo("Reliquary Tower", 296, Rarity.UNCOMMON, mage.cards.r.ReliquaryTower.class)); cards.add(new SetCardInfo("Renegade Silent", 53, Rarity.UNCOMMON, mage.cards.r.RenegadeSilent.class)); cards.add(new SetCardInfo("Return to Dust", 211, Rarity.UNCOMMON, mage.cards.r.ReturnToDust.class)); + cards.add(new SetCardInfo("Reverse the Polarity", 54, Rarity.RARE, mage.cards.r.ReverseThePolarity.class)); cards.add(new SetCardInfo("River of Tears", 297, Rarity.RARE, mage.cards.r.RiverOfTears.class)); cards.add(new SetCardInfo("Rockfall Vale", 298, Rarity.RARE, mage.cards.r.RockfallVale.class)); cards.add(new SetCardInfo("Rogue's Passage", 299, Rarity.UNCOMMON, mage.cards.r.RoguesPassage.class)); @@ -194,6 +197,7 @@ public final class DoctorWho extends ExpansionSet { cards.add(new SetCardInfo("Sol Ring", 245, Rarity.UNCOMMON, mage.cards.s.SolRing.class)); cards.add(new SetCardInfo("Solemn Simulacrum", 246, Rarity.RARE, mage.cards.s.SolemnSimulacrum.class)); cards.add(new SetCardInfo("Sonic Screwdriver", 184, Rarity.UNCOMMON, mage.cards.s.SonicScrewdriver.class)); + cards.add(new SetCardInfo("Sontaran General", 96, Rarity.UNCOMMON, mage.cards.s.SontaranGeneral.class)); cards.add(new SetCardInfo("Star Whale", 55, Rarity.UNCOMMON, mage.cards.s.StarWhale.class)); cards.add(new SetCardInfo("Start the TARDIS", 56, Rarity.UNCOMMON, mage.cards.s.StartTheTARDIS.class)); cards.add(new SetCardInfo("Stormcarved Coast", 308, Rarity.RARE, mage.cards.s.StormcarvedCoast.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/NextSpellCastHasAbilityEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/NextSpellCastHasAbilityEffect.java index 8908bef6d6b..d9ccbc25cca 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/NextSpellCastHasAbilityEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/NextSpellCastHasAbilityEffect.java @@ -13,6 +13,8 @@ import mage.players.Player; import mage.util.CardUtil; import mage.watchers.common.SpellsCastWatcher; +import java.util.UUID; + /** * @author xenohedron */ @@ -21,17 +23,25 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl { private int spellsCast; private final Ability ability; private final FilterCard filter; + private final TargetController targetController; public NextSpellCastHasAbilityEffect(Ability ability) { this(ability, StaticFilters.FILTER_CARD); } - public NextSpellCastHasAbilityEffect(Ability ability, FilterCard filter) { + this(ability, StaticFilters.FILTER_CARD, TargetController.SOURCE_CONTROLLER); + } + public NextSpellCastHasAbilityEffect(Ability ability, TargetController targetController) { + this(ability, StaticFilters.FILTER_CARD, targetController); + } + public NextSpellCastHasAbilityEffect(Ability ability, FilterCard filter, TargetController targetController) { super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.ability = ability; this.filter = filter; + this.targetController = targetController; staticText = "the next " + filter.getMessage().replace("card", "spell") - + " you cast this turn has " + CardUtil.getTextWithFirstCharLowerCase(CardUtil.stripReminderText(ability.getRule())); + + (targetController == TargetController.SOURCE_CONTROLLER ? " you cast" : " target player casts") + + " this turn has " + CardUtil.getTextWithFirstCharLowerCase(CardUtil.stripReminderText(ability.getRule())); } private NextSpellCastHasAbilityEffect(final NextSpellCastHasAbilityEffect effect) { @@ -39,6 +49,7 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl { this.spellsCast = effect.spellsCast; this.ability = effect.ability; this.filter = effect.filter; + this.targetController = effect.targetController; } @Override @@ -57,17 +68,28 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); + UUID playerId; + switch (targetController){ + case SOURCE_TARGETS: + playerId = source.getFirstTarget(); + break; + case SOURCE_CONTROLLER: + playerId = source.getControllerId(); + break; + default: + throw new UnsupportedOperationException("Value for targetController in NextSpellCastHasAbilityEffect not supported: " + targetController); + } + Player player = game.getPlayer(playerId); SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (player == null || watcher == null) { return false; } //check if a spell was cast before - if (watcher.getCount(source.getControllerId()) > spellsCast) { + if (watcher.getCount(playerId) > spellsCast) { discard(); // only one use return false; } - for (Card card : game.getExile().getAllCardsByRange(game, source.getControllerId())) { + for (Card card : game.getExile().getAllCardsByRange(game, playerId)) { if (filter.match(card, game)) { game.getState().addOtherAbility(card, ability); } @@ -94,7 +116,7 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl { .forEach(card -> game.getState().addOtherAbility(card, ability)); for (StackObject stackObject : game.getStack()) { - if (!(stackObject instanceof Spell) || !stackObject.isControlledBy(source.getControllerId())) { + if (!(stackObject instanceof Spell) || !stackObject.isControlledBy(playerId)) { continue; } // TODO: Distinguish "you cast" to exclude copies diff --git a/Mage/src/main/java/mage/target/targetadjustment/EachOpponentPermanentTargetsAdjuster.java b/Mage/src/main/java/mage/target/targetadjustment/EachOpponentPermanentTargetsAdjuster.java new file mode 100644 index 00000000000..e4260892c34 --- /dev/null +++ b/Mage/src/main/java/mage/target/targetadjustment/EachOpponentPermanentTargetsAdjuster.java @@ -0,0 +1,48 @@ +package mage.target.targetadjustment; + +import mage.abilities.Ability; +import mage.filter.Filter; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public class EachOpponentPermanentTargetsAdjuster implements TargetAdjuster { + private final TargetPermanent blueprintTarget; + + /** + * Duplicates the permanent target for each opponent. + * Filtering of permanent's controllers will be handled inside, so + * 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) { + this.blueprintTarget = blueprintTarget.copy(); //Defensively copy the blueprint to ensure immutability + } + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent == null) { + continue; + } + TargetPermanent newTarget = blueprintTarget.copy(); + Filter filter = newTarget.getFilter(); + filter.add(new ControllerIdPredicate(opponentId)); + if (newTarget.canChoose(ability.getControllerId(), ability, game)) { + filter.setMessage(filter.getMessage()+" controlled by " + opponent.getLogName()); + ability.addTarget(newTarget); + } + } + } +} diff --git a/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java b/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java index 20904454459..31a3ffee340 100644 --- a/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java +++ b/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java @@ -11,5 +11,6 @@ import java.io.Serializable; @FunctionalInterface public interface TargetAdjuster extends Serializable { + // Warning: This is not Copyable, do not use changeable data inside (only use static objects like Filter) void adjustTargets(Ability ability, Game game); }