diff --git a/.gitattributes b/.gitattributes index ba4145634c8..db440e4e4ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -981,6 +981,7 @@ res/cardsfolder/b/breath_of_malfegor.txt svneol=native#text/plain res/cardsfolder/b/breathstealer.txt svneol=native#text/plain res/cardsfolder/b/breeding_pit.txt svneol=native#text/plain res/cardsfolder/b/breeding_pool.txt svneol=native#text/plain +res/cardsfolder/b/breezekeeper.txt -text res/cardsfolder/b/briar_patch.txt svneol=native#text/plain res/cardsfolder/b/briar_shield.txt svneol=native#text/plain res/cardsfolder/b/briarberry_cohort.txt svneol=native#text/plain @@ -1365,6 +1366,7 @@ res/cardsfolder/c/clifftop_retreat.txt -text res/cardsfolder/c/clinging_darkness.txt svneol=native#text/plain res/cardsfolder/c/cloak_of_confusion.txt svneol=native#text/plain res/cardsfolder/c/cloak_of_feathers.txt svneol=native#text/plain +res/cardsfolder/c/cloak_of_invisibility.txt -text res/cardsfolder/c/cloak_of_mists.txt svneol=native#text/plain res/cardsfolder/c/clock_of_omens.txt svneol=native#text/plain res/cardsfolder/c/clockwork_avian.txt -text @@ -1632,6 +1634,7 @@ res/cardsfolder/c/cryptic_command.txt svneol=native#text/plain res/cardsfolder/c/cryptwailing.txt svneol=native#text/plain res/cardsfolder/c/crystal_ball.txt svneol=native#text/plain res/cardsfolder/c/crystal_chimes.txt svneol=native#text/plain +res/cardsfolder/c/crystal_golem.txt -text res/cardsfolder/c/crystal_quarry.txt svneol=native#text/plain res/cardsfolder/c/crystal_rod.txt svneol=native#text/plain res/cardsfolder/c/crystal_seer.txt svneol=native#text/plain @@ -2092,6 +2095,7 @@ res/cardsfolder/d/dread_warlock.txt svneol=native#text/plain res/cardsfolder/d/dreadship_reef.txt svneol=native#text/plain res/cardsfolder/d/dreadwing.txt svneol=native#text/plain res/cardsfolder/d/dream_cache.txt svneol=native#text/plain +res/cardsfolder/d/dream_fighter.txt -text res/cardsfolder/d/dream_fracture.txt svneol=native#text/plain res/cardsfolder/d/dream_prowler.txt svneol=native#text/plain res/cardsfolder/d/dream_stalker.txt svneol=native#text/plain @@ -4834,6 +4838,7 @@ res/cardsfolder/m/merfolk_looter.txt svneol=native#text/plain res/cardsfolder/m/merfolk_mesmerist.txt svneol=native#text/plain res/cardsfolder/m/merfolk_observer.txt svneol=native#text/plain res/cardsfolder/m/merfolk_of_the_pearl_trident.txt svneol=native#text/plain +res/cardsfolder/m/merfolk_raiders.txt -text res/cardsfolder/m/merfolk_seastalkers.txt svneol=native#text/plain res/cardsfolder/m/merfolk_seer.txt svneol=native#text/plain res/cardsfolder/m/merfolk_skyscout.txt svneol=native#text/plain @@ -4969,6 +4974,7 @@ res/cardsfolder/m/mishras_groundbreaker.txt svneol=native#text/plain res/cardsfolder/m/mishras_helix.txt svneol=native#text/plain res/cardsfolder/m/misinformation.txt svneol=native#text/plain res/cardsfolder/m/misshapen_fiend.txt svneol=native#text/plain +res/cardsfolder/m/mist_dragon.txt -text res/cardsfolder/m/mist_leopard.txt svneol=native#text/plain res/cardsfolder/m/mistbind_clique.txt svneol=native#text/plain res/cardsfolder/m/mistblade_shinobi.txt svneol=native#text/plain @@ -6098,6 +6104,7 @@ res/cardsfolder/r/rain_of_rust.txt svneol=native#text/plain res/cardsfolder/r/rain_of_salt.txt svneol=native#text/plain res/cardsfolder/r/rain_of_tears.txt svneol=native#text/plain res/cardsfolder/r/rainbow_crow.txt -text +res/cardsfolder/r/rainbow_efreet.txt -text res/cardsfolder/r/rainbow_vale.txt svneol=native#text/plain res/cardsfolder/r/raise_dead.txt svneol=native#text/plain res/cardsfolder/r/raise_the_alarm.txt svneol=native#text/plain @@ -6589,6 +6596,7 @@ res/cardsfolder/s/sanctum_gargoyle.txt svneol=native#text/plain res/cardsfolder/s/sanctum_plowbeast.txt svneol=native#text/plain res/cardsfolder/s/sand_silos.txt svneol=native#text/plain res/cardsfolder/s/sand_squid.txt svneol=native#text/plain +res/cardsfolder/s/sandbar_crocodile.txt -text res/cardsfolder/s/sandbar_merfolk.txt svneol=native#text/plain res/cardsfolder/s/sandbar_serpent.txt svneol=native#text/plain res/cardsfolder/s/sandskin.txt svneol=native#text/plain @@ -7920,6 +7928,9 @@ res/cardsfolder/t/tectonic_rift.txt -text res/cardsfolder/t/teekas_dragon.txt svneol=native#text/plain res/cardsfolder/t/teetering_peaks.txt svneol=native#text/plain res/cardsfolder/t/teferis_care.txt -text +res/cardsfolder/t/teferis_drake.txt -text +res/cardsfolder/t/teferis_honor_guard.txt -text +res/cardsfolder/t/teferis_isle.txt -text res/cardsfolder/t/teferis_puzzle_box.txt svneol=native#text/plain res/cardsfolder/t/teferis_response.txt svneol=native#text/plain res/cardsfolder/t/tek.txt svneol=native#text/plain @@ -8167,6 +8178,7 @@ res/cardsfolder/t/toil_to_renown.txt svneol=native#text/plain res/cardsfolder/t/toils_of_night_and_day.txt svneol=native#text/plain res/cardsfolder/t/tolaria_west.txt svneol=native#text/plain res/cardsfolder/t/tolarian_academy.txt svneol=native#text/plain +res/cardsfolder/t/tolarian_drake.txt -text res/cardsfolder/t/tolarian_emissary.txt svneol=native#text/plain res/cardsfolder/t/tolarian_entrancer.txt svneol=native#text/plain res/cardsfolder/t/tolarian_sentinel.txt svneol=native#text/plain @@ -8496,8 +8508,10 @@ res/cardsfolder/v/vampiric_spirit.txt svneol=native#text/plain res/cardsfolder/v/vampiric_touch.txt svneol=native#text/plain res/cardsfolder/v/vampiric_tutor.txt svneol=native#text/plain res/cardsfolder/v/vampirism.txt svneol=native#text/plain +res/cardsfolder/v/vanishing.txt -text res/cardsfolder/v/vanquish.txt svneol=native#text/plain res/cardsfolder/v/vapor_snag.txt svneol=native#text/plain +res/cardsfolder/v/vaporous_djinn.txt -text res/cardsfolder/v/varchilds_crusader.txt svneol=native#text/plain res/cardsfolder/v/vastwood_animist.txt svneol=native#text/plain res/cardsfolder/v/vastwood_gorger.txt svneol=native#text/plain @@ -8671,6 +8685,7 @@ res/cardsfolder/v/vivify.txt svneol=native#text/plain res/cardsfolder/v/vivisection.txt svneol=native#text/plain res/cardsfolder/v/vizzerdrix.txt svneol=native#text/plain res/cardsfolder/v/vodalian_hypnotist.txt svneol=native#text/plain +res/cardsfolder/v/vodalian_illusionist.txt -text res/cardsfolder/v/vodalian_knights.txt svneol=native#text/plain res/cardsfolder/v/vodalian_mage.txt svneol=native#text/plain res/cardsfolder/v/vodalian_merchant.txt svneol=native#text/plain diff --git a/res/cardsfolder/b/breezekeeper.txt b/res/cardsfolder/b/breezekeeper.txt new file mode 100644 index 00000000000..48634374145 --- /dev/null +++ b/res/cardsfolder/b/breezekeeper.txt @@ -0,0 +1,12 @@ +Name:Breezekeeper +ManaCost:3 U +Types:Creature Djinn +Text:no text +PT:4/4 +K:Flying +K:Phasing +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/breezekeeper.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.) +SetInfo:VIS|Common|http://magiccards.info/scans/en/vi/27.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/c/cloak_of_invisibility.txt b/res/cardsfolder/c/cloak_of_invisibility.txt new file mode 100644 index 00000000000..b4e0bd22ea8 --- /dev/null +++ b/res/cardsfolder/c/cloak_of_invisibility.txt @@ -0,0 +1,12 @@ +Name:Cloak of Invisibility +ManaCost:U +Types:Enchantment Aura +Text:no text +K:Enchant creature +A:SP$ Attach | Cost$ U | ValidTgts$ Creature | AILogic$ Pump +S:Mode$ Continuous | Affected$ Permanent.EnchantedBy | AddKeyword$ Phasing & HIDDEN CARDNAME can't be blocked except by Walls. | Description$ Enchanted creature has phasing and can't be blocked except by Walls. +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/cloak_of_invisibility.jpg +SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/58.jpg +Oracle:Enchant creature\nEnchanted creature has phasing and can't be blocked except by Walls. (It phases in or out before its controller untaps during each of his or her untap steps. While it's phased out, it's treated as though it doesn't exist.) +End \ No newline at end of file diff --git a/res/cardsfolder/c/crystal_golem.txt b/res/cardsfolder/c/crystal_golem.txt new file mode 100644 index 00000000000..3d39cc248d5 --- /dev/null +++ b/res/cardsfolder/c/crystal_golem.txt @@ -0,0 +1,12 @@ +Name:Crystal Golem +ManaCost:4 +Types:Artifact Creature Golem +Text:no text +PT:3/3 +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | Execute$ TrigPhase | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your end step, CARDNAME phases out. +SVar:TrigPhase:DB$ Phases | Defined$ Self +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/crystal_golem.jpg +SetInfo:MIR|Uncommon|http://magiccards.info/scans/en/mr/263.jpg +Oracle:At the beginning of your end step, Crystal Golem phases out. (While it's phased out, it's treated as though it doesn't exist. It phases in before you untap during your next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/d/dream_fighter.txt b/res/cardsfolder/d/dream_fighter.txt new file mode 100644 index 00000000000..8b2362d0e5e --- /dev/null +++ b/res/cardsfolder/d/dream_fighter.txt @@ -0,0 +1,15 @@ +Name:Dream Fighter +ManaCost:2 U +Types:Creature Human Soldier +Text:no text +PT:1/1 +T:Mode$ Blocks | ValidCard$ Card.Self | ValidAttacker$ Creature | Execute$ TrigPhaseAttacker | TriggerDescription$ Whenever CARDNAME blocks or becomes blocked by a creature, Dream Fighter and that creature phase out. +T:Mode$ Blocks | ValidCard$ Creature | ValidAttacker$ Card.Self | Execute$ TrigPhaseBlocker | Secondary$ True | TriggerDescription$ Whenever CARDNAME blocks or becomes blocked by a creature, Dream Fighter and that creature phase out. +SVar:TrigPhaseAttacker:DB$ Phase | Defined$ TriggeredAttacker | SubAbility$ SVar=DBPhaseSelf +SVar:TrigPhaseBlocker:DB$ Phase | Defined$ TriggeredBlocker | SubAbility$ SVar=DBPhaseSelf +SVar:DBPhaseSelf:DB$ Phase | Defined$ Self +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/dream_fighter.jpg +SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/63.jpg +Oracle:Whenever Dream Fighter blocks or becomes blocked by a creature, Dream Fighter and that creature phase out. (While they're phased out, they're treated as though they don't exist. Each one phases in before its controller untaps during his or her next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/m/merfolk_raiders.txt b/res/cardsfolder/m/merfolk_raiders.txt new file mode 100644 index 00000000000..9328de2d9c6 --- /dev/null +++ b/res/cardsfolder/m/merfolk_raiders.txt @@ -0,0 +1,12 @@ +Name:Merfolk Raiders +ManaCost:1 U +Types:Creature Merfolk Soldier +Text:no text +PT:2/3 +K:Islandwalk +K:Phasing +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/merfolk_raiders.jpg +Oracle:Islandwalk\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.) +SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/75.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/m/mist_dragon.txt b/res/cardsfolder/m/mist_dragon.txt new file mode 100644 index 00000000000..e5c64d83bda --- /dev/null +++ b/res/cardsfolder/m/mist_dragon.txt @@ -0,0 +1,14 @@ +Name:Mist Dragon +ManaCost:4 U U +Types:Creature Dragon +Text:no text +PT:4/4 +A:AB$ Pump | Cost$ 0 | Defined$ Self | KW$ Flying | Permanent$ True | SpellDescription$ CARDNAME gains flying. (This effect lasts indefinitely.) +A:AB$ Debuff | Cost$ 0 | Defined$ Self | Keywords$ Flying | Permanent$ True | SpellDescription$ CARDNAME loses flying. (This effect lasts indefinitely.) +A:AB$ Phases | Cost$ 3 U U | Defined$ Self | SpellDescription$ CARDNAME phases out. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/mist_dragon.jpg +SetInfo:MIR|Rare|http://magiccards.info/scans/en/mr/79.jpg +Oracle:{0}: Mist Dragon gains flying. (This effect lasts indefinitely.)\n{0}: Mist Dragon loses flying. (This effect lasts indefinitely.)\n{3}{U}{U}: Mist Dragon phases out. (While it's phased out, it's treated as though it doesn't exist. It phases in before you untap during your next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/r/rainbow_efreet.txt b/res/cardsfolder/r/rainbow_efreet.txt new file mode 100644 index 00000000000..71a401d3b21 --- /dev/null +++ b/res/cardsfolder/r/rainbow_efreet.txt @@ -0,0 +1,13 @@ +Name:Rainbow Efreet +ManaCost:3 U +Types:Creature Efreet +Text:no text +PT:3/1 +K:Flying +A:AB$ Phases | Cost$ U U | Defined$ Self | SpellDescription$ CARDNAME phases out. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/rainbow_efreet.jpg +SetInfo:VIS|Rare|http://magiccards.info/scans/en/vi/41.jpg +Oracle:Flying\n{U}{U}: Rainbow Efreet phases out. (While it's phased out, it's treated as though it doesn't exist. It phases in before you untap during your next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/s/sandbar_crocodile.txt b/res/cardsfolder/s/sandbar_crocodile.txt new file mode 100644 index 00000000000..b8a5f0363de --- /dev/null +++ b/res/cardsfolder/s/sandbar_crocodile.txt @@ -0,0 +1,11 @@ +Name:Sandbar Crocodile +ManaCost:4 U +Types:Creature Crocodile +Text:no text +PT:6/5 +K:Phasing +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/sandbar_crocodile.jpg +Oracle:Phasing (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.) +SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/88.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/t/teferis_drake.txt b/res/cardsfolder/t/teferis_drake.txt new file mode 100644 index 00000000000..169cace96cc --- /dev/null +++ b/res/cardsfolder/t/teferis_drake.txt @@ -0,0 +1,12 @@ +Name:Teferi's Drake +ManaCost:2 U +Types:Creature Drake +Text:no text +PT:3/2 +K:Flying +K:Phasing +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/teferis_drake.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.) +SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/97.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/t/teferis_honor_guard.txt b/res/cardsfolder/t/teferis_honor_guard.txt new file mode 100644 index 00000000000..ca03779690a --- /dev/null +++ b/res/cardsfolder/t/teferis_honor_guard.txt @@ -0,0 +1,13 @@ +Name:Teferi's Honor Guard +ManaCost:2 W +Types:Creature Human Knight +Text:no text +PT:2/2 +K:Flanking +A:AB$ Phases | Cost$ U U | Defined$ Self | SpellDescription$ CARDNAME phases out. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/teferis_honor_guard.jpg +SetInfo:VIS|Uncommon|http://magiccards.info/scans/en/vi/122.jpg +Oracle:Flanking (Whenever a creature without flanking blocks this creature, the blocking creature gets -1/-1 until end of turn.)\n{U}{U}: Teferi's Honor Guard phases out. (While it's phased out, it's treated as though it doesn't exist. It phases in before you untap during your next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/t/teferis_isle.txt b/res/cardsfolder/t/teferis_isle.txt new file mode 100644 index 00000000000..eae3f05fd47 --- /dev/null +++ b/res/cardsfolder/t/teferis_isle.txt @@ -0,0 +1,12 @@ +Name:Teferi's Isle +ManaCost:no cost +Types:Legendary Land +Text:no text +K:Phasing +K:CARDNAME enters the battlefield tapped. +A:AB$ Mana | Cost$ T | Produced$ U | Amount$ 2 | SpellDescription$ Add U U to your mana pool. +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/teferis_isle.jpg +Oracle:Phasing (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.)\nTeferi's Isle enters the battlefield tapped.\n{T}: Add {U}{U} to your mana pool. +SetInfo:MIR|Rare|http://magiccards.info/scans/en/mr/315.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/t/tolarian_drake.txt b/res/cardsfolder/t/tolarian_drake.txt new file mode 100644 index 00000000000..10031f4bf8e --- /dev/null +++ b/res/cardsfolder/t/tolarian_drake.txt @@ -0,0 +1,12 @@ +Name:Tolarian Drake +ManaCost:2 U +Types:Creature Drake +Text:no text +PT:2/4 +K:Flying +K:Phasing +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/tolarian_drake.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.) +SetInfo:WTH|Common|http://magiccards.info/scans/en/wl/55.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/v/vanishing.txt b/res/cardsfolder/v/vanishing.txt new file mode 100644 index 00000000000..0a6322b5e0f --- /dev/null +++ b/res/cardsfolder/v/vanishing.txt @@ -0,0 +1,13 @@ +Name:Vanishing +ManaCost:U +Types:Enchantment Aura +Text:no text +K:Enchant creature +A:SP$ Attach | Cost$ U | ValidTgts$ Creature | AILogic$ Curse +A:AB$ Phases | Cost$ U U | Defined$ Enchanted | SpellDescription$ Enchanted creature phases out. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/vanishing.jpg +SetInfo:VIS|Common|http://magiccards.info/scans/en/vi/48.jpg +Oracle:Enchant creature\n{U}{U}: Enchanted creature phases out. (While it's phased out, it's treated as though it doesn't exist. It phases in before its controller untaps during his or her next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/v/vaporous_djinn.txt b/res/cardsfolder/v/vaporous_djinn.txt new file mode 100644 index 00000000000..a5cf592e706 --- /dev/null +++ b/res/cardsfolder/v/vaporous_djinn.txt @@ -0,0 +1,14 @@ +Name:Vaporous Djinn +ManaCost:2 U U +Types:Creature Djinn +Text:no text +PT:3/4 +K:Flying +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigPhase | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, CARDNAME phases out unless you pay {U}{U}. +SVar:TrigPhase:DB$ Phases | Defined$ Self | UnlessCost$ U U | UnlessPayer$ You +SVar:RemAIDeck:True +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/vaporous_djinn.jpg +SetInfo:MIR|Uncommon|http://magiccards.info/scans/en/mr/101.jpg +Oracle:Flying\nAt the beginning of your upkeep, Vaporous Djinn phases out unless you pay {U}{U}. (While it's phased out, it's treated as though it doesn't exist. It phases in before you untap during your next untap step.) +End \ No newline at end of file diff --git a/res/cardsfolder/v/vodalian_illusionist.txt b/res/cardsfolder/v/vodalian_illusionist.txt new file mode 100644 index 00000000000..fb9ff6411a0 --- /dev/null +++ b/res/cardsfolder/v/vodalian_illusionist.txt @@ -0,0 +1,13 @@ +Name:Vodalian Illusionist +ManaCost:2 U +Types:Creature Merfolk Wizard +Text:no text +PT:2/2 +K:Flanking +A:AB$ Phases | Cost$ U U | ValidTgts$ Creature | SpellDescription$ Target creature phases out. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/vodalian_illusionist.jpg +SetInfo:WTH|Uncommon|http://magiccards.info/scans/en/wl/58.jpg +Oracle:{U}{U}, {T}: Target creature phases out. (While it's phased out, it's treated as though it doesn't exist. It phases in before its controller untaps during his or her next untap step.) +End \ No newline at end of file diff --git a/src/main/java/forge/AllZoneUtil.java b/src/main/java/forge/AllZoneUtil.java index c38ffc74b41..adf2cf465c0 100644 --- a/src/main/java/forge/AllZoneUtil.java +++ b/src/main/java/forge/AllZoneUtil.java @@ -249,9 +249,10 @@ public abstract class AllZoneUtil { all.addAll(player.getZone(Zone.Graveyard).getCards()); all.addAll(player.getZone(Zone.Hand).getCards()); all.addAll(player.getZone(Zone.Library).getCards()); // not sure if library should be included. - all.addAll(player.getZone(Zone.Battlefield).getCards()); + all.addAll(player.getZone(Zone.Battlefield).getCards(false)); all.addAll(player.getZone(Zone.Exile).getCards()); // Spawnsire of Ulamog plays spells from here? } + all.addAll(AllZone.getStackZone().getCards()); return all; } diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 134c200a890..8370f44f958 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -113,6 +113,9 @@ public class Card extends GameEntity implements Comparable { private boolean madness = false; private boolean suspendCast = false; private boolean suspend = false; + + private boolean phasedOut = false; + private boolean directlyPhasedOut = true; //for Vanguard / Manapool / Emblems etc. private boolean isImmutable = false; @@ -4692,6 +4695,71 @@ public class Card extends GameEntity implements Comparable { return kicked; } + public boolean isPhasedOut() { + return phasedOut; + } + + public void setPhasedOut(boolean phasedOut) { + this.phasedOut = phasedOut; + } + + public void phase(){ + this.phase(true); + } + + public void phase(boolean direct){ + boolean phasingIn = this.isPhasedOut(); + + if (!this.switchPhaseState()){ + // Switch Phase State returns False if the Permanent can't Phase Out + return; + } + + if (!phasingIn){ + this.setDirectlyPhasedOut(direct); + } + + for (Card eq : this.getEquippedBy()){ + if (eq.isPhasedOut() == phasingIn){ + eq.phase(false); + } + } + + for (Card aura : this.getEnchantedBy()){ + if (aura.isPhasedOut() == phasingIn){ + aura.phase(false); + } + } + } + + private boolean switchPhaseState(){ + if (!this.phasedOut && this.hasKeyword("CARDNAME can't phase out.")){ + return false; + } + + this.phasedOut = !this.phasedOut; + if (this.phasedOut && isToken()){ + // 702.23k Phased-out tokens cease to exist as a state-based action. See rule 704.5d. + // 702.23d The phasing event doesn't actually cause a permanent to change zones or control, + // even though it's treated as though it's not on the battlefield and not under its controller's control while it's phased out. + // Zone-change triggers don't trigger when a permanent phases in or out. + + // Suppressed Exiling is as close as we can get to "ceasing to exist" + AllZone.getTriggerHandler().suppressMode("ChangesZone"); + AllZone.getGameAction().exile(this); + AllZone.getTriggerHandler().clearSuppression("ChangesZone"); + } + return true; + } + + public boolean isDirectlyPhasedOut(){ + return this.directlyPhasedOut; + } + + public void setDirectlyPhasedOut(boolean direct){ + this.directlyPhasedOut = direct; + } + /** *

isReflectedLand.

* diff --git a/src/main/java/forge/CombatUtil.java b/src/main/java/forge/CombatUtil.java index 9928edf2694..6437e7b42e8 100644 --- a/src/main/java/forge/CombatUtil.java +++ b/src/main/java/forge/CombatUtil.java @@ -65,7 +65,7 @@ public class CombatUtil { if (blocker.isTapped() && !AllZoneUtil.isCardInPlay("Masako the Humorless", blocker.getController())) return false; - if (blocker.hasKeyword("CARDNAME can't block.") || blocker.hasKeyword("CARDNAME can't attack or block.")) + if (blocker.hasKeyword("CARDNAME can't block.") || blocker.hasKeyword("CARDNAME can't attack or block.") || blocker.isPhasedOut()) return false; CardList kulrath = AllZoneUtil.getCardsIn(Zone.Battlefield, "Kulrath Knight"); @@ -463,7 +463,7 @@ public class CombatUtil { * @return a boolean. */ public static boolean canAttack(Card c) { - if (c.isTapped() || (c.hasSickness() && !c.isEnchantedBy("Instill Energy"))) return false; + if (c.isTapped() || c.isPhasedOut() || (c.hasSickness() && !c.isEnchantedBy("Instill Energy"))) return false; return canAttackNextTurn(c); } diff --git a/src/main/java/forge/ComputerUtil.java b/src/main/java/forge/ComputerUtil.java index 9bb55f16440..c10ec583d7a 100644 --- a/src/main/java/forge/ComputerUtil.java +++ b/src/main/java/forge/ComputerUtil.java @@ -1061,7 +1061,7 @@ public class ComputerUtil { * @return a {@link forge.CardList} object. */ static public CardList chooseExileFrom(Constant.Zone zone, String type, Card activate, Card target, int amount) { - CardList typeList = new CardList(AllZone.getComputerPlayer().getZone(zone).getCards()); + CardList typeList = AllZone.getComputerPlayer().getCardsIn(zone); typeList = typeList.getValidCards(type.split(","), activate.getController(), activate); if (target != null && target.getController().isComputer() && typeList.contains(target)) typeList.remove(target); // don't exile the card we're pumping diff --git a/src/main/java/forge/DefaultPlayerZone.java b/src/main/java/forge/DefaultPlayerZone.java index 3192f8d0541..8152527a773 100644 --- a/src/main/java/forge/DefaultPlayerZone.java +++ b/src/main/java/forge/DefaultPlayerZone.java @@ -17,7 +17,7 @@ public class DefaultPlayerZone extends PlayerZone implements java.io.Serializabl /** Constant serialVersionUID=-5687652485777639176L. */ private static final long serialVersionUID = -5687652485777639176L; - private List cards = new ArrayList(); + protected List cards = new ArrayList(); private final Constant.Zone zoneName; private final Player player; private boolean update = true; @@ -260,7 +260,13 @@ public class DefaultPlayerZone extends PlayerZone implements java.io.Serializabl * * @return an array of {@link forge.Card} objects. */ - public final Card[] getCards() { + public Card[] getCards() { + return getCards(true); + } + + @Override + public Card[] getCards(boolean filter) { + // Non-Battlefield PlayerZones don't care about the filter Card[] c = new Card[cards.size()]; cards.toArray(c); return c; diff --git a/src/main/java/forge/GuiDisplay4.java b/src/main/java/forge/GuiDisplay4.java index 03337d31b95..cbd6ac5bfc1 100644 --- a/src/main/java/forge/GuiDisplay4.java +++ b/src/main/java/forge/GuiDisplay4.java @@ -836,7 +836,7 @@ public class GuiDisplay4 extends JFrame implements CardContainer, Display, NewCo public void update(final Observable a, final Object b) { PlayerZone pZone = (PlayerZone) a; - Card[] c = pZone.getCards(); + Card[] c = pZone.getCards(false); GuiDisplayUtil.setupPlayZone(playerPlayPanel, c); } @@ -850,7 +850,7 @@ public class GuiDisplay4 extends JFrame implements CardContainer, Display, NewCo public void update(final Observable a, final Object b) { PlayerZone pZone = (PlayerZone) a; - Card[] c = pZone.getCards(); + Card[] c = pZone.getCards(false); GuiDisplayUtil.setupPlayZone(oppPlayPanel, c); } diff --git a/src/main/java/forge/IPlayerZone.java b/src/main/java/forge/IPlayerZone.java index f2854d03b81..ae11057a55c 100644 --- a/src/main/java/forge/IPlayerZone.java +++ b/src/main/java/forge/IPlayerZone.java @@ -79,6 +79,7 @@ interface IPlayerZone { * * @return an array of {@link forge.Card} objects. */ + Card[] getCards(boolean filter); Card[] getCards(); Card[] getCards(int n); diff --git a/src/main/java/forge/PhaseUtil.java b/src/main/java/forge/PhaseUtil.java index fec4ba6efd9..301ea2a81e1 100644 --- a/src/main/java/forge/PhaseUtil.java +++ b/src/main/java/forge/PhaseUtil.java @@ -48,7 +48,7 @@ public class PhaseUtil { // For tokens a player starts the game with they don't recover from Sum. Sickness on first turn if (turn.getTurn() > 0) { - CardList list = turn.getCardsIn(Zone.Battlefield); + CardList list = turn.getCardsIncludePhasingIn(Zone.Battlefield); for (Card c : list) c.setSickness(false); } @@ -56,8 +56,7 @@ public class PhaseUtil { AllZone.getGameAction().resetActivationsPerTurn(); - CardList lands = AllZoneUtil.getPlayerLandsInPlay(turn); - lands = lands.filter(CardListFilter.untapped); + CardList lands = AllZoneUtil.getPlayerLandsInPlay(turn).filter(CardListFilter.untapped); turn.setNumPowerSurgeLands(lands.size()); // anything before this point happens regardless of whether the Untap phase is skipped @@ -68,6 +67,7 @@ public class PhaseUtil { } // Phasing would happen here + doPhasing(turn); doUntap(); @@ -77,6 +77,43 @@ public class PhaseUtil { AllZone.getPhase().setNeedToNextPhase(true); } + private static void doPhasing(Player turn){ + // Needs to include phased out cards + CardList list = turn.getCardsIncludePhasingIn(Constant.Zone.Battlefield).filter(new CardListFilter() { + + @Override + public boolean addCard(Card c) { + return ((c.isPhasedOut() && c.isDirectlyPhasedOut()) || c.hasKeyword("Phasing")); + } + }); + + // If c has things attached to it, they phase out simultaneously, and will phase back in with it + // If c is attached to something, it will phase out on its own, and try to attach back to that thing when it comes back + for(Card c : list){ + if (c.isPhasedOut()){ + c.phase(); + } + else if (c.hasKeyword("Phasing")){ + // 702.23g If an object would simultaneously phase out directly and indirectly, it just phases out indirectly. + if (c.isAura()){ + GameEntity ent = c.getEnchanting(); + + if (ent instanceof Card && list.contains((Card)ent)){ + continue; + } + } + else if (c.isEquipment() && c.isEquipping()){ + if (list.contains(c.getEquippingCard())){ + continue; + } + } + // TODO: Fortification + c.phase(); + } + } + } + + /** *

doUntap.

*/ diff --git a/src/main/java/forge/Player.java b/src/main/java/forge/Player.java index 0139daee603..979affffdcc 100644 --- a/src/main/java/forge/Player.java +++ b/src/main/java/forge/Player.java @@ -871,6 +871,11 @@ public abstract class Player extends GameEntity { return new CardList(cards); } + public CardList getCardsIncludePhasingIn(final Constant.Zone zone) { + Card[] cards = zone == Zone.Stack ? AllZone.getStackZone().getCards() : getZone(zone).getCards(false); + return new CardList(cards); + } + /** * gets a list of first N cards in the requested zone. This function makes a CardList from Card[]. * diff --git a/src/main/java/forge/PlayerZone_ComesIntoPlay.java b/src/main/java/forge/PlayerZone_ComesIntoPlay.java index 8677aebb57f..b7d9557ada9 100644 --- a/src/main/java/forge/PlayerZone_ComesIntoPlay.java +++ b/src/main/java/forge/PlayerZone_ComesIntoPlay.java @@ -1,5 +1,8 @@ package forge; +import java.util.ArrayList; +import java.util.Iterator; + import forge.Constant.Zone; import forge.card.cardFactory.CardFactoryUtil; import forge.card.spellability.Ability; @@ -311,4 +314,28 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone { trigger = b; leavesTrigger = b; } + + + @Override + public Card[] getCards(boolean filter) { + // Battlefield filters out Phased Out cards by default. Needs to call getCards(false) to get Phased Out cards + Card[] c; + if (!filter){ + c = new Card[cards.size()]; + cards.toArray(c); + } + else{ + Iterator itr = cards.iterator(); + ArrayList list = new ArrayList(); + while(itr.hasNext()){ + Card crd = itr.next(); + if (!crd.isPhasedOut()){ + list.add(crd); + } + } + c = new Card[list.size()]; + list.toArray(c); + } + return c; + } } diff --git a/src/main/java/forge/card/abilityFactory/AbilityFactory.java b/src/main/java/forge/card/abilityFactory/AbilityFactory.java index b1de257619d..6c75d6a2924 100644 --- a/src/main/java/forge/card/abilityFactory/AbilityFactory.java +++ b/src/main/java/forge/card/abilityFactory/AbilityFactory.java @@ -551,6 +551,16 @@ public class AbilityFactory { SA = AbilityFactory_PermanentState.createDrawbackTapOrUntap(this); } } + + else if (API.equals("Phases")) { + if (isAb) { + SA = AbilityFactory_PermanentState.createAbilityPhases(this); + } else if (isSp) { + SA = AbilityFactory_PermanentState.createSpellPhases(this); + } else if (isDb) { + SA = AbilityFactory_PermanentState.createDrawbackPhases(this); + } + } else if (API.equals("PreventDamage")) { if (isAb) { diff --git a/src/main/java/forge/card/abilityFactory/AbilityFactory_PermanentState.java b/src/main/java/forge/card/abilityFactory/AbilityFactory_PermanentState.java index 50790a0660b..321cbe1c46b 100644 --- a/src/main/java/forge/card/abilityFactory/AbilityFactory_PermanentState.java +++ b/src/main/java/forge/card/abilityFactory/AbilityFactory_PermanentState.java @@ -1676,6 +1676,330 @@ public class AbilityFactory_PermanentState { } } - //Phasing? Something else? Who knows! + // ****************************************** + // ************** Phases ******************** + // ****************************************** + // Phases generally Phase Out. Time and Tide is the only card that can force + // Phased Out cards in. + /** + *

+ * createAbilityPhases. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @return a {@link forge.card.spellability.SpellAbility} object. + */ + public static SpellAbility createAbilityPhases(final AbilityFactory af) { + final SpellAbility abPhases = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) { + private static final long serialVersionUID = 5445572699000471299L; + + @Override + public String getStackDescription() { + return phasesStackDescription(af, this); + } + + @Override + public boolean canPlayAI() { + return phasesCanPlayAI(af, this); + } + + @Override + public void resolve() { + phasesResolve(af, this); + } + + @Override + public boolean doTrigger(boolean mandatory) { + return phasesTrigger(af, this, mandatory); + } + + }; + return abPhases; + } + + /** + *

+ * createSpellPhases. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @return a {@link forge.card.spellability.SpellAbility} object. + */ + public static SpellAbility createSpellPhases(final AbilityFactory af) { + final SpellAbility spPhases = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) { + private static final long serialVersionUID = -4990932993654533449L; + + @Override + public String getStackDescription() { + return phasesStackDescription(af, this); + } + + @Override + public boolean canPlayAI() { + return phasesCanPlayAI(af, this); + } + + @Override + public void resolve() { + phasesResolve(af, this); + } + + }; + return spPhases; + } + + /** + *

+ * createDrawbackPhases. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @return a {@link forge.card.spellability.SpellAbility} object. + */ + public static SpellAbility createDrawbackPhases(final AbilityFactory af) { + final SpellAbility dbPhases = new Ability_Sub(af.getHostCard(), af.getAbTgt()) { + private static final long serialVersionUID = -4990932993654533449L; + + @Override + public String getStackDescription() { + return phasesStackDescription(af, this); + } + + @Override + public void resolve() { + phasesResolve(af, this); + } + + @Override + public boolean chkAI_Drawback() { + return phasesPlayDrawbackAI(af, this); + } + + @Override + public boolean doTrigger(boolean mandatory) { + return phasesTrigger(af, this, mandatory); + } + + }; + return dbPhases; + } + + /** + *

+ * phasesStackDescription. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @return a {@link java.lang.String} object. + */ + private static String phasesStackDescription(AbilityFactory af, SpellAbility sa) { + // when getStackDesc is called, just build exactly what is happening + StringBuilder sb = new StringBuilder(); + final HashMap params = af.getMapParams(); + Card source = sa.getSourceCard(); + + if (sa instanceof Ability_Sub) + sb.append(" "); + else + sb.append(sa.getSourceCard()).append(" - "); + + ArrayList tgtCards; + Target tgt = af.getAbTgt(); + if (tgt != null) + tgtCards = tgt.getTargetCards(); + else { + tgtCards = AbilityFactory.getDefinedCards(source, params.get("Defined"), sa); + } + + Iterator it = tgtCards.iterator(); + while (it.hasNext()) { + sb.append(it.next()); + if (it.hasNext()) + sb.append(", "); + } + sb.append(" Phases Out."); + + Ability_Sub subAb = sa.getSubAbility(); + if (subAb != null) + sb.append(subAb.getStackDescription()); + + return sb.toString(); + } + + /** + *

+ * phasesCanPlayAI. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @return a boolean. + */ + private static boolean phasesCanPlayAI(final AbilityFactory af, SpellAbility sa) { + // This still needs to be fleshed out + Target tgt = sa.getTarget(); + Card source = sa.getSourceCard(); + final HashMap params = af.getMapParams(); + + Random r = MyRandom.random; + boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn() + 1); + + ArrayList tgtCards; + if (tgt == null) { + tgtCards = AbilityFactory.getDefinedCards(source, params.get("Defined"), sa); + if (tgtCards.contains(source)) { + // Protect it from something + } else { + //Card def = tgtCards.get(0); + // Phase this out if it might attack me, or before it can be + // declared as a blocker + } + + return false; + } else { + if (!phasesPrefTargeting(tgt, af, sa, false)) + return false; + } + + Ability_Sub subAb = sa.getSubAbility(); + if (subAb != null) + randomReturn &= subAb.chkAI_Drawback(); + + return randomReturn; + } + + /** + *

+ * phasesTrigger. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @param mandatory a boolean. + * @return a boolean. + */ + private static boolean phasesTrigger(AbilityFactory af, SpellAbility sa, boolean mandatory) { + Target tgt = sa.getTarget(); + + if (tgt == null) { + if (mandatory) + return true; + + return false; + } else { + if (phasesPrefTargeting(tgt, af, sa, mandatory)) { + return true; + } else if (mandatory) { + // not enough preferred targets, but mandatory so keep going: + return phasesUnpreferredTargeting(af, sa, mandatory); + } + } + + return false; + } + + /** + *

+ * phasesPlayDrawbackAI. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @return a boolean. + */ + private static boolean phasesPlayDrawbackAI(final AbilityFactory af, SpellAbility sa) { + // AI cannot use this properly until he can use SAs during Humans turn + Target tgt = af.getAbTgt(); + + boolean randomReturn = true; + + if (tgt == null) { + + } else { + if (!phasesPrefTargeting(tgt, af, sa, false)) + return false; + } + + Ability_Sub subAb = sa.getSubAbility(); + if (subAb != null) + randomReturn &= subAb.chkAI_Drawback(); + + return randomReturn; + } + + /** + *

+ * phasesPrefTargeting. + *

+ * + * @param tgt a {@link forge.card.spellability.Target} object. + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @param mandatory a boolean. + * @return a boolean. + */ + private static boolean phasesPrefTargeting(Target tgt, AbilityFactory af, SpellAbility sa, boolean mandatory) { + //Card source = sa.getSourceCard(); + + //CardList phaseList = AllZoneUtil.getCardsIn(Zone.Battlefield).getTargetableCards(source) + // .getValidCards(tgt.getValidTgts(), source.getController(), source); + + //CardList aiPhaseList = phaseList.getController(AllZone.getComputerPlayer()); + + // If Something in the Phase List might die from a bad combat, or a + // spell on the stack save it + + //CardList humanPhaseList = phaseList.getController(AllZone.getHumanPlayer()); + + // If something in the Human List is causing issues, phase it out + + return false; + } + + /** + *

+ * phasesUnpreferredTargeting. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @param mandatory a boolean. + * @return a boolean. + */ + private static boolean phasesUnpreferredTargeting(AbilityFactory af, SpellAbility sa, boolean mandatory) { + Card source = sa.getSourceCard(); + Target tgt = sa.getTarget(); + + CardList list = AllZoneUtil.getCardsIn(Zone.Battlefield); + list = list.getValidCards(tgt.getValidTgts(), source.getController(), source).getTargetableCards(source); + + return false; + } + + /** + *

+ * phasesResolve. + *

+ * + * @param af a {@link forge.card.abilityFactory.AbilityFactory} object. + * @param sa a {@link forge.card.spellability.SpellAbility} object. + */ + private static void phasesResolve(final AbilityFactory af, final SpellAbility sa) { + HashMap params = af.getMapParams(); + Card card = sa.getSourceCard(); + Target tgt = sa.getTarget(); + ArrayList tgtCards = null; + + if (tgt != null) + tgtCards = tgt.getTargetCards(); + else { + tgtCards = AbilityFactory.getDefinedCards(card, params.get("Defined"), sa); + } + + for (Card tgtC : tgtCards) { + tgtC.phase(); + } + } }// end of AbilityFactory_PermanentState class diff --git a/src/main/java/forge/card/cardFactory/CardFactoryUtil.java b/src/main/java/forge/card/cardFactory/CardFactoryUtil.java index 5b4d80a66d9..7c002af5b38 100644 --- a/src/main/java/forge/card/cardFactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardFactory/CardFactoryUtil.java @@ -1385,7 +1385,7 @@ public class CardFactoryUtil { // An animated artifact equipmemt can't equip a creature @Override public boolean canPlay() { - return AllZone.getZoneOf(sourceCard).is(Constant.Zone.Battlefield) && !sourceCard.isCreature() + return super.canPlay() && !sourceCard.isCreature() && Phase.canCastSorcery(sourceCard.getController()); } diff --git a/src/main/java/forge/card/cost/CostExile.java b/src/main/java/forge/card/cost/CostExile.java index 66552cbc53d..1faec539310 100644 --- a/src/main/java/forge/card/cost/CostExile.java +++ b/src/main/java/forge/card/cost/CostExile.java @@ -85,16 +85,17 @@ public class CostExile extends CostPartWithList { @Override public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) { - PlayerZone zone = activator.getZone(getFrom()); + CardList typeList = activator.getCardsIn(getFrom()); if (!getThis()) { - CardList typeList = new CardList(zone.getCards()); typeList = typeList.getValidCards(getType().split(";"), activator, source); Integer amount = convertAmount(); - if (amount != null && typeList.size() < amount) + if (amount != null && typeList.size() < amount){ return false; - } else if (!zone.contains(source)) + } + } else if (!typeList.contains(source)){ return false; + } return true; } diff --git a/src/main/java/forge/card/spellability/SpellAbility_Restriction.java b/src/main/java/forge/card/spellability/SpellAbility_Restriction.java index b5b4fd49d3a..c5485b9241b 100644 --- a/src/main/java/forge/card/spellability/SpellAbility_Restriction.java +++ b/src/main/java/forge/card/spellability/SpellAbility_Restriction.java @@ -136,7 +136,7 @@ public class SpellAbility_Restriction extends SpellAbility_Variables { * @return a boolean. */ public boolean canPlay(Card c, SpellAbility sa) { - if (!AllZone.getZoneOf(c).is(zone)) + if (!AllZone.getZoneOf(c).is(zone) || c.isPhasedOut()) return false; Player activator = sa.getActivatingPlayer(); diff --git a/src/main/java/forge/card/staticAbility/StaticAbility.java b/src/main/java/forge/card/staticAbility/StaticAbility.java index 9bea1b35f6f..f467d821387 100644 --- a/src/main/java/forge/card/staticAbility/StaticAbility.java +++ b/src/main/java/forge/card/staticAbility/StaticAbility.java @@ -176,7 +176,7 @@ public class StaticAbility { if (mapParams.containsKey("EffectZone")) effectZone = Zone.smartValueOf(mapParams.get("EffectZone")); - if( effectZone != null && !AllZone.getZoneOf(hostCard).getZoneType().equals(effectZone)) + if( effectZone != null && (!AllZone.getZoneOf(hostCard).getZoneType().equals(effectZone) || hostCard.isPhasedOut())) return false; if(mapParams.containsKey("Threshold") && !controller.hasThreshold()) diff --git a/src/main/java/forge/card/trigger/Trigger.java b/src/main/java/forge/card/trigger/Trigger.java index d16adeaef53..20a878e8cbb 100644 --- a/src/main/java/forge/card/trigger/Trigger.java +++ b/src/main/java/forge/card/trigger/Trigger.java @@ -228,7 +228,7 @@ public abstract class Trigger { if (AllZone.getZoneOf(hostCard) == null) { return false; } - if (!triggerZones.contains(AllZone.getZoneOf(hostCard).getZoneType())) { + if (!triggerZones.contains(AllZone.getZoneOf(hostCard).getZoneType()) || hostCard.isPhasedOut()) { return false; } } diff --git a/src/main/java/forge/gui/game/CardDetailPanel.java b/src/main/java/forge/gui/game/CardDetailPanel.java index 0232911e92a..360e8317301 100644 --- a/src/main/java/forge/gui/game/CardDetailPanel.java +++ b/src/main/java/forge/gui/game/CardDetailPanel.java @@ -191,6 +191,11 @@ public class CardDetailPanel extends JPanel implements CardContainer { area.append(text); } + if (card.isPhasedOut()){ + if (area.length() != 0) area.append("\n"); + area.append("Phased Out"); + } + //counter text Counters[] counters = Counters.values(); for (Counters counter : counters) {