From fb27a0d9561f16fbac3c6be16c20b7b630b07cf0 Mon Sep 17 00:00:00 2001 From: Sol Date: Tue, 8 Jan 2013 04:29:56 +0000 Subject: [PATCH] - Force certain triggers to wait for the next WaitingTrigger run (e.g. Fix Balefire Liege issue), there may be a few more of these that need to be forced - Fixed "BecomesTarget" triggering for the same Object more than once for the same spell --- src/main/java/forge/Card.java | 16 +++++----- src/main/java/forge/GameAction.java | 10 +++--- .../abilityfactory/effects/ClashEffect.java | 2 +- .../card/cardfactory/CardFactoryUtil.java | 2 +- .../card/spellability/AbilityManaPart.java | 2 +- .../card/spellability/SpellPermanent.java | 2 +- .../forge/card/trigger/TriggerHandler.java | 5 +-- src/main/java/forge/game/GameState.java | 2 +- src/main/java/forge/game/phase/Combat.java | 2 +- .../java/forge/game/phase/CombatUtil.java | 8 ++--- .../java/forge/game/phase/PhaseHandler.java | 2 +- src/main/java/forge/game/phase/PhaseUtil.java | 2 +- src/main/java/forge/game/player/Player.java | 16 +++++----- src/main/java/forge/game/zone/MagicStack.java | 31 ++++++++++++------- 14 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 5279b77c750..0accbc218d8 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -269,7 +269,7 @@ public class Card extends GameEntity implements Comparable { || (cur == CardCharacteristicName.Transformed && state == CardCharacteristicName.Original)) { HashMap runParams = new HashMap(); runParams.put("Transformer", this); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false); } return true; @@ -375,7 +375,7 @@ public class Card extends GameEntity implements Comparable { // Run triggers final Map runParams = new TreeMap(); runParams.put("Card", this); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, runParams, false); } return result; } @@ -1243,7 +1243,7 @@ public class Card extends GameEntity implements Comparable { runParams.put("Card", this); runParams.put("CounterType", counterType); for (int i = 0; i < addAmount; i++) { - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, runParams, false); } // play the Add Counter sound @@ -1282,7 +1282,7 @@ public class Card extends GameEntity implements Comparable { runParams.put("Card", this); runParams.put("CounterType", counterName); for (int i = 0; i < delta; i++) { - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams, false); } if (counterName.equals(CounterType.TIME) && (newValue == 0)) { @@ -3834,7 +3834,7 @@ public class Card extends GameEntity implements Comparable { final Map runParams = new TreeMap(); runParams.put("Equipment", this); runParams.put("Card", c); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Unequip, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Unequip, runParams, false); } /** @@ -4838,7 +4838,7 @@ public class Card extends GameEntity implements Comparable { // Run triggers final Map runParams = new TreeMap(); runParams.put("Card", this); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams, false); } this.setTapped(true); @@ -4856,7 +4856,7 @@ public class Card extends GameEntity implements Comparable { // Run triggers final Map runParams = new TreeMap(); runParams.put("Card", this); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, runParams, false); // Play the Untap sound Singletons.getModel().getGame().getEvents().post(new SetTappedEvent(false)); @@ -8278,7 +8278,7 @@ public class Card extends GameEntity implements Comparable { runParams.put("DamageTarget", this); runParams.put("DamageAmount", damageToAdd); runParams.put("IsCombatDamage", isCombat); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false); if (this.isPlaneswalker()) { this.subtractCounter(CounterType.LOYALTY, damageToAdd); diff --git a/src/main/java/forge/GameAction.java b/src/main/java/forge/GameAction.java index 855c436f2d1..080ff45209b 100644 --- a/src/main/java/forge/GameAction.java +++ b/src/main/java/forge/GameAction.java @@ -237,7 +237,7 @@ public class GameAction { runParams.put("Origin", null); } runParams.put("Destination", zoneTo.getZoneType().name()); - game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams); + game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams, false); // AllZone.getStack().chooseOrderOfSimultaneousStackEntryAll(); if (suppress) { @@ -443,7 +443,7 @@ public class GameAction { final HashMap runParams = new HashMap(); runParams.put("Card", c); - game.getTriggerHandler().runTrigger(TriggerType.ChangesController, runParams); + game.getTriggerHandler().runTrigger(TriggerType.ChangesController, runParams, false); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); for (Player p : game.getPlayers()) { @@ -700,7 +700,7 @@ public class GameAction { runParams.put("Origin", null); } runParams.put("Destination", ZoneType.Library.name()); - game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams); + game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams, false); if (p != null) { p.updateLabelObservers(); @@ -1050,7 +1050,7 @@ public class GameAction { this.checkStaticAbilities(); final HashMap runParams = new HashMap(); - game.getTriggerHandler().runTrigger(TriggerType.Always, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Always, runParams, false); for (Card c : game.getCardsIn(ZoneType.Battlefield)) { @@ -1292,7 +1292,7 @@ public class GameAction { // Run triggers final HashMap runParams = new HashMap(); runParams.put("Card", c); - game.getTriggerHandler().runTrigger(TriggerType.Sacrificed, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Sacrificed, runParams, false); return true; } diff --git a/src/main/java/forge/card/abilityfactory/effects/ClashEffect.java b/src/main/java/forge/card/abilityfactory/effects/ClashEffect.java index 41b9244ed60..e81f568d119 100644 --- a/src/main/java/forge/card/abilityfactory/effects/ClashEffect.java +++ b/src/main/java/forge/card/abilityfactory/effects/ClashEffect.java @@ -53,7 +53,7 @@ public class ClashEffect extends SpellEffect { runParams.put("Won", "False"); } - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Clashed, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Clashed, runParams, false); } } diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 7ce823d9b9c..f11abc96890 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -1247,7 +1247,7 @@ public class CardFactoryUtil { final HashMap runParams = new HashMap(); runParams.put("Card", spell.getSourceCard()); runParams.put("Championed", card); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Championed, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Championed, runParams, false); } } } // selectCard() diff --git a/src/main/java/forge/card/spellability/AbilityManaPart.java b/src/main/java/forge/card/spellability/AbilityManaPart.java index e4a01a8eaea..3731cdfb86f 100644 --- a/src/main/java/forge/card/spellability/AbilityManaPart.java +++ b/src/main/java/forge/card/spellability/AbilityManaPart.java @@ -144,7 +144,7 @@ public class AbilityManaPart implements java.io.Serializable { runParams.put("Player", player); runParams.put("AbilityMana", sa); runParams.put("Produced", produced); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.TapsForMana, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.TapsForMana, runParams, false); } // end produceMana(String) diff --git a/src/main/java/forge/card/spellability/SpellPermanent.java b/src/main/java/forge/card/spellability/SpellPermanent.java index 84f455821a6..eb5b9add312 100644 --- a/src/main/java/forge/card/spellability/SpellPermanent.java +++ b/src/main/java/forge/card/spellability/SpellPermanent.java @@ -120,7 +120,7 @@ public class SpellPermanent extends Spell { final HashMap runParams = new HashMap(); runParams.put("Card", source); runParams.put("Championed", source.getChampionedCard()); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Championed, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Championed, runParams, false); } else { Singletons.getModel().getGame().getAction().sacrifice(this.getSourceCard(), null); } diff --git a/src/main/java/forge/card/trigger/TriggerHandler.java b/src/main/java/forge/card/trigger/TriggerHandler.java index 879137db766..f7c3f1b300f 100644 --- a/src/main/java/forge/card/trigger/TriggerHandler.java +++ b/src/main/java/forge/card/trigger/TriggerHandler.java @@ -262,8 +262,9 @@ public class TriggerHandler { * a {@link java.lang.String} object. * @param runParams * a {@link java.util.Map} object. + * @param forceHeldTriggers Force certain triggers to be added the waitingTriggers if stack isnt frozen */ - public final void runTrigger(final TriggerType mode, final Map runParams) { + public final void runTrigger(final TriggerType mode, final Map runParams, boolean holdTrigger) { if (this.suppressedModes.contains(mode)) { return; } @@ -272,7 +273,7 @@ public class TriggerHandler { //runWaitingTrigger(new TriggerWaiting(mode, runParams)); - if (game.getStack().isFrozen()) { + if (game.getStack().isFrozen() || holdTrigger) { waitingTriggers.add(new TriggerWaiting(mode, runParams)); } else { runWaitingTrigger(new TriggerWaiting(mode, runParams), true); diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java index c758e17e4c4..24341bfa807 100644 --- a/src/main/java/forge/game/GameState.java +++ b/src/main/java/forge/game/GameState.java @@ -502,7 +502,7 @@ public class GameState { final Map runParams = new TreeMap(); runParams.put("Player", p); - this.getTriggerHandler().runTrigger(TriggerType.LosesGame, runParams); + this.getTriggerHandler().runTrigger(TriggerType.LosesGame, runParams, false); } diff --git a/src/main/java/forge/game/phase/Combat.java b/src/main/java/forge/game/phase/Combat.java index 1d9e3e7854c..b3277f22cb0 100644 --- a/src/main/java/forge/game/phase/Combat.java +++ b/src/main/java/forge/game/phase/Combat.java @@ -676,7 +676,7 @@ public class Combat { // Run Unblocked Trigger final HashMap runParams = new HashMap(); runParams.put("Attacker", attacker); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false); } } diff --git a/src/main/java/forge/game/phase/CombatUtil.java b/src/main/java/forge/game/phase/CombatUtil.java index dcb5563bd6e..e69ed9e5618 100644 --- a/src/main/java/forge/game/phase/CombatUtil.java +++ b/src/main/java/forge/game/phase/CombatUtil.java @@ -2799,7 +2799,7 @@ public class CombatUtil { otherAttackers.remove(c); runParams.put("OtherAttackers", otherAttackers); runParams.put("Attacked", Singletons.getModel().getGame().getCombat().getDefenderByAttacker(c)); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Attacks, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Attacks, runParams, false); // Annihilator: if (!c.getDamageHistory().getCreatureAttackedThisCombat()) { @@ -2917,7 +2917,7 @@ public class CombatUtil { // Run triggers final HashMap runParams = new HashMap(); runParams.put("Card", c); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false); } /** @@ -2958,12 +2958,12 @@ public class CombatUtil { final HashMap runParams = new HashMap(); runParams.put("Attacker", a); runParams.put("Blocker", b); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Blocks, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Blocks, runParams, false); if (!a.getDamageHistory().getCreatureGotBlockedThisCombat()) { final int blockers = Singletons.getModel().getGame().getCombat().getBlockers(a).size(); runParams.put("NumBlockers", blockers); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackerBlocked, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackerBlocked, runParams, false); // Bushido for (final Ability ab : CardFactoryUtil.getBushidoEffects(a)) { diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 8d6ca1fe19b..247db3836dc 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -395,7 +395,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { final HashMap runParams = new HashMap(); runParams.put("Phase", this.getPhase().Name); runParams.put("Player", this.getPlayerTurn()); - game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams, false); } diff --git a/src/main/java/forge/game/phase/PhaseUtil.java b/src/main/java/forge/game/phase/PhaseUtil.java index f3830c35258..1c51b778181 100644 --- a/src/main/java/forge/game/phase/PhaseUtil.java +++ b/src/main/java/forge/game/phase/PhaseUtil.java @@ -200,7 +200,7 @@ public class PhaseUtil { final HashMap runParams = new HashMap(); runParams.put("Attackers", list); runParams.put("AttackingPlayer", Singletons.getModel().getGame().getCombat().getAttackingPlayer()); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackersDeclared, runParams); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.AttackersDeclared, runParams, false); for (final Card c : list) { CombatUtil.checkDeclareAttackers(c); diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index 0f77ebf746a..69bb8f4ea84 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -256,7 +256,7 @@ public abstract class Player extends GameEntity implements Comparable { // Run triggers final HashMap runParams = new HashMap(); runParams.put("Scheme", activeScheme); - game.getTriggerHandler().runTrigger(TriggerType.SetInMotion, runParams); + game.getTriggerHandler().runTrigger(TriggerType.SetInMotion, runParams, false); } /** @@ -458,7 +458,7 @@ public abstract class Player extends GameEntity implements Comparable { final HashMap runParams = new HashMap(); runParams.put("Player", this); runParams.put("LifeAmount", lifeGain); - game.getTriggerHandler().runTrigger(TriggerType.LifeGained, runParams); + game.getTriggerHandler().runTrigger(TriggerType.LifeGained, runParams, false); } else { System.out.println("Player - trying to gain negative or 0 life"); } @@ -514,7 +514,7 @@ public abstract class Player extends GameEntity implements Comparable { final HashMap runParams = new HashMap(); runParams.put("Player", this); runParams.put("LifeAmount", toLose); - game.getTriggerHandler().runTrigger(TriggerType.LifeLost, runParams); + game.getTriggerHandler().runTrigger(TriggerType.LifeLost, runParams, false); return lifeLost; } @@ -654,7 +654,7 @@ public abstract class Player extends GameEntity implements Comparable { runParams.put("DamageTarget", this); runParams.put("DamageAmount", damageToDo); runParams.put("IsCombatDamage", isCombat); - game.getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams); + game.getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false); return true; } @@ -1438,7 +1438,7 @@ public abstract class Player extends GameEntity implements Comparable { final HashMap runParams = new HashMap(); runParams.put("Card", c); runParams.put("Number", this.numDrawnThisTurn); - game.getTriggerHandler().runTrigger(TriggerType.Drawn, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Drawn, runParams, false); } // lose: else if (!Preferences.DEV_MODE || Singletons.getModel().getPreferences().getPrefBoolean(FPref.DEV_MILLING_LOSS)) { @@ -1723,7 +1723,7 @@ public abstract class Player extends GameEntity implements Comparable { runParams.put("Player", this); runParams.put("Card", c); runParams.put("Cause", cause); - game.getTriggerHandler().runTrigger(TriggerType.Discarded, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Discarded, runParams, false); } // end doDiscard @@ -1895,7 +1895,7 @@ public abstract class Player extends GameEntity implements Comparable { // Run triggers final HashMap runParams = new HashMap(); runParams.put("Player", this); - game.getTriggerHandler().runTrigger(TriggerType.Shuffled, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Shuffled, runParams, false); // Play the shuffle sound Singletons.getModel().getGame().getEvents().post(new ShuffleEvent()); @@ -1963,7 +1963,7 @@ public abstract class Player extends GameEntity implements Comparable { // Run triggers final HashMap runParams = new HashMap(); runParams.put("Card", land); - game.getTriggerHandler().runTrigger(TriggerType.LandPlayed, runParams); + game.getTriggerHandler().runTrigger(TriggerType.LandPlayed, runParams, false); } game.getStack().unfreezeStack(); diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index 407406691fc..1b52ca7b8bf 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -19,6 +19,7 @@ package forge.game.zone; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Stack; @@ -694,40 +695,48 @@ public class MagicStack extends MyObservable { // run for them. if (!sp.getSourceCard().isCopiedSpell() && !(sp instanceof AbilityStatic) && !sp.isCopied()) { // Run SpellAbilityCast triggers - final HashMap runParams = new HashMap(); + HashMap runParams = new HashMap(); runParams.put("Cost", sp.getPayCosts()); runParams.put("Player", sp.getSourceCard().getController()); runParams.put("Activator", sp.getActivatingPlayer()); runParams.put("CastSA", sp); - game.getTriggerHandler().runTrigger(TriggerType.SpellAbilityCast, runParams); + game.getTriggerHandler().runTrigger(TriggerType.SpellAbilityCast, runParams, true); // Run SpellCast triggers if (sp.isSpell()) { - game.getTriggerHandler().runTrigger(TriggerType.SpellCast, runParams); + game.getTriggerHandler().runTrigger(TriggerType.SpellCast, runParams, true); } // Run AbilityCast triggers if (sp.isAbility() && !sp.isTrigger()) { - game.getTriggerHandler().runTrigger(TriggerType.AbilityCast, runParams); + game.getTriggerHandler().runTrigger(TriggerType.AbilityCast, runParams, true); } // Run Cycled triggers if (sp.isCycling()) { runParams.clear(); runParams.put("Card", sp.getSourceCard()); - game.getTriggerHandler().runTrigger(TriggerType.Cycled, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Cycled, runParams, false); } // Run BecomesTarget triggers - runParams.clear(); + // Create a new object, since the triggers aren't happening right away + runParams = new HashMap(); runParams.put("SourceSA", sp); - if (chosenTargets.size() > 0) { + if (chosenTargets.size() > 0) { + HashSet distinctObjects = new HashSet(); for (final TargetChoices tc : chosenTargets) { if ((tc != null) && (tc.getTargetCards() != null)) { for (final Object tgt : tc.getTargets()) { + // Track distinct objects so Becomes targets don't trigger for things like: + // Seeds of Strength or Pyrotechnics + if (distinctObjects.contains(tgt)) { + continue; + } + + distinctObjects.add(tgt); runParams.put("Target", tgt); - - game.getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams); + game.getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams, false); } } } @@ -738,11 +747,11 @@ public class MagicStack extends MyObservable { else if (sp.getTargetCard() != null) { runParams.put("Target", sp.getTargetCard()); - game.getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams); + game.getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams, false); } else if (sp.getTargetPlayer() != null) { runParams.put("Target", sp.getTargetPlayer()); - game.getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams); + game.getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams, false); } }