From 7cc313bc43a1fb80b8eacba7face877484fb001e Mon Sep 17 00:00:00 2001 From: L_J Date: Sun, 3 Jun 2018 11:20:46 +0200 Subject: [PATCH] Implemented "force pay mana" for Word of Command --- Mage.Sets/src/mage/cards/w/WordOfCommand.java | 29 ++++++++++++++++--- .../abilities/costs/mana/ManaCostsImpl.java | 20 +++++++++++++ Mage/src/main/java/mage/players/ManaPool.java | 29 +++++++++++++++---- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/Mage.Sets/src/mage/cards/w/WordOfCommand.java b/Mage.Sets/src/mage/cards/w/WordOfCommand.java index 53713f4c0e3..f9e0ec9a9ed 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfCommand.java +++ b/Mage.Sets/src/mage/cards/w/WordOfCommand.java @@ -49,6 +49,7 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import mage.players.ManaPool; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; @@ -119,16 +120,36 @@ class WordOfCommandEffect extends OneShotEffect { // The player plays that card if able if (card != null) { + // While doing so, the player can activate mana abilities only if they're from lands that player controls RestrictionEffect effect = new WordOfCommandCantActivateEffect(); effect.setTargetPointer(new FixedTarget(targetPlayer.getId())); - game.addEffect(effect, source); // While doing so, the player can activate mana abilities only if they're from lands that player controls - // TODO: and only if mana they produce is spent to activate other mana abilities of lands he or she controls and/or play that card (so you can't tap out the player's lands) + game.addEffect(effect, source); + + // and only if mana they produce is spent to activate other mana abilities of lands he or she controls and/or play that card + ManaPool manaPool = targetPlayer.getManaPool(); + boolean autoPayment = manaPool.isAutoPayment(); + boolean autoPaymentRestricted = manaPool.isAutoPaymentRestricted(); + manaPool.setAutoPayment(true); + manaPool.setAutoPaymentRestricted(true); + manaPool.setForcedToPay(true); + int bookmark = game.bookmarkState(); + if ((card.isLand() && (!targetPlayer.canPlayLand() || !game.getActivePlayerId().equals(targetPlayer.getId()))) || !targetPlayer.playCard(card, game, false, true, new MageObjectReference(source.getSourceObject(game), game))) { - game.informPlayers(targetPlayer.getLogName() + " didn't play " + card.getLogName()); // TODO: needs an automatic check for whether the card is castable (so it can't be cancelled if that's the case) + game.informPlayers(targetPlayer.getLogName() + " didn't play " + card.getLogName()); } + manaPool.setForcedToPay(false); // duplicate in case of a a new mana pool existing - probably not necessary, but just in case + manaPool.setAutoPayment(autoPayment); + manaPool.setAutoPaymentRestricted(autoPaymentRestricted); + manaPool = targetPlayer.getManaPool(); // a rollback creates a new mana pool for the player, so it's necessary to find it again + manaPool.setForcedToPay(false); + manaPool.setAutoPayment(autoPayment); + manaPool.setAutoPaymentRestricted(autoPaymentRestricted); + game.removeBookmark(bookmark); + targetPlayer.resetStoredBookmark(game); + for (RestrictionEffect eff : game.getContinuousEffects().getRestrictionEffects()) { if (eff instanceof WordOfCommandCantActivateEffect) { eff.discard(); @@ -197,7 +218,7 @@ class WordOfCommandDelayedTriggeredAbility extends DelayedTriggeredAbility { private UUID cardId; WordOfCommandDelayedTriggeredAbility(Effect effect, UUID cardId) { - super(effect, Duration.EndOfStep); + super(effect, Duration.EndOfTurn); this.cardId = cardId; this.usesStack = false; } diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java index f5e8f766ca8..f4148349bdd 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java @@ -265,6 +265,10 @@ public class ManaCostsImpl extends ArrayList implements M // if auto payment is inactive and no mana type was clicked manually - do nothing return; } + ManaCosts referenceCosts = null; + if (pool.isForcedToPay()) { + referenceCosts = this.copy(); + } // attempt to pay colorless costs (not generic) mana costs first for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof ColorlessManaCost) { @@ -344,6 +348,22 @@ public class ManaCostsImpl extends ArrayList implements M } // stop using mana of the clicked mana type pool.lockManaType(); + handleForcedToPayOnlyForCurrentPayment(game, pool, referenceCosts); + } + + private void handleForcedToPayOnlyForCurrentPayment(Game game, ManaPool pool, ManaCosts referenceCosts) { + // for Word of Command + if (pool.isForcedToPay()) { + if (referenceCosts != null && this.getPayment().equals(referenceCosts.getPayment())) { + UUID playerId = pool.getPlayerId(); + Player player = game.getPlayer(playerId); + if (player != null) { + game.undo(playerId); + this.clearPaid(); + game.bookmarkState(); + } + } + } } @Override diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index 2448b8a9220..686a64edcff 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -62,6 +62,7 @@ public class ManaPool implements Serializable { private boolean autoPayment; // auto payment from mana pool: true - mode is active private boolean autoPaymentRestricted; // auto payment from mana pool: true - if auto Payment is on, it will only pay if one kind of mana is in the pool private ManaType unlockedManaType; // type of mana that was selected to pay manually + private boolean forcedToPay; // for Word of Command private final Set doNotEmptyManaTypes = new HashSet<>(); @@ -70,6 +71,7 @@ public class ManaPool implements Serializable { autoPayment = true; autoPaymentRestricted = true; unlockedManaType = null; + forcedToPay = false; } public ManaPool(final ManaPool pool) { @@ -80,6 +82,7 @@ public class ManaPool implements Serializable { this.autoPayment = pool.autoPayment; this.autoPaymentRestricted = pool.autoPaymentRestricted; this.unlockedManaType = pool.unlockedManaType; + this.forcedToPay = pool.forcedToPay; this.doNotEmptyManaTypes.addAll(pool.doNotEmptyManaTypes); } @@ -138,6 +141,7 @@ public class ManaPool implements Serializable { lockManaType(); // pay only one mana if mana payment is set to manually return true; } + for (ManaPoolItem mana : manaItems) { if (filter != null) { if (!filter.match(mana.getSourceObject(), game)) { @@ -465,17 +469,21 @@ public class ManaPool implements Serializable { } public void setAutoPayment(boolean autoPayment) { - this.autoPayment = autoPayment; - } - - public void setAutoPaymentRestricted(boolean autoPaymentRestricted) { - this.autoPaymentRestricted = autoPaymentRestricted; + if (!forcedToPay) { + this.autoPayment = autoPayment; + } } public boolean isAutoPaymentRestricted() { return autoPaymentRestricted; } + public void setAutoPaymentRestricted(boolean autoPaymentRestricted) { + if (!forcedToPay) { + this.autoPaymentRestricted = autoPaymentRestricted; + } + } + public ManaType getUnlockedManaType() { return unlockedManaType; } @@ -515,4 +523,15 @@ public class ManaPool implements Serializable { return itemsCopy; } + public void setForcedToPay(boolean forcedToPay) { + this.forcedToPay = forcedToPay; + } + + public boolean isForcedToPay() { + return forcedToPay; + } + + public UUID getPlayerId() { + return playerId; + } }