From a11e7bbcb8140f1804529ec1ca6f79b8865949f7 Mon Sep 17 00:00:00 2001 From: Sol Date: Thu, 6 Feb 2014 03:01:21 +0000 Subject: [PATCH] - Introduce PhaseIn and PhaseOut triggers - Added Teferi's Imp (as an example of both) --- .gitattributes | 3 ++ .../src/main/java/forge/game/card/Card.java | 17 +++++++- .../forge/game/trigger/TriggerPhaseIn.java | 34 ++++++++++++++++ .../forge/game/trigger/TriggerPhaseOut.java | 40 +++++++++++++++++++ .../java/forge/game/trigger/TriggerType.java | 2 + forge-gui/res/cardsfolder/t/teferis_imp.txt | 12 ++++++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 forge-game/src/main/java/forge/game/trigger/TriggerPhaseIn.java create mode 100644 forge-game/src/main/java/forge/game/trigger/TriggerPhaseOut.java create mode 100644 forge-gui/res/cardsfolder/t/teferis_imp.txt diff --git a/.gitattributes b/.gitattributes index 768da791148..87a5b996cbc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -590,6 +590,8 @@ forge-game/src/main/java/forge/game/trigger/TriggerLosesGame.java -text forge-game/src/main/java/forge/game/trigger/TriggerNewGame.java -text forge-game/src/main/java/forge/game/trigger/TriggerPayCumulativeUpkeep.java -text forge-game/src/main/java/forge/game/trigger/TriggerPhase.java svneol=native#text/plain +forge-game/src/main/java/forge/game/trigger/TriggerPhaseIn.java -text +forge-game/src/main/java/forge/game/trigger/TriggerPhaseOut.java -text forge-game/src/main/java/forge/game/trigger/TriggerPlanarDice.java -text forge-game/src/main/java/forge/game/trigger/TriggerPlaneswalkedFrom.java -text forge-game/src/main/java/forge/game/trigger/TriggerPlaneswalkedTo.java -text @@ -12328,6 +12330,7 @@ forge-gui/res/cardsfolder/t/teferis_care.txt -text forge-gui/res/cardsfolder/t/teferis_curse.txt -text forge-gui/res/cardsfolder/t/teferis_drake.txt -text forge-gui/res/cardsfolder/t/teferis_honor_guard.txt -text +forge-gui/res/cardsfolder/t/teferis_imp.txt -text forge-gui/res/cardsfolder/t/teferis_isle.txt -text forge-gui/res/cardsfolder/t/teferis_moat.txt -text forge-gui/res/cardsfolder/t/teferis_puzzle_box.txt svneol=native#text/plain diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index c4735cb7f19..9824861b28f 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -4879,7 +4879,7 @@ public class Card extends GameEntity implements Comparable { final boolean phasingIn = this.isPhasedOut(); if (!this.switchPhaseState()) { - // Switch Phase State returns False if the Permanent can't Phase Out + // Switch Phase State bails early if the Permanent can't Phase Out return; } @@ -4913,6 +4913,15 @@ public class Card extends GameEntity implements Comparable { return false; } + final Map runParams = new TreeMap(); + runParams.put("Card", this); + + if (!this.isPhasedOut()) { + // If this is currently PhasedIn, it's about to phase out. + // Run trigger before it does because triggers don't work with phased out objects + getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false); + } + this.phasedOut = !this.phasedOut; final Combat combat = this.getGame().getPhaseHandler().getCombat(); if (combat != null && this.phasedOut) { @@ -4934,6 +4943,12 @@ public class Card extends GameEntity implements Comparable { getGame().getAction().exile(this); getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } + + if (!this.phasedOut) { + // Just phased in, time to run the phased in trigger + getGame().getTriggerHandler().runTrigger(TriggerType.PhaseIn, runParams, false); + } + return true; } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerPhaseIn.java b/forge-game/src/main/java/forge/game/trigger/TriggerPhaseIn.java new file mode 100644 index 00000000000..605eac13b11 --- /dev/null +++ b/forge-game/src/main/java/forge/game/trigger/TriggerPhaseIn.java @@ -0,0 +1,34 @@ +package forge.game.trigger; + +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +import java.util.Map; + +public class TriggerPhaseIn extends Trigger { + + public TriggerPhaseIn(final Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /** {@inheritDoc} */ + @Override + public final boolean performTest(final java.util.Map runParams2) { + final Card phaser = (Card) runParams2.get("Card"); + + if (this.mapParams.containsKey("ValidCard")) { + if (!phaser.isValid(this.mapParams.get("ValidCard").split(","), this.getHostCard().getController(), + this.getHostCard())) { + return false; + } + } + + return true; + } + + /** {@inheritDoc} */ + @Override + public final void setTriggeringObjects(final SpellAbility sa) { + sa.setTriggeringObject("Card", this.getRunParams().get("Card")); + } +} diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerPhaseOut.java b/forge-game/src/main/java/forge/game/trigger/TriggerPhaseOut.java new file mode 100644 index 00000000000..aefe9952010 --- /dev/null +++ b/forge-game/src/main/java/forge/game/trigger/TriggerPhaseOut.java @@ -0,0 +1,40 @@ +package forge.game.trigger; + +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +import java.util.Map; + +public class TriggerPhaseOut extends Trigger { + + public TriggerPhaseOut(final Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /** {@inheritDoc} */ + @Override + public final boolean performTest(final java.util.Map runParams2) { + final Card phaser = (Card) runParams2.get("Card"); + + if (this.mapParams.containsKey("ValidCard")) { + if (this.mapParams.get("ValidCard").equals("Card.Self")) { + // Since Phased out cards aren't visible in .isValid, use a special check here. + // NOTE: All Phase Out Triggers should use ValidCard$ Card.Self + if (phaser != this.getHostCard()) { + return false; + } + } else if (!phaser.isValid(this.mapParams.get("ValidCard").split(","), this.getHostCard().getController(), + this.getHostCard())) { + return false; + } + } + + return true; + } + + /** {@inheritDoc} */ + @Override + public final void setTriggeringObjects(final SpellAbility sa) { + sa.setTriggeringObject("Card", this.getRunParams().get("Card")); + } +} diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java index f2af44940d2..4688292cc04 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java @@ -46,6 +46,8 @@ public enum TriggerType { NewGame(TriggerNewGame.class), PayCumulativeUpkeep(TriggerPayCumulativeUpkeep.class), Phase(TriggerPhase.class), + PhaseIn(TriggerPhaseIn.class), + PhaseOut(TriggerPhaseOut.class), PlanarDice(TriggerPlanarDice.class), PlaneswalkedFrom(TriggerPlaneswalkedFrom.class), PlaneswalkedTo(TriggerPlaneswalkedTo.class), diff --git a/forge-gui/res/cardsfolder/t/teferis_imp.txt b/forge-gui/res/cardsfolder/t/teferis_imp.txt new file mode 100644 index 00000000000..9509710543f --- /dev/null +++ b/forge-gui/res/cardsfolder/t/teferis_imp.txt @@ -0,0 +1,12 @@ +Name:Teferi's Imp +ManaCost:2 U +Types:Creature Imp +PT:1/1 +K:Flying +K:Phasing +T:Mode$ PhaseOut | ValidCard$ Card.Self | Execute$ TrigDiscard | TriggerDescription$ Whenever CARDNAME phases out, discard a card. +SVar:TrigDiscard:DB$ Discard | Defined$ You | Mode$ TgtChoose | NumCards$ 1 +T:Mode$ PhaseIn | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ Whenever CARDNAME phases in, draw a card. +SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 +SVar:Picture:http://www.wizards.com/global/images/magic/general/teferis_imp.jpg +Oracle:Flying\nPhasing (This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist.)\nWhenever Teferi's Imp phases out, discard a card.\nWhenever Teferi's Imp phases in, draw a card.