diff --git a/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java index 44d101cfcc6..ec85e8a38d3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java @@ -89,9 +89,10 @@ public void resolve(SpellAbility sa) { list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa); + CardCollectionView lastStateBattlefield = game.copyLastStateBattlefield(); Map params = AbilityKey.newMap(); - params.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield()); - CardZoneTable table = new CardZoneTable(game.getLastStateBattlefield(), game.getLastStateGraveyard()); + params.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); + CardZoneTable table = new CardZoneTable(lastStateBattlefield, game.getLastStateGraveyard()); params.put(AbilityKey.InternalTriggerTable, table); Map cachedMap = Maps.newHashMap(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java index fb571a3ec51..0c8567c3738 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java @@ -59,9 +59,10 @@ public void resolve(SpellAbility sa) { tgtCards = GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard, sa); + CardCollectionView lastStateBattlefield = game.copyLastStateBattlefield(); Map params = AbilityKey.newMap(); - params.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield()); - CardZoneTable table = getChangeZoneTable(sa, game.getLastStateBattlefield(), CardCollection.EMPTY); + params.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); + CardZoneTable table = getChangeZoneTable(sa, lastStateBattlefield, CardCollection.EMPTY); params.put(AbilityKey.InternalTriggerTable, table); Map cachedMap = Maps.newHashMap(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java index 44ed4ded06b..bf08822927f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java @@ -82,10 +82,11 @@ public void resolve(SpellAbility sa) { list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa); + CardCollectionView lastStateBattlefield = game.copyLastStateBattlefield(); Map cachedMap = Maps.newHashMap(); Map params = AbilityKey.newMap(); - params.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield()); - CardZoneTable table = new CardZoneTable(game.getLastStateBattlefield(), CardCollection.EMPTY); + params.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); + CardZoneTable table = new CardZoneTable(lastStateBattlefield, CardCollection.EMPTY); params.put(AbilityKey.InternalTriggerTable, table); for (Card sac : list) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java index da14f41f5a5..1fedd3c5990 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java @@ -100,9 +100,10 @@ public void resolve(SpellAbility sa) { final boolean destroy = sa.hasParam("Destroy"); final boolean remSacrificed = sa.hasParam("RememberSacrificed"); final boolean optional = sa.hasParam("Optional"); + CardCollectionView lastStateBattlefield = game.copyLastStateBattlefield(); Map params = AbilityKey.newMap(); - params.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield()); - CardZoneTable table = new CardZoneTable(game.getLastStateBattlefield(), CardCollection.EMPTY); + params.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); + CardZoneTable table = new CardZoneTable(lastStateBattlefield, CardCollection.EMPTY); params.put(AbilityKey.InternalTriggerTable, table); if (valid.equals("Self") && game.getZoneOf(card) != null) { diff --git a/forge-game/src/main/java/forge/game/card/CardZoneTable.java b/forge-game/src/main/java/forge/game/card/CardZoneTable.java index 663bde08fff..6d470d79e06 100644 --- a/forge-game/src/main/java/forge/game/card/CardZoneTable.java +++ b/forge-game/src/main/java/forge/game/card/CardZoneTable.java @@ -39,8 +39,8 @@ public CardZoneTable() { } public CardZoneTable(CardCollectionView lastStateBattlefield, CardCollectionView lastStateGraveyard) { - this.lastStateBattlefield = ObjectUtils.firstNonNull(lastStateBattlefield, CardCollection.EMPTY); - this.lastStateGraveyard = ObjectUtils.firstNonNull(lastStateGraveyard, CardCollection.EMPTY); + setLastStateBattlefield(ObjectUtils.firstNonNull(lastStateBattlefield, CardCollection.EMPTY)); + setLastStateGraveyard(ObjectUtils.firstNonNull(lastStateGraveyard, CardCollection.EMPTY)); } public CardCollectionView getLastStateBattlefield() { @@ -50,10 +50,11 @@ public CardCollectionView getLastStateGraveyard() { return lastStateGraveyard; } public void setLastStateBattlefield(CardCollectionView lastState) { - this.lastStateBattlefield = lastState; + // store it in a new object, it might be from Game which can also refresh itself + this.lastStateBattlefield = new CardCollection(lastState); } public void setLastStateGraveyard(CardCollectionView lastState) { - this.lastStateGraveyard = lastState; + this.lastStateGraveyard = new CardCollection(lastState); } /** diff --git a/forge-game/src/main/java/forge/game/cost/CostExile.java b/forge-game/src/main/java/forge/game/cost/CostExile.java index 07dd6a397f0..9bd992523fd 100644 --- a/forge-game/src/main/java/forge/game/cost/CostExile.java +++ b/forge-game/src/main/java/forge/game/cost/CostExile.java @@ -257,12 +257,11 @@ else if (type.contains("FromTopGrave")) { @Override protected Card doPayment(Player payer, SpellAbility ability, Card targetCard, final boolean effect) { - final Game game = targetCard.getGame(); Map moveParams = AbilityKey.newMap(); - moveParams.put(AbilityKey.LastStateBattlefield, game.getLastStateBattlefield()); - moveParams.put(AbilityKey.LastStateGraveyard, game.getLastStateGraveyard()); + moveParams.put(AbilityKey.LastStateBattlefield, table.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, table.getLastStateGraveyard()); moveParams.put(AbilityKey.InternalTriggerTable, table); - Card newCard = game.getAction().exile(targetCard, null, moveParams); + Card newCard = targetCard.getGame().getAction().exile(targetCard, null, moveParams); SpellAbilityEffect.handleExiledWith(newCard, ability); return newCard; } diff --git a/forge-game/src/main/java/forge/game/cost/CostPartWithList.java b/forge-game/src/main/java/forge/game/cost/CostPartWithList.java index 07745b56478..648b34c493f 100644 --- a/forge-game/src/main/java/forge/game/cost/CostPartWithList.java +++ b/forge-game/src/main/java/forge/game/cost/CostPartWithList.java @@ -118,8 +118,8 @@ public final boolean executePayment(Player payer, SpellAbility ability, Card tar // always returns true, made this to inline with return protected boolean executePayment(Player payer, SpellAbility ability, CardCollectionView targetCards, final boolean effect) { - table.setLastStateBattlefield(payer.getGame().getLastStateBattlefield()); - table.setLastStateGraveyard(payer.getGame().getLastStateGraveyard()); + table.setLastStateBattlefield(payer.getGame().copyLastStateBattlefield()); + table.setLastStateGraveyard(payer.getGame().copyLastStateGraveyard()); handleBeforePayment(payer, ability, targetCards); if (canPayListAtOnce()) { // This is used by reveal. Without it when opponent would reveal hand, you'll get N message boxes. diff --git a/forge-game/src/main/java/forge/game/cost/CostSacrifice.java b/forge-game/src/main/java/forge/game/cost/CostSacrifice.java index 1d75a3d0c5e..445673663bd 100644 --- a/forge-game/src/main/java/forge/game/cost/CostSacrifice.java +++ b/forge-game/src/main/java/forge/game/cost/CostSacrifice.java @@ -147,8 +147,8 @@ protected Card doPayment(Player payer, SpellAbility ability, Card targetCard, fi final Game game = targetCard.getGame(); // no table there, it is already handled by CostPartWithList Map moveParams = AbilityKey.newMap(); - moveParams.put(AbilityKey.LastStateBattlefield, game.getLastStateBattlefield()); - moveParams.put(AbilityKey.LastStateGraveyard, game.getLastStateGraveyard()); + moveParams.put(AbilityKey.LastStateBattlefield, table.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, table.getLastStateGraveyard()); moveParams.put(AbilityKey.InternalTriggerTable, table); return game.getAction().sacrifice(targetCard, ability, effect, moveParams); } 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 0cac96efda1..b5460630831 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -591,13 +591,9 @@ private final void finishResolving(final SpellAbility sa, final boolean fizzle) unfreezeStack(); sa.resetOnceResolved(); - //game.getAction().checkStaticAbilities(); game.getPhaseHandler().onStackResolved(); curResolvingCard = null; - - // xManaCostPaid will reset when cast the spell, comment out to fix Venarian Gold - // sa.getHostCard().setXManaCostPaid(0); } private final void removeCardFromStack(final SpellAbility sa, final SpellAbilityStackInstance si, final boolean fizzle) {