diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index 1821f5a547a..fd51609471a 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -39,6 +39,7 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Table; import com.google.common.eventbus.EventBus; +import forge.GameCommand; import forge.card.CardRarity; import forge.card.CardStateName; import forge.card.CardType.Supertype; @@ -99,6 +100,8 @@ public class Game { public final Phase endOfTurn; public final Untap untap; public final Phase upkeep; + // to execute commands for "current" phase each time state based action is checked + public final List sbaCheckedCommandList; public final MagicStack stack; public final CostPaymentStack costPaymentStack = new CostPaymentStack(); private final PhaseHandler phaseHandler; @@ -308,6 +311,8 @@ public class Game { endOfCombat = new Phase(PhaseType.COMBAT_END); endOfTurn = new Phase(PhaseType.END_OF_TURN); + sbaCheckedCommandList = new ArrayList<>(); + // update players view.updatePlayers(this); @@ -382,6 +387,17 @@ public class Game { return cleanup; } + public void addSBACheckedCommand(final GameCommand c) { + sbaCheckedCommandList.add(c); + } + public final void runSBACheckedCommands() { + for (final GameCommand c : sbaCheckedCommandList) { + c.run(); + } + sbaCheckedCommandList.clear(); + } + + public final PhaseHandler getPhaseHandler() { return phaseHandler; } diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 42080ebc811..bb0f8937db3 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import forge.game.spellability.SpellAbilityStackInstance; import org.apache.commons.lang3.tuple.ImmutablePair; import com.google.common.base.Predicate; @@ -1158,11 +1157,7 @@ public class GameAction { // sol(10/29) added for Phase updates, state effects shouldn't be // checked during Spell Resolution (except when persist-returning if (game.getStack().isResolving()) { - Iterator it = game.getStack().iterator(); - SpellAbility top = it.next().getSpellAbility(true); - if (!top.hasParam("CheckStates") && !top.getSubAbility().hasParam("CheckStates")) { - return; - } + return; } if (game.isGameOver()) { @@ -1376,6 +1371,9 @@ public class GameAction { if (!refreeze) { game.getStack().unfreezeStack(); } + + // Run all commands that are queued to run after state based actions are checked + game.runSBACheckedCommands(); } private boolean stateBasedAction_Saga(Card c, CardZoneTable table) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java index 9da9fa7df9c..809c3d775e6 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java @@ -283,31 +283,24 @@ public class EffectEffect extends SpellAbilityEffect { if ((duration == null) || duration.equals("EndOfTurn")) { game.getEndOfTurn().addUntil(endEffect); - } - else if (duration.equals("UntilHostLeavesPlay")) { + } else if (duration.equals("UntilHostLeavesPlay")) { hostCard.addLeavesPlayCommand(endEffect); - } - else if (duration.equals("UntilHostLeavesPlayOrEOT")) { + } else if (duration.equals("UntilHostLeavesPlayOrEOT")) { game.getEndOfTurn().addUntil(endEffect); hostCard.addLeavesPlayCommand(endEffect); - } - else if (duration.equals("UntilYourNextTurn")) { + } else if (duration.equals("UntilYourNextTurn")) { game.getCleanup().addUntil(controller, endEffect); - } - else if (duration.equals("UntilYourNextUpkeep")) { + } else if (duration.equals("UntilYourNextUpkeep")) { game.getUpkeep().addUntil(controller, endEffect); - } - else if (duration.equals("UntilEndOfCombat")) { + } else if (duration.equals("UntilEndOfCombat")) { game.getEndOfCombat().addUntil(endEffect); - } - else if (duration.equals("UntilTheEndOfYourNextTurn")) { + } else if (duration.equals("UntilTheEndOfYourNextTurn")) { if (game.getPhaseHandler().isPlayerTurn(controller)) { game.getEndOfTurn().registerUntilEnd(controller, endEffect); } else { game.getEndOfTurn().addUntilEnd(controller, endEffect); } - } - else if (duration.equals("ThisTurnAndNextTurn")) { + } else if (duration.equals("ThisTurnAndNextTurn")) { game.getUntap().addAt(new GameCommand() { private static final long serialVersionUID = -5054153666503075717L; @@ -316,6 +309,8 @@ public class EffectEffect extends SpellAbilityEffect { game.getEndOfTurn().addUntil(endEffect); } }); + } else if (duration.equals("UntilStateBasedActionChecked")) { + game.addSBACheckedCommand(endEffect); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java index 39aa63f34bb..562c1fa85a5 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java @@ -15,7 +15,6 @@ import forge.game.player.Player; import forge.game.replacement.ReplacementType; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; -import forge.game.zone.ZoneType; import forge.util.CardTranslation; import forge.util.Localizer; @@ -78,24 +77,6 @@ public class FightEffect extends DamageBaseEffect { final Map runParams = AbilityKey.newMap(); runParams.put(AbilityKey.Fighters, fighters); game.getTriggerHandler().runTrigger(TriggerType.FightOnce, runParams, false); - - if (sa.hasParam("ConditionWinnerDefined")) { - Card mustWin = AbilityUtils.getDefinedCards(host, sa.getParam("ConditionWinnerDefined"), sa).get(0); - Card mustLose = null; - for (Card l : fighters) { - if (l != mustWin) { - mustLose = l; - } - } - game.getAction().checkStateEffects(true); - SpellAbility sub = sa.getAdditionalAbility("WinSubAbility"); - if (mustWin.getZone().getZoneType().equals(ZoneType.Battlefield) && mustLose != null && - !mustLose.getZone().getZoneType().equals(ZoneType.Battlefield)) { - if (sub != null) { - AbilityUtils.resolve(sub); - } - } - } } private static List getFighters(SpellAbility sa) { diff --git a/forge-gui/res/cardsfolder/upcoming/skyshroud_ambush.txt b/forge-gui/res/cardsfolder/upcoming/skyshroud_ambush.txt index 368f29b64fd..5a93b826b81 100644 --- a/forge-gui/res/cardsfolder/upcoming/skyshroud_ambush.txt +++ b/forge-gui/res/cardsfolder/upcoming/skyshroud_ambush.txt @@ -2,8 +2,9 @@ Name:Skyshroud Ambush ManaCost:1 G Types:Instant A:SP$ Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Choose target creature you control | ImprintCards$ ThisTargetedCard | SubAbility$ DBFight | StackDescription$ Target creature you control [{c:ThisTargetedCard}] | SpellDescription$ Target creature you control fights target creature you don't control. When the creature you control wins the fight, draw a card. -SVar:DBFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control | RememberObjects$ ThisTargetedCard | ConditionWinnerDefined$ Imprinted | WinSubAbility$ DBImmediateTrigger | CheckStates$ True | SubAbility$ DBCleanup | StackDescription$ fights target creature you don't control [{c:ThisTargetedCard}]. When the creature you control wins the fight, draw a card. -SVar:DBImmediateTrigger:DB$ ImmediateTrigger | Execute$ TrigDraw | Secondary$ True | StackDescription$ None | TriggerDescription$ When the creature you control wins the fight, draw a card. +SVar:DBFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control | RememberObjects$ ThisTargetedCard | SubAbility$ DBEffect | StackDescription$ fights target creature you don't control [{c:ThisTargetedCard}]. When the creature you control wins the fight, draw a card. +SVar:DBEffect:DB$ Effect | Triggers$ TrigWin | RememberObjects$ Remembered | ImprintCards$ Imprinted | Duration$ UntilStateBasedActionChecked | SubAbility$ DBCleanup +SVar:TrigWin:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Creature.IsRemembered | IsPresent$ Creature.IsImprinted | NoResolvingCheck$ True | Execute$ TrigDraw | TriggerDescription$ When the creature you control wins the fight, draw a card. SVar:TrigDraw:DB$ Draw | NumCards$ 1 SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True Oracle:Target creature you control fights target creature you don't control. When the creature you control wins the fight, draw a card.