From 3e4f405fb3d13f49c3f819e943191893edd3986c Mon Sep 17 00:00:00 2001 From: Hellfish Date: Sat, 5 Nov 2011 13:32:31 +0000 Subject: [PATCH] *Added Convoke for the human only. (AI will always pay full cost currently.) *Converted Sprout Swarm to script and completed it. *Added Autochthon Wurm Conclave Equenaut Conclave Phalanx Conclave's Blessing Devouring Light Gather Courage Guardian of Vitu-Ghazi Hour of Reckoning Kavu Primarch Overwhelm Root-Kin Ally Scatter the Seeds Siege Wurm Sundering Vitae --- .gitattributes | 14 +++ res/cardsfolder/a/autochthon_wurm.txt | 12 +++ res/cardsfolder/c/conclave_equenaut.txt | 12 +++ res/cardsfolder/c/conclave_phalanx.txt | 14 +++ res/cardsfolder/c/conclaves_blessing.txt | 14 +++ res/cardsfolder/d/devouring_light.txt | 11 +++ res/cardsfolder/g/gather_courage.txt | 11 +++ res/cardsfolder/g/guardian_of_vitu_ghazi.txt | 12 +++ res/cardsfolder/h/hour_of_reckoning.txt | 12 +++ res/cardsfolder/k/kavu_primarch.txt | 13 +++ res/cardsfolder/o/overwhelm.txt | 11 +++ res/cardsfolder/r/root_kin_ally.txt | 12 +++ res/cardsfolder/s/scatter_the_seeds.txt | 11 +++ res/cardsfolder/s/siege_wurm.txt | 11 +++ res/cardsfolder/s/sprout_swarm.txt | 5 +- res/cardsfolder/s/sundering_vitae.txt | 11 +++ src/main/java/forge/CardUtil.java | 27 +++++ src/main/java/forge/GameAction.java | 99 ++++++++++++++++++- .../card/cardfactory/CardFactoryInstants.java | 48 +-------- src/main/java/forge/card/cost/CostMana.java | 27 +++++ .../forge/card/spellability/SpellAbility.java | 25 +++++ .../forge/gui/input/InputPayManaCost.java | 59 ++++++++--- 22 files changed, 409 insertions(+), 62 deletions(-) create mode 100644 res/cardsfolder/a/autochthon_wurm.txt create mode 100644 res/cardsfolder/c/conclave_equenaut.txt create mode 100644 res/cardsfolder/c/conclave_phalanx.txt create mode 100644 res/cardsfolder/c/conclaves_blessing.txt create mode 100644 res/cardsfolder/d/devouring_light.txt create mode 100644 res/cardsfolder/g/gather_courage.txt create mode 100644 res/cardsfolder/g/guardian_of_vitu_ghazi.txt create mode 100644 res/cardsfolder/h/hour_of_reckoning.txt create mode 100644 res/cardsfolder/k/kavu_primarch.txt create mode 100644 res/cardsfolder/o/overwhelm.txt create mode 100644 res/cardsfolder/r/root_kin_ally.txt create mode 100644 res/cardsfolder/s/scatter_the_seeds.txt create mode 100644 res/cardsfolder/s/siege_wurm.txt create mode 100644 res/cardsfolder/s/sundering_vitae.txt diff --git a/.gitattributes b/.gitattributes index 34eeb6ecfee..972882c52fd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -485,6 +485,7 @@ res/cardsfolder/a/aurora_eidolon.txt svneol=native#text/plain res/cardsfolder/a/aurora_griffin.txt svneol=native#text/plain res/cardsfolder/a/auspicious_ancestor.txt svneol=native#text/plain res/cardsfolder/a/austere_command.txt svneol=native#text/plain +res/cardsfolder/a/autochthon_wurm.txt -text res/cardsfolder/a/avacynian_priest.txt -text res/cardsfolder/a/avacyns_pilgrim.txt -text res/cardsfolder/a/avalanche.txt svneol=native#text/plain @@ -1501,6 +1502,9 @@ res/cardsfolder/c/compulsion.txt svneol=native#text/plain res/cardsfolder/c/compulsive_research.txt svneol=native#text/plain res/cardsfolder/c/concentrate.txt svneol=native#text/plain res/cardsfolder/c/conch_horn.txt svneol=native#text/plain +res/cardsfolder/c/conclave_equenaut.txt -text +res/cardsfolder/c/conclave_phalanx.txt -text +res/cardsfolder/c/conclaves_blessing.txt -text res/cardsfolder/c/concordant_crossroads.txt svneol=native#text/plain res/cardsfolder/c/concussive_bolt.txt svneol=native#text/plain res/cardsfolder/c/condemn.txt svneol=native#text/plain @@ -2007,6 +2011,7 @@ res/cardsfolder/d/devoted_hero.txt svneol=native#text/plain res/cardsfolder/d/devoted_retainer.txt svneol=native#text/plain res/cardsfolder/d/devour_in_shadow.txt svneol=native#text/plain res/cardsfolder/d/devouring_deep.txt svneol=native#text/plain +res/cardsfolder/d/devouring_light.txt -text res/cardsfolder/d/devouring_rage.txt -text res/cardsfolder/d/devouring_strossus.txt -text res/cardsfolder/d/devouring_swarm.txt svneol=native#text/plain @@ -3098,6 +3103,7 @@ res/cardsfolder/g/gate_hound.txt svneol=native#text/plain res/cardsfolder/g/gate_to_phyrexia.txt svneol=native#text/plain res/cardsfolder/g/gatekeeper_of_malakir.txt svneol=native#text/plain res/cardsfolder/g/gathan_raiders.txt svneol=native#text/plain +res/cardsfolder/g/gather_courage.txt -text res/cardsfolder/g/gatherer_of_graces.txt svneol=native#text/plain res/cardsfolder/g/gatstaf_shepherd_gatstaf_howler.txt -text res/cardsfolder/g/gauntlet_of_might.txt svneol=native#text/plain @@ -3558,6 +3564,7 @@ res/cardsfolder/g/guardian_idol.txt svneol=native#text/plain res/cardsfolder/g/guardian_of_cloverdell.txt svneol=native#text/plain res/cardsfolder/g/guardian_of_solitude.txt svneol=native#text/plain res/cardsfolder/g/guardian_of_the_guildpact.txt svneol=native#text/plain +res/cardsfolder/g/guardian_of_vitu_ghazi.txt -text res/cardsfolder/g/guardian_seraph.txt svneol=native#text/plain res/cardsfolder/g/guardian_zendikon.txt svneol=native#text/plain res/cardsfolder/g/guardians_magemark.txt svneol=native#text/plain @@ -3848,6 +3855,7 @@ res/cardsfolder/h/horseshoe_crab.txt svneol=native#text/plain res/cardsfolder/h/hostile_realm.txt svneol=native#text/plain res/cardsfolder/h/hot_springs.txt svneol=native#text/plain res/cardsfolder/h/hotheaded_giant.txt -text +res/cardsfolder/h/hour_of_reckoning.txt -text res/cardsfolder/h/hoverguard_observer.txt svneol=native#text/plain res/cardsfolder/h/hoverguard_sweepers.txt svneol=native#text/plain res/cardsfolder/h/hovermyr.txt svneol=native#text/plain @@ -4295,6 +4303,7 @@ res/cardsfolder/k/kavu_lair.txt svneol=native#text/plain res/cardsfolder/k/kavu_mauler.txt svneol=native#text/plain res/cardsfolder/k/kavu_monarch.txt svneol=native#text/plain res/cardsfolder/k/kavu_predator.txt svneol=native#text/plain +res/cardsfolder/k/kavu_primarch.txt -text res/cardsfolder/k/kavu_recluse.txt svneol=native#text/plain res/cardsfolder/k/kavu_runner.txt svneol=native#text/plain res/cardsfolder/k/kavu_scout.txt svneol=native#text/plain @@ -5804,6 +5813,7 @@ res/cardsfolder/o/overrun.txt svneol=native#text/plain res/cardsfolder/o/oversold_cemetery.txt svneol=native#text/plain res/cardsfolder/o/oversoul_of_dusk.txt svneol=native#text/plain res/cardsfolder/o/overtaker.txt svneol=native#text/plain +res/cardsfolder/o/overwhelm.txt -text res/cardsfolder/o/overwhelming_forces.txt svneol=native#text/plain res/cardsfolder/o/overwhelming_intellect.txt svneol=native#text/plain res/cardsfolder/o/overwhelming_stampede.txt svneol=native#text/plain @@ -6738,6 +6748,7 @@ res/cardsfolder/r/roofstalker_wight.txt svneol=native#text/plain res/cardsfolder/r/root_cage.txt svneol=native#text/plain res/cardsfolder/r/root_elemental.txt svneol=native#text/plain res/cardsfolder/r/root_greevil.txt -text +res/cardsfolder/r/root_kin_ally.txt -text res/cardsfolder/r/root_maze.txt svneol=native#text/plain res/cardsfolder/r/root_sliver.txt svneol=native#text/plain res/cardsfolder/r/root_spider.txt svneol=native#text/plain @@ -6952,6 +6963,7 @@ res/cardsfolder/s/scarwood_goblins.txt svneol=native#text/plain res/cardsfolder/s/scarwood_hag.txt svneol=native#text/plain res/cardsfolder/s/scarwood_treefolk.txt svneol=native#text/plain res/cardsfolder/s/scathe_zombies.txt svneol=native#text/plain +res/cardsfolder/s/scatter_the_seeds.txt -text res/cardsfolder/s/scattershot.txt svneol=native#text/plain res/cardsfolder/s/scattershot_archer.txt svneol=native#text/plain res/cardsfolder/s/scavenged_weaponry.txt svneol=native#text/plain @@ -7298,6 +7310,7 @@ res/cardsfolder/s/sidewinder_sliver.txt svneol=native#text/plain res/cardsfolder/s/siege_gang_commander.txt svneol=native#text/plain res/cardsfolder/s/siege_mastodon.txt svneol=native#text/plain res/cardsfolder/s/siege_of_towers.txt svneol=native#text/plain +res/cardsfolder/s/siege_wurm.txt -text res/cardsfolder/s/sift.txt svneol=native#text/plain res/cardsfolder/s/sift_through_sands.txt -text res/cardsfolder/s/sighted_caste_sorcerer.txt svneol=native#text/plain @@ -8063,6 +8076,7 @@ res/cardsfolder/s/sunblast_angel.txt svneol=native#text/plain res/cardsfolder/s/suncrusher.txt svneol=native#text/plain res/cardsfolder/s/sunder.txt svneol=native#text/plain res/cardsfolder/s/sunder_from_within.txt svneol=native#text/plain +res/cardsfolder/s/sundering_vitae.txt -text res/cardsfolder/s/sunfire_balm.txt svneol=native#text/plain res/cardsfolder/s/sunflare_shaman.txt svneol=native#text/plain res/cardsfolder/s/sunglasses_of_urza.txt svneol=native#text/plain diff --git a/res/cardsfolder/a/autochthon_wurm.txt b/res/cardsfolder/a/autochthon_wurm.txt new file mode 100644 index 00000000000..6c26f48770b --- /dev/null +++ b/res/cardsfolder/a/autochthon_wurm.txt @@ -0,0 +1,12 @@ +Name:Autochthon Wurm +ManaCost:10 G G G W W +Types:Creature Wurm +Text:no text +PT:9/14 +K:Trample +K:Convoke +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/autochthon_wurm.jpg +SetInfo:RAV|Rare|http://magiccards.info/scans/en/rav/191.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nTrample +End \ No newline at end of file diff --git a/res/cardsfolder/c/conclave_equenaut.txt b/res/cardsfolder/c/conclave_equenaut.txt new file mode 100644 index 00000000000..709788a6bdb --- /dev/null +++ b/res/cardsfolder/c/conclave_equenaut.txt @@ -0,0 +1,12 @@ +Name:Conclave Equenaut +ManaCost:4 W W +Types:Creature Human Soldier +Text:no text +PT:3/3 +K:Flying +K:Convoke +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/conclave_equenaut.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/9.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nFlying +End \ No newline at end of file diff --git a/res/cardsfolder/c/conclave_phalanx.txt b/res/cardsfolder/c/conclave_phalanx.txt new file mode 100644 index 00000000000..c10506b8323 --- /dev/null +++ b/res/cardsfolder/c/conclave_phalanx.txt @@ -0,0 +1,14 @@ +Name:Conclave Phalanx +ManaCost:4 W +Types:Creature Human Soldier +Text:no text +PT:2/4 +K:Convoke +T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 1 life for each creature you control. +SVar:TrigGainLife:AB$GainLife | Cost$ 0 | Defined$ You | LifeAmount$ X +SVar:X:Count$Valid Creature.YouCtrl +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/conclave_phalanx.jpg +SetInfo:RAV|Uncommon|http://magiccards.info/scans/en/rav/10.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nWhen Conclave Phalanx enters the battlefield, you gain 1 life for each creature you control. +End \ No newline at end of file diff --git a/res/cardsfolder/c/conclaves_blessing.txt b/res/cardsfolder/c/conclaves_blessing.txt new file mode 100644 index 00000000000..0994474f10d --- /dev/null +++ b/res/cardsfolder/c/conclaves_blessing.txt @@ -0,0 +1,14 @@ +Name:Conclave's Blessing +ManaCost:3 W +Types:Enchantment Aura +Text:no text +K:Convoke +A:SP$Attach | Cost$ 3 W | ValidTgts$ Creature | AILogic$ Pump +S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddToughness$ X | Description$ Enchanted creature gets +0/+2 for each other creature you control. +SVar:X:SVar$OtherCreats/Twice +SVar:OtherCreats:Count$Valid Creature.YouCtrl/Minus.1 +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/conclaves_blessing.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/11.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nEnchant creature\nEnchanted creature gets +0/+2 for each other creature you control. +End \ No newline at end of file diff --git a/res/cardsfolder/d/devouring_light.txt b/res/cardsfolder/d/devouring_light.txt new file mode 100644 index 00000000000..c727b26bf17 --- /dev/null +++ b/res/cardsfolder/d/devouring_light.txt @@ -0,0 +1,11 @@ +Name:Devouring Light +ManaCost:1 W W +Types:Instant +Text:no text +K:Convoke +A:SP$ ChangeZone | Cost$ 1 W W | ValidTgts$ Creature.attacking,Creature.blocking | TgtPrompt$ Select target attacking or blocking creature. | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile target attacking or blocking creature. +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/devouring_light.jpg +SetInfo:RAV|Uncommon|http://magiccards.info/scans/en/rav/13.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nExile target attacking or blocking creature. +End \ No newline at end of file diff --git a/res/cardsfolder/g/gather_courage.txt b/res/cardsfolder/g/gather_courage.txt new file mode 100644 index 00000000000..dc35b15b078 --- /dev/null +++ b/res/cardsfolder/g/gather_courage.txt @@ -0,0 +1,11 @@ +Name:Gather Courage +ManaCost:G +Types:Instant +Text:no text +K:Convoke +A:SP$Pump | Cost$ G | Tgt$ TgtC | NumAtt$ 2 | NumDef$ 2 | SpellDescription$ Target creature gets +2/+2 until end of turn. +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/gather_courage.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/165.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nTarget creature gets +2/+2 until end of turn. +End \ No newline at end of file diff --git a/res/cardsfolder/g/guardian_of_vitu_ghazi.txt b/res/cardsfolder/g/guardian_of_vitu_ghazi.txt new file mode 100644 index 00000000000..14b46d14778 --- /dev/null +++ b/res/cardsfolder/g/guardian_of_vitu_ghazi.txt @@ -0,0 +1,12 @@ +Name:Guardian of Vitu-Ghazi +ManaCost:6 G W +Types:Creature Elemental +Text:no text +PT:4/7 +K:Convoke +K:Vigilance +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/guardian_of_vitu_ghazi.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/212.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nVigilance +End \ No newline at end of file diff --git a/res/cardsfolder/h/hour_of_reckoning.txt b/res/cardsfolder/h/hour_of_reckoning.txt new file mode 100644 index 00000000000..2d97c6c1fd1 --- /dev/null +++ b/res/cardsfolder/h/hour_of_reckoning.txt @@ -0,0 +1,12 @@ +Name:Hour of Reckoning +ManaCost:4 W W W +Types:Sorcery +Text:no text +K:Convoke +A:SP$DestroyAll | Cost$ 4 W W W | ValidCards$ Creature.nonToken | SpellDescription$ Destroy all nonToken creatures. +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/hour_of_reckoning.jpg +SetInfo:RAV|Rare|http://magiccards.info/scans/en/rav/21.jpg +SetInfo:COM|Rare|http://magiccards.info/scans/en/cmd/15.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nDestroy all nontoken creatures. +End \ No newline at end of file diff --git a/res/cardsfolder/k/kavu_primarch.txt b/res/cardsfolder/k/kavu_primarch.txt new file mode 100644 index 00000000000..c5455af8a4a --- /dev/null +++ b/res/cardsfolder/k/kavu_primarch.txt @@ -0,0 +1,13 @@ +Name:Kavu Primarch +ManaCost:3 G +Types:Creature Kavu +Text:no text +PT:3/3 +K:Convoke +K:Kicker:4 +K:etbCounter:P1P1:4:isValid Card.kicked:If CARDNAME was kicked, it enters the battlefield with four +1/+1 counters on it. +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/kavu_primarch.jpg +SetInfo:FUT|Common|http://magiccards.info/scans/en/fut/128.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its total cost by {1} or by one mana of that creature's color.)\nKicker {4} (You may pay an additional {4} as you cast this spell.)\nIf Kavu Primarch was kicked, it enters the battlefield with four +1/+1 counters on it. +End \ No newline at end of file diff --git a/res/cardsfolder/o/overwhelm.txt b/res/cardsfolder/o/overwhelm.txt new file mode 100644 index 00000000000..d91ea3bab12 --- /dev/null +++ b/res/cardsfolder/o/overwhelm.txt @@ -0,0 +1,11 @@ +Name:Overwhelm +ManaCost:5 G G +Types:Sorcery +Text:no text +K:Convoke +A:SP$PumpAll | Cost$ 5 G G | ValidCards$ Creature.YouCtrl | NumAtt$ 3 | NumDef$ 3 | SpellDescription$ Creatures you control get +3/+3 until end of turn. +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/overwhelm.jpg +SetInfo:RAV|Uncommon|http://magiccards.info/scans/en/rav/175.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nCreatures you control get +3/+3 until end of turn. +End \ No newline at end of file diff --git a/res/cardsfolder/r/root_kin_ally.txt b/res/cardsfolder/r/root_kin_ally.txt new file mode 100644 index 00000000000..d9b9e926d70 --- /dev/null +++ b/res/cardsfolder/r/root_kin_ally.txt @@ -0,0 +1,12 @@ +Name:Root-Kin Ally +ManaCost:4 G G +Types:Creature Elemental Warrior +Text:no text +PT:3/3 +K:Convoke +A:AB$Pump | Cost$ tapXType<2/Creature> | Defined$ Self | NumAtt$ 2 | NumDef$ 2 | SpellDescription$ CARDNAME gets +2/+2 until end of turn. +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/root_kin_ally.jpg +SetInfo:RAV|Uncommon|http://magiccards.info/scans/en/rav/180.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nTap two untapped creatures you control: Root-Kin Ally gets +2/+2 until end of turn. +End \ No newline at end of file diff --git a/res/cardsfolder/s/scatter_the_seeds.txt b/res/cardsfolder/s/scatter_the_seeds.txt new file mode 100644 index 00000000000..132524e95e2 --- /dev/null +++ b/res/cardsfolder/s/scatter_the_seeds.txt @@ -0,0 +1,11 @@ +Name:Scatter the Seeds +ManaCost:3 G G +Types:Instant +Text:no text +K:Convoke +A:SP$ Token | Cost$ G | TokenAmount$ 3 | TokenName$ Saproling | TokenTypes$ Creature,Saproling | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put three 1/1 green Saproling creature tokens onto the battlefield. +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/scatter_the_seeds.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/181.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nPut three 1/1 green Saproling creature tokens onto the battlefield. +End \ No newline at end of file diff --git a/res/cardsfolder/s/siege_wurm.txt b/res/cardsfolder/s/siege_wurm.txt new file mode 100644 index 00000000000..71cc17afe20 --- /dev/null +++ b/res/cardsfolder/s/siege_wurm.txt @@ -0,0 +1,11 @@ +Name:Siege Wurm +ManaCost:5 G G +Types:Creature Wurm +Text:no text +PT:5/5 +K:Convoke +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/siege_wurm.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/183.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nTrample +End \ No newline at end of file diff --git a/res/cardsfolder/s/sprout_swarm.txt b/res/cardsfolder/s/sprout_swarm.txt index 6e114412548..38064c127f4 100644 --- a/res/cardsfolder/s/sprout_swarm.txt +++ b/res/cardsfolder/s/sprout_swarm.txt @@ -1,7 +1,10 @@ Name:Sprout Swarm ManaCost:1 G Types:Instant -Text:(NOTE: "Convoke" is not implemented.) +Text:no text +K:Convoke +A:SP$ Token | Cost$ 1 G | TokenAmount$ 1 | TokenName$ Saproling | TokenTypes$ Creature,Saproling | TokenOwner$ You | TokenColors$ Green | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put a 1/1 green Saproling creature token onto the battlefield. +SVar:Buyback:3 SVar:RemRandomDeck:True SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/sprout_swarm.jpg diff --git a/res/cardsfolder/s/sundering_vitae.txt b/res/cardsfolder/s/sundering_vitae.txt new file mode 100644 index 00000000000..14fc7bfb5bc --- /dev/null +++ b/res/cardsfolder/s/sundering_vitae.txt @@ -0,0 +1,11 @@ +Name:Sundering Vitae +ManaCost:2 G +Types:Instant +Text:no text +K:Convoke +A:SP$ Destroy | Cost$ 2 G | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/sundering_vitae.jpg +SetInfo:RAV|Common|http://magiccards.info/scans/en/rav/185.jpg +Oracle:Convoke (Each creature you tap while casting this spell reduces its cost by {1} or by one mana of that creature's color.)\nDestroy target artifact or enchantment. +End \ No newline at end of file diff --git a/src/main/java/forge/CardUtil.java b/src/main/java/forge/CardUtil.java index e9abe940b08..f1f63af969f 100644 --- a/src/main/java/forge/CardUtil.java +++ b/src/main/java/forge/CardUtil.java @@ -16,6 +16,7 @@ import org.apache.commons.lang3.StringUtils; import forge.card.mana.ManaCost; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityList; +import forge.gui.input.InputPayManaCostUtil; import forge.item.CardPrinted; import forge.properties.ForgeProps; import forge.properties.NewConstants; @@ -928,5 +929,31 @@ public final class CardUtil { return res; } + + public static ArrayList getConvokableColors(final Card cardToConvoke, ManaCost cost) + { + ArrayList usableColors = new ArrayList(); + + if(cost.getColorlessManaAmount() > 0) + { + usableColors.add("colorless"); + } + for(CardColor col : cardToConvoke.getColor()) + { + for(String strCol : col.toStringArray()) + { + if(strCol.equals("colorless")) + { + continue; + } + if(cost.toString().contains(InputPayManaCostUtil.getShortColorString(strCol))) + { + usableColors.add(strCol.toString()); + } + } + } + + return usableColors; + } } // end class CardUtil diff --git a/src/main/java/forge/GameAction.java b/src/main/java/forge/GameAction.java index 5151de5dd65..dd7d9fa5eb0 100644 --- a/src/main/java/forge/GameAction.java +++ b/src/main/java/forge/GameAction.java @@ -36,6 +36,7 @@ import forge.gui.GuiUtils; import forge.gui.input.InputMulligan; import forge.gui.input.InputPayManaCost; import forge.gui.input.InputPayManaCostAbility; +import forge.gui.input.InputPayManaCostUtil; import forge.item.CardPrinted; import forge.properties.ForgeProps; import forge.properties.NewConstants.Lang.GameAction.GameActionText; @@ -2032,7 +2033,103 @@ public class GameAction { this.exile(chosen); } + manaCost = new ManaCost(originalCost.toString()); + manaCost.decreaseColorlessMana(numToExile); } + } else if (spell.getSourceCard().hasKeyword("Convoke")) { + CardList untappedCreats = spell.getActivatingPlayer().getCardsIn(Zone.Battlefield).getType("Creature"); + untappedCreats = untappedCreats.filter(new CardListFilter() { + public boolean addCard(Card c) { + return !c.isTapped(); + } + }); + + if(untappedCreats.size() != 0) + { + ArrayList choices = new ArrayList(); + for(Card c : untappedCreats) { + choices.add(c); + } + choices.add("DONE"); + ArrayList usableColors = new ArrayList(); + ManaCost newCost = new ManaCost(originalCost.toString()); + Object tapForConvoke = null; + if(sa.getActivatingPlayer().isHuman()) + { + tapForConvoke = GuiUtils.getChoiceOptional("Tap for Convoke? " + newCost.toString(), choices.toArray()); + } + else { + //TODO: AI to choose a creature to tap would go here + //Probably along with deciding how many creatures to tap + } + while(tapForConvoke != null && (tapForConvoke instanceof Card) && untappedCreats.size() != 0) { + Card workingCard = (Card) tapForConvoke; + usableColors = CardUtil.getConvokableColors(workingCard, newCost); + + if(usableColors.size() != 0) + { + String chosenColor = usableColors.get(0); + if(usableColors.size() > 1) + { + if(sa.getActivatingPlayer().isHuman()) + { + chosenColor = (String)GuiUtils.getChoice("Convoke for which color?", usableColors.toArray()); + } + else + { + //TODO: AI for choosing which color to convoke goes here. + } + } + + if(chosenColor.equals("colorless")) + { + newCost.decreaseColorlessMana(1); + } + else + { + String newCostStr = newCost.toString(); + newCostStr = newCostStr.replaceFirst(InputPayManaCostUtil.getShortColorString(chosenColor), ""); + newCost = new ManaCost(newCostStr.trim()); + } + + sa.addTappedForConvoke(workingCard); + choices.remove(workingCard); + untappedCreats.remove(workingCard); + if(choices.size() < 2 || newCost.getConvertedManaCost() == 0) { + break; + } + } + else + { + untappedCreats.remove(workingCard); + } + + if(sa.getActivatingPlayer().isHuman()) + { + tapForConvoke = GuiUtils.getChoiceOptional("Tap for Convoke? " + newCost.toString(), choices.toArray()); + } + else { + //TODO: AI to choose a creature to tap would go here + } + } + + //will only be null if user cancelled. + if(tapForConvoke != null) { + //Convoked creats are tapped here with triggers suppressed, + //Then again when payment is done(In InputPayManaCost.done()) with suppression cleared. + //This is to make sure that triggers go off at the right time + //AND that you can't use mana tapabilities of convoked creatures + //to pay the convoked cost. + AllZone.getTriggerHandler().suppressMode("Taps"); + for(Card c : sa.getTappedForConvoke()) { + c.tap(); + } + AllZone.getTriggerHandler().clearSuppression("Taps"); + + manaCost = newCost; + } + } + } } // isSpell @@ -2535,7 +2632,7 @@ public class GameAction { AllZone.getInputControl().setInput(sa.getAfterPayMana()); } } else if (sa.getBeforePayMana() == null) { - AllZone.getInputControl().setInput(new InputPayManaCost(sa)); + AllZone.getInputControl().setInput(new InputPayManaCost(sa,manaCost)); } else { AllZone.getInputControl().setInput(sa.getBeforePayMana()); } diff --git a/src/main/java/forge/card/cardfactory/CardFactoryInstants.java b/src/main/java/forge/card/cardfactory/CardFactoryInstants.java index 1f8e52bb309..8618e0c84a4 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryInstants.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryInstants.java @@ -52,53 +52,7 @@ public class CardFactoryInstants { public static Card getCard(final Card card, final String cardName) { // *************** START *********** START ************************** - if (cardName.equals("Sprout Swarm")) { - final SpellAbility spellOne = new Spell(card) { - private static final long serialVersionUID = -609007714604161377L; - - @Override - public boolean canPlayAI() { - return false; - } - - @Override - public void resolve() { - CardFactoryUtil.makeTokenSaproling(card.getController()); - } - }; // SpellAbility - - final SpellAbility spellTwo = new Spell(card) { - private static final long serialVersionUID = -1387385820860395676L; - - @Override - public void resolve() { - CardFactoryUtil.makeTokenSaproling(card.getController()); - // return card to the hand - final PlayerZone hand = card.getController().getZone(Constant.Zone.Hand); - AllZone.getGameAction().moveTo(hand, card); - } - }; // SpellAbility - - spellOne.setManaCost("1 G"); - spellTwo.setManaCost("4 G"); - spellTwo.setAdditionalManaCost("3"); - - spellOne.setDescription("Put a 1/1 green Saproling token onto the battlefield."); - spellTwo.setDescription("Buyback 3 (You may pay an additional 3 as you cast this spell. " - + "If you do, put this card into your hand as it resolves.)"); - - spellOne.setStackDescription("Sprout Swarm - Put a 1/1 green Saproling token onto the battlefield"); - spellTwo.setStackDescription("Sprout Swarm - Buyback, Put a 1/1 green " - + "Saproling token onto the battlefield"); - - spellTwo.setIsBuyBackAbility(true); - - card.addSpellAbility(spellOne); - card.addSpellAbility(spellTwo); - } // *************** END ************ END ************************** - - // *************** START *********** START ************************** - else if (cardName.equals("Fact or Fiction")) { + if (cardName.equals("Fact or Fiction")) { final SpellAbility spell = new Spell(card) { private static final long serialVersionUID = 1481112451519L; diff --git a/src/main/java/forge/card/cost/CostMana.java b/src/main/java/forge/card/cost/CostMana.java index e457f1172cc..8ebf9201eb2 100644 --- a/src/main/java/forge/card/cost/CostMana.java +++ b/src/main/java/forge/card/cost/CostMana.java @@ -387,11 +387,38 @@ public class CostMana extends CostPart { source.setXManaCostPaid(0); CostUtil.setInput(CostMana.inputPayXMana(sa, payment, costMana, costMana.getXMana())); } + + //If this is a spell with convoke, re-tap all creatures used for it. + //This is done to make sure Taps triggers go off at the right time + //(i.e. AFTER cost payment, they are tapped previously as well so that + //any mana tapabilities can't be used in payment as well as being tapped for convoke) + + if(sa.getTappedForConvoke() != null) + { + AllZone.getTriggerHandler().suppressMode("Untaps"); + for(Card c : sa.getTappedForConvoke()) { + c.untap(); + c.tap(); + } + AllZone.getTriggerHandler().clearSuppression("Untaps"); + sa.clearTappedForConvoke(); + } } @Override public void selectButtonCancel() { + //If we're paying for a spell with convoke, untap all creatures used for it. + if(sa.getTappedForConvoke() != null) + { + AllZone.getTriggerHandler().suppressMode("Untaps"); + for(Card c : sa.getTappedForConvoke()) { + c.untap(); + } + AllZone.getTriggerHandler().clearSuppression("Untaps"); + sa.clearTappedForConvoke(); + } + this.stop(); this.resetManaCost(); payment.cancelCost(); diff --git a/src/main/java/forge/card/spellability/SpellAbility.java b/src/main/java/forge/card/spellability/SpellAbility.java index a38aaeea3b5..dbd66075edb 100644 --- a/src/main/java/forge/card/spellability/SpellAbility.java +++ b/src/main/java/forge/card/spellability/SpellAbility.java @@ -108,6 +108,8 @@ public abstract class SpellAbility { public void execute(final Object o) { } }; + + private CardList tappedForConvoke = null; /** *

@@ -1706,5 +1708,28 @@ public abstract class SpellAbility { public void setChosenTarget(Target chosenTarget) { this.chosenTarget = chosenTarget; // TODO: Add 0 to parameter's name. } + + public void addTappedForConvoke(Card c) + { + if(tappedForConvoke == null) + { + tappedForConvoke = new CardList(); + } + + tappedForConvoke.add(c); + } + + public CardList getTappedForConvoke() + { + return tappedForConvoke; + } + + public void clearTappedForConvoke() + { + if(tappedForConvoke != null) + { + tappedForConvoke.clear(); + } + } } diff --git a/src/main/java/forge/gui/input/InputPayManaCost.java b/src/main/java/forge/gui/input/InputPayManaCost.java index 8ab7cdc2a86..fbd41c0f992 100644 --- a/src/main/java/forge/gui/input/InputPayManaCost.java +++ b/src/main/java/forge/gui/input/InputPayManaCost.java @@ -72,6 +72,18 @@ public class InputPayManaCost extends Input { } } + /** + *

+ * Constructor for Input_PayManaCost. + *

+ * + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + */ + public InputPayManaCost(final SpellAbility sa) { + this(sa,new ManaCost(sa.getManaCost())); + } + /** *

* Constructor for Input_PayManaCost. @@ -79,9 +91,12 @@ public class InputPayManaCost extends Input { * * @param sa * a {@link forge.card.spellability.SpellAbility} object. + * + * @param manaCostToPay + * a {@link forge.card.mana.ManaCost} object. */ - public InputPayManaCost(final SpellAbility sa) { - this.originalManaCost = sa.getManaCost(); // Change + public InputPayManaCost(final SpellAbility sa, final ManaCost manaCostToPay) { + this.originalManaCost = manaCostToPay.toString(); // Change this.originalCard = sa.getSourceCard(); this.spell = sa; @@ -95,7 +110,7 @@ public class InputPayManaCost extends Input { AllZone.getStack().add(this.spell); } } else { - this.manaCost = AllZone.getGameAction().getSpellCostChange(sa, new ManaCost(this.originalManaCost)); + this.manaCost = manaCostToPay;//AllZone.getGameAction().getSpellCostChange(sa, new ManaCost(this.originalManaCost)); } } else { this.manaCost = new ManaCost(sa.getManaCost()); @@ -196,25 +211,43 @@ public class InputPayManaCost extends Input { } AllZone.getInputControl().resetInput(); } + + //If this is a spell with convoke, re-tap all creatures used for it. + //This is done to make sure Taps triggers go off at the right time + //(i.e. AFTER cost payment, they are tapped previously as well so that + //any mana tapabilities can't be used in payment as well as being tapped for convoke) + + if(spell.getTappedForConvoke() != null) + { + AllZone.getTriggerHandler().suppressMode("Untaps"); + for(Card c : spell.getTappedForConvoke()) { + c.untap(); + c.tap(); + } + AllZone.getTriggerHandler().clearSuppression("Untaps"); + spell.clearTappedForConvoke(); + } } } /** {@inheritDoc} */ @Override public final void selectButtonCancel() { + //If this is a spell with convoke, untap all creatures used for it. + if(spell.getTappedForConvoke() != null) + { + AllZone.getTriggerHandler().suppressMode("Untaps"); + for(Card c : spell.getTappedForConvoke()) { + c.untap(); + } + AllZone.getTriggerHandler().clearSuppression("Untaps"); + spell.clearTappedForConvoke(); + } + this.resetManaCost(); AllZone.getHumanPlayer().getManaPool().unpaid(this.spell, true); AllZone.getHumanPlayer().getZone(Zone.Battlefield).updateObservers(); // DO - // NOT - // REMOVE - // THIS, - // otherwise - // the - // cards - // don't - // always - // tap - + this.stop(); }