From 83c94322c6d030c2375975019153a4c7f3b9ddf4 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 14 Mar 2022 21:14:12 -0400 Subject: [PATCH] refactored some instances of Player::moveCardToExileWithInfo --- Mage.Sets/src/mage/cards/a/Aetherling.java | 2 +- Mage.Sets/src/mage/cards/a/Alms.java | 14 +-- .../src/mage/cards/a/AnuridBrushhopper.java | 2 +- .../src/mage/cards/f/FreneticSliver.java | 2 +- .../mage/cards/g/GhostCouncilOfOrzhova.java | 2 +- .../mage/cards/h/HikariTwilightGuardian.java | 2 +- Mage.Sets/src/mage/cards/n/NaturesKiss.java | 20 ++-- .../src/mage/cards/n/NezahalPrimalTide.java | 2 +- Mage.Sets/src/mage/cards/n/NorinTheWary.java | 3 +- Mage.Sets/src/mage/cards/s/Saltskitter.java | 2 +- .../cards/abilities/keywords/ReboundTest.java | 2 +- .../common/ExileSourceFromGraveCost.java | 33 +++--- .../common/ExileTopCardOfGraveyardCost.java | 34 +++--- .../ExileTopCreatureCardOfGraveyardCost.java | 30 ++--- ...xileCardYouChooseTargetOpponentEffect.java | 40 +++---- ...ttlefieldOwnerNextEndStepSourceEffect.java | 49 +++----- .../abilities/keyword/MadnessAbility.java | 51 ++++++--- .../abilities/keyword/ReboundAbility.java | 106 +++++++----------- 18 files changed, 183 insertions(+), 213 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/Aetherling.java b/Mage.Sets/src/mage/cards/a/Aetherling.java index 6e7020a9580..ff6d6b5f8a0 100644 --- a/Mage.Sets/src/mage/cards/a/Aetherling.java +++ b/Mage.Sets/src/mage/cards/a/Aetherling.java @@ -29,7 +29,7 @@ public final class Aetherling extends CardImpl { this.toughness = new MageInt(5); // {U}: Exile Aetherling. Return it to the battlefield under its owner's control at the beginning of the next end step. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true), new ManaCostsImpl("{U}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(), new ManaCostsImpl("{U}"))); // {U}: Aetherling can't be blocked this turn this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedSourceEffect(Duration.EndOfTurn), new ManaCostsImpl("{U}"))); // {1}: Aetherling gets +1/-1 until end of turn. diff --git a/Mage.Sets/src/mage/cards/a/Alms.java b/Mage.Sets/src/mage/cards/a/Alms.java index db16df42257..bf6b4c84e4e 100644 --- a/Mage.Sets/src/mage/cards/a/Alms.java +++ b/Mage.Sets/src/mage/cards/a/Alms.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileTopCardOfGraveyardCost; @@ -11,21 +9,23 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class Alms extends CardImpl { public Alms(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); // {1}, Exile the top card of your graveyard: Prevent the next 1 damage that would be dealt to target creature this turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), new GenericManaCost(1)); - ability.addCost(new ExileTopCardOfGraveyardCost(1)); + Ability ability = new SimpleActivatedAbility( + new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), new GenericManaCost(1) + ); + ability.addCost(new ExileTopCardOfGraveyardCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AnuridBrushhopper.java b/Mage.Sets/src/mage/cards/a/AnuridBrushhopper.java index 1668edee293..c509e050fa2 100644 --- a/Mage.Sets/src/mage/cards/a/AnuridBrushhopper.java +++ b/Mage.Sets/src/mage/cards/a/AnuridBrushhopper.java @@ -29,7 +29,7 @@ public final class AnuridBrushhopper extends CardImpl { // Discard two cards: Exile Anurid Brushhopper. Return it to the battlefield under its owner's control at the beginning of the next end step. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true), + new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(), new DiscardTargetCost(new TargetCardInHand(2, new FilterCard("two cards"))))); } diff --git a/Mage.Sets/src/mage/cards/f/FreneticSliver.java b/Mage.Sets/src/mage/cards/f/FreneticSliver.java index 49275b38b04..8c33b99f5f8 100644 --- a/Mage.Sets/src/mage/cards/f/FreneticSliver.java +++ b/Mage.Sets/src/mage/cards/f/FreneticSliver.java @@ -77,7 +77,7 @@ class FreneticSliverEffect extends OneShotEffect { return false; } if (player.flipCoin(source, game, true)) { - return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true).apply(game, source); + return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect().apply(game, source); } else { return perm.sacrifice(source, game); } diff --git a/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java b/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java index 51099f92ec8..08c01994e6e 100644 --- a/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java +++ b/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java @@ -44,7 +44,7 @@ public final class GhostCouncilOfOrzhova extends CardImpl { // {1}, Sacrifice a creature: Exile Ghost Council of Orzhova. Return it to the battlefield under its owner's control at the beginning of the next end step. ability = new SimpleActivatedAbility( Zone.BATTLEFIELD, - new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true), + new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(), new GenericManaCost(1)); ability.addCost(new SacrificeTargetCost( new TargetControlledCreaturePermanent( diff --git a/Mage.Sets/src/mage/cards/h/HikariTwilightGuardian.java b/Mage.Sets/src/mage/cards/h/HikariTwilightGuardian.java index 116f61bd0c9..ac55282303b 100644 --- a/Mage.Sets/src/mage/cards/h/HikariTwilightGuardian.java +++ b/Mage.Sets/src/mage/cards/h/HikariTwilightGuardian.java @@ -31,7 +31,7 @@ public final class HikariTwilightGuardian extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever you cast a Spirit or Arcane spell, you may exile Hikari, Twilight Guardian. If you do, return it to the battlefield under its owner's control at the beginning of the next end step. - Effect effect = new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true); + Effect effect = new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(); effect.setText("you may exile {this}. If you do, return it to the battlefield under its owner's control at the beginning of the next end step"); this.addAbility(new SpellCastControllerTriggeredAbility(effect, StaticFilters.FILTER_SPIRIT_OR_ARCANE_CARD, true)); } diff --git a/Mage.Sets/src/mage/cards/n/NaturesKiss.java b/Mage.Sets/src/mage/cards/n/NaturesKiss.java index 4ba50dcd6e5..7c235419058 100644 --- a/Mage.Sets/src/mage/cards/n/NaturesKiss.java +++ b/Mage.Sets/src/mage/cards/n/NaturesKiss.java @@ -1,32 +1,30 @@ - package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileTopCardOfGraveyardCost; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class NaturesKiss extends CardImpl { public NaturesKiss(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -34,10 +32,12 @@ public final class NaturesKiss extends CardImpl { this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); - + // {1}, Exile the top card of your graveyard: Enchanted creature gets +1/+1 until end of turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{1}")); - ability.addCost(new ExileTopCardOfGraveyardCost(1)); + Ability ability = new SimpleActivatedAbility(new BoostEnchantedEffect( + 1, 1, Duration.EndOfTurn + ), new GenericManaCost(1)); + ability.addCost(new ExileTopCardOfGraveyardCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java b/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java index 9ad28f9576d..d1eae780649 100644 --- a/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java +++ b/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java @@ -58,7 +58,7 @@ public final class NezahalPrimalTide extends CardImpl { new DrawCardSourceControllerEffect(1), filter, false, SetTargetPointer.NONE)); // Discard three cards: Exile Nezahal. Return it to the battlefield tapped under its owner's control at the beginning of the next end step. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true, true), + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true), new DiscardTargetCost(new TargetCardInHand(3, new FilterCard("three cards"))))); } diff --git a/Mage.Sets/src/mage/cards/n/NorinTheWary.java b/Mage.Sets/src/mage/cards/n/NorinTheWary.java index dd19ec242e5..6778ecf1a86 100644 --- a/Mage.Sets/src/mage/cards/n/NorinTheWary.java +++ b/Mage.Sets/src/mage/cards/n/NorinTheWary.java @@ -13,7 +13,6 @@ import mage.constants.SuperType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; /** * @@ -48,7 +47,7 @@ public final class NorinTheWary extends CardImpl { class NorinTheWaryTriggeredAbility extends TriggeredAbilityImpl { public NorinTheWaryTriggeredAbility() { - super(Zone.BATTLEFIELD, new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true), false); + super(Zone.BATTLEFIELD, new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(), false); } public NorinTheWaryTriggeredAbility(final NorinTheWaryTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/s/Saltskitter.java b/Mage.Sets/src/mage/cards/s/Saltskitter.java index 673cf8c5c84..eca33af6caa 100644 --- a/Mage.Sets/src/mage/cards/s/Saltskitter.java +++ b/Mage.Sets/src/mage/cards/s/Saltskitter.java @@ -32,7 +32,7 @@ public final class Saltskitter extends CardImpl { this.toughness = new MageInt(4); // Whenever another creature enters the battlefield, exile Saltskitter. Return Saltskitter to the battlefield under its owner's control at the beginning of the next end step. - this.addAbility(new EntersBattlefieldAllTriggeredAbility(new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(), filter)); } private Saltskitter(final Saltskitter card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReboundTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReboundTest.java index 889788ec3d2..60e56bdcf2f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReboundTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReboundTest.java @@ -64,7 +64,7 @@ public class ReboundTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Distortion Strike", "Memnite"); setStopAt(3, PhaseStep.PRECOMBAT_MAIN); - execute(); + execute();assertAllCommandsUsed(); //check exile and graveyard assertPowerToughness(playerA, "Memnite", 2, 1); diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileSourceFromGraveCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileSourceFromGraveCost.java index e6dcf15e195..51fad57ba09 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ExileSourceFromGraveCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ExileSourceFromGraveCost.java @@ -1,7 +1,5 @@ - package mage.abilities.costs.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; @@ -10,8 +8,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author magenoxx_at_gmail.com */ public class ExileSourceFromGraveCost extends CostImpl { @@ -20,36 +19,36 @@ public class ExileSourceFromGraveCost extends CostImpl { this.text = "exile {this} from your graveyard"; } - public ExileSourceFromGraveCost(ExileSourceFromGraveCost cost) { + private ExileSourceFromGraveCost(final ExileSourceFromGraveCost cost) { super(cost); } @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { Player controller = game.getPlayer(controllerId); - if (controller != null) { - Card card = game.getCard(source.getSourceId()); - if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { - controller.moveCardToExileWithInfo(card, null, "", source, game, Zone.GRAVEYARD, true); - // 117.11. The actions performed when paying a cost may be modified by effects. - // Even if they are, meaning the actions that are performed don't match the actions - // that are called for, the cost has still been paid. - // so return state here is not important because the user indended to exile the target anyway - paid = true; - } + if (controller == null) { + return paid; + } + Card card = game.getCard(source.getSourceId()); + if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { + controller.moveCards(card, Zone.EXILED, source, game); + // 117.11. The actions performed when paying a cost may be modified by effects. + // Even if they are, meaning the actions that are performed don't match the actions + // that are called for, the cost has still been paid. + // so return state here is not important because the user indended to exile the target anyway + paid = true; } return paid; } @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - Card card = game.getCard(source.getSourceId()); - return card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD; + return game.getCard(source.getSourceId()) != null + && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD; } @Override public ExileSourceFromGraveCost copy() { return new ExileSourceFromGraveCost(this); } - } diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileTopCardOfGraveyardCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileTopCardOfGraveyardCost.java index 9784495831c..417910fd555 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ExileTopCardOfGraveyardCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ExileTopCardOfGraveyardCost.java @@ -1,6 +1,5 @@ package mage.abilities.costs.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; @@ -9,45 +8,40 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author fireshoes */ public class ExileTopCardOfGraveyardCost extends CostImpl { - private final int amount; - - public ExileTopCardOfGraveyardCost(int amount) { - this.amount = amount; + public ExileTopCardOfGraveyardCost() { this.text = "Exile the top card of your graveyard"; } - public ExileTopCardOfGraveyardCost(ExileTopCardOfGraveyardCost cost) { + private ExileTopCardOfGraveyardCost(final ExileTopCardOfGraveyardCost cost) { super(cost); - this.amount = cost.amount; } @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { Player controller = game.getPlayer(controllerId); - if(controller == null) { + if (controller == null) { return false; } - return controller.getGraveyard().size() >= amount; + return !controller.getGraveyard().isEmpty(); } @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { Player controller = game.getPlayer(controllerId); - if(controller != null) { - Card topCard = null; - for (Card card :controller.getGraveyard().getCards(game)) { - topCard = card; - } - if (topCard != null) { - controller.moveCardToExileWithInfo(topCard, null, "", source, game, Zone.GRAVEYARD, true); - paid = true; - } + if (controller == null) { + return paid; + } + Card topCard = controller.getGraveyard().getTopCard(game); + if (topCard != null) { + controller.moveCards(topCard, Zone.EXILED, source, game); + paid = true; } return paid; } @@ -56,4 +50,4 @@ public class ExileTopCardOfGraveyardCost extends CostImpl { public ExileTopCardOfGraveyardCost copy() { return new ExileTopCardOfGraveyardCost(this); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java index 94e1e91fd00..acaac231f6a 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ExileTopCreatureCardOfGraveyardCost.java @@ -1,6 +1,5 @@ package mage.abilities.costs.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; @@ -9,8 +8,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author fireshoes */ public class ExileTopCreatureCardOfGraveyardCost extends CostImpl { @@ -30,7 +30,7 @@ public class ExileTopCreatureCardOfGraveyardCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { Player controller = game.getPlayer(controllerId); - if(controller == null) { + if (controller == null) { return false; } return controller.getGraveyard().size() >= amount; @@ -39,17 +39,19 @@ public class ExileTopCreatureCardOfGraveyardCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { Player controller = game.getPlayer(controllerId); - if(controller != null) { - Card topCard = null; - for (Card card :controller.getGraveyard().getCards(game)) { - if (card.isCreature(game)) { - topCard = card; - } - } - if (topCard != null) { - controller.moveCardToExileWithInfo(topCard, null, "", source, game, Zone.GRAVEYARD, true); - paid = true; - } + if (controller == null) { + return paid; + } + Card topCard = controller + .getGraveyard() + .getCards(game) + .stream() + .filter(card -> card.isCreature(game)) + .findFirst() + .orElse(null); + if (topCard != null) { + controller.moveCards(topCard, Zone.EXILED, source, game); + paid = true; } return paid; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java index 656a8d387d5..6e9aee91faf 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ExileCardYouChooseTargetOpponentEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; @@ -12,25 +11,20 @@ import mage.players.Player; import mage.target.TargetCard; /** - * * @author LevelX2 */ public class ExileCardYouChooseTargetOpponentEffect extends OneShotEffect { - private FilterCard filter; - - public ExileCardYouChooseTargetOpponentEffect() { - this(new FilterCard("a card")); - } + private final FilterCard filter; public ExileCardYouChooseTargetOpponentEffect(FilterCard filter) { super(Outcome.Discard); - staticText = new StringBuilder("Target opponent reveals their hand. You choose ") - .append(filter.getMessage()).append(" from it and exile that card").toString(); + this.staticText = "Target opponent reveals their hand. You choose " + + filter.getMessage() + " from it and exile that card"; this.filter = filter; } - public ExileCardYouChooseTargetOpponentEffect(final ExileCardYouChooseTargetOpponentEffect effect) { + private ExileCardYouChooseTargetOpponentEffect(final ExileCardYouChooseTargetOpponentEffect effect) { super(effect); this.filter = effect.filter; } @@ -39,26 +33,22 @@ public class ExileCardYouChooseTargetOpponentEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(source.getFirstTarget()); - Card sourceCard = game.getCard(source.getSourceId()); - if (controller != null && opponent != null) { - if (!opponent.getHand().isEmpty()) { - opponent.revealCards(sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ')' : "Exile", opponent.getHand(), game); - TargetCard target = new TargetCard(Zone.HAND, filter); - if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { - Card card = opponent.getHand().get(target.getFirstTarget(), game); - if (card != null) { - controller.moveCardToExileWithInfo(card, null, "", source, game, Zone.HAND, true); - } - } - } - return true; + if (controller == null || opponent == null + || opponent.getHand().count(filter, game) < 1) { + return false; } - return false; + opponent.revealCards(source, opponent.getHand(), game); + TargetCard target = new TargetCard(Zone.HAND, filter); + controller.choose(Outcome.Exile, opponent.getHand(), target, game); + Card card = opponent.getHand().get(target.getFirstTarget(), game); + if (card != null) { + controller.moveCards(card, Zone.EXILED, source, game); + } + return true; } @Override public ExileCardYouChooseTargetOpponentEffect copy() { return new ExileCardYouChooseTargetOpponentEffect(this); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileReturnBattlefieldOwnerNextEndStepSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileReturnBattlefieldOwnerNextEndStepSourceEffect.java index 3c12c7fc737..405223fe11d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ExileReturnBattlefieldOwnerNextEndStepSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ExileReturnBattlefieldOwnerNextEndStepSourceEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; @@ -9,69 +8,55 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.targetpointer.FixedTarget; /** - * * @author LevelX2 */ public class ExileReturnBattlefieldOwnerNextEndStepSourceEffect extends OneShotEffect { - private boolean returnAlways; - private boolean returnTapped; + private final boolean returnTapped; public ExileReturnBattlefieldOwnerNextEndStepSourceEffect() { this(false); } - public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(boolean returnAlways) { - this(returnAlways, false); - } - /** - * - * @param returnAlways Return the permanent also if it does not go to exile - * but is moved to another zone (e.g. command zone by commander replacement - * effect) * @param returnTapped Does the source return tapped to the battlefield */ - public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(boolean returnAlways, boolean returnTapped) { + public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(boolean returnTapped) { super(Outcome.Benefit); this.returnTapped = returnTapped; - this.returnAlways = returnAlways; - staticText = "exile {this}. Return it to the battlefield " - + (returnTapped ? "tapped " : "") - + "under its owner's control at the beginning of the next end step"; + staticText = "exile {this}. Return it to the battlefield " + (returnTapped ? "tapped " : "") + + "under its owner's control at the beginning of the next end step"; } public ExileReturnBattlefieldOwnerNextEndStepSourceEffect(ExileReturnBattlefieldOwnerNextEndStepSourceEffect effect) { super(effect); - this.returnAlways = effect.returnAlways; this.returnTapped = effect.returnTapped; } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - int zcc = game.getState().getZoneChangeCounter(permanent.getId()); - boolean exiled = controller.moveCardToExileWithInfo(permanent, source.getSourceId(), permanent.getIdName(), source, game, Zone.BATTLEFIELD, true); - if (exiled || (returnAlways && (zcc == game.getState().getZoneChangeCounter(permanent.getId()) - 1))) { - //create delayed triggered ability and return it from every public zone it was next moved to - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnToBattlefieldUnderOwnerControlSourceEffect(returnTapped, zcc + 1)); - game.addDelayedTriggeredAbility(delayedAbility, source); - } - } + if (controller == null) { + return false; + } + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { return true; } - return false; + controller.moveCards(permanent, Zone.EXILED, source, game); + //create delayed triggered ability and return it from every public zone it was next moved to + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new ReturnToBattlefieldUnderOwnerControlTargetEffect(returnTapped, true) + .setTargetPointer(new FixedTarget(permanent.getId(), game)) + ), source); + return true; } @Override public ExileReturnBattlefieldOwnerNextEndStepSourceEffect copy() { return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(this); } - } diff --git a/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java b/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java index 366da4513b0..da2b84a2eae 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java @@ -1,7 +1,11 @@ package mage.abilities.keyword; +import mage.ApprovingObject; import mage.MageObject; -import mage.abilities.*; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.StaticAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.Condition; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.mana.ManaCost; @@ -18,7 +22,6 @@ import mage.game.stack.Spell; import mage.players.Player; import java.util.UUID; -import mage.ApprovingObject; /** * 702.33. Madness @@ -124,13 +127,17 @@ class MadnessReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { return false; } + if (controller == null) { + return false; + } Card card = game.getCard(event.getTargetId()); - if (card == null) { return false; } + if (card == null) { + return false; + } // TODO, deal with deprecated call - if (controller.moveCardToExileWithInfo(card, source.getSourceId(), "Madness", source, game, ((ZoneChangeEvent) event).getFromZone(), true)) { + if (controller.moveCards(card, Zone.EXILED, source, game)) { game.applyEffects(); // needed to add Madness ability to cards (e.g. by Falkenrath Gorger) GameEvent gameEvent = new MadnessCardExiledEvent(card.getId(), source, controller.getId()); game.fireEvent(gameEvent); @@ -190,13 +197,19 @@ class MadnessTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean resolve(Game game) { - if (super.resolve(game)) { return true; } + if (super.resolve(game)) { + return true; + } Card card = game.getCard(getSourceId()); - if (card == null) { return false; } + if (card == null) { + return false; + } Player owner = game.getPlayer(card.getOwnerId()); - if (owner == null) { return false; } + if (owner == null) { + return false; + } // if cast was not successfull, the card is moved to graveyard owner.moveCards(card, Zone.GRAVEYARD, this, game); @@ -205,7 +218,7 @@ class MadnessTriggeredAbility extends TriggeredAbilityImpl { @Override public String getTriggerPhrase() { - return "When this card is exiled this way, " ; + return "When this card is exiled this way, "; } } @@ -237,15 +250,21 @@ class MadnessCastEffect extends OneShotEffect { } @Override - public MadnessCastEffect copy() { return new MadnessCastEffect(this); } + public MadnessCastEffect copy() { + return new MadnessCastEffect(this); + } @Override public boolean apply(Game game, Ability source) { Card card = game.getCard(source.getSourceId()); - if (card == null) { return false; } + if (card == null) { + return false; + } Player owner = game.getPlayer(card.getOwnerId()); - if (owner == null) { return false; } + if (owner == null) { + return false; + } // Replace with the new cost SpellAbility castByMadness = card.getSpellAbility().copy(); @@ -268,9 +287,13 @@ enum MadnessCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject madnessSpell = game.getLastKnownInformation(source.getSourceId(), Zone.STACK, source.getSourceObjectZoneChangeCounter() - 1); - if (!(madnessSpell instanceof Spell)) { return false; } + if (!(madnessSpell instanceof Spell)) { + return false; + } - if (((Spell) madnessSpell).getSpellAbility() == null) { return false; } + if (((Spell) madnessSpell).getSpellAbility() == null) { + return false; + } return ((Spell) madnessSpell).getSpellAbility().getSpellAbilityCastMode() == SpellAbilityCastMode.MADNESS; } diff --git a/Mage/src/main/java/mage/abilities/keyword/ReboundAbility.java b/Mage/src/main/java/mage/abilities/keyword/ReboundAbility.java index f3a6c0f5f37..5898f19bba8 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ReboundAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ReboundAbility.java @@ -3,22 +3,21 @@ package mage.abilities.keyword; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.Card; +import mage.cards.CardsImpl; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; -import mage.game.ExileZone; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.stack.Spell; import mage.players.Player; - -import java.util.UUID; -import mage.ApprovingObject; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; /** * This ability has no effect by default and will always return false on the @@ -49,7 +48,7 @@ public class ReboundAbility extends SimpleStaticAbility { super(Zone.STACK, new ReboundCastFromHandReplacementEffect()); } - public ReboundAbility(ReboundAbility ability) { + public ReboundAbility(final ReboundAbility ability) { super(ability); } @@ -57,18 +56,22 @@ public class ReboundAbility extends SimpleStaticAbility { public ReboundAbility copy() { return new ReboundAbility(this); } + + @Override + public String getRule() { + return "Rebound (If you cast this spell from your hand, " + + "exile it as it resolves. At the beginning of your next upkeep, " + + "you may cast this card from exile without paying its mana cost.)"; + } } class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { ReboundCastFromHandReplacementEffect() { super(Duration.WhileOnStack, Outcome.Benefit); - this.staticText = "Rebound (If you cast this spell from your hand, " - + "exile it as it resolves. At the beginning of your next upkeep, " - + "you may cast this card from exile without paying its mana cost.)"; } - ReboundCastFromHandReplacementEffect(ReboundCastFromHandReplacementEffect effect) { + private ReboundCastFromHandReplacementEffect(final ReboundCastFromHandReplacementEffect effect) { super(effect); } @@ -84,17 +87,14 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { // by a spell like Cancel, or because all of its targets are illegal), rebound has no effect. // The spell is simply put into your graveyard. You won’t get to cast it again next turn. // (2010-06-15) - if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK - && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD - && event.getSourceId() != null - && event.getSourceId().equals(source.getSourceId())) { // if countered the source.sourceId is different or null if it fizzles - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null - && spell.getFromZone() == Zone.HAND) { - return true; - } - } - return false; + if (((ZoneChangeEvent) event).getFromZone() != Zone.STACK + || ((ZoneChangeEvent) event).getToZone() != Zone.GRAVEYARD + || event.getSourceId() == null + || !event.getSourceId().equals(source.getSourceId())) { + return false; + } // if countered the source.sourceId is different or null if it fizzles + Spell spell = game.getStack().getSpell(event.getTargetId()); + return spell != null && spell.getFromZone() == Zone.HAND; } @Override @@ -102,23 +102,19 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { Spell sourceSpell = game.getStack().getSpell(source.getSourceId()); if (sourceSpell != null && sourceSpell.isCopy()) { return false; - } else { - Card sourceCard = game.getCard(source.getSourceId()); - if (sourceCard != null) { - Player player = game.getPlayer(sourceCard.getOwnerId()); - if (player != null) { - // Add the delayed triggered effect - ReboundEffectCastFromExileDelayedTrigger trigger - = new ReboundEffectCastFromExileDelayedTrigger(source.getSourceId(), source.getSourceId()); - game.addDelayedTriggeredAbility(trigger, source); - - player.moveCardToExileWithInfo(sourceCard, sourceCard.getId(), - player.getName() + " Rebound", source, game, Zone.STACK, true); - return true; - } - } } - return false; + Card sourceCard = game.getCard(source.getSourceId()); + if (sourceCard == null) { + return false; + } + Player player = game.getPlayer(sourceCard.getOwnerId()); + if (player == null) { + return false; + } + // Add the delayed triggered effect + player.moveCardsToExile(sourceCard, source, game, true, null, "Rebound"); + game.addDelayedTriggeredAbility(new ReboundEffectCastFromExileDelayedTrigger(sourceCard, game), source); + return true; } @Override @@ -130,13 +126,11 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility { - ReboundEffectCastFromExileDelayedTrigger(UUID cardId, UUID sourceId) { - super(new ReboundCastSpellFromExileEffect()); - setSourceId(sourceId); // TODO: WTF?! - this.optional = true; + ReboundEffectCastFromExileDelayedTrigger(Card card, Game game) { + super(new ReboundCastSpellFromExileEffect().setTargetPointer(new FixedTarget(card, game)), Duration.Custom, true, true); } - ReboundEffectCastFromExileDelayedTrigger(ReboundEffectCastFromExileDelayedTrigger ability) { + private ReboundEffectCastFromExileDelayedTrigger(final ReboundEffectCastFromExileDelayedTrigger ability) { super(ability); } @@ -152,7 +146,7 @@ class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return MyTurnCondition.instance.apply(game, this); + return game.isActivePlayer(getControllerId()); } @Override @@ -169,41 +163,25 @@ class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility { */ class ReboundCastSpellFromExileEffect extends OneShotEffect { - private static String castFromExileText = "Rebound - You may cast {this} " - + "from exile without paying its mana cost"; - ReboundCastSpellFromExileEffect() { super(Outcome.PlayForFree); - staticText = castFromExileText; } - ReboundCastSpellFromExileEffect(ReboundCastSpellFromExileEffect effect) { + private ReboundCastSpellFromExileEffect(final ReboundCastSpellFromExileEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - ExileZone zone = game.getExile().getExileZone(source.getSourceId()); - if (zone == null - || zone.isEmpty()) { - return false; - } - Card reboundCard = zone.get(source.getSourceId(), game); Player player = game.getPlayer(source.getControllerId()); - if (player != null - && reboundCard != null) { - game.getState().setValue("PlayFromNotOwnHandZone" + reboundCard.getId(), Boolean.TRUE); - Boolean cardWasCast = player.cast(player.chooseAbilityForCast(reboundCard, game, true), - game, true, new ApprovingObject(source, game)); - game.getState().setValue("PlayFromNotOwnHandZone" + reboundCard.getId(), null); - return cardWasCast; - } - return false; + Card reboundCard = game.getCard(getTargetPointer().getFirst(game, source)); + return player != null && reboundCard != null && CardUtil.castSpellWithAttributesForFree( + player, source, game, new CardsImpl(reboundCard), StaticFilters.FILTER_CARD + ); } @Override public ReboundCastSpellFromExileEffect copy() { return new ReboundCastSpellFromExileEffect(this); } - }