diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 5e0c18341f8..d571ce9a719 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -79,6 +79,10 @@ public class GameAction { } public Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer position, SpellAbility cause) { + return changeZone(zoneFrom, zoneTo, c, position, cause, Maps.newHashMap()); + } + + public Card changeZone(final Zone zoneFrom, Zone zoneTo, final Card c, Integer position, SpellAbility cause, Map params) { if (c.isCopiedSpell() || (c.isImmutable() && zoneTo.is(ZoneType.Exile))) { // Remove Effect from command immediately, this is essential when some replacement // effects happen during the resolving of a spellability ("the next time ..." effect) @@ -287,6 +291,8 @@ public class GameAction { repParams.put("Cause", cause); repParams.put("Origin", zoneFrom != null ? zoneFrom.getZoneType() : null); repParams.put("Destination", zoneTo.getZoneType()); + + repParams.putAll(params); ReplacementResult repres = game.getReplacementHandler().run(repParams); if (repres != ReplacementResult.NotReplaced) { @@ -301,7 +307,7 @@ public class GameAction { if (game.getStack().isResolving(c) && !zoneTo.is(ZoneType.Graveyard) && repres == ReplacementResult.Prevented) { copied.getOwner().removeInboundToken(copied); - return moveToGraveyard(c, cause); + return moveToGraveyard(c, cause, params); } copied.getOwner().removeInboundToken(copied); return c; @@ -385,11 +391,13 @@ public class GameAction { runParams.put("Destination", zoneTo.getZoneType().name()); runParams.put("SpellAbilityStackInstance", game.stack.peek()); runParams.put("IndividualCostPaymentInstance", game.costPaymentStack.peek()); + runParams.putAll(params); game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams, true); if (zoneFrom != null && zoneFrom.is(ZoneType.Battlefield)) { final Map runParams2 = Maps.newHashMap(); runParams2.put("Card", lastKnownInfo); runParams2.put("OriginalController", zoneFrom.getPlayer()); + runParams2.putAll(params); game.getTriggerHandler().runTrigger(TriggerType.ChangesController, runParams2, false); } // AllZone.getStack().chooseOrderOfSimultaneousStackEntryAll(); @@ -444,7 +452,7 @@ public class GameAction { // Ask controller if it wants to be on top or bottom of other meld. unmeldPosition++; } - changeZone(null, zoneTo, unmeld, position, cause); + changeZone(null, zoneTo, unmeld, position, cause, params); } // Reveal if face-down if (c.isFaceDown()) { @@ -527,12 +535,20 @@ public class GameAction { } public final Card moveTo(final Zone zoneTo, Card c, SpellAbility cause) { + return moveTo(zoneTo, c, cause, Maps.newHashMap()); + } + + public final Card moveTo(final Zone zoneTo, Card c, SpellAbility cause, Map params) { // FThreads.assertExecutedByEdt(false); // This code must never be executed from EDT, // use FThreads.invokeInNewThread to run code in a pooled thread - return moveTo(zoneTo, c, null, cause); + return moveTo(zoneTo, c, null, cause, params); } public final Card moveTo(final Zone zoneTo, Card c, Integer position, SpellAbility cause) { + return moveTo(zoneTo, c, position, cause, Maps.newHashMap()); + } + + public final Card moveTo(final Zone zoneTo, Card c, Integer position, SpellAbility cause, Map params) { // Ideally move to should never be called without a prevZone // Remove card from Current Zone, if it has one final Zone zoneFrom = game.getZoneOf(c); @@ -540,7 +556,7 @@ public class GameAction { // Card lastKnownInfo = c; - c = changeZone(zoneFrom, zoneTo, c, position, cause); + c = changeZone(zoneFrom, zoneTo, c, position, cause, params); if (zoneFrom == null) { c.setCastFrom(null); @@ -605,81 +621,126 @@ public class GameAction { } public final Card moveToStack(final Card c, SpellAbility cause) { + return moveToStack(c, cause, Maps.newHashMap()); + } + public final Card moveToStack(final Card c, SpellAbility cause, Map params) { final Zone stack = game.getStackZone(); - return moveTo(stack, c, cause); + return moveTo(stack, c, cause, params); } public final Card moveToGraveyard(final Card c, SpellAbility cause) { + return moveToGraveyard(c, cause, Maps.newHashMap()); + } + public final Card moveToGraveyard(final Card c, SpellAbility cause, Map params) { final PlayerZone grave = c.getOwner().getZone(ZoneType.Graveyard); // must put card in OWNER's graveyard not controller's - return moveTo(grave, c, cause); + return moveTo(grave, c, cause, params); } public final Card moveToHand(final Card c, SpellAbility cause) { + return moveToHand(c, cause, Maps.newHashMap()); + } + + public final Card moveToHand(final Card c, SpellAbility cause, Map params) { final PlayerZone hand = c.getOwner().getZone(ZoneType.Hand); - return moveTo(hand, c, cause); + return moveTo(hand, c, cause, params); } public final Card moveToPlay(final Card c, SpellAbility cause) { + return moveToPlay(c, cause, Maps.newHashMap()); + } + + public final Card moveToPlay(final Card c, SpellAbility cause, Map params) { final PlayerZone play = c.getController().getZone(ZoneType.Battlefield); - return moveTo(play, c, cause); + return moveTo(play, c, cause, params); } public final Card moveToPlay(final Card c, final Player p, SpellAbility cause) { + return moveToPlay(c, p, cause, Maps.newHashMap()); + } + + public final Card moveToPlay(final Card c, final Player p, SpellAbility cause, Map params) { // move to a specific player's Battlefield final PlayerZone play = p.getZone(ZoneType.Battlefield); - return moveTo(play, c, cause); + return moveTo(play, c, cause, params); } public final Card moveToBottomOfLibrary(final Card c, SpellAbility cause) { - return moveToLibrary(c, -1, cause); + return moveToBottomOfLibrary(c, cause, Maps.newHashMap()); + } + + public final Card moveToBottomOfLibrary(final Card c, SpellAbility cause, Map params) { + return moveToLibrary(c, -1, cause, params); } public final Card moveToLibrary(final Card c, SpellAbility cause) { - return moveToLibrary(c, 0, cause); + return moveToLibrary(c, cause, Maps.newHashMap()); + } + + public final Card moveToLibrary(final Card c, SpellAbility cause, Map params) { + return moveToLibrary(c, 0, cause, params); } public final Card moveToLibrary(Card c, int libPosition, SpellAbility cause) { + return moveToLibrary(c, libPosition, cause, Maps.newHashMap()); + } + + public final Card moveToLibrary(Card c, int libPosition, SpellAbility cause, Map params) { final PlayerZone library = c.getOwner().getZone(ZoneType.Library); if (libPosition == -1 || libPosition > library.size()) { libPosition = library.size(); } - return changeZone(game.getZoneOf(c), library, c, libPosition, cause); + return changeZone(game.getZoneOf(c), library, c, libPosition, cause, params); } public final Card moveToVariantDeck(Card c, ZoneType zone, int deckPosition, SpellAbility cause) { + return moveToVariantDeck(c, zone, deckPosition, cause, Maps.newHashMap()); + } + + public final Card moveToVariantDeck(Card c, ZoneType zone, int deckPosition, SpellAbility cause, Map params) { final PlayerZone deck = c.getOwner().getZone(zone); if (deckPosition == -1 || deckPosition > deck.size()) { deckPosition = deck.size(); } - return changeZone(game.getZoneOf(c), deck, c, deckPosition, cause); + return changeZone(game.getZoneOf(c), deck, c, deckPosition, cause, params); } public final Card exile(final Card c, SpellAbility cause) { + return exile(c, cause, Maps.newHashMap()); + } + public final Card exile(final Card c, SpellAbility cause, Map params) { if (game.isCardExiled(c)) { return c; } final PlayerZone removed = c.getOwner().getZone(ZoneType.Exile); - return moveTo(removed, c, cause); + return moveTo(removed, c, cause, params); } public final Card moveTo(final ZoneType name, final Card c, SpellAbility cause) { - return moveTo(name, c, 0, cause); + return moveTo(name, c, cause, Maps.newHashMap()); + } + + public final Card moveTo(final ZoneType name, final Card c, SpellAbility cause, Map params) { + return moveTo(name, c, 0, cause, params); + } + + public final Card moveTo(final ZoneType name, final Card c, final int libPosition, SpellAbility cause) { + return moveTo(name, c, libPosition, cause, Maps.newHashMap()); } - public final Card moveTo(final ZoneType name, final Card c, final int libPosition, SpellAbility cause) { + public final Card moveTo(final ZoneType name, final Card c, final int libPosition, SpellAbility cause, Map params) { // Call specific functions to set PlayerZone, then move onto moveTo switch(name) { - case Hand: return moveToHand(c, cause); - case Library: return moveToLibrary(c, libPosition, cause); - case Battlefield: return moveToPlay(c, cause); - case Graveyard: return moveToGraveyard(c, cause); - case Exile: return exile(c, cause); - case Stack: return moveToStack(c, cause); - case PlanarDeck: return moveToVariantDeck(c, ZoneType.PlanarDeck, libPosition, cause); - case SchemeDeck: return moveToVariantDeck(c, ZoneType.SchemeDeck, libPosition, cause); + case Hand: return moveToHand(c, cause, params); + case Library: return moveToLibrary(c, libPosition, cause, params); + case Battlefield: return moveToPlay(c, cause, params); + case Graveyard: return moveToGraveyard(c, cause, params); + case Exile: return exile(c, cause, params); + case Stack: return moveToStack(c, cause, params); + case PlanarDeck: return moveToVariantDeck(c, ZoneType.PlanarDeck, libPosition, cause, params); + case SchemeDeck: return moveToVariantDeck(c, ZoneType.SchemeDeck, libPosition, cause, params); default: // sideboard will also get there - return moveTo(c.getOwner().getZone(name), c, cause); + return moveTo(c.getOwner().getZone(name), c, cause, params); } } @@ -1034,7 +1095,7 @@ public class GameAction { if (!perm.isInZone(tgtZone) || !perm.canBeEnchantedBy(c, true) || (perm.isPhasedOut() && !c.isPhasedOut())) { c.unEnchantEntity(perm); - moveToGraveyard(c, null); + moveToGraveyard(c, null, Maps.newHashMap()); checkAgain = true; } } else if (entity instanceof Player) { @@ -1052,13 +1113,13 @@ public class GameAction { } if (invalid) { c.unEnchantEntity(pl); - moveToGraveyard(c, null); + moveToGraveyard(c, null, Maps.newHashMap()); checkAgain = true; } } if (c.isInPlay() && !c.isEnchanting()) { - moveToGraveyard(c, null); + moveToGraveyard(c, null, Maps.newHashMap()); checkAgain = true; } return checkAgain; @@ -1231,7 +1292,7 @@ public class GameAction { for (Card c : list) { if (c.getCounters(CounterType.LOYALTY) <= 0) { - moveToGraveyard(c, null); + moveToGraveyard(c, null, Maps.newHashMap()); // Play the Destroy sound game.fireEvent(new GameEventCardDestroyed()); recheck = true; @@ -1456,7 +1517,7 @@ public class GameAction { return null; } - final Card newCard = moveToGraveyard(c, cause); + final Card newCard = moveToGraveyard(c, cause, Maps.newHashMap()); return newCard; } @@ -1678,7 +1739,7 @@ public class GameAction { if (!isCommander) { toMulligan = new CardCollection(p.getCardsIn(ZoneType.Hand)); for (final Card c : toMulligan) { - moveToLibrary(c, null); + moveToLibrary(c, null, Maps.newHashMap()); } try { Thread.sleep(100); //delay for a tiny bit to give UI a chance catch up @@ -1690,7 +1751,7 @@ public class GameAction { } else { List toExile = Lists.newArrayList(toMulligan); for (Card c : toExile) { - exile(c, null); + exile(c, null, Maps.newHashMap()); } exiledDuringMulligans.addAll(p, toExile); try { @@ -1716,7 +1777,7 @@ public class GameAction { Player p = kv.getKey(); Collection cc = kv.getValue(); for (Card c : cc) { - moveToLibrary(c, null); + moveToLibrary(c, null, Maps.newHashMap()); } p.shuffle(null); } diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index c9e3cbdf6bf..b67d2f3fc5c 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -142,7 +142,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable params = Maps.newHashMap(); + params.put("StackSa", sa); + params.put("StackSi", si); + params.put("Fizzle", fizzle); + game.getAction().moveToGraveyard(source, null, params); } }