diff --git a/Mage.Sets/src/mage/cards/a/Afterlife.java b/Mage.Sets/src/mage/cards/a/Afterlife.java index 8a22501935e..c42353d06a2 100644 --- a/Mage.Sets/src/mage/cards/a/Afterlife.java +++ b/Mage.Sets/src/mage/cards/a/Afterlife.java @@ -1,6 +1,6 @@ package mage.cards.a; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,7 +11,6 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author Backfir3 */ public final class Afterlife extends CardImpl { @@ -23,7 +22,7 @@ public final class Afterlife extends CardImpl { // 1/1 white Spirit creature token with flying. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new SpiritWhiteToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new SpiritWhiteToken())); } private Afterlife(final Afterlife card) { diff --git a/Mage.Sets/src/mage/cards/a/AnOfferYouCantRefuse.java b/Mage.Sets/src/mage/cards/a/AnOfferYouCantRefuse.java index 37ee35918ea..8bba15096f8 100644 --- a/Mage.Sets/src/mage/cards/a/AnOfferYouCantRefuse.java +++ b/Mage.Sets/src/mage/cards/a/AnOfferYouCantRefuse.java @@ -1,15 +1,12 @@ package mage.cards.a; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.filter.StaticFilters; -import mage.game.Game; import mage.game.permanent.token.TreasureToken; -import mage.game.stack.Spell; import mage.target.TargetSpell; import java.util.UUID; @@ -23,7 +20,10 @@ public final class AnOfferYouCantRefuse extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Counter target noncreature spell. Its controller creates two Treasure tokens. - this.getSpellAbility().addEffect(new AnOfferYouCantRefuseEffect()); + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect( + new TreasureToken(), 2, false, CreateTokenControllerTargetEffect.TargetKind.SPELL + )); this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_NON_CREATURE)); } @@ -35,32 +35,4 @@ public final class AnOfferYouCantRefuse extends CardImpl { public AnOfferYouCantRefuse copy() { return new AnOfferYouCantRefuse(this); } -} - -class AnOfferYouCantRefuseEffect extends OneShotEffect { - - AnOfferYouCantRefuseEffect() { - super(Outcome.Benefit); - staticText = "counter target noncreature spell. Its controller creates two Treasure tokens"; - } - - private AnOfferYouCantRefuseEffect(final AnOfferYouCantRefuseEffect effect) { - super(effect); - } - - @Override - public AnOfferYouCantRefuseEffect copy() { - return new AnOfferYouCantRefuseEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Spell spell = game.getSpell(getTargetPointer().getFirst(game, source)); - if (spell == null) { - return false; - } - game.getStack().counter(spell.getId(), source, game);; - new TreasureToken().putOntoBattlefield(2, game, source, spell.getControllerId()); - return true; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AngelicAscension.java b/Mage.Sets/src/mage/cards/a/AngelicAscension.java index d7daae4e405..a99075ed26c 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicAscension.java +++ b/Mage.Sets/src/mage/cards/a/AngelicAscension.java @@ -1,6 +1,6 @@ package mage.cards.a; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ public final class AngelicAscension extends CardImpl { // Exile target creature or planeswalker. Its controller creates a 4/4 white Angel creature token with flying. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new AngelToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new AngelToken())); this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker()); } diff --git a/Mage.Sets/src/mage/cards/b/BeastWithin.java b/Mage.Sets/src/mage/cards/b/BeastWithin.java index 375b0b29d48..522002a7157 100644 --- a/Mage.Sets/src/mage/cards/b/BeastWithin.java +++ b/Mage.Sets/src/mage/cards/b/BeastWithin.java @@ -1,6 +1,6 @@ package mage.cards.b; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +21,7 @@ public final class BeastWithin extends CardImpl { // Destroy target permanent. Its controller creates a 3/3 green Beast creature token. this.getSpellAbility().addTarget(new TargetPermanent()); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new BeastToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new BeastToken())); } private BeastWithin(final BeastWithin card) { diff --git a/Mage.Sets/src/mage/cards/b/BovineIntervention.java b/Mage.Sets/src/mage/cards/b/BovineIntervention.java index d51271e1e9b..dadd23f2e86 100644 --- a/Mage.Sets/src/mage/cards/b/BovineIntervention.java +++ b/Mage.Sets/src/mage/cards/b/BovineIntervention.java @@ -1,6 +1,6 @@ package mage.cards.b; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -22,7 +22,7 @@ public final class BovineIntervention extends CardImpl { // Destroy target artifact or creature. Its controller creates a 2/2 white Ox creature token. this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new Ox22Token())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new Ox22Token())); } private BovineIntervention(final BovineIntervention card) { diff --git a/Mage.Sets/src/mage/cards/b/BuyYourSilence.java b/Mage.Sets/src/mage/cards/b/BuyYourSilence.java index 5a0d1b44a0b..fcae2266d01 100644 --- a/Mage.Sets/src/mage/cards/b/BuyYourSilence.java +++ b/Mage.Sets/src/mage/cards/b/BuyYourSilence.java @@ -1,6 +1,6 @@ package mage.cards.b; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ public final class BuyYourSilence extends CardImpl { // Exile target nonland permanent. Its controller creates a Treasure token. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new TreasureToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new TreasureToken())); this.getSpellAbility().addTarget(new TargetNonlandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java b/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java index 4f0de762380..c11f905fe5e 100644 --- a/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java +++ b/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.VigilanceAbility; @@ -41,7 +41,7 @@ public final class CavalierOfDawn extends CardImpl { // When Cavalier of Dawn enters the battlefield, destroy up to one target nonland permanent. Its controller creates a 3/3 colorless Golem artifact creature token. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability.addEffect(new CreateTokenControllerTargetPermanentEffect(new GolemToken())); + ability.addEffect(new CreateTokenControllerTargetEffect(new GolemToken())); ability.addTarget(new TargetNonlandPermanent(0, 1, false)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CityscapeLeveler.java b/Mage.Sets/src/mage/cards/c/CityscapeLeveler.java index 4bf871910d1..0920ecc99c7 100644 --- a/Mage.Sets/src/mage/cards/c/CityscapeLeveler.java +++ b/Mage.Sets/src/mage/cards/c/CityscapeLeveler.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.UnearthAbility; @@ -21,7 +21,6 @@ import mage.target.common.TargetNonlandPermanent; import java.util.UUID; /** - * * @author weirddan455 */ public final class CityscapeLeveler extends CardImpl { @@ -38,7 +37,7 @@ public final class CityscapeLeveler extends CardImpl { // When you cast this spell and whenever Cityscape Leveler attacks, destroy up to one target nonland permanent. Its controller creates a tapped Powerstone token. Ability ability = new CityscapeLevelerAbility(); - ability.addEffect(new CreateTokenControllerTargetPermanentEffect(new PowerstoneToken(), 1, true)); + ability.addEffect(new CreateTokenControllerTargetEffect(new PowerstoneToken(), 1, true)); ability.addTarget(new TargetNonlandPermanent(0, 1)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CommanderSofiaDaguerre.java b/Mage.Sets/src/mage/cards/c/CommanderSofiaDaguerre.java index c9068c50703..dab93d77ff8 100644 --- a/Mage.Sets/src/mage/cards/c/CommanderSofiaDaguerre.java +++ b/Mage.Sets/src/mage/cards/c/CommanderSofiaDaguerre.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.constants.SubType; import mage.constants.SuperType; @@ -43,7 +43,7 @@ public final class CommanderSofiaDaguerre extends CardImpl { // Crash Landing -- When Commander Sofia Daguerre enters the battlefield, // destroy up to one target legendary permanent. That permanent's controller creates a Junk token. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability.addEffect(new CreateTokenControllerTargetPermanentEffect(new JunkToken()) + ability.addEffect(new CreateTokenControllerTargetEffect(new JunkToken()) .setText("that permanent's controller creates a Junk token")); ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability.withFlavorWord("Crash Landing")); diff --git a/Mage.Sets/src/mage/cards/c/CribSwap.java b/Mage.Sets/src/mage/cards/c/CribSwap.java index 3c8bfe176c4..cb605543bd7 100644 --- a/Mage.Sets/src/mage/cards/c/CribSwap.java +++ b/Mage.Sets/src/mage/cards/c/CribSwap.java @@ -1,7 +1,7 @@ package mage.cards.c; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; @@ -14,7 +14,6 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author LevelX2 */ public final class CribSwap extends CardImpl { @@ -27,7 +26,7 @@ public final class CribSwap extends CardImpl { this.addAbility(new ChangelingAbility()); // Exile target creature. Its controller creates a 1/1 colorless Shapeshifter creature token with changeling. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new CribSwapShapeshifterWhiteToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new CribSwapShapeshifterWhiteToken())); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java b/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java index 68a6c79e46f..2b7f676589a 100644 --- a/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java +++ b/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java @@ -6,7 +6,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class GallowsAtWillowHill extends CardImpl { // {3}, {tap}, Tap three untapped Humans you control: Destroy target creature. Its controller creates a 1/1 white Spirit creature token with flying. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new GenericManaCost(3)); - ability.addEffect(new CreateTokenControllerTargetPermanentEffect(new SpiritWhiteToken())); + ability.addEffect(new CreateTokenControllerTargetEffect(new SpiritWhiteToken())); ability.addCost(new TapSourceCost()); ability.addCost(new TapTargetCost(new TargetControlledPermanent(3, 3, humanFilter, false))); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/g/GenerousGift.java b/Mage.Sets/src/mage/cards/g/GenerousGift.java index 2cc56d5068b..61a6acec94a 100644 --- a/Mage.Sets/src/mage/cards/g/GenerousGift.java +++ b/Mage.Sets/src/mage/cards/g/GenerousGift.java @@ -1,6 +1,6 @@ package mage.cards.g; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ public final class GenerousGift extends CardImpl { // Destroy target permanent. Its controller creates a 3/3 green Elephant creature token. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new ElephantToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new ElephantToken())); this.getSpellAbility().addTarget(new TargetPermanent()); } diff --git a/Mage.Sets/src/mage/cards/g/GetLost.java b/Mage.Sets/src/mage/cards/g/GetLost.java index 35333bd2e07..220c5ea43b9 100644 --- a/Mage.Sets/src/mage/cards/g/GetLost.java +++ b/Mage.Sets/src/mage/cards/g/GetLost.java @@ -1,6 +1,6 @@ package mage.cards.g; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,7 +32,7 @@ public final class GetLost extends CardImpl { // Destroy target creature, enchantment, or planeswalker. Its controller creates two Map tokens. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new MapToken(), 2, false)); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new MapToken(), 2, false)); this.getSpellAbility().addTarget(new TargetPermanent(filter)); } diff --git a/Mage.Sets/src/mage/cards/p/Pongify.java b/Mage.Sets/src/mage/cards/p/Pongify.java index 0517107f8cd..c9f484c05a8 100644 --- a/Mage.Sets/src/mage/cards/p/Pongify.java +++ b/Mage.Sets/src/mage/cards/p/Pongify.java @@ -1,7 +1,7 @@ package mage.cards.p; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,7 +12,6 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author dustinconrad */ public final class Pongify extends CardImpl { @@ -22,7 +21,7 @@ public final class Pongify extends CardImpl { // Destroy target creature. It can't be regenerated. That creature's controller creates a 3/3 green Ape creature token. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new ApeToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new ApeToken())); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/r/Ravenform.java b/Mage.Sets/src/mage/cards/r/Ravenform.java index 65628c3c304..a2ab3415d5e 100644 --- a/Mage.Sets/src/mage/cards/r/Ravenform.java +++ b/Mage.Sets/src/mage/cards/r/Ravenform.java @@ -1,6 +1,6 @@ package mage.cards.r; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.ForetellAbility; import mage.cards.CardImpl; @@ -22,7 +22,7 @@ public final class Ravenform extends CardImpl { // Exile target artifact or creature. Its controller creates a 1/1 blue Bird creature token with flying. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new BlueBirdToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new BlueBirdToken())); this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE)); // Foretell {U} diff --git a/Mage.Sets/src/mage/cards/r/ReduceToMemory.java b/Mage.Sets/src/mage/cards/r/ReduceToMemory.java index 58e2c2222f9..8cf93966b55 100644 --- a/Mage.Sets/src/mage/cards/r/ReduceToMemory.java +++ b/Mage.Sets/src/mage/cards/r/ReduceToMemory.java @@ -1,6 +1,6 @@ package mage.cards.r; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -23,7 +23,7 @@ public final class ReduceToMemory extends CardImpl { // Exile target nonland permanent. Its controller creates a 3/2 red and white spirit creature token. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new Spirit32Token())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new Spirit32Token())); this.getSpellAbility().addTarget(new TargetNonlandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/r/Resculpt.java b/Mage.Sets/src/mage/cards/r/Resculpt.java index bfe25cdf02d..8fbc42e76de 100644 --- a/Mage.Sets/src/mage/cards/r/Resculpt.java +++ b/Mage.Sets/src/mage/cards/r/Resculpt.java @@ -1,6 +1,6 @@ package mage.cards.r; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +21,7 @@ public final class Resculpt extends CardImpl { // Exile target artifact or creature. Its controller creates a 4/4 blue and red Elemental creature token. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new Elemental44Token())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new Elemental44Token())); this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE)); } diff --git a/Mage.Sets/src/mage/cards/s/SawtuskDemolisher.java b/Mage.Sets/src/mage/cards/s/SawtuskDemolisher.java index e8c810d3d52..563da83624b 100644 --- a/Mage.Sets/src/mage/cards/s/SawtuskDemolisher.java +++ b/Mage.Sets/src/mage/cards/s/SawtuskDemolisher.java @@ -5,7 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.MutatesSourceTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.CreateTokenTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.MutateAbility; @@ -52,7 +52,7 @@ public final class SawtuskDemolisher extends CardImpl { // Whenever this creature mutates, destroy target noncreature permanent. Its controller creates a 3/3 green Beast creature token. Ability ability = new MutatesSourceTriggeredAbility(new DestroyTargetEffect()); - ability.addEffect(new CreateTokenControllerTargetPermanentEffect(new BeastToken())); + ability.addEffect(new CreateTokenControllerTargetEffect(new BeastToken())); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SecureTheScene.java b/Mage.Sets/src/mage/cards/s/SecureTheScene.java index 3cd4fc6423d..8d8a570ae87 100644 --- a/Mage.Sets/src/mage/cards/s/SecureTheScene.java +++ b/Mage.Sets/src/mage/cards/s/SecureTheScene.java @@ -1,6 +1,6 @@ package mage.cards.s; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ public final class SecureTheScene extends CardImpl { // Exile target nonland permanent. Its controller creates a 1/1 white Soldier creature token. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new SoldierToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new SoldierToken())); this.getSpellAbility().addTarget(new TargetNonlandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/s/StrixSerenade.java b/Mage.Sets/src/mage/cards/s/StrixSerenade.java new file mode 100644 index 00000000000..3749059f10d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StrixSerenade.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicates; +import mage.game.permanent.token.SwanSongBirdToken; +import mage.target.TargetSpell; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class StrixSerenade extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("artifact, creature, or planeswalker spell"); + + static { + filter.add(Predicates.or( + CardType.ARTIFACT.getPredicate(), + CardType.CREATURE.getPredicate(), + CardType.PLANESWALKER.getPredicate() + )); + } + + public StrixSerenade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); + + // Counter target artifact, creature, or planeswalker spell. Its controller creates a 2/2 blue Bird creature token with flying. + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect( + new SwanSongBirdToken(), CreateTokenControllerTargetEffect.TargetKind.SPELL + )); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + } + + private StrixSerenade(final StrixSerenade card) { + super(card); + } + + @Override + public StrixSerenade copy() { + return new StrixSerenade(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StrokeOfMidnight.java b/Mage.Sets/src/mage/cards/s/StrokeOfMidnight.java index d7990ac218c..84995a90a3d 100644 --- a/Mage.Sets/src/mage/cards/s/StrokeOfMidnight.java +++ b/Mage.Sets/src/mage/cards/s/StrokeOfMidnight.java @@ -1,6 +1,6 @@ package mage.cards.s; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +21,7 @@ public final class StrokeOfMidnight extends CardImpl { // Destroy target nonland permanent. Its controller creates a 1/1 white Human creature token. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new HumanToken())); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect(new HumanToken())); this.getSpellAbility().addTarget(new TargetNonlandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/s/SwanSong.java b/Mage.Sets/src/mage/cards/s/SwanSong.java index cd1bfd569d3..0f8c71b9eef 100644 --- a/Mage.Sets/src/mage/cards/s/SwanSong.java +++ b/Mage.Sets/src/mage/cards/s/SwanSong.java @@ -1,23 +1,19 @@ package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; -import mage.game.Game; import mage.game.permanent.token.SwanSongBirdToken; -import mage.game.permanent.token.Token; -import mage.game.stack.Spell; import mage.target.TargetSpell; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SwanSong extends CardImpl { @@ -25,16 +21,21 @@ public final class SwanSong extends CardImpl { private static final FilterSpell filter = new FilterSpell("enchantment, instant, or sorcery spell"); static { - filter.add(Predicates.or(CardType.ENCHANTMENT.getPredicate(), + filter.add(Predicates.or( + CardType.ENCHANTMENT.getPredicate(), CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate())); + CardType.SORCERY.getPredicate() + )); } public SwanSong(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Counter target enchantment, instant or sorcery spell. Its controller creates a 2/2 blue Bird creature token with flying. - this.getSpellAbility().addEffect(new SwanSongEffect()); + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addEffect(new CreateTokenControllerTargetEffect( + new SwanSongBirdToken(), CreateTokenControllerTargetEffect.TargetKind.SPELL + )); this.getSpellAbility().addTarget(new TargetSpell(filter)); } @@ -46,37 +47,4 @@ public final class SwanSong extends CardImpl { public SwanSong copy() { return new SwanSong(this); } -} - -class SwanSongEffect extends OneShotEffect { - - SwanSongEffect() { - super(Outcome.Benefit); - this.staticText = "Counter target enchantment, instant, or sorcery spell. Its controller creates a 2/2 blue Bird creature token with flying"; - } - - private SwanSongEffect(final SwanSongEffect effect) { - super(effect); - } - - @Override - public SwanSongEffect copy() { - return new SwanSongEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - boolean countered = false; - for (UUID targetId : getTargetPointer().getTargets(game, source)) { - Spell spell = game.getStack().getSpell(targetId); - if (game.getStack().counter(targetId, source, game)) { - countered = true; - } - if (spell != null) { - Token token = new SwanSongBirdToken(); - token.putOntoBattlefield(1, game, source, spell.getControllerId()); - } - } - return countered; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java b/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java index d3e045ff22f..a8765f90ee9 100644 --- a/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java +++ b/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java @@ -6,7 +6,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -20,7 +20,6 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author TheElk801 */ public final class TransmogrifyingWand extends CardImpl { @@ -40,7 +39,7 @@ public final class TransmogrifyingWand extends CardImpl { new DestroyTargetEffect(), new GenericManaCost(1) ); - ability.addEffect(new CreateTokenControllerTargetPermanentEffect(new OxToken())); + ability.addEffect(new CreateTokenControllerTargetEffect(new OxToken())); ability.addCost(new TapSourceCost()); ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance())); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/u/UnyieldingGatekeeper.java b/Mage.Sets/src/mage/cards/u/UnyieldingGatekeeper.java index 139dc896374..6cff9a562a6 100644 --- a/Mage.Sets/src/mage/cards/u/UnyieldingGatekeeper.java +++ b/Mage.Sets/src/mage/cards/u/UnyieldingGatekeeper.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect; +import mage.abilities.effects.common.CreateTokenControllerTargetEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileThenReturnTargetEffect; import mage.constants.Outcome; @@ -89,7 +89,7 @@ class UnyieldingGatekeeperEffect extends OneShotEffect { false, false, PutCards.BATTLEFIELD_TAPPED).apply(game, source); } else { new ExileTargetEffect().apply(game, source); - new CreateTokenControllerTargetPermanentEffect(new DetectiveToken()).apply(game, source); + new CreateTokenControllerTargetEffect(new DetectiveToken()).apply(game, source); } return true; } diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3.java b/Mage.Sets/src/mage/sets/ModernHorizons3.java index c13f2da9134..410c1d3970a 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3.java @@ -102,6 +102,7 @@ public final class ModernHorizons3 extends ExpansionSet { cards.add(new SetCardInfo("Sorin, Ravenous Neonate", 245, Rarity.MYTHIC, mage.cards.s.SorinRavenousNeonate.class)); cards.add(new SetCardInfo("Spawn-Gang Commander", 140, Rarity.UNCOMMON, mage.cards.s.SpawnGangCommander.class)); cards.add(new SetCardInfo("Strength of the Harvest", 258, Rarity.UNCOMMON, mage.cards.s.StrengthOfTheHarvest.class)); + cards.add(new SetCardInfo("Strix Serenade", 71, Rarity.RARE, mage.cards.s.StrixSerenade.class)); cards.add(new SetCardInfo("Stump Stomp", 259, Rarity.UNCOMMON, mage.cards.s.StumpStomp.class)); cards.add(new SetCardInfo("Suppression Ray", 260, Rarity.UNCOMMON, mage.cards.s.SuppressionRay.class)); cards.add(new SetCardInfo("Swamp", 306, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/mh3/StrixSerenadeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/mh3/StrixSerenadeTest.java new file mode 100644 index 00000000000..54205fe4ff7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/mh3/StrixSerenadeTest.java @@ -0,0 +1,74 @@ +package org.mage.test.cards.single.mh3; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class StrixSerenadeTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.s.StrixSerenade Strix Serenade} {U} + * Instant + * Counter target artifact, creature, or planeswalker spell. Its controller creates a 2/2 blue Bird creature token with flying. + */ + private static final String serenade = "Strix Serenade"; + + @Test + public void test_Simple() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.HAND, playerA, serenade); + addCard(Zone.HAND, playerB, "Mox Ruby"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Mox Ruby"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, serenade, "Mox Ruby", "Mox Ruby"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Mox Ruby", 1); + assertPermanentCount(playerB, "Bird Token", 1); + } + + @Test + public void test_Simple_OwnSpellTargetted() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.HAND, playerA, serenade); + addCard(Zone.HAND, playerA, "Mox Ruby"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mox Ruby"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, serenade, "Mox Ruby", "Mox Ruby"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Mox Ruby", 1); + assertPermanentCount(playerA, "Bird Token", 1); + } + + @Test + public void test_CantBeCountered_CreateToken() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.HAND, playerA, serenade); + addCard(Zone.HAND, playerB, "Chandra, Awakened Inferno"); // Can't be countered + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 6); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Chandra, Awakened Inferno"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, serenade, "Chandra, Awakened Inferno", "Chandra, Awakened Inferno"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerB, "Chandra, Awakened Inferno", 1); + assertPermanentCount(playerB, "Bird Token", 1); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenControllerTargetPermanentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenControllerTargetEffect.java similarity index 56% rename from Mage/src/main/java/mage/abilities/effects/common/CreateTokenControllerTargetPermanentEffect.java rename to Mage/src/main/java/mage/abilities/effects/common/CreateTokenControllerTargetEffect.java index 1aa42c8411d..78953e426b8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenControllerTargetPermanentEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenControllerTargetEffect.java @@ -5,8 +5,8 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; +import mage.game.Controllable; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; import mage.players.Player; import mage.util.CardUtil; @@ -14,46 +14,78 @@ import mage.util.CardUtil; /** * @author Susucr *
- * Have the Controller of target permanent (or LKI controller) create Tokens. + * Have the Controller of target object (permanent, or spell) create Tokens. */ -public class CreateTokenControllerTargetPermanentEffect extends OneShotEffect { +public class CreateTokenControllerTargetEffect extends OneShotEffect { private final Token token; private final DynamicValue amount; private final boolean tapped; - public CreateTokenControllerTargetPermanentEffect(Token token) { + /** + * What the target is supposed to be, to retrieve its controller from + */ + public enum TargetKind { + PERMANENT, + SPELL + } + + private final TargetKind targetKind; + + public CreateTokenControllerTargetEffect(Token token) { this(token, 1, false); } - public CreateTokenControllerTargetPermanentEffect(Token token, int amount, boolean tapped) { + public CreateTokenControllerTargetEffect(Token token, TargetKind targetKind) { + this(token, 1, false, targetKind); + } + + public CreateTokenControllerTargetEffect(Token token, int amount, boolean tapped) { this(token, StaticValue.get(amount), tapped); } - public CreateTokenControllerTargetPermanentEffect(Token token, DynamicValue amount, boolean tapped) { + public CreateTokenControllerTargetEffect(Token token, int amount, boolean tapped, TargetKind targetKind) { + this(token, StaticValue.get(amount), tapped, targetKind); + } + + public CreateTokenControllerTargetEffect(Token token, DynamicValue amount, boolean tapped) { + this(token, amount, tapped, TargetKind.PERMANENT); + } + + public CreateTokenControllerTargetEffect(Token token, DynamicValue amount, boolean tapped, TargetKind targetKind) { super(Outcome.Neutral); this.token = token; this.amount = amount.copy(); this.tapped = tapped; this.staticText = makeText(); + this.targetKind = targetKind; } - protected CreateTokenControllerTargetPermanentEffect(final CreateTokenControllerTargetPermanentEffect effect) { + protected CreateTokenControllerTargetEffect(final CreateTokenControllerTargetEffect effect) { super(effect); this.token = effect.token.copy(); this.amount = effect.amount.copy(); this.tapped = effect.tapped; + this.targetKind = effect.targetKind; } @Override - public CreateTokenControllerTargetPermanentEffect copy() { - return new CreateTokenControllerTargetPermanentEffect(this); + public CreateTokenControllerTargetEffect copy() { + return new CreateTokenControllerTargetEffect(this); } @Override public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent != null) { - Player controllerOfTarget = game.getPlayer(permanent.getControllerId()); + Controllable controllable = null; + switch (targetKind) { + case PERMANENT: + controllable = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); + break; + case SPELL: + controllable = game.getSpellOrLKIStack(getTargetPointer().getFirst(game, source)); + break; + } + if (controllable != null) { + Player controllerOfTarget = game.getPlayer(controllable.getControllerId()); if (controllerOfTarget != null) { int value = amount.calculate(game, source, this); return token.putOntoBattlefield(value, game, source, controllerOfTarget.getId(), tapped, false);