From f3e384e890b7c0109ea85f00379cb4060e56a58e Mon Sep 17 00:00:00 2001 From: Hellfish Date: Sun, 20 Jan 2013 19:27:54 +0000 Subject: [PATCH] *Initial Planechase commit *Added Planes Academy at Tolaria West Fields of Summer Goldmeadow Krosa Lethe Lake Llanowar Panopticon Raven's Run The Fourth Sphere The Great Forest The Hippodrome *Added phenomenon Mutual Epiphany --- .gitattributes | 20 ++ res/blockdata/setdata.txt | 4 +- res/cardsfolder/a/academy_at_tolaria_west.txt | 16 + res/cardsfolder/f/fields_of_summer.txt | 16 + res/cardsfolder/g/goldmeadow.txt | 16 + res/cardsfolder/k/krosa.txt | 15 + res/cardsfolder/l/lethe_lake.txt | 16 + res/cardsfolder/l/llanowar.txt | 16 + res/cardsfolder/m/mutual_epiphany.txt | 11 + res/cardsfolder/p/panopticon.txt | 16 + res/cardsfolder/r/ravens_run.txt | 18 + res/cardsfolder/t/the_fourth_sphere.txt | 16 + res/cardsfolder/t/the_great_forest.txt | 15 + res/cardsfolder/t/the_hippodrome.txt | 16 + .../forge/card/abilityfactory/ApiType.java | 2 + .../effects/PlaneswalkEffect.java | 31 ++ .../effects/RollPlanarDiceEffect.java | 34 ++ .../card/cardfactory/CardFactoryUtil.java | 4 + .../forge/card/trigger/TriggerPlanarDice.java | 75 ++++ .../card/trigger/TriggerPlaneswalkedFrom.java | 68 ++++ .../card/trigger/TriggerPlaneswalkedTo.java | 68 ++++ .../java/forge/card/trigger/TriggerType.java | 3 + .../forge/control/input/InputMulligan.java | 12 +- src/main/java/forge/deck/CardCollections.java | 9 + src/main/java/forge/game/GameNew.java | 11 + src/main/java/forge/game/GameState.java | 71 +++- src/main/java/forge/game/MatchController.java | 4 +- .../java/forge/game/MatchStartHelper.java | 20 ++ src/main/java/forge/game/PlanarDice.java | 53 +++ .../forge/game/PlayerStartConditions.java | 16 + .../java/forge/game/phase/PhaseHandler.java | 69 ++-- src/main/java/forge/game/player/Player.java | 73 ++++ src/main/java/forge/gui/framework/EDocID.java | 2 + src/main/java/forge/gui/home/VHomeUI.java | 5 +- .../gui/home/variant/CSubmenuPlanechase.java | 217 +++++++++++ .../gui/home/variant/VSubmenuPlanechase.java | 338 ++++++++++++++++++ .../gui/match/nonsingleton/CCommand.java | 6 +- .../gui/match/nonsingleton/VCommand.java | 8 +- src/main/java/forge/model/FModel.java | 5 +- 39 files changed, 1377 insertions(+), 38 deletions(-) create mode 100644 res/cardsfolder/a/academy_at_tolaria_west.txt create mode 100644 res/cardsfolder/f/fields_of_summer.txt create mode 100644 res/cardsfolder/g/goldmeadow.txt create mode 100644 res/cardsfolder/k/krosa.txt create mode 100644 res/cardsfolder/l/lethe_lake.txt create mode 100644 res/cardsfolder/l/llanowar.txt create mode 100644 res/cardsfolder/m/mutual_epiphany.txt create mode 100644 res/cardsfolder/p/panopticon.txt create mode 100644 res/cardsfolder/r/ravens_run.txt create mode 100644 res/cardsfolder/t/the_fourth_sphere.txt create mode 100644 res/cardsfolder/t/the_great_forest.txt create mode 100644 res/cardsfolder/t/the_hippodrome.txt create mode 100644 src/main/java/forge/card/abilityfactory/effects/PlaneswalkEffect.java create mode 100644 src/main/java/forge/card/abilityfactory/effects/RollPlanarDiceEffect.java create mode 100644 src/main/java/forge/card/trigger/TriggerPlanarDice.java create mode 100644 src/main/java/forge/card/trigger/TriggerPlaneswalkedFrom.java create mode 100644 src/main/java/forge/card/trigger/TriggerPlaneswalkedTo.java create mode 100644 src/main/java/forge/game/PlanarDice.java create mode 100644 src/main/java/forge/gui/home/variant/CSubmenuPlanechase.java create mode 100644 src/main/java/forge/gui/home/variant/VSubmenuPlanechase.java diff --git a/.gitattributes b/.gitattributes index 34d6da0aa53..3ba675fde45 100644 --- a/.gitattributes +++ b/.gitattributes @@ -56,6 +56,7 @@ res/cardsfolder/a/abyssal_nightstalker.txt svneol=native#text/plain res/cardsfolder/a/abyssal_nocturnus.txt svneol=native#text/plain res/cardsfolder/a/abyssal_persecutor.txt svneol=native#text/plain res/cardsfolder/a/abyssal_specter.txt svneol=native#text/plain +res/cardsfolder/a/academy_at_tolaria_west.txt -text res/cardsfolder/a/academy_rector.txt svneol=native#text/plain res/cardsfolder/a/academy_researchers.txt -text res/cardsfolder/a/academy_ruins.txt svneol=native#text/plain @@ -3431,6 +3432,7 @@ res/cardsfolder/f/field_of_reality.txt svneol=native#text/plain res/cardsfolder/f/field_of_souls.txt svneol=native#text/plain res/cardsfolder/f/field_surgeon.txt svneol=native#text/plain res/cardsfolder/f/fieldmist_borderpost.txt svneol=native#text/plain +res/cardsfolder/f/fields_of_summer.txt -text res/cardsfolder/f/fiend_hunter.txt -text res/cardsfolder/f/fiend_of_the_shadows.txt -text res/cardsfolder/f/fierce_empath.txt svneol=native#text/plain @@ -4197,6 +4199,7 @@ res/cardsfolder/g/golden_bear.txt svneol=native#text/plain res/cardsfolder/g/golden_urn.txt svneol=native#text/plain res/cardsfolder/g/golden_wish.txt -text res/cardsfolder/g/goldenglow_moth.txt svneol=native#text/plain +res/cardsfolder/g/goldmeadow.txt -text res/cardsfolder/g/goldmeadow_dodger.txt svneol=native#text/plain res/cardsfolder/g/goldmeadow_harrier.txt svneol=native#text/plain res/cardsfolder/g/goldmeadow_lookout.txt svneol=native#text/plain @@ -5560,6 +5563,7 @@ res/cardsfolder/k/krenkos_command.txt -text res/cardsfolder/k/kresh_the_bloodbraided.txt svneol=native#text/plain res/cardsfolder/k/kris_mage.txt svneol=native#text/plain res/cardsfolder/k/krond_the_dawn_clad.txt -text +res/cardsfolder/k/krosa.txt -text res/cardsfolder/k/krosan_archer.txt svneol=native#text/plain res/cardsfolder/k/krosan_avenger.txt svneol=native#text/plain res/cardsfolder/k/krosan_beast.txt svneol=native#text/plain @@ -5730,6 +5734,7 @@ res/cardsfolder/l/leshracs_sigil.txt svneol=native#text/plain res/cardsfolder/l/lesser_gargadon.txt svneol=native#text/plain res/cardsfolder/l/lesser_werewolf.txt -text svneol=unset#text/plain res/cardsfolder/l/lethargy_trap.txt svneol=native#text/plain +res/cardsfolder/l/lethe_lake.txt -text res/cardsfolder/l/leveler.txt svneol=native#text/plain res/cardsfolder/l/leviathan.txt -text res/cardsfolder/l/levitation.txt svneol=native#text/plain @@ -5845,6 +5850,7 @@ res/cardsfolder/l/living_wall.txt svneol=native#text/plain res/cardsfolder/l/living_wish.txt -text res/cardsfolder/l/livonya_silone.txt svneol=native#text/plain res/cardsfolder/l/lizard_warrior.txt svneol=native#text/plain +res/cardsfolder/l/llanowar.txt -text res/cardsfolder/l/llanowar_augur.txt svneol=native#text/plain res/cardsfolder/l/llanowar_behemoth.txt svneol=native#text/plain res/cardsfolder/l/llanowar_cavalry.txt svneol=native#text/plain @@ -6654,6 +6660,7 @@ res/cardsfolder/m/musician.txt -text res/cardsfolder/m/mutagenic_growth.txt svneol=native#text/plain res/cardsfolder/m/mutavault.txt svneol=native#text/plain res/cardsfolder/m/mutilate.txt svneol=native#text/plain +res/cardsfolder/m/mutual_epiphany.txt -text res/cardsfolder/m/muzzle.txt svneol=native#text/plain res/cardsfolder/m/mwonvuli_acid_moss.txt svneol=native#text/plain res/cardsfolder/m/mwonvuli_beast_tracker.txt -text @@ -7245,6 +7252,7 @@ res/cardsfolder/p/panic.txt svneol=native#text/plain res/cardsfolder/p/panic_attack.txt svneol=native#text/plain res/cardsfolder/p/panic_spellbomb.txt svneol=native#text/plain res/cardsfolder/p/panoptic_mirror.txt -text +res/cardsfolder/p/panopticon.txt -text res/cardsfolder/p/panther_warriors.txt svneol=native#text/plain res/cardsfolder/p/paperfin_rascal.txt svneol=native#text/plain res/cardsfolder/p/paradigm_shift.txt svneol=native#text/plain @@ -7973,6 +7981,7 @@ res/cardsfolder/r/ravenous_skirge.txt svneol=native#text/plain res/cardsfolder/r/ravenous_trap.txt svneol=native#text/plain res/cardsfolder/r/ravenous_vampire.txt -text res/cardsfolder/r/ravens_crime.txt svneol=native#text/plain +res/cardsfolder/r/ravens_run.txt -text res/cardsfolder/r/ravens_run_dragoon.txt svneol=native#text/plain res/cardsfolder/r/raving_oni_slave.txt svneol=native#text/plain res/cardsfolder/r/ray_of_command.txt svneol=native#text/plain @@ -10367,6 +10376,9 @@ res/cardsfolder/t/thawing_glaciers.txt svneol=native#text/plain res/cardsfolder/t/the_abyss.txt svneol=native#text/plain res/cardsfolder/t/the_brute.txt svneol=native#text/plain res/cardsfolder/t/the_fallen.txt -text +res/cardsfolder/t/the_fourth_sphere.txt -text +res/cardsfolder/t/the_great_forest.txt -text +res/cardsfolder/t/the_hippodrome.txt -text res/cardsfolder/t/the_hive.txt svneol=native#text/plain res/cardsfolder/t/the_iron_guardian_stirs.txt -text res/cardsfolder/t/the_lady_of_the_mountain.txt svneol=native#text/plain @@ -13385,6 +13397,7 @@ src/main/java/forge/card/abilityfactory/effects/PeekAndRevealEffect.java -text src/main/java/forge/card/abilityfactory/effects/PermanentCreatureEfect.java -text src/main/java/forge/card/abilityfactory/effects/PermanentNoncreatureEffect.java -text src/main/java/forge/card/abilityfactory/effects/PhasesEffect.java -text +src/main/java/forge/card/abilityfactory/effects/PlaneswalkEffect.java -text src/main/java/forge/card/abilityfactory/effects/PlayEffect.java -text src/main/java/forge/card/abilityfactory/effects/PoisonEffect.java -text src/main/java/forge/card/abilityfactory/effects/ProtectAllEffect.java -text @@ -13401,6 +13414,7 @@ src/main/java/forge/card/abilityfactory/effects/RestartGameEffect.java -text src/main/java/forge/card/abilityfactory/effects/RevealEffect.java -text src/main/java/forge/card/abilityfactory/effects/RevealEffectBase.java svneol=native#text/plain src/main/java/forge/card/abilityfactory/effects/RevealHandEffect.java -text +src/main/java/forge/card/abilityfactory/effects/RollPlanarDiceEffect.java -text src/main/java/forge/card/abilityfactory/effects/SacrificeAllEffect.java -text src/main/java/forge/card/abilityfactory/effects/SacrificeEffect.java -text src/main/java/forge/card/abilityfactory/effects/ScryEffect.java -text @@ -13523,6 +13537,9 @@ src/main/java/forge/card/trigger/TriggerLifeGained.java svneol=native#text/plain src/main/java/forge/card/trigger/TriggerLifeLost.java svneol=native#text/plain src/main/java/forge/card/trigger/TriggerLosesGame.java -text src/main/java/forge/card/trigger/TriggerPhase.java svneol=native#text/plain +src/main/java/forge/card/trigger/TriggerPlanarDice.java -text +src/main/java/forge/card/trigger/TriggerPlaneswalkedFrom.java -text +src/main/java/forge/card/trigger/TriggerPlaneswalkedTo.java -text src/main/java/forge/card/trigger/TriggerSacrificed.java svneol=native#text/plain src/main/java/forge/card/trigger/TriggerSetInMotion.java -text src/main/java/forge/card/trigger/TriggerShuffled.java svneol=native#text/plain @@ -13602,6 +13619,7 @@ src/main/java/forge/game/GameType.java -text src/main/java/forge/game/GlobalRuleChange.java -text src/main/java/forge/game/MatchController.java -text src/main/java/forge/game/MatchStartHelper.java -text +src/main/java/forge/game/PlanarDice.java -text src/main/java/forge/game/PlayerStartConditions.java -text src/main/java/forge/game/event/BlockerAssignedEvent.java -text src/main/java/forge/game/event/CardDamagedEvent.java -text @@ -13821,8 +13839,10 @@ src/main/java/forge/gui/home/settings/VSubmenuDownloaders.java -text src/main/java/forge/gui/home/settings/VSubmenuPreferences.java -text src/main/java/forge/gui/home/settings/package-info.java svneol=native#text/plain src/main/java/forge/gui/home/variant/CSubmenuArchenemy.java -text +src/main/java/forge/gui/home/variant/CSubmenuPlanechase.java -text src/main/java/forge/gui/home/variant/CSubmenuVanguard.java -text src/main/java/forge/gui/home/variant/VSubmenuArchenemy.java -text +src/main/java/forge/gui/home/variant/VSubmenuPlanechase.java -text src/main/java/forge/gui/home/variant/VSubmenuVanguard.java -text src/main/java/forge/gui/match/CMatchUI.java -text src/main/java/forge/gui/match/ControlWinLose.java -text diff --git a/res/blockdata/setdata.txt b/res/blockdata/setdata.txt index e8c6c545fed..e7c52f65df6 100644 --- a/res/blockdata/setdata.txt +++ b/res/blockdata/setdata.txt @@ -92,4 +92,6 @@ Index:82|Code2:M13|Code3:M13|Name:Magic 2013 Index:83|Code2:RTR|Code3:RTR|Name:Return to Ravnica Index:86|Code2:VAN|Code3:VAN|Name:Vanguard -Index:87|Code2:ARC|Code3:ARC|Name:Archenemy \ No newline at end of file +Index:87|Code2:ARC|Code3:ARC|Name:Archenemy +Index:88|Code2:HOP|Code3:HOP|Name:Planechase +Index:89|Code2:PC2|Code3:PC2|Name:Planechase 2012 Edition \ No newline at end of file diff --git a/res/cardsfolder/a/academy_at_tolaria_west.txt b/res/cardsfolder/a/academy_at_tolaria_west.txt new file mode 100644 index 00000000000..fafcb973a40 --- /dev/null +++ b/res/cardsfolder/a/academy_at_tolaria_west.txt @@ -0,0 +1,16 @@ +Name:Academy at Tolaria West +ManaCost:no cost +Types:Plane Dominaria +Text:no text +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | IsPresent$ Card.YouCtrl | PresentZone$ Hand | PresentCompare$ EQ0 | Execute$ AcademicDraw | TriggerDescription$ At the beginning of your end step, if you have no cards in hand, draw seven cards. +SVar:AcademicDraw:AB$ Draw | Cost$ 0 | Defined$ You | NumCards$ 7 +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, discard your hand. +SVar:RolledChaos:AB$ Discard | Cost$ 0 | Mode$ Hand | Defined$ You +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/academy_at_tolaria_west.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/academy-at-tolaria-west.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/f/fields_of_summer.txt b/res/cardsfolder/f/fields_of_summer.txt new file mode 100644 index 00000000000..c73a8342cb4 --- /dev/null +++ b/res/cardsfolder/f/fields_of_summer.txt @@ -0,0 +1,16 @@ +Name:Fields of Summer +ManaCost:no cost +Types:Plane Moag +Text:no text +T:Mode$ SpellCast | OptionalDecider$ TriggeredPlayer | TriggerZones$ Command | Execute$ LifeSummer | TriggerDescription$ Whenever a player casts a spell, that player may gain 2 life. +SVar:LifeSummer:AB$ GainLife | Cost$ 0 | Defined$ TriggeredPlayer | LifeAmount$ 2 +T:Mode$ PlanarDice | Result$ Chaos | OptionalDecider$ You | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, you may gain 10 life. +SVar:RolledChaos:AB$ GainLife | Cost$ 0 | LifeAmount$ 10 | Defined$ You +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up. +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/fields_of_summer.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/fields-of-summer.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/g/goldmeadow.txt b/res/cardsfolder/g/goldmeadow.txt new file mode 100644 index 00000000000..9d4a53c4e77 --- /dev/null +++ b/res/cardsfolder/g/goldmeadow.txt @@ -0,0 +1,16 @@ +Name:Goldmeadow +ManaCost:no cost +Types:Plane Lorwyn +Text:no text +T:Mode$ ChangesZone | ValidCard$ Land | Destination$ Battlefield | Execute$ TripleGoat | TriggerZones$ Command | TriggerDescription$ Whenever a land enters the battlefield, that land's controller puts three 0/1 white Goat creature tokens onto the battlefield. +SVar:TripleGoat:AB$ Token | Cost$ 0 | TokenName$ Goat | TokenTypes$ Creature,Goat | TokenPower$ 0 | TokenToughness$ 1 | TokenColors$ White | TokenOwner$ TriggeredCardController | TokenImage$ W 0 1 Goat | TokenAmount$ 3 +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, put a 0/1 white Goat creature token onto the battlefield. +SVar:RolledChaos:AB$ Token | Cost$ 0 | TokenName$ Goat | TokenTypes$ Creature,Goat | TokenPower$ 0 | TokenToughness$ 1 | TokenColors$ White | TokenOwner$ TriggeredCardController | TokenImage$ W 0 1 Goat | TokenAmount$ 1 +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/goldmeadow.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/goldmeadow.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/k/krosa.txt b/res/cardsfolder/k/krosa.txt new file mode 100644 index 00000000000..bdda700baf0 --- /dev/null +++ b/res/cardsfolder/k/krosa.txt @@ -0,0 +1,15 @@ +Name:Krosa +ManaCost:no cost +Types:Plane Dominaria +Text:no text +S:Mode$ Continuous | EffectZone$ Command | Affected$ Creature | AddPower$ 2 | AddPower$ 2 | Description$ All Creatures get +2/+2. +T:Mode$ PlanarDice | Result$ Chaos | OptionalDecider$ You | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, you may add W U B R G to your mana pool. +A:AB$ Mana | Cost$ 0 | Produced$ W U B R G +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up. +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/krosa.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/krosa.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/l/lethe_lake.txt b/res/cardsfolder/l/lethe_lake.txt new file mode 100644 index 00000000000..d00655856eb --- /dev/null +++ b/res/cardsfolder/l/lethe_lake.txt @@ -0,0 +1,16 @@ +Name:Lethe Lake +ManaCost:no cost +Types:Plane Arkhos +Text:no text +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ LetheMill | TriggerDescription$ At the beginning of your upkeep, put the top ten cards of your library into your graveyard. +SVar:LetheMill:AB$ Mill | Cost$ 0 | Defined$ You | NumCards$ 10 +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, target player puts the top 10 cards of his or her library into his or her graveyard. +SVar:RolledChaos:AB$ Mill | Cost$ 0 | ValidTgts$ Player | TgtPrompt$ Choose target player to mill. | NumCards$ 10 +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/lethe_lake.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/lethe-lake.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/l/llanowar.txt b/res/cardsfolder/l/llanowar.txt new file mode 100644 index 00000000000..ccf3d2eda9e --- /dev/null +++ b/res/cardsfolder/l/llanowar.txt @@ -0,0 +1,16 @@ +Name:Llanowar +ManaCost:no cost +Types:Plane Dominaria +Text:no text +S:Mode$ Continuous | Affected$ Creature | EffectZone$ Command | AddAbility$ LlanowarAb | Description$ All creatures have "T: Add G G to your mana pool.". +SVar:LlanowarAb:AB$ Mana | Cost$ T | Amount$ 2 | Produced$ G | SpellDescription$ Add G G to your mana pool. +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, untap all creatures you control. +SVar:RolledChaos:AB$ UntapAll | Cost$ 0 | ValidCards$ Creature.YouCtrl +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/llanowar.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/llanowar.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/m/mutual_epiphany.txt b/res/cardsfolder/m/mutual_epiphany.txt new file mode 100644 index 00000000000..1d42059db30 --- /dev/null +++ b/res/cardsfolder/m/mutual_epiphany.txt @@ -0,0 +1,11 @@ +Name:Mutual Epiphany +ManaCost:no cost +Types:Phenomenon +Text:no text +T:Mode$ PlaneswalkedTo | ValidCard$ Card.Self | TriggerZones$ Command | Execute$ Epiphany | TriggerDescription$ When you encounter CARDNAME, each player draws 4 cards. (Then planeswalk away from this phenomenon) +SVar:Epiphany:AB$ Draw | Cost$ 0 | Defined$ Each | NumCards$ 4 | SubAbility$ PWAway | SpellDescription$ Each player draws four cards. +SVar:PWAway:DB$ Planeswalk | Cost$ 0 +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/mutual_epiphany.jpg +SetInfo:PC2|Common|http://magiccards.info/extras/phenomenon/planechase-2012-edition/mutual-epiphany.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/p/panopticon.txt b/res/cardsfolder/p/panopticon.txt new file mode 100644 index 00000000000..b8cc4c9aa75 --- /dev/null +++ b/res/cardsfolder/p/panopticon.txt @@ -0,0 +1,16 @@ +Name:Panopticon +ManaCost:no cost +Types:Plane Mirrodin +Text:no text +T:Mode$ PlaneswalkedTo | ValidCard$ Card.Self | TriggerZones$ Command | Execute$ PanopticonDraw | TriggerDescription$ When you planeswalk to CARDNAME, draw a card. +T:Mode$ Phase | Phase$ Draw | ValidPlayer$ You | Execute$ PanopticonDraw | TriggerDescription$ At the beginning of your draw step, draw an additional card. +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ PanopticonDraw | TriggerDescription$ Whenever you roll Chaos, draw a card. +SVar:PanopticonDraw:AB$ Draw | Cost$ 0 | Defined$ You | NumCards$ 1 +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/panopticon.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/panopticon.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/r/ravens_run.txt b/res/cardsfolder/r/ravens_run.txt new file mode 100644 index 00000000000..924f221763f --- /dev/null +++ b/res/cardsfolder/r/ravens_run.txt @@ -0,0 +1,18 @@ +Name:Raven's Run +ManaCost:no cost +Types:Plane Shadowmoor +Text:no text +S:Mode$ Continuous | EffectZone$ Command | Affected$ Creature | AddKeyword$ Wither | Description$ All Creatures have Wither (They deal damage to creatures in the form of -1/-1 counters.) +T:Mode$ PlanarDice | Result$ Chaos | OptionalDecider$ You | TriggerZones$ Command | Execute$ RolledChaos1 | TriggerDescription$ Whenever you roll Chaos, put a -1/-1 counter on target creature, two -1/-1 counters on another target creature, and three -1/-1 counters on a third target creature. +SVar:RolledChaos1:AB$ PutCounter | Cost$ 0 | ValidTgts$ Creature | CounterType$ M1M1 | CounterNum$ 1 | RememberTargets$ True | SubAbility$ RolledChaos2 +SVar:RolledChaos2:DB$ PutCounter | ValidTgts$ Creature.IsNotRemembered | CounterType$ M1M1 | CounterNum$ 2 | RememberTargets$ True | SubAbility$ RolledChaos3 +SVar:RolledChaos3:DB$ PutCounter | ValidTgts$ Creature.IsNotRemembered | CounterType$ M1M1 | CounterNum$ 3 | SubAbility$ RolledChaosCleanup +SVar:RolledChaosCleanup:DB$ Cleanup | ClearRemembered$ True +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up. +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/ravens_run.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/ravens-run.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/t/the_fourth_sphere.txt b/res/cardsfolder/t/the_fourth_sphere.txt new file mode 100644 index 00000000000..9ab4c48307a --- /dev/null +++ b/res/cardsfolder/t/the_fourth_sphere.txt @@ -0,0 +1,16 @@ +Name:The Fourth Sphere +ManaCost:no cost +Types:Plane Phyrexia +Text:no text +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ FourthSac | TriggerDescription$ At the beginning of your upkeep, sacrifice a nonblack creature. +SVar:FourthSac:AB$ Sacrifice | Cost$ 0 | Defined$ You | SacValid$ Creature.nonBlack +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, put a 2/2 black zombie token onto the battlefield. +SVar:RolledChaos:AB$Token | Cost$ 0 | TokenImage$ B 2 2 Zombie | TokenName$ Zombie | TokenColors$ Black | TokenTypes$ Creature,Zombie | TokenPower$ 2 | TokenToughness$ 2 | TokenOwner$ You | TokenAmount$ 2 +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/the_fourth_sphere.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/the-fourth-sphere.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/t/the_great_forest.txt b/res/cardsfolder/t/the_great_forest.txt new file mode 100644 index 00000000000..3e723e1e77f --- /dev/null +++ b/res/cardsfolder/t/the_great_forest.txt @@ -0,0 +1,15 @@ +Name:The Great Forest +ManaCost:no cost +Types:Plane Lorwyn +Text:no text +S:Mode$ Continuous | EffectZone$ Command | GlobalRule$ Each creature assigns combat damage equal to its toughness rather than its power. | Description$ Each creature assigns combat damage equal to its toughness rather than its power. +T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos,creatures you control get +0/+2 and gain trample until end of turn. +SVar:RolledChaos:AB$ PumpAll | Cost$ 0 | ValidCards$ Creature.ActivePlayerCtrl | NumDef$ 2 | KW$ Trample +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/the_great_forest.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/the-great-forest.jpg +End \ No newline at end of file diff --git a/res/cardsfolder/t/the_hippodrome.txt b/res/cardsfolder/t/the_hippodrome.txt new file mode 100644 index 00000000000..7d6e5bee5e8 --- /dev/null +++ b/res/cardsfolder/t/the_hippodrome.txt @@ -0,0 +1,16 @@ +Name:The Hippodrome +ManaCost:no cost +Types:Plane Segovia +Text:no text +S:Mode$ Continuous | EffectZone$ Command | Affected$ Creature | AddPower$ -5 | Description$ All Creatures get -5/-0. +T:Mode$ PlanarDice | Result$ Chaos | OptionalDecider$ You | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll Chaos, you may destroy target creature if it's power is 0 or less. +SVar:RolledChaos:AB$ Destroy | Cost$ 0 | ValidCards$ Creature | ConditionCheckSVar$ TgtPow | ConditionCompareSVar$ LE0 +SVar:TgtPow:Targeted$CardPower +T:Mode$ PlanarDice | Result$ Planeswalk | TriggerZones$ Command | Execute$ RolledWalk | Secondary$ True | TriggerDescription$ Whenever you roll Planeswalk, put this card on the bottom of its owner's planar deck face down, then move the top card of your planar deck off that planar deck and turn it face up. +SVar:RolledWalk:AB$ Planeswalk | Cost$ 0 +A:AB$ RollPlanarDice | Cost$ X | SorcerySpeed$ True | ActivationZone$ Command | SpellDescription$ Roll the planar dice. +SVar:X:Count$RolledThisTurn +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/the_hippodrome.jpg +SetInfo:HOP|Common|http://magiccards.info/extras/plane/planechase/the-hippodrome.jpg +End \ No newline at end of file diff --git a/src/main/java/forge/card/abilityfactory/ApiType.java b/src/main/java/forge/card/abilityfactory/ApiType.java index 35160b47b68..ad0b0a6f420 100644 --- a/src/main/java/forge/card/abilityfactory/ApiType.java +++ b/src/main/java/forge/card/abilityfactory/ApiType.java @@ -70,6 +70,7 @@ public enum ApiType { PermanentCreature (PermanentCreatureEfect.class, PermanentCreatureAi.class), PermanentNoncreature (PermanentNoncreatureEffect.class, PermanentNoncreatureAi.class), Phases (PhasesEffect.class, PhasesAi.class), + Planeswalk(PlaneswalkEffect.class, AlwaysPlayAi.class), Play (PlayEffect.class, PlayAi.class), Poison (PoisonEffect.class, PoisonAi.class), PreventDamage (DamagePreventEffect.class, DamagePreventAi.class), @@ -92,6 +93,7 @@ public enum ApiType { RestartGame (RestartGameEffect.class, RestartGameAi.class), Reveal (RevealEffect.class, RevealAi.class), RevealHand (RevealHandEffect.class, RevealHandAi.class), + RollPlanarDice (RollPlanarDiceEffect.class, CannotPlayAi.class), Sacrifice (SacrificeEffect.class, SacrificeAi.class), SacrificeAll (SacrificeAllEffect.class, SacrificeAllAi.class), Scry (ScryEffect.class, ScryAi.class), diff --git a/src/main/java/forge/card/abilityfactory/effects/PlaneswalkEffect.java b/src/main/java/forge/card/abilityfactory/effects/PlaneswalkEffect.java new file mode 100644 index 00000000000..302ee04df6f --- /dev/null +++ b/src/main/java/forge/card/abilityfactory/effects/PlaneswalkEffect.java @@ -0,0 +1,31 @@ +package forge.card.abilityfactory.effects; + +import forge.Singletons; +import forge.card.abilityfactory.SpellEffect; +import forge.card.spellability.SpellAbility; +import forge.game.GameState; +import forge.game.player.Player; + +/** + * TODO: Write javadoc for this type. + * + */ +public class PlaneswalkEffect extends SpellEffect { + + /* (non-Javadoc) + * @see forge.card.abilityfactory.SpellEffect#resolve(forge.card.spellability.SpellAbility) + */ + @Override + public void resolve(SpellAbility sa) { + GameState game = Singletons.getModel().getGame(); + + System.out.println("AF Planeswalking!"); + + for(Player p : game.getPlayers()) + { + p.leaveCurrentPlane(); + } + sa.getActivatingPlayer().planeswalk(); + } + +} diff --git a/src/main/java/forge/card/abilityfactory/effects/RollPlanarDiceEffect.java b/src/main/java/forge/card/abilityfactory/effects/RollPlanarDiceEffect.java new file mode 100644 index 00000000000..6148ecc9751 --- /dev/null +++ b/src/main/java/forge/card/abilityfactory/effects/RollPlanarDiceEffect.java @@ -0,0 +1,34 @@ +package forge.card.abilityfactory.effects; + +import forge.GameActionUtil; +import forge.Singletons; +import forge.card.abilityfactory.SpellEffect; +import forge.card.spellability.SpellAbility; +import forge.game.PlanarDice; +import forge.game.player.Player; + +/** + * TODO: Write javadoc for this type. + * + */ +public class RollPlanarDiceEffect extends SpellEffect { + + /* (non-Javadoc) + * @see forge.card.abilityfactory.SpellEffect#resolve(forge.card.spellability.SpellAbility) + */ + @Override + public void resolve(SpellAbility sa) { + boolean countedTowardsCost = !sa.hasParam("NotCountedTowardsCost"); + + Player roller = sa.getActivatingPlayer(); + if(countedTowardsCost) + { + + Singletons.getModel().getGame().getPhaseHandler().incPlanarDiceRolledthisTurn(); + } + PlanarDice result = PlanarDice.roll(roller); + + GameActionUtil.showInfoDialg(roller.getName() + " rolled " + result.toString()); + + } +} diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index abca2ec452a..f5875e55b06 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -2129,6 +2129,10 @@ public class CardFactoryUtil { if (l[0].startsWith("RememberedSize")) { return CardFactoryUtil.doXMath(c.getRemembered().size(), m, c); } + + if (l[0].startsWith("RolledThisTurn")) { + return Singletons.getModel().getGame().getPhaseHandler().getPlanarDiceRolledthisTurn(); + } final String[] sq; sq = l[0].split("\\."); diff --git a/src/main/java/forge/card/trigger/TriggerPlanarDice.java b/src/main/java/forge/card/trigger/TriggerPlanarDice.java new file mode 100644 index 00000000000..63a50409826 --- /dev/null +++ b/src/main/java/forge/card/trigger/TriggerPlanarDice.java @@ -0,0 +1,75 @@ +package forge.card.trigger; + +import java.util.Map; + +import forge.Card; +import forge.card.spellability.SpellAbility; +import forge.game.PlanarDice; + +/** + * TODO: Write javadoc for this type. + * + */ +public class TriggerPlanarDice extends Trigger { + + /** + *

+ * Constructor for Trigger_RollPlanarDice. + *

+ * + * @param params + * a {@link java.util.HashMap} object. + * @param host + * a {@link forge.Card} object. + * @param intrinsic + * the intrinsic + */ + public TriggerPlanarDice(final java.util.Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#performTest(java.util.Map) + */ + @Override + public boolean performTest(Map runParams2) { + if (this.getMapParams().containsKey("ValidPlayer")) { + if (!matchesValid(runParams2.get("Player"), this.getMapParams().get("ValidPlayer").split(","), + this.getHostCard())) { + return false; + } + } + + if (this.getMapParams().containsKey("Result")) { + PlanarDice cond = PlanarDice.smartValueOf(this.getMapParams().get("Result")); + if(cond != ((PlanarDice)runParams2.get("Result"))) { + return false; + } + } + + return true; + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#getCopy() + */ + @Override + public Trigger getCopy() { + final Trigger copy = new TriggerPlanarDice(this.getMapParams(), this.getHostCard(), this.isIntrinsic()); + if (this.getOverridingAbility() != null) { + copy.setOverridingAbility(this.getOverridingAbility()); + } + + copyFieldsTo(copy); + return copy; + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#setTriggeringObjects(forge.card.spellability.SpellAbility) + */ + @Override + public void setTriggeringObjects(SpellAbility sa) { + //THE BLACKEST TRIGGERINGOBJECT FOR THE MOST BRUTAL OF ALL TRIGGERS! NOOOOOTHIIIIIING! + } + +} diff --git a/src/main/java/forge/card/trigger/TriggerPlaneswalkedFrom.java b/src/main/java/forge/card/trigger/TriggerPlaneswalkedFrom.java new file mode 100644 index 00000000000..7444fa879b1 --- /dev/null +++ b/src/main/java/forge/card/trigger/TriggerPlaneswalkedFrom.java @@ -0,0 +1,68 @@ +package forge.card.trigger; + +import java.util.Map; + +import forge.Card; +import forge.card.spellability.SpellAbility; + +/** + * TODO: Write javadoc for this type. + * + */ +public class TriggerPlaneswalkedFrom extends Trigger { + + /** + *

+ * Constructor for Trigger_PlaneswalkedTo. + *

+ * + * @param params + * a {@link java.util.HashMap} object. + * @param host + * a {@link forge.Card} object. + * @param intrinsic + * the intrinsic + */ + public TriggerPlaneswalkedFrom(final Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#performTest(java.util.Map) + */ + @Override + public boolean performTest(Map runParams2) { + if (this.getMapParams().containsKey("ValidCard")) { + final Card moved = (Card) runParams2.get("Card"); + if (!moved.isValid(this.getMapParams().get("ValidCard").split(","), this.getHostCard().getController(), + this.getHostCard())) { + return false; + } + } + + return true; + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#getCopy() + */ + @Override + public Trigger getCopy() { + final Trigger copy = new TriggerPlaneswalkedTo(this.getMapParams(), this.getHostCard(), this.isIntrinsic()); + if (this.getOverridingAbility() != null) { + copy.setOverridingAbility(this.getOverridingAbility()); + } + + copyFieldsTo(copy); + return copy; + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#setTriggeringObjects(forge.card.spellability.SpellAbility) + */ + @Override + public void setTriggeringObjects(SpellAbility sa) { + sa.setTriggeringObject("Card", this.getRunParams().get("Card")); + } + +} diff --git a/src/main/java/forge/card/trigger/TriggerPlaneswalkedTo.java b/src/main/java/forge/card/trigger/TriggerPlaneswalkedTo.java new file mode 100644 index 00000000000..d997fd86566 --- /dev/null +++ b/src/main/java/forge/card/trigger/TriggerPlaneswalkedTo.java @@ -0,0 +1,68 @@ +package forge.card.trigger; + +import java.util.Map; + +import forge.Card; +import forge.card.spellability.SpellAbility; + +/** + * TODO: Write javadoc for this type. + * + */ +public class TriggerPlaneswalkedTo extends Trigger { + + /** + *

+ * Constructor for Trigger_PlaneswalkedTo. + *

+ * + * @param params + * a {@link java.util.HashMap} object. + * @param host + * a {@link forge.Card} object. + * @param intrinsic + * the intrinsic + */ + public TriggerPlaneswalkedTo(final Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#performTest(java.util.Map) + */ + @Override + public boolean performTest(Map runParams2) { + if (this.getMapParams().containsKey("ValidCard")) { + final Card moved = (Card) runParams2.get("Card"); + if (!moved.isValid(this.getMapParams().get("ValidCard").split(","), this.getHostCard().getController(), + this.getHostCard())) { + return false; + } + } + + return true; + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#getCopy() + */ + @Override + public Trigger getCopy() { + final Trigger copy = new TriggerPlaneswalkedTo(this.getMapParams(), this.getHostCard(), this.isIntrinsic()); + if (this.getOverridingAbility() != null) { + copy.setOverridingAbility(this.getOverridingAbility()); + } + + copyFieldsTo(copy); + return copy; + } + + /* (non-Javadoc) + * @see forge.card.trigger.Trigger#setTriggeringObjects(forge.card.spellability.SpellAbility) + */ + @Override + public void setTriggeringObjects(SpellAbility sa) { + sa.setTriggeringObject("Card", this.getRunParams().get("Card")); + } + +} diff --git a/src/main/java/forge/card/trigger/TriggerType.java b/src/main/java/forge/card/trigger/TriggerType.java index 70edd795529..3de64f9b95c 100644 --- a/src/main/java/forge/card/trigger/TriggerType.java +++ b/src/main/java/forge/card/trigger/TriggerType.java @@ -48,6 +48,9 @@ public enum TriggerType { Shuffled(TriggerShuffled.class), LandPlayed(TriggerLandPlayed.class), LosesGame(TriggerLosesGame.class), + PlanarDice(TriggerPlanarDice.class), + PlaneswalkedTo(TriggerPlaneswalkedTo.class), + PlaneswalkedFrom(TriggerPlaneswalkedFrom.class), SetInMotion(TriggerSetInMotion.class); private final Class classTrigger; diff --git a/src/main/java/forge/control/input/InputMulligan.java b/src/main/java/forge/control/input/InputMulligan.java index d4f6d704687..94fa5a6b6a9 100644 --- a/src/main/java/forge/control/input/InputMulligan.java +++ b/src/main/java/forge/control/input/InputMulligan.java @@ -31,7 +31,9 @@ import forge.GameActionUtil; import forge.Singletons; import forge.card.abilityfactory.AbilityFactory; import forge.card.spellability.SpellAbility; +import forge.card.trigger.TriggerType; import forge.game.GameState; +import forge.game.GameType; import forge.game.player.ComputerUtil; import forge.game.player.Player; import forge.game.zone.Zone; @@ -176,9 +178,15 @@ public class InputMulligan extends Input { ga.checkStateEffects(); Singletons.getModel().getMatch().getInput().clearInput(); - - //Set Field shown to current player. + Player next = game.getPhaseHandler().getPlayerTurn(); + + if(game.getType() == GameType.Planechase) + { + next.initPlane(); + } + + //Set Field shown to current player. VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(next); SDisplayUtil.showTab(nextField); diff --git a/src/main/java/forge/deck/CardCollections.java b/src/main/java/forge/deck/CardCollections.java index e6407e3352b..a518392a40d 100644 --- a/src/main/java/forge/deck/CardCollections.java +++ b/src/main/java/forge/deck/CardCollections.java @@ -35,6 +35,7 @@ public class CardCollections { private final IStorage sealed; private final IStorage cube; private final IStorage scheme; + private final IStorage plane; /** * TODO: Write javadoc for Constructor. @@ -47,6 +48,7 @@ public class CardCollections { this.sealed = new StorageImmediatelySerialized(new DeckGroupSerializer(new File(file, "sealed"))); this.cube = new StorageImmediatelySerialized(new DeckSerializer(new File(file, "cube"))); this.scheme = new StorageImmediatelySerialized(new DeckSerializer(new File(file, "scheme"))); + this.plane = new StorageImmediatelySerialized(new DeckSerializer(new File(file, "plane"))); System.out.printf("Read decks: %d constructed, %d sealed, %d draft, %d cubes, %d scheme.%n", constructed.getCount(), sealed.getCount(), draft.getCount(), cube.getCount(), scheme.getCount()); @@ -99,4 +101,11 @@ public class CardCollections { return this.scheme; } + /** + * @return the plane + */ + public IStorage getPlane() { + return plane; + } + } diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java index d7428dd49c9..d5baea8e497 100644 --- a/src/main/java/forge/game/GameNew.java +++ b/src/main/java/forge/game/GameNew.java @@ -243,6 +243,17 @@ public class GameNew { if (schemes != null) { player.setSchemeDeck(schemes); } + + Iterable planes = p.getValue().getPlanes(player); + if (planes != null) { + ArrayList l = new ArrayList(); + for(Card c : planes) + { + l.add(c); + } + CardLists.shuffle(l); + player.setPlanarDeck(l); + } Deck toUse; diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java index a4636440285..b671b9b0093 100644 --- a/src/main/java/forge/game/GameState.java +++ b/src/main/java/forge/game/GameState.java @@ -61,10 +61,14 @@ import forge.game.zone.ZoneType; * "cleaned up" at each new game. */ public class GameState { + private final GameType type; private final List roIngamePlayers; private final List allPlayers; private final List ingamePlayers = new ArrayList(); - + + private final List communalPlanarDeck = new ArrayList(); + private Card activePlane = null; + private final Cleanup cleanup = new Cleanup(); private final EndOfTurn endOfTurn = new EndOfTurn(); private final EndOfCombat endOfCombat = new EndOfCombat(); @@ -91,7 +95,8 @@ public class GameState { * Constructor. * @param players2 */ - public GameState(Iterable players2) { /* no more zones to map here */ + public GameState(Iterable players2, GameType t) { /* no more zones to map here */ + type = t; List players = new ArrayList(); for (LobbyPlayer p : players2) { Player pl = getIngamePlayer(p); @@ -516,6 +521,13 @@ public class GameState { return events; } + /** + * @return the type of game (Constructed/Limited/Planechase/etc...) + */ + public GameType getType() { + return type; + } + /** * TODO: Write javadoc for this method. * @param card @@ -550,4 +562,59 @@ public class GameState { return abilities; } + + /** + * @return the activePlane + */ + public Card getActivePlane() { + return activePlane; + } + + /** + * @param activePlane0 the activePlane to set + */ + public void setActivePlane(Card activePlane0) { + this.activePlane = activePlane0; + } + + /** + * + * Currently unused. Base for the Single Planar deck option. (Rule 901.15) + */ + public void setCommunalPlaneDeck(List deck) { + communalPlanarDeck.clear(); + communalPlanarDeck.addAll(deck); + CardLists.shuffle(communalPlanarDeck); + + for(Player p : roIngamePlayers) + { + p.setPlanarDeck(communalPlanarDeck); + } + } + + /** + * + * Currently unused. Base for the Single Planar deck option. (Rule 901.15) + */ + public void initCommunalPlane() + { + getTriggerHandler().suppressMode(TriggerType.PlaneswalkedTo); + Card firstPlane = null; + while(true) + { + firstPlane = communalPlanarDeck.get(0); + communalPlanarDeck.remove(0); + if(firstPlane.getType().contains("Phenomenon")) + { + communalPlanarDeck.add(firstPlane); + } + else + { + this.getPhaseHandler().getPlayerTurn().getZone(ZoneType.Command).add(firstPlane); + break; + } + } + + getTriggerHandler().clearSuppression(TriggerType.PlaneswalkedTo); + } } diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index 6ba911bf9d2..43fb55cb8d9 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -95,8 +95,8 @@ public class MatchController { public void startRound() { // Will this lose all the ordering? - currentGame = Singletons.getModel().newGame(players.keySet()); - + currentGame = Singletons.getModel().newGame(players.keySet(),gameType); + // Instantiate AI input = new InputControl(currentGame); diff --git a/src/main/java/forge/game/MatchStartHelper.java b/src/main/java/forge/game/MatchStartHelper.java index 4cc68b1c9b0..8eeb510efdd 100644 --- a/src/main/java/forge/game/MatchStartHelper.java +++ b/src/main/java/forge/game/MatchStartHelper.java @@ -68,6 +68,26 @@ public class MatchStartHelper { players.put(player, start); } + + public void addPlanechasePlayer(final LobbyPlayer player, final Deck deck, final Iterable planes) { + PlayerStartConditions start = new PlayerStartConditions(deck); + + start.setPlanes(new Function>() { + + @Override + public Iterable apply(Player p) { + List res = new ArrayList(); + for (CardPrinted cp : planes) { + res.add(cp.toForgeCard(p)); + } + + return res; + } + + }); + + players.put(player, start); + } public Map getPlayerMap() { diff --git a/src/main/java/forge/game/PlanarDice.java b/src/main/java/forge/game/PlanarDice.java new file mode 100644 index 00000000000..beef7ac1cf1 --- /dev/null +++ b/src/main/java/forge/game/PlanarDice.java @@ -0,0 +1,53 @@ +package forge.game; + +import java.util.HashMap; +import java.util.TreeMap; + +import forge.Singletons; +import forge.card.trigger.TriggerType; +import forge.game.player.Player; + +/** + * Represents the planar dice for Planechase games. + * + */ +public enum PlanarDice { + Planeswalk, + Chaos, + Blank; + + public static PlanarDice roll(Player roller) + { + PlanarDice res = Blank; + int i = forge.util.MyRandom.getRandom().nextInt(6); + if (i == 0) + res = Planeswalk; + if (i == 1) + res = Chaos; + + HashMap runParams = new HashMap(); + runParams.put("Player", roller); + runParams.put("Result", res); + Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.PlanarDice, runParams,false); + + + return res; + } + + /** + * Parses a string into an enum member. + * @param string to parse + * @return enum equivalent + */ + public static PlanarDice smartValueOf(String value) { + + final String valToCompate = value.trim(); + for (final PlanarDice v : PlanarDice.values()) { + if (v.name().compareToIgnoreCase(valToCompate) == 0) { + return v; + } + } + + throw new RuntimeException("Element " + value + " not found in TriggerType enum"); + } +} diff --git a/src/main/java/forge/game/PlayerStartConditions.java b/src/main/java/forge/game/PlayerStartConditions.java index d0ee81fa350..f91f610913f 100644 --- a/src/main/java/forge/game/PlayerStartConditions.java +++ b/src/main/java/forge/game/PlayerStartConditions.java @@ -1,6 +1,7 @@ package forge.game; import com.google.common.base.Function; + import forge.Card; import forge.deck.Deck; import forge.game.player.Player; @@ -15,6 +16,7 @@ public class PlayerStartConditions { private Function> cardsOnBattlefield = null; private Function> cardsInCommand = null; private Function> schemes = null; + private Function> planes = null; public PlayerStartConditions(Deck deck0) { originalDeck = deck0; @@ -93,5 +95,19 @@ public class PlayerStartConditions { currentDeck = originalDeck; } + /** + * @return the planes + */ + public Iterable getPlanes(final Player p) { + return planes == null ? null : planes.apply(p); + } + + /** + * @param planes0 the planes to set + */ + public void setPlanes(Function> planes0) { + this.planes = planes0; + } + } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 247db3836dc..953da4604c6 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -31,6 +31,7 @@ import forge.Singletons; import forge.card.spellability.SpellAbilityStackInstance; import forge.card.trigger.TriggerType; import forge.game.GameState; +import forge.game.GameType; import forge.game.event.EndOfTurnEvent; import forge.game.event.ManaBurnEvent; import forge.game.player.Player; @@ -64,7 +65,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { private int nCombatsThisTurn = 0; private boolean bPreventCombatDamageThisTurn = false; - + private int planarDiceRolledthisTurn = 0; + private Player playerTurn = null; // priority player @@ -472,6 +474,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { if (!this.bRepeat) { this.setPlayerTurn(this.handleNextTurn()); } + this.planarDiceRolledthisTurn = 0; // Play the End Turn sound Singletons.getModel().getGame().getEvents().post(new EndOfTurnEvent()); break; @@ -546,6 +549,16 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { Player next = getNextActivePlayer(); VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(next); SDisplayUtil.showTab(nextField); + + if(game.getType() == GameType.Planechase) { + Card p = game.getActivePlane(); + if(p != null) + { + p.clearControllers(); + p.addController(next); + game.getAction().controllerChangeZoneCorrection(p); + } + } return next; } @@ -735,26 +748,29 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { //is turned face down and put on the bottom of its owner's scheme //deck the next time a player would receive priority. //(This is a state-based action. See rule 704.) - for (int i = 0; i < game.getCardsIn(ZoneType.Command).size(); i++) { - Card c = game.getCardsIn(ZoneType.Command).get(i); - if (c.isScheme() && !c.isType("Ongoing")) { - - boolean foundonstack = false; - for (SpellAbilityStackInstance si : game.getStack().getStack()) { - if (si.getSourceCard().equals(c)) { - - foundonstack = true; - break; + if(game.getType() == GameType.Archenemy) + { + for (int i = 0; i < game.getCardsIn(ZoneType.Command).size(); i++) { + Card c = game.getCardsIn(ZoneType.Command).get(i); + if (c.isScheme() && !c.isType("Ongoing")) { + + boolean foundonstack = false; + for (SpellAbilityStackInstance si : game.getStack().getStack()) { + if (si.getSourceCard().equals(c)) { + + foundonstack = true; + break; + } + } + if (!foundonstack) { + + game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); + c.getController().getZone(ZoneType.Command).remove(c); + i--; + game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); + + c.getController().getSchemeDeck().add(c); } - } - if (!foundonstack) { - - game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - c.getController().getZone(ZoneType.Command).remove(c); - i--; - game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); - - c.getController().getSchemeDeck().add(c); } } } @@ -845,4 +861,17 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { public final void setPreventCombatDamageThisTurn(final boolean b) { this.bPreventCombatDamageThisTurn = true; } + + /** + * @return the planarDiceRolledthisTurn + */ + public int getPlanarDiceRolledthisTurn() { + return planarDiceRolledthisTurn; + } + + + public void incPlanarDiceRolledthisTurn() { + this.planarDiceRolledthisTurn++; + } + } diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index aabfa1faa12..3996569fcf3 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -65,6 +65,7 @@ import forge.game.event.SpellResolvedEvent; import forge.game.phase.PhaseHandler; import forge.game.zone.PlayerZone; import forge.game.zone.PlayerZoneBattlefield; +import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.properties.ForgePreferences.FPref; @@ -142,6 +143,9 @@ public abstract class Player extends GameEntity implements Comparable { /** The zones. */ private final Map zones = new EnumMap(ZoneType.class); + private List planarDeck = new ArrayList(); + private Card currentPlane = null; + private PlayerStatistics stats = new PlayerStatistics(); private final List schemeDeck = new ArrayList(); @@ -3169,4 +3173,73 @@ public abstract class Player extends GameEntity implements Comparable { game.getAction().playSpellAbility(ab, this); } + /** + * + * Takes the top plane of the planar deck and put it face up in the command zone. + * Then runs triggers. + */ + public void planeswalk() + { + //Run PlaneswalkedFrom triggers here. + HashMap runParams = new HashMap(); + runParams.put("Card", currentPlane); + game.getTriggerHandler().runTrigger(TriggerType.PlaneswalkedFrom, runParams,false); + + currentPlane = planarDeck.get(0); + + planarDeck.remove(0); + getZone(ZoneType.Command).add(currentPlane); + + game.setActivePlane(currentPlane); + //Run PlaneswalkedTo triggers here. + runParams.put("Card", currentPlane); + game.getTriggerHandler().runTrigger(TriggerType.PlaneswalkedTo, runParams,false); + } + + /** + * + * Puts my currently active plane, if any, at the bottom of my planar deck. + */ + public void leaveCurrentPlane() + { + if(currentPlane != null) + { + Zone com = game.getZoneOf(currentPlane); + com.remove(currentPlane); + currentPlane.clearControllers(); + planarDeck.add(currentPlane); + currentPlane = null; + } + } + + public void setPlanarDeck(List pd) + { + planarDeck = pd; + } + + /** + * + * Sets up the first plane of a round. + */ + public void initPlane() + { + Card firstPlane = null; + while(true) + { + firstPlane = planarDeck.get(0); + planarDeck.remove(0); + if(firstPlane.getType().contains("Phenomenon")) + { + planarDeck.add(firstPlane); + } + else + { + currentPlane = firstPlane; + getZone(ZoneType.Command).add(firstPlane); + break; + } + } + + game.setActivePlane(currentPlane); + } } diff --git a/src/main/java/forge/gui/framework/EDocID.java b/src/main/java/forge/gui/framework/EDocID.java index 1318242d998..a370661c30e 100644 --- a/src/main/java/forge/gui/framework/EDocID.java +++ b/src/main/java/forge/gui/framework/EDocID.java @@ -27,6 +27,7 @@ import forge.gui.home.settings.VSubmenuAvatars; import forge.gui.home.settings.VSubmenuDownloaders; import forge.gui.home.settings.VSubmenuPreferences; import forge.gui.home.variant.VSubmenuArchenemy; +import forge.gui.home.variant.VSubmenuPlanechase; import forge.gui.home.variant.VSubmenuVanguard; import forge.gui.match.views.VAntes; import forge.gui.match.views.VCombat; @@ -76,6 +77,7 @@ public enum EDocID { /** */ HOME_DRAFT (VSubmenuDraft.SINGLETON_INSTANCE), /** */ HOME_SEALED (VSubmenuSealed.SINGLETON_INSTANCE), /** */ HOME_VANGUARD (VSubmenuVanguard.SINGLETON_INSTANCE), /** */ + HOME_PLANECHASE (VSubmenuPlanechase.SINGLETON_INSTANCE), /** */ REPORT_MESSAGE (VMessage.SINGLETON_INSTANCE), /** */ REPORT_STACK (VStack.SINGLETON_INSTANCE), /** */ diff --git a/src/main/java/forge/gui/home/VHomeUI.java b/src/main/java/forge/gui/home/VHomeUI.java index e240fc926bb..185a93449f5 100644 --- a/src/main/java/forge/gui/home/VHomeUI.java +++ b/src/main/java/forge/gui/home/VHomeUI.java @@ -55,6 +55,7 @@ import forge.gui.home.settings.VSubmenuAvatars; import forge.gui.home.settings.VSubmenuDownloaders; import forge.gui.home.settings.VSubmenuPreferences; import forge.gui.home.variant.VSubmenuArchenemy; +import forge.gui.home.variant.VSubmenuPlanechase; import forge.gui.home.variant.VSubmenuVanguard; import forge.gui.toolbox.ExperimentalLabel; import forge.gui.toolbox.FLabel; @@ -119,8 +120,8 @@ public enum VHomeUI implements IVTopLevelUI { //allSubmenus.add(VSubmenuExit.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuArchenemy.SINGLETON_INSTANCE); - - allSubmenus.add(VSubmenuVanguard.SINGLETON_INSTANCE); + allSubmenus.add(VSubmenuVanguard.SINGLETON_INSTANCE); + allSubmenus.add(VSubmenuPlanechase.SINGLETON_INSTANCE); // For each group: init its panel final SortedMap allGroupPanels = new TreeMap(); diff --git a/src/main/java/forge/gui/home/variant/CSubmenuPlanechase.java b/src/main/java/forge/gui/home/variant/CSubmenuPlanechase.java new file mode 100644 index 00000000000..6035ec5ca7b --- /dev/null +++ b/src/main/java/forge/gui/home/variant/CSubmenuPlanechase.java @@ -0,0 +1,217 @@ +package forge.gui.home.variant; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; + +import com.google.common.collect.Iterables; + +import forge.Command; +import forge.GameActionUtil; +import forge.Singletons; +import forge.control.FControl; +import forge.control.Lobby; +import forge.deck.Deck; +import forge.deck.DeckgenUtil; +import forge.game.GameType; +import forge.game.MatchController; +import forge.game.MatchStartHelper; +import forge.game.player.LobbyPlayer; +import forge.game.player.PlayerType; +import forge.gui.SOverlayUtils; +import forge.gui.deckeditor.CDeckEditorUI; +import forge.gui.deckeditor.controllers.CEditorScheme; +import forge.gui.framework.ICDoc; +import forge.gui.toolbox.FDeckChooser; +import forge.item.CardPrinted; +import forge.properties.ForgePreferences; +import forge.properties.ForgePreferences.FPref; + +/** + * Controls the constructed submenu in the home UI. + * + *

(C at beginning of class name denotes a control class.) + * + */ +public enum CSubmenuPlanechase implements ICDoc { + /** */ + SINGLETON_INSTANCE; + private final VSubmenuPlanechase view = VSubmenuPlanechase.SINGLETON_INSTANCE; + + + /* (non-Javadoc) + * @see forge.gui.home.ICSubmenu#initialize() + */ + @Override + public void update() { + // Nothing to see here... + } + + /* (non-Javadoc) + * @see forge.gui.home.ICSubmenu#initialize() + */ + @Override + public void initialize() { + + VSubmenuPlanechase.SINGLETON_INSTANCE.getLblEditor().setCommand(new Command() { + @Override + public void execute() { + //TODO:Enter Planar deck editor here! + //CDeckEditorUI.SINGLETON_INSTANCE.setCurrentEditorController(new CEditorScheme()); + //FControl.SINGLETON_INSTANCE.changeState(FControl.DECK_EDITOR_CONSTRUCTED); + } + }); + + final ForgePreferences prefs = Singletons.getModel().getPreferences(); + for (FDeckChooser fdc : view.getDeckChoosers()) { + fdc.initialize(); + } + + // Checkbox event handling + view.getBtnStart().addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + startGame(); + } + }); + + // Checkbox event handling + view.getCbSingletons().addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + prefs.setPref(FPref.DECKGEN_SINGLETONS, + String.valueOf(view.getCbSingletons().isSelected())); + prefs.save(); + } + }); + + view.getCbArtifacts().addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + prefs.setPref( + FPref.DECKGEN_ARTIFACTS, String.valueOf(view.getCbArtifacts().isSelected())); + prefs.save(); + } + }); + + view.getCbRemoveSmall().addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + prefs.setPref( + FPref.DECKGEN_NOSMALL, String.valueOf(view.getCbRemoveSmall().isSelected())); + prefs.save(); + } + }); + + // Pre-select checkboxes + view.getCbSingletons().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_SINGLETONS)); + view.getCbArtifacts().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_ARTIFACTS)); + view.getCbRemoveSmall().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_NOSMALL)); + } + + + /** @param lists0   {@link java.util.List}<{@link javax.swing.JList}> */ + private void startGame() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + SOverlayUtils.startGameOverlay(); + SOverlayUtils.showOverlay(); + } + }); + + final SwingWorker worker = new SwingWorker() { + @Override + public Object doInBackground() { + Random rnd = new Random(); + + boolean usedDefaults = false; + + Lobby lobby = Singletons.getControl().getLobby(); + MatchStartHelper helper = new MatchStartHelper(); + List playerDecks = new ArrayList(); + for (int i = 0; i < view.getNumPlayers(); i++) { + Deck d = view.getDeckChoosers().get(i).getDeck(); + + if (d == null) { + //ERROR! + GameActionUtil.showInfoDialg("No deck selected for player " + (i + 1)); + return null; + } + playerDecks.add(d); + + + List planes = null; + Object obj = view.getPlanarDeckLists().get(i).getSelectedValue(); + + boolean useDefault = VSubmenuPlanechase.SINGLETON_INSTANCE.getCbUseDefaultPlanes().isSelected(); + useDefault &= !playerDecks.get(i).getSideboard().isEmpty(); + + System.out.println(useDefault); + if (useDefault) { + + planes = playerDecks.get(i).getSideboard().toFlatList(); + System.out.println(planes.toString()); + usedDefaults = true; + + } else { + + if (obj instanceof String) { + String sel = (String) obj; + if (sel.equals("Random")) { + + planes = Iterables.get(view.getAllPlanarDecks(), rnd.nextInt(Iterables.size(view.getAllPlanarDecks()))).getSideboard().toFlatList(); + } else { + + //Generate + planes = DeckgenUtil.generateSchemeDeck().getSideboard().toFlatList(); + } + } else { + planes = ((Deck) obj).getSideboard().toFlatList(); + } + } + if (planes == null) { + //ERROR! + GameActionUtil.showInfoDialg("No planar deck selected for player" + (i+1) + "!"); + return null; + } + + if (usedDefaults) { + + GameActionUtil.showInfoDialg("Player " + (i+1) + " will use a default planar deck."); + } + + LobbyPlayer player = lobby.findLocalPlayer(i == 0 ? PlayerType.HUMAN : PlayerType.COMPUTER); + + helper.addPlanechasePlayer(player, playerDecks.get(i), planes); + } + + MatchController mc = Singletons.getModel().getMatch(); + mc.initMatch(GameType.Planechase, helper.getPlayerMap()); + mc.startRound(); + + return null; + } + + @Override + public void done() { + SOverlayUtils.hideOverlay(); + } + }; + worker.execute(); + } + + + /* (non-Javadoc) + * @see forge.gui.framework.ICDoc#getCommandOnSelect() + */ + @Override + public Command getCommandOnSelect() { + return null; + } +} diff --git a/src/main/java/forge/gui/home/variant/VSubmenuPlanechase.java b/src/main/java/forge/gui/home/variant/VSubmenuPlanechase.java new file mode 100644 index 00000000000..46c4902acb4 --- /dev/null +++ b/src/main/java/forge/gui/home/variant/VSubmenuPlanechase.java @@ -0,0 +1,338 @@ +package forge.gui.home.variant; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; + +import net.miginfocom.swing.MigLayout; +import forge.Singletons; +import forge.deck.Deck; +import forge.game.player.PlayerType; +import forge.gui.framework.DragCell; +import forge.gui.framework.DragTab; +import forge.gui.framework.EDocID; +import forge.gui.home.EMenuGroup; +import forge.gui.home.IVSubmenu; +import forge.gui.home.LblHeader; +import forge.gui.home.StartButton; +import forge.gui.home.VHomeUI; +import forge.gui.toolbox.ExperimentalLabel; +import forge.gui.toolbox.FCheckBox; +import forge.gui.toolbox.FDeckChooser; +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FList; +import forge.gui.toolbox.FPanel; +import forge.gui.toolbox.FRadioButton; +import forge.gui.toolbox.FScrollPane; +import forge.gui.toolbox.FSkin; +import forge.gui.toolbox.FTabbedPane; + +/** + * Assembles Swing components of constructed submenu singleton. + * + *

(V at beginning of class name denotes a view class.) + * + */ +public enum VSubmenuPlanechase implements IVSubmenu { + /** */ + SINGLETON_INSTANCE; + + // Fields used with interface IVDoc + private DragCell parentCell; + private final DragTab tab = new DragTab("Planechase Mode"); + + /** */ + private final LblHeader lblTitle = new LblHeader("Variant: Planechase"); + + private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); + + private final StartButton btnStart = new StartButton(); + + private final JCheckBox cbSingletons = new FCheckBox("Singleton Mode"); + private final JCheckBox cbArtifacts = new FCheckBox("Remove Artifacts"); + private final JCheckBox cbRemoveSmall = new FCheckBox("Remove Small Creatures"); + + ////////////////////////////// + + private ExperimentalLabel lblEditor = new ExperimentalLabel("Planar Deck Editor"); + private final FTabbedPane tabPane = new FTabbedPane(); + private final List playerPanels = new ArrayList(); + private final List deckChoosers = new ArrayList(); + private final List planarDeckLists = new ArrayList(); + private final List allPlanarDecks = new ArrayList(); + private final JCheckBox cbUseDefaultPlanes = new FCheckBox("Use default planar decks if possible."); + private final List fieldRadios = new ArrayList(); + private final ButtonGroup grpFields = new ButtonGroup(); + private int currentNumTabsShown = 8; + + ////////////////////////////// + + private VSubmenuPlanechase() { + + lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); + + //This listener will look for any of the radio buttons being selected + //and call the method that shows/hides tabs appropriately. + ItemListener iListener = new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent arg0) { + FRadioButton aButton = (FRadioButton) arg0.getSource(); + + if (arg0.getStateChange() == ItemEvent.SELECTED) { + changeTabs(Integer.parseInt(aButton.getText())); + } + } + + }; + + //Create all 8 player settings panel + FRadioButton tempRadio = null; + FPanel tempPanel; + FDeckChooser tempChooser; + FList tempPlanarDeckList; + + //Settings panel + FPanel settingsPanel = new FPanel(); + settingsPanel.setLayout(new MigLayout("wrap 2")); + FPanel radioPane = new FPanel(); + radioPane.setLayout(new MigLayout("wrap 1")); + radioPane.setOpaque(false); + radioPane.add(new FLabel.Builder().text("Set number of opponents").build(), "wrap"); + for (int i = 1; i < 8; i++) { + tempRadio = new FRadioButton(); + tempRadio.setText(String.valueOf(i)); + fieldRadios.add(tempRadio); + grpFields.add(tempRadio); + tempRadio.setSelected(true); + tempRadio.addItemListener(iListener); + radioPane.add(tempRadio, "wrap,align 50% 50%"); + } + settingsPanel.add(radioPane, "span 1 2"); + settingsPanel.add(cbUseDefaultPlanes); + settingsPanel.add(lblEditor); + tabPane.add("Settings", settingsPanel); + + //Player panels (Human + 7 AIs) + for (int i = 0; i < 8; i++) { + tempPanel = new FPanel(); + tempPanel.setLayout(new MigLayout("insets 0, gap 0 , wrap 2, flowy")); + + tempChooser = new FDeckChooser("Select deck:", i == 0 ? PlayerType.HUMAN : PlayerType.COMPUTER); + tempChooser.initialize(); + + deckChoosers.add(tempChooser); + + tempPanel.add(tempChooser, "span 1 2, w 44%!, gap 0 0 20px 20px, growy, pushy, wrap"); + + tempPanel.add(new FLabel.Builder().text("Select Planar deck:").build(), "flowy"); + + tempPlanarDeckList = new FList(); + + Vector listData = new Vector(); + listData.add("Random"); + listData.add("Generate"); + for (Deck planarDeck : Singletons.getModel().getDecks().getPlane()) { + listData.add(planarDeck); + } + + tempPlanarDeckList.setListData(listData); + tempPlanarDeckList.setSelectedIndex(0); + tempPlanarDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + + JScrollPane scrPlanes = new FScrollPane(tempPlanarDeckList, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + tempPanel.add(scrPlanes, "h 90%!,wrap"); + planarDeckLists.add(tempPlanarDeckList); + + playerPanels.add(tempPanel); + if (i == 0) { + tabPane.add("Human", tempPanel); + } else { + tabPane.add("Opponent " + i, tempPanel); + } + } + + final String strCheckboxConstraints = "w 200px!, h 30px!, gap 0 20px 0 0"; + pnlStart.setOpaque(false); + pnlStart.add(cbSingletons, strCheckboxConstraints); + pnlStart.add(btnStart, "span 1 3, growx, pushx, align center"); + pnlStart.add(cbArtifacts, strCheckboxConstraints); + pnlStart.add(cbRemoveSmall, strCheckboxConstraints); + } + + private void changeTabs(int toShow) { + if (toShow < currentNumTabsShown) { + for (int i = currentNumTabsShown; i > toShow + 1; i--) { + tabPane.remove(i); + } + currentNumTabsShown = tabPane.getComponentCount() - 1; + } + else { + for (int i = currentNumTabsShown; i <= toShow; i++) { + tabPane.add("Opponent " + i, playerPanels.get(i)); + } + currentNumTabsShown = tabPane.getComponentCount() - 1; + } + } + + /* (non-Javadoc) + * @see forge.gui.home.IVSubmenu#getGroupEnum() + */ + @Override + public EMenuGroup getGroupEnum() { + return EMenuGroup.VARIANT; + } + + /* (non-Javadoc) + * @see forge.gui.home.IVSubmenu#getMenuTitle() + */ + @Override + public String getMenuTitle() { + return "Planechase"; + } + + /* (non-Javadoc) + * @see forge.gui.home.IVSubmenu#getItemEnum() + */ + @Override + public EDocID getItemEnum() { + return EDocID.HOME_PLANECHASE; + } + + /* (non-Javadoc) + * @see forge.gui.home.IVSubmenu#populate() + */ + @Override + public void populate() { + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().removeAll(); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().setLayout(new MigLayout("insets 0, gap 0, wrap 1, ax right")); + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(lblTitle, "w 80%!, h 40px!, gap 0 0 15px 15px, span 2, ax right"); + + for (FDeckChooser fdc : deckChoosers) { + fdc.populate(); + } + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(tabPane, "gap 0 0 50px 50px, growx, growy"); + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlStart, "span 1, ax center"); + + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().revalidate(); + VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().repaintSelf(); + + } + + + /** @return {@link javax.swing.JButton} */ + public JButton getBtnStart() { + return this.btnStart; + } + + + /** @return {@link javax.swing.JCheckBox} */ + public JCheckBox getCbSingletons() { + return cbSingletons; + } + + /** @return {@link javax.swing.JCheckBox} */ + public JCheckBox getCbArtifacts() { + return cbArtifacts; + } + + /** @return {@link javax.swing.JCheckBox} */ + public JCheckBox getCbRemoveSmall() { + return cbRemoveSmall; + } + + //========== Overridden from IVDoc + + /* (non-Javadoc) + * @see forge.gui.framework.IVDoc#getDocumentID() + */ + @Override + public EDocID getDocumentID() { + return EDocID.HOME_PLANECHASE; + } + + /* (non-Javadoc) + * @see forge.gui.framework.IVDoc#getTabLabel() + */ + @Override + public DragTab getTabLabel() { + return tab; + } + + /* (non-Javadoc) + * @see forge.gui.framework.IVDoc#getLayoutControl() + */ + @Override + public CSubmenuPlanechase getLayoutControl() { + return CSubmenuPlanechase.SINGLETON_INSTANCE; + } + + /* (non-Javadoc) + * @see forge.gui.framework.IVDoc#setParentCell(forge.gui.framework.DragCell) + */ + @Override + public void setParentCell(DragCell cell0) { + this.parentCell = cell0; + } + + /* (non-Javadoc) + * @see forge.gui.framework.IVDoc#getParentCell() + */ + @Override + public DragCell getParentCell() { + return parentCell; + } + + /** + * + * @return a deckchooser for every player + */ + public List getDeckChoosers() { + return deckChoosers; + } + + public int getNumPlayers() { + return currentNumTabsShown; + } + + /** + * @return the lblEditor + */ + public ExperimentalLabel getLblEditor() { + return lblEditor; + } + + /** + * @return the cbUseDefaultPlanes + */ + public JCheckBox getCbUseDefaultPlanes() { + return cbUseDefaultPlanes; + } + + /** + * @return the archenemySchemes + */ + public List getPlanarDeckLists() { + return planarDeckLists; + } + + /** + * @return the allSchemeDecks + */ + public List getAllPlanarDecks() { + return allPlanarDecks; + } +} diff --git a/src/main/java/forge/gui/match/nonsingleton/CCommand.java b/src/main/java/forge/gui/match/nonsingleton/CCommand.java index 8950652d1f1..0a9fac90356 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CCommand.java +++ b/src/main/java/forge/gui/match/nonsingleton/CCommand.java @@ -36,7 +36,7 @@ import forge.gui.framework.ICDoc; import forge.gui.match.CMatchUI; import forge.gui.match.controllers.CMessage; /** - * Controls Swing components of a player's field instance. + * Controls Swing components of a player's command instance. */ public class CCommand implements ICDoc { private final Player player; @@ -61,10 +61,10 @@ public class CCommand implements ICDoc { }; /** - * Controls Swing components of a player's field instance. + * Controls Swing components of a player's command instance. * * @param p0   {@link forge.game.player.Player} - * @param v0   {@link forge.gui.match.nonsingleton.VField} + * @param v0   {@link forge.gui.match.nonsingleton.VCommand} */ public CCommand(final Player p0, final VCommand v0) { this.player = p0; diff --git a/src/main/java/forge/gui/match/nonsingleton/VCommand.java b/src/main/java/forge/gui/match/nonsingleton/VCommand.java index d901e4d8836..b4dc3be18ac 100644 --- a/src/main/java/forge/gui/match/nonsingleton/VCommand.java +++ b/src/main/java/forge/gui/match/nonsingleton/VCommand.java @@ -31,7 +31,7 @@ import forge.gui.toolbox.FSkin; import forge.view.arcane.PlayArea; /** - * Assembles Swing components of a player field instance. + * Assembles Swing components of a player command instance. * *

(V at beginning of class name denotes a view class.) */ @@ -51,7 +51,7 @@ public class VCommand implements IVDoc { //========= Constructor /** - * Assembles Swing components of a player field instance. + * Assembles Swing components of a player command instance. * * @param player0   {@link forge.game.player.Player} * @param id0   {@link forge.gui.framework.EDocID} @@ -136,7 +136,7 @@ public class VCommand implements IVDoc { //========= Retrieval methods /** - * Gets the player currently associated with this field. + * Gets the player currently associated with this command. * @return {@link forge.game.player.Player} */ public Player getPlayer() { @@ -146,7 +146,7 @@ public class VCommand implements IVDoc { /** * Gets the tabletop. * - * @return PlayArea where cards for this field are in play + * @return PlayArea where cards for this command are in play */ public PlayArea getTabletop() { return this.tabletop; diff --git a/src/main/java/forge/model/FModel.java b/src/main/java/forge/model/FModel.java index 1ff5edf92f6..1da99e7a0fc 100644 --- a/src/main/java/forge/model/FModel.java +++ b/src/main/java/forge/model/FModel.java @@ -36,6 +36,7 @@ import forge.card.cardfactory.CardFactory; import forge.deck.CardCollections; import forge.error.ExceptionHandler; import forge.game.GameState; +import forge.game.GameType; import forge.game.MatchController; import forge.game.limited.GauntletMini; import forge.game.player.LobbyPlayer; @@ -427,8 +428,8 @@ public enum FModel { * TODO: Write javadoc for this method. * @param players */ - public GameState newGame(Iterable players) { - gameState = new GameState(players); + public GameState newGame(Iterable players, GameType type) { + gameState = new GameState(players,type); return gameState; }