From b821ec7af5bf75b99ba28bc6a13176726af7c148 Mon Sep 17 00:00:00 2001 From: Rob Schnautz Date: Thu, 24 Jan 2019 04:57:54 +0000 Subject: [PATCH 01/54] Add token scripts and download URLs. --- .../cardsfolder/upcoming/awaken_the_erstwhile.txt | 2 +- .../res/cardsfolder/upcoming/depose_deploy.txt | 2 +- .../cardsfolder/upcoming/dovin_grand_arbiter.txt | 2 +- .../cardsfolder/upcoming/ethereal_absolution.txt | 2 +- .../res/cardsfolder/upcoming/goblin_gathering.txt | 2 +- .../upcoming/knight_of_the_last_breath.txt | 2 +- .../cardsfolder/upcoming/mesmerizing_benthid.txt | 2 +- .../res/cardsfolder/upcoming/smothering_tithe.txt | 3 +-- .../res/cardsfolder/upcoming/thrash_threat.txt | 2 +- .../res/cardsfolder/upcoming/warrant_warden.txt | 2 +- .../res/cardsfolder/upcoming/watchful_giant.txt | 2 +- forge-gui/res/lists/token-images.txt | 14 +++++++++++++- forge-gui/res/tokenscripts/c_a_treasure_sac.txt | 5 +++++ .../res/tokenscripts/u_0_2_illusion_mesmerize.txt | 9 +++++++++ 14 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 forge-gui/res/tokenscripts/c_a_treasure_sac.txt create mode 100644 forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt diff --git a/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt b/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt index 52018c5c221..9f4a1887fb5 100644 --- a/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt +++ b/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt @@ -2,6 +2,6 @@ Name:Awaken the Erstwhile ManaCost:3 B B Types:Sorcery A:SP$ RepeatEach | Cost$ 3 B B | RepeatPlayers$ Player | RepeatSubAbility$ DBDiscard | SpellDescription$ Each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens. -SVar:DBToken:DB$ Token | TokenAmount$ X | TokenName$ Zombie | TokenTypes$ Creature,Zombie | TokenOwner$ You | TokenColors$ Black | TokenPower$ 2 | TokenToughness$ 2 | References$ X +SVar:DBToken:DB$ Token | TokenAmount$ X | TokenScript$ b_2_2_zombie | TokenOwner$ You | LegacyImage$ b 2 2 zombie rna | References$ X SVar:X:Remembered$Amount Oracle:Each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens. diff --git a/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt b/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt index 7237e0cc680..eadf1a642cb 100644 --- a/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt +++ b/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt @@ -11,7 +11,7 @@ ALTERNATE Name:Deploy ManaCost:2 W U Types:Instant -A:SP$ Token | Cost$ 2 W U | TokenAmount$ 2 | TokenOwner$ You | TokenScript$ c_1_1_a_thopter_flying | SubAbility$ DBGainLife | SpellDescription$ Create two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control. +A:SP$ Token | Cost$ 2 W U | TokenAmount$ 2 | TokenOwner$ You | TokenScript$ c_1_1_a_thopter_flying | LegacyImage$ c 1 1 a thopter flying rna | SubAbility$ DBGainLife | SpellDescription$ Create two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control. SVar:DBGainLife:DB$ GainLife | LifeAmount$ X | References$ X SVar:X:Count$TypeYouCtrl.Creature Oracle:Create two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control. diff --git a/forge-gui/res/cardsfolder/upcoming/dovin_grand_arbiter.txt b/forge-gui/res/cardsfolder/upcoming/dovin_grand_arbiter.txt index 54d1b89048c..a27a07d3d7b 100644 --- a/forge-gui/res/cardsfolder/upcoming/dovin_grand_arbiter.txt +++ b/forge-gui/res/cardsfolder/upcoming/dovin_grand_arbiter.txt @@ -5,7 +5,7 @@ Loyalty:3 A:AB$ Effect | Cost$ AddCounter<1/LOYALTY> | Name$ CARDNAME Effect | Triggers$ TrigSpellCast | SVars$ TrigPutCounter | SpellDescription$ Until end of turn, whenever a creature you control deals combat damage to a player, put a loyalty counter on CARDNAME. SVar:X:Count$Valid Creature.YouCtrl SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ LOYALTY | CounterNum$ 1 -A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenName$ Thopter | TokenTypes$ Artifact,Creature,Thopter | TokenOwner$ You | TokenColors$ Colorless | TokenPower$ 1 | TokenToughness$ 1 | TokenKeywords$ Flying | SubAbility$ DBGainLife | SpellDescription$ Create a 1/1 colorless Thopter artifact creature token with flying. +A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ c_1_1_a_thopter_flying | TokenOwner$ You | LegacyImage$ c 1 1 a thopter flying rna | SubAbility$ DBGainLife | SpellDescription$ Create a 1/1 colorless Thopter artifact creature token with flying. SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 | SpellDescription$ You gain 1 life. DeckHas:Ability$Token A:AB$ Dig | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | DigNum$ 10 | ChangeNum$ 3 | DestinationZone$ Hand | DestinationZone2$ Library | LibraryPosition$ -1 | Choices$ Card.nonLand | SpellDescription$ Look at the top ten cards of your library. Put three of them into your hand and the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/upcoming/ethereal_absolution.txt b/forge-gui/res/cardsfolder/upcoming/ethereal_absolution.txt index 288224e09e9..3c789a573ff 100644 --- a/forge-gui/res/cardsfolder/upcoming/ethereal_absolution.txt +++ b/forge-gui/res/cardsfolder/upcoming/ethereal_absolution.txt @@ -6,7 +6,7 @@ S:Mode$ Continuous | Affected$ Creature.OppCtrl | AddPower$ -1 | AddToughness$ - SVar:PlayMain1:TRUE SVar:RemRandomDeck:True A:AB$ ChangeZone | Cost$ 4 W B | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Card.OppOwn | SubAbility$ DBToken | SpellDescription$ Exile target card from an opponent's graveyard. If it was a creature card, you create a 1/1 white and black Spirit creature token with flying. -SVar:DBToken:DB$ Token | ConditionDefined$ Targeted | ConditionPresent$ Creature | ConditionCompare$ EQ1 | TokenAmount$ 1 | TokenScript$ wb_1_1_spirit_flying | TokenOwner$ You | SubAbility$ DBCleanup +SVar:DBToken:DB$ Token | ConditionDefined$ Targeted | ConditionPresent$ Creature | ConditionCompare$ EQ1 | TokenAmount$ 1 | TokenScript$ wb_1_1_spirit_flying | TokenOwner$ You | SubAbility$ DBCleanup | LegacyImage$ wb 1 1 spirit flying rna SVar:DBCleanup:DB$Cleanup | ClearRemembered$ True DeckHas:Ability$Token Oracle:Creatures you control get +1/+1.\nCreatures your opponents control get -1/-1.\n{2}{W}{B}: Exile target card from an opponent's graveyard. If it was a creature card, you create a 1/1 white and black Spirit creature token with flying. diff --git a/forge-gui/res/cardsfolder/upcoming/goblin_gathering.txt b/forge-gui/res/cardsfolder/upcoming/goblin_gathering.txt index af886dfda2a..949beb5d67d 100644 --- a/forge-gui/res/cardsfolder/upcoming/goblin_gathering.txt +++ b/forge-gui/res/cardsfolder/upcoming/goblin_gathering.txt @@ -1,7 +1,7 @@ Name:Goblin Gathering ManaCost:2 R Types:Sorcery -A:SP$ Token | Cost$ 2 R | TokenAmount$ X | TokenScript$ r_1_1_goblin | TokenOwner$ You | References$ X | SpellDescription$ Create a number of 1/1 red Goblin creature tokens equal to two plus the number of cards named CARDNAME in your graveyard. +A:SP$ Token | Cost$ 2 R | TokenAmount$ X | TokenScript$ r_1_1_goblin | LegacyImage$ r 1 1 goblin rna | TokenOwner$ You | References$ X | SpellDescription$ Create a number of 1/1 red Goblin creature tokens equal to two plus the number of cards named Goblin Gathering in your graveyard. SVar:X:Count$ValidGraveyard Card.YouOwn+namedGoblin Gathering/Plus.2 DeckHints:Name$Goblin Gathering DeckHas:Ability$Token diff --git a/forge-gui/res/cardsfolder/upcoming/knight_of_the_last_breath.txt b/forge-gui/res/cardsfolder/upcoming/knight_of_the_last_breath.txt index cf506cad0c6..a28bc189702 100644 --- a/forge-gui/res/cardsfolder/upcoming/knight_of_the_last_breath.txt +++ b/forge-gui/res/cardsfolder/upcoming/knight_of_the_last_breath.txt @@ -2,7 +2,7 @@ Name:Knight of the Last Breath ManaCost:5 W B Types:Creature Giant Knight PT:4/4 -A:AB$ Token | Cost$ 3 Sac<1/Creature.nonToken+Other/another creature> | TokenAmount$ 1 | TokenScript$ wb_1_1_spirit_flying | TokenOwner$ You | SpellDescription$ Create a 1/1 white and black Spirit creature token with flying. +A:AB$ Token | Cost$ 3 Sac<1/Creature.nonToken+Other/another creature> | TokenAmount$ 1 | TokenScript$ wb_1_1_spirit_flying | TokenOwner$ You | LegacyImage$ wb 1 1 spirit flying rna | SpellDescription$ Create a 1/1 white and black Spirit creature token with flying. SVar:RemRandomDeck:True K:Afterlife:3 SVar:AIPreference:SacCost$Creature.cmcLE1 diff --git a/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt b/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt index 7187cc3021e..2e24fa33b4d 100644 --- a/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt +++ b/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt @@ -3,7 +3,7 @@ ManaCost:3 U U Types:Creature Octopus PT:4/5 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 0/2 blue Illusion creature tokens with flying, it doesn't untap during its controller's next untap step. -SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenName$ Illusion | TokenTypes$ Creature,Illusion | TokenOwner$ You | TokenColors$ Blue | TokenPower$ 0 | TokenToughness$ 2 | TokenKeywords$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True +SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ u_0_2_illusion_mesmerize | TokenOwner$ You | LegacyImage$ u 0 2 illusion mesmerize rna SVar:PlayMain1:TRUE SVar:RemRandomDeck:True S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Hexproof | CheckSVar$ X | SVarCompare$ GE1 | Description$ CARDNAME has hexproof as long as you control an Illusion. diff --git a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt index 9f9e33bcdc1..fe24282b545 100644 --- a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt +++ b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt @@ -2,6 +2,5 @@ Name:Smothering Tithe ManaCost:3 W Types:Enchantment T:Mode$ Drawn | ValidCard$ Card.OppOwn | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with flying{T}, Sacrifice this artifact: Add one mana of any color. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Treasure | TokenTypes$ Artifact,Treasure | TokenOwner$ TriggeredPlayer | TokenColors$ Colorless | TokenImage$ c treasure | TokenAbilities$ ABTreasureMana | TokenAltImages$ c_treasure2,c_treasure3,c_treasure4 -SVar:ABTreasureMana:DB$ Token | TokenAmount$ 1 | TokenName$ +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ TriggeredPlayer | LegacyImage$ c a treasure sac Oracle:Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color." diff --git a/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt b/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt index edebe152dde..14706116cf1 100644 --- a/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt +++ b/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt @@ -12,5 +12,5 @@ ALTERNATE Name:Threat ManaCost:2 R G Types:Sorcery -A:SP$ Token | Cost$ 2 R G | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ rg_4_4_beast_trample | SpellDescription$ Create a 4/4 red and green Beast creature token with trample. +A:SP$ Token | Cost$ 2 R G | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ rg_4_4_beast_trample | LegacyImage$ rg 4 4 beast trample rna | SpellDescription$ Create a 4/4 red and green Beast creature token with trample. Oracle:Create a 4/4 red and green Beast creature token with trample. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt b/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt index 614c5d7126b..07e1dd9cdd8 100644 --- a/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt +++ b/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt @@ -10,7 +10,7 @@ ALTERNATE Name:Warden ManaCost:3 W U Types:Sorcery -A:SP$ Token | Cost$ 3 W U | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ wu_4_4_sphinx_flying_vigilance | SpellDescription$ Create a 4/4 white and blue Sphinx creature token with flying and vigilance. +A:SP$ Token | Cost$ 3 W U | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ wu_4_4_sphinx_flying_vigilance | LegacyImage$ wu 4 4 sphinx flying vigilance rna | SpellDescription$ Create a 4/4 white and blue Sphinx creature token with flying and vigilance. Oracle:Create a 4/4 white and blue Sphinx creature token with flying and vigilance. diff --git a/forge-gui/res/cardsfolder/upcoming/watchful_giant.txt b/forge-gui/res/cardsfolder/upcoming/watchful_giant.txt index d214f346e1e..cfbd1508df9 100644 --- a/forge-gui/res/cardsfolder/upcoming/watchful_giant.txt +++ b/forge-gui/res/cardsfolder/upcoming/watchful_giant.txt @@ -3,7 +3,7 @@ ManaCost:5 W Types:Creature Giant Soldier PT:3/6 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 1/1 white Human creature token. -SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenOwner$ You | SpellDescription$ Create a 1/1 white Human creature token. +SVar:TrigToken:DB$Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | LegacyImage$ w 1 1 human rna | TokenOwner$ You | SpellDescription$ Create a 1/1 white Human creature token. DeckHints:Type$Human DeckHas:Ability$Token Oracle:When Watchful Giant enters the battlefield, create a 1/1 white Human creature token. diff --git a/forge-gui/res/lists/token-images.txt b/forge-gui/res/lists/token-images.txt index a5bd7a64a39..8a5bbadb95a 100644 --- a/forge-gui/res/lists/token-images.txt +++ b/forge-gui/res/lists/token-images.txt @@ -38,6 +38,7 @@ b_2_2_zombie_m13.jpg https://downloads.cardforge.org/images/to b_2_2_zombie_m14.jpg https://downloads.cardforge.org/images/tokens/b_2_2_zombie_m14.jpg b_2_2_zombie_mbs.jpg https://downloads.cardforge.org/images/tokens/b_2_2_zombie_mbs.jpg b_2_2_zombie_knight.jpg https://downloads.cardforge.org/images/tokens/b_2_2_zombie_knight.jpg +b_2_2_zombie_rna.jpg https://downloads.cardforge.org/images/tokens/b_2_2_zombie_rna.jpg b_2_4_spider.jpg https://downloads.cardforge.org/images/tokens/b_2_4_spider.jpg b_3_3_angel.jpg https://downloads.cardforge.org/images/tokens/b_3_3_angel.jpg b_3_3_kavu.jpg https://downloads.cardforge.org/images/tokens/b_3_3_kavu.jpg @@ -65,6 +66,7 @@ c_0_1_pest.jpg https://downloads.cardforge.org/images/to c_0_1_prism.jpg https://downloads.cardforge.org/images/tokens/c_0_1_prism.jpg c_0_2_wall.jpg https://downloads.cardforge.org/images/tokens/c_0_2_wall.jpg c_10_10_eldrazi.jpg https://downloads.cardforge.org/images/tokens/c_10_10_eldrazi.jpg +c_1_1_a_thopter_flying_rna.jpg https://downloads.cardforge.org/images/tokens/c_1_1_a_thopter_flying_rna.jpg c_1_1_eldrazi_scion.jpg https://downloads.cardforge.org/images/tokens/c_1_1_eldrazi_scion.jpg c_1_1_eldrazi_scion2.jpg https://downloads.cardforge.org/images/tokens/c_1_1_eldrazi_scion2.jpg c_1_1_eldrazi_scion3.jpg https://downloads.cardforge.org/images/tokens/c_1_1_eldrazi_scion3.jpg @@ -103,6 +105,7 @@ c_5_5_tuktuk_the_returned.jpg https://downloads.cardforge.org/images/to c_6_12_construct.jpg https://downloads.cardforge.org/images/tokens/c_6_12_construct.jpg c_7_7_eldrazi.jpg https://downloads.cardforge.org/images/tokens/c_7_7_eldrazi.jpg c_9_9_golem.jpg https://downloads.cardforge.org/images/tokens/c_9_9_golem.jpg +c_a_treasure_sac_rna.jpg https://downloads.cardforge.org/images/tokens/c_a_treasure_sac_rna.jpg c_gold.jpg https://downloads.cardforge.org/images/tokens/c_gold.jpg c_x_x_horror.jpg https://downloads.cardforge.org/images/tokens/c_x_x_horror.jpg c_x_x_riptide_replicator.jpg https://downloads.cardforge.org/images/tokens/c_x_x_riptide_replicator.jpg @@ -154,6 +157,7 @@ g_2_2_boar.jpg https://downloads.cardforge.org/images/to g_2_2_cat_warrior.jpg https://downloads.cardforge.org/images/tokens/g_2_2_cat_warrior.jpg g_2_2_lizard.jpg https://downloads.cardforge.org/images/tokens/g_2_2_lizard.jpg g_2_2_ooze.jpg https://downloads.cardforge.org/images/tokens/g_2_2_ooze.jpg +g_2_2_ooze_rna.jpg https://downloads.cardforge.org/images/tokens/g_2_2_ooze_rna.jpg g_2_2_wolf.jpg https://downloads.cardforge.org/images/tokens/g_2_2_wolf.jpg g_2_2_wolf_bng.jpg https://downloads.cardforge.org/images/tokens/g_2_2_wolf_bng.jpg g_2_2_wolf_isd.jpg https://downloads.cardforge.org/images/tokens/g_2_2_wolf_isd.jpg @@ -176,11 +180,13 @@ g_3_3_boar.jpg https://downloads.cardforge.org/images/to g_3_3_centaur.jpg https://downloads.cardforge.org/images/tokens/g_3_3_centaur.jpg g_3_3_centaur_bng.jpg https://downloads.cardforge.org/images/tokens/g_3_3_centaur_bng.jpg g_3_3_centaur_pro_black.jpg https://downloads.cardforge.org/images/tokens/g_3_3_centaur_pro_black.jpg +g_3_3_centaur_rna.jpg https://downloads.cardforge.org/images/tokens/g_3_3_centaur_rna.jpg g_3_3_centaur_rtr.jpg https://downloads.cardforge.org/images/tokens/g_3_3_centaur_rtr.jpg g_3_3_elephant.jpg https://downloads.cardforge.org/images/tokens/g_3_3_elephant.jpg g_3_3_elephant_ody.jpg https://downloads.cardforge.org/images/tokens/g_3_3_elephant_ody.jpg g_3_3_elephant_wwk.jpg https://downloads.cardforge.org/images/tokens/g_3_3_elephant_wwk.jpg g_3_3_frog_lizard.jpg https://downloads.cardforge.org/images/tokens/g_3_3_frog_lizard.jpg +g_3_3_frog_lizard_rna.jpg https://downloads.cardforge.org/images/tokens/g_3_3_frog_lizard_rna.jpg g_4_4_beast.jpg https://downloads.cardforge.org/images/tokens/g_4_4_beast.jpg g_4_4_beast_zen.jpg https://downloads.cardforge.org/images/tokens/g_4_4_beast_zen.jpg g_4_4_elemental.jpg https://downloads.cardforge.org/images/tokens/g_4_4_elemental.jpg @@ -221,6 +227,7 @@ r_1_1_goblin_dom.jpg https://downloads.cardforge.org/images/to r_1_1_goblin_m13.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_m13.jpg r_1_1_goblin_nph.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_nph.jpg r_1_1_goblin_rav.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_rav.jpg +r_1_1_goblin_rna.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_rna.jpg r_1_1_goblin_rtr.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_rtr.jpg r_1_1_goblin_scout.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_scout.jpg r_1_1_goblin_som.jpg https://downloads.cardforge.org/images/tokens/r_1_1_goblin_som.jpg @@ -261,6 +268,7 @@ rg_1_1_goblin_warrior.jpg https://downloads.cardforge.org/images/to rg_2_2_satyr.jpg https://downloads.cardforge.org/images/tokens/rg_2_2_satyr.jpg rg_3_4_stangg_twin.jpg https://downloads.cardforge.org/images/tokens/rg_3_4_stangg_twin.jpg rg_4_4_giant_warrior.jpg https://downloads.cardforge.org/images/tokens/rg_4_4_giant_warrior.jpg +rg_4_4_beast_trample_rna.jpg https://downloads.cardforge.org/images/tokens/rg_4_4_beast_trample.jpg rg_5_5_elemental.jpg https://downloads.cardforge.org/images/tokens/rg_5_5_elemental.jpg rw_1_1_goblin_soldier.jpg https://downloads.cardforge.org/images/tokens/rw_1_1_goblin_soldier.jpg rw_1_1_goblin_soldier_eve.jpg https://downloads.cardforge.org/images/tokens/rw_1_1_goblin_soldier_eve.jpg @@ -268,6 +276,7 @@ rw_1_1_soldier.jpg https://downloads.cardforge.org/images/to u_0_1_homunculus.jpg https://downloads.cardforge.org/images/tokens/u_0_1_homunculus.jpg u_0_1_plant_wall.jpg https://downloads.cardforge.org/images/tokens/u_0_1_plant_wall.jpg u_0_1_starfish.jpg https://downloads.cardforge.org/images/tokens/u_0_1_starfish.jpg +u_0_2_illusion_mesmerize_rna.jpg https://downloads.cardforge.org/images/tokens/u_0_2_illusion_mesmerize_rna.jpg u_1_0_elemental.jpg https://downloads.cardforge.org/images/tokens/u_1_0_elemental.jpg u_1_1_bird.jpg https://downloads.cardforge.org/images/tokens/u_1_1_bird.jpg u_1_1_bird_eve.jpg https://downloads.cardforge.org/images/tokens/u_1_1_bird_eve.jpg @@ -309,6 +318,7 @@ w_1_1_citizen.jpg https://downloads.cardforge.org/images/to w_1_1_goldmeadow_harrier.jpg https://downloads.cardforge.org/images/tokens/w_1_1_goldmeadow_harrier.jpg w_1_1_human.jpg https://downloads.cardforge.org/images/tokens/w_1_1_human.jpg w_1_1_human_avr.jpg https://downloads.cardforge.org/images/tokens/w_1_1_human_avr.jpg +w_1_1_human_rna.jpg https://downloads.cardforge.org/images/tokens/w_1_1_human_rna.jpg w_1_1_kithkin_soldier.jpg https://downloads.cardforge.org/images/tokens/w_1_1_kithkin_soldier.jpg w_1_1_kithkin_soldier_shm.jpg https://downloads.cardforge.org/images/tokens/w_1_1_kithkin_soldier_shm.jpg w_1_1_knight.jpg https://downloads.cardforge.org/images/tokens/w_1_1_knight.jpg @@ -366,13 +376,15 @@ w_x_x_reflection.jpg https://downloads.cardforge.org/images/to wb_1_1_cleric.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_cleric.jpg wb_1_1_spirit.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit.jpg wb_1_1_spirit_gtc.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit_gtc.jpg +wb_1_1_spirit_rna.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit_rna.jpg wrg_8_8_beast.jpg https://downloads.cardforge.org/images/tokens/wrg_8_8_beast.jpg wu_1_1_bird.jpg https://downloads.cardforge.org/images/tokens/wu_1_1_bird.jpg - +wu_4_4_sphinx_flying_vigilance_rna.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_sphinx_flying_vigilance_rna.jpg # Emblems chandra_the_firebrand_effect.jpg https://downloads.cardforge.org/images/tokens/chandra_the_firebrand_effect.jpg +emblem_domri_chaos_bringer_rna.jpg https://downloads.cardforge.org/images/tokens/emblem_domri_chaos_bringer_rna.jpg emblem_domri_rade.jpg https://downloads.cardforge.org/images/tokens/emblem_domri_rade.jpg emblem_elspeth_knight_errant.jpg https://downloads.cardforge.org/images/tokens/emblem_elspeth_knight_errant.jpg emblem_elspeth_suns_champion.jpg https://downloads.cardforge.org/images/tokens/emblem_elspeth_suns_champion.jpg diff --git a/forge-gui/res/tokenscripts/c_a_treasure_sac.txt b/forge-gui/res/tokenscripts/c_a_treasure_sac.txt new file mode 100644 index 00000000000..6ba1beb174b --- /dev/null +++ b/forge-gui/res/tokenscripts/c_a_treasure_sac.txt @@ -0,0 +1,5 @@ +Name:Treasure +ManaCost:no cost +Types:Artifact Treasure +A:AB$ Mana | Cost$ T Sac<1/CARDNAME|this artifact> | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color. +Oracle:{T}, Sacrifice this artifact: Add one mana of any color. \ No newline at end of file diff --git a/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt b/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt new file mode 100644 index 00000000000..7a146c397df --- /dev/null +++ b/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt @@ -0,0 +1,9 @@ +Name:Illusion +Types:Creature Illusion +ManaCost:no cost +Colors:blue +PT:0/2 +T:Mode$ AttackerBlocked | ValidBlocker$ Card.Self | Execute$ TrigPump | TriggerDescription$ Whenever this creature blocks a creature, that creature doesn't untap during its controller's next untap step. +SVar:TrigPump:DB$ Pump | Defined$ TriggeredAttacker | KW$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True +SVar:HasBlockEffect:TRUE +Oracle:Whenever this creature blocks a creature, that creature doesn't untap during its controller's next untap step. \ No newline at end of file From 956ab8e96e7c8ea1f8f072568db2a0a6ebede4b0 Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 24 Jan 2019 08:08:52 +0300 Subject: [PATCH 02/54] - Added more AI SVars for RNA. - Added some comments for the needed script fixes. - Fixed Dross Scorpion trigger description. --- forge-gui/res/cardsfolder/d/dross_scorpion.txt | 4 ++-- forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt | 1 + forge-gui/res/cardsfolder/upcoming/captive_audience.txt | 2 ++ forge-gui/res/cardsfolder/upcoming/depose_deploy.txt | 1 + forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt | 1 + forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt | 2 +- forge-gui/res/cardsfolder/upcoming/kaya_orzhov_usurper.txt | 1 + forge-gui/res/cardsfolder/upcoming/kayas_wrath.txt | 1 + forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt | 2 ++ forge-gui/res/cardsfolder/upcoming/mirror_march.txt | 1 + forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt | 1 + forge-gui/res/cardsfolder/upcoming/repudiate_replicate.txt | 1 + forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt | 1 + forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt | 4 +++- forge-gui/res/cardsfolder/upcoming/thrash_threat.txt | 1 + forge-gui/res/cardsfolder/upcoming/warrant_warden.txt | 1 + 16 files changed, 21 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/d/dross_scorpion.txt b/forge-gui/res/cardsfolder/d/dross_scorpion.txt index eac2b6b704c..10f6ad724dd 100644 --- a/forge-gui/res/cardsfolder/d/dross_scorpion.txt +++ b/forge-gui/res/cardsfolder/d/dross_scorpion.txt @@ -2,8 +2,8 @@ Name:Dross Scorpion ManaCost:4 Types:Artifact Creature Scorpion PT:3/1 -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Artifact.Creature+Other | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigUntap | TriggerDescription$ Whenever CARDNAME or another artifact creature dies, -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigUntap | TriggerDescription$ you may untap target artifact. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Artifact.Creature+Other | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigUntap | TriggerDescription$ Whenever CARDNAME or another artifact creature dies, you may untap target artifact. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigUntap | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another artifact creature dies, you may untap target artifact. SVar:TrigUntap:DB$Untap | ValidTgts$ Artifact | TgtPrompt$ Choose target artifact. SVar:Picture:http://www.wizards.com/global/images/magic/general/dross_scorpion.jpg Oracle:Whenever Dross Scorpion or another artifact creature dies, you may untap target artifact. diff --git a/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt b/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt index 52018c5c221..b75eba83008 100644 --- a/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt +++ b/forge-gui/res/cardsfolder/upcoming/awaken_the_erstwhile.txt @@ -4,4 +4,5 @@ Types:Sorcery A:SP$ RepeatEach | Cost$ 3 B B | RepeatPlayers$ Player | RepeatSubAbility$ DBDiscard | SpellDescription$ Each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens. SVar:DBToken:DB$ Token | TokenAmount$ X | TokenName$ Zombie | TokenTypes$ Creature,Zombie | TokenOwner$ You | TokenColors$ Black | TokenPower$ 2 | TokenToughness$ 2 | References$ X SVar:X:Remembered$Amount +DeckHas:Ability$Token Oracle:Each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens. diff --git a/forge-gui/res/cardsfolder/upcoming/captive_audience.txt b/forge-gui/res/cardsfolder/upcoming/captive_audience.txt index 74b834089a1..1c69175352c 100644 --- a/forge-gui/res/cardsfolder/upcoming/captive_audience.txt +++ b/forge-gui/res/cardsfolder/upcoming/captive_audience.txt @@ -1,3 +1,4 @@ +# -- THIS SCRIPT NEEDS REWRITING (non-functional) -- Name:Captive Audience ManaCost:5 B R Types:Enchantment @@ -21,4 +22,5 @@ T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | E SVar:TrigChoose:DB$ ChooseCard | Defined$ You | Choices$ Player.Opponent | Mandatory$ True | SubAbility$ DBChangeZone SVar:DBChangeZone:DB$ ChangeZone | Defined$ Self | Origin$ All | Destination$ Battlefield | GainControl$ True SVar:RemRandomDeck:True +DeckHas:Ability$Token Oracle:Captive Audience enters the battlefield under the control of an opponent of your choice.\nAt the beginning of your upkeep, choose one that hasn't been chosen —\n• Your life total becomes 4.\n• Discard your hand.\n• Each opponent creates five 2/2 black Zombie creature tokens. diff --git a/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt b/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt index 7237e0cc680..9dca5b34c32 100644 --- a/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt +++ b/forge-gui/res/cardsfolder/upcoming/depose_deploy.txt @@ -14,4 +14,5 @@ Types:Instant A:SP$ Token | Cost$ 2 W U | TokenAmount$ 2 | TokenOwner$ You | TokenScript$ c_1_1_a_thopter_flying | SubAbility$ DBGainLife | SpellDescription$ Create two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control. SVar:DBGainLife:DB$ GainLife | LifeAmount$ X | References$ X SVar:X:Count$TypeYouCtrl.Creature +DeckHas:Ability$Token Oracle:Create two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control. diff --git a/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt b/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt index c0826ba22c4..72a7e9e4c1a 100644 --- a/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt +++ b/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt @@ -6,4 +6,5 @@ T:Mode$ SpellCast | ValidCard$ Instant | ValidActivatingPlayer$ You | TriggerZon SVar:TrigGainLife:DB$GainLife | Defined$ You | LifeAmount$ 2 | SubAbility$ DBDraw SVar:DBDraw:DB$Draw | Defined$ You | NumCards$ 1 SVar:X:Count$IfMainPhase +DeckHas:Ability$LifeGain Oracle:When Dovin's Acuity enters the battlefield, you gain 2 life and draw a card.\nWhenever you cast an instant spell during your main phase, you may return Dovin's Acuity to its owner's hand. diff --git a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt index ba8a5ce6505..a75291fad70 100644 --- a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt +++ b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt @@ -4,6 +4,6 @@ Types:Creature Human Shaman PT:2/2 K:Haste T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, you may sacrifice a creature. When you do, CARDNAME deals 2 damage to target opponent or planeswalker. -SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 | AILogic$ CARDNAME +SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 Oracle:Haste\nAt the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker. diff --git a/forge-gui/res/cardsfolder/upcoming/kaya_orzhov_usurper.txt b/forge-gui/res/cardsfolder/upcoming/kaya_orzhov_usurper.txt index a4ad4753f09..09ef6b8cd66 100644 --- a/forge-gui/res/cardsfolder/upcoming/kaya_orzhov_usurper.txt +++ b/forge-gui/res/cardsfolder/upcoming/kaya_orzhov_usurper.txt @@ -10,4 +10,5 @@ A:AB$ ChangeZone | Cost$ -1/-1/Card.nonLand/nonland permanent with converted man A:AB$ DealDamage | Cost$ PayLife<5/-5/Card> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Player | NumDmg$ X | References$ X | SubAbility$ DBYouGainLife | SpellDescription$ CARDNAME deals damage to target player equal to the number of cards that player owns in exile and you gain that much life. SVar:DBYouGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X SVar:X:TargetedPlayer$CardsInExile +DeckHas:Ability$LifeGain Oracle:[+1]: Exile up to two target cards from a single graveyard. You gain 2 life if at least one creature card was exiled this way.\n[-1]: Exile target nonland permanent with converted mana cost 1 or less.\n[-5]: Kaya, Orzhov Usurper deals damage to target player equal to the number of cards that player owns in exile and you gain that much life. diff --git a/forge-gui/res/cardsfolder/upcoming/kayas_wrath.txt b/forge-gui/res/cardsfolder/upcoming/kayas_wrath.txt index 2a411a0bf18..f843c6c1ac5 100644 --- a/forge-gui/res/cardsfolder/upcoming/kayas_wrath.txt +++ b/forge-gui/res/cardsfolder/upcoming/kayas_wrath.txt @@ -4,4 +4,5 @@ Types:Sorcery A:SP$ DestroyAll | Cost$ W W B B | ValidCards$ Creature | RememberDestroyed$ True | SubAbility$ DBGainLife | SpellDescription$ Destroy all creatures. You gain life equal to the number of creatures you controlled that were destroyed this way. SVar:DBGainLife:DB$ GainLife | LifeAmount$ X | References$ X SVar:X:RememberedLKI$FilterControlledByRemembered_Number$1 +DeckHas:Ability$LifeGain Oracle:Destroy all creatures. You gain life equal to the number of creatures you controlled that were destroyed this way. diff --git a/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt b/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt index 7187cc3021e..e893aa87cb5 100644 --- a/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt +++ b/forge-gui/res/cardsfolder/upcoming/mesmerizing_benthid.txt @@ -9,4 +9,6 @@ SVar:RemRandomDeck:True S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Hexproof | CheckSVar$ X | SVarCompare$ GE1 | Description$ CARDNAME has hexproof as long as you control an Illusion. SVar:X:Count$Valid Illusion.YouCtrl SVar:BuffedBy:Illusion +DeckHas:Ability$Token +DeckHints:Type$Illusion Oracle:When Mesmerizing Benthid enters the battlefield, create two 0/2 blue Illusion creature tokens with "Whenever this creature blocks a creature, that creature doesn't untap during its controller's next untap step."\nMesmerizing Benthid has hexproof as long as you control an Illusion. diff --git a/forge-gui/res/cardsfolder/upcoming/mirror_march.txt b/forge-gui/res/cardsfolder/upcoming/mirror_march.txt index 3c4ab33701a..2dec7304ab9 100644 --- a/forge-gui/res/cardsfolder/upcoming/mirror_march.txt +++ b/forge-gui/res/cardsfolder/upcoming/mirror_march.txt @@ -5,4 +5,5 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creatu SVar:TrigFlipACoin:DB$FlipACoin | FlipUntilYouLose$ True | SaveNumFlipsToSVar$ MirrorAmount | NoCall$ True | LoseSubAbility$ DBCopies SVar:DBCopies:DB$ CopyPermanent | PumpKeywords$ Haste | AtEOT$ Exile | Defined$ TriggeredCard | NumCopies$ MirrorAmount SVar:MirrorAmount:Number$0 +DeckHas:Ability$Token Oracle:Whenever a nontoken creature enters the battlefield under your control, flip a coin until you lose a flip. For each flip you won, create a token that's a copy of that creature. Those tokens gain haste. Exile them at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt b/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt index 9fa6b78a92b..5925680ff5d 100644 --- a/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt +++ b/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt @@ -7,5 +7,6 @@ K:Trample T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFlip | TriggerDescription$ When CARDNAME enters the battlefield, flip a coin for each creature that isn't a Demon, Dragons, or coins. Destroy each creature whose coin comes up tails. SVar:TrigFlip:DB$ FlipACoin | FlipUntilYouLose$ True | SaveNumFlipsToSVar$ X | LoseSubAbility$ DBDestroy SVar:DBDestroy:DB$ DestroyAll | ValidCards$ Creature.IsNotChosenType | References$ X +# -- THIS LINE NEEDS FIXING (doesn't reference the types correctly) -- SVar:X:Count$Valid Creature.isn Oracle:Flying, trample\nWhen Rakdos, the Showstopper enters the battlefield, flip a coin for each creature that isn't a Demon, Devil, or Imp. Destroy each creature whose coin comes up tails. diff --git a/forge-gui/res/cardsfolder/upcoming/repudiate_replicate.txt b/forge-gui/res/cardsfolder/upcoming/repudiate_replicate.txt index 7d8b9e7e81b..703e617ab39 100644 --- a/forge-gui/res/cardsfolder/upcoming/repudiate_replicate.txt +++ b/forge-gui/res/cardsfolder/upcoming/repudiate_replicate.txt @@ -12,4 +12,5 @@ Name:Replicate ManaCost:1 G U Types:Sorcery A:SP$ CopyPermanent | Cost$ 1 G U | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SpellDescription$ Create a token that's a copy of target creature you control. +DeckHas:Ability$Token Oracle:Create a token that’s a copy of target creature you control. diff --git a/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt b/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt index 1b5afe60ff8..b372bbcb6fa 100644 --- a/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt +++ b/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt @@ -5,4 +5,5 @@ PT:6/6 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME enters the battlefield, your number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. SVar:TrigEffect:DB$Effect | Name$ CARDNAME Effect | StaticAbilities$ KWPump SVar:KWPump:Mode$ Continuous | EffectZone$ Command | Affected$ Creature.YouCtrl+powerLTY | AddHiddenKeyword$ CARDNAME can't block. | Description$ Creatures your opponents control with power less than or equal to that number can't block this turn. +# -- THIS SCRIPT NEEDS FIXING (doesn't have the count var) -- Oracle:When Rumbling Ruin enters the battlefield, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt index 9f9e33bcdc1..fb1ecc53237 100644 --- a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt +++ b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt @@ -2,6 +2,8 @@ Name:Smothering Tithe ManaCost:3 W Types:Enchantment T:Mode$ Drawn | ValidCard$ Card.OppOwn | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with flying{T}, Sacrifice this artifact: Add one mana of any color. +# -- THIS SCRIPT NEEDS FIXING (the Unless cost part isn't defined, token definition is odd below) SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Treasure | TokenTypes$ Artifact,Treasure | TokenOwner$ TriggeredPlayer | TokenColors$ Colorless | TokenImage$ c treasure | TokenAbilities$ ABTreasureMana | TokenAltImages$ c_treasure2,c_treasure3,c_treasure4 -SVar:ABTreasureMana:DB$ Token | TokenAmount$ 1 | TokenName$ +SVar:ABTreasureMana:DB$ Token | TokenAmount$ 1 | TokenName$ +DeckHas:Ability$Token Oracle:Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color." diff --git a/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt b/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt index edebe152dde..0512ba7b66a 100644 --- a/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt +++ b/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt @@ -13,4 +13,5 @@ Name:Threat ManaCost:2 R G Types:Sorcery A:SP$ Token | Cost$ 2 R G | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ rg_4_4_beast_trample | SpellDescription$ Create a 4/4 red and green Beast creature token with trample. +DeckHas:Ability$Token Oracle:Create a 4/4 red and green Beast creature token with trample. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt b/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt index 614c5d7126b..a1d1b60c01a 100644 --- a/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt +++ b/forge-gui/res/cardsfolder/upcoming/warrant_warden.txt @@ -11,6 +11,7 @@ Name:Warden ManaCost:3 W U Types:Sorcery A:SP$ Token | Cost$ 3 W U | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ wu_4_4_sphinx_flying_vigilance | SpellDescription$ Create a 4/4 white and blue Sphinx creature token with flying and vigilance. +DeckHas:Ability$Token Oracle:Create a 4/4 white and blue Sphinx creature token with flying and vigilance. From 7ebe97f8023f8de5419ee48014536fc24a09b024 Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 24 Jan 2019 08:27:54 +0300 Subject: [PATCH 03/54] - Added TODO labels. --- forge-gui/res/cardsfolder/upcoming/captive_audience.txt | 2 +- forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt | 2 +- forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt | 2 +- forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/captive_audience.txt b/forge-gui/res/cardsfolder/upcoming/captive_audience.txt index 1c69175352c..d5eeb9922a9 100644 --- a/forge-gui/res/cardsfolder/upcoming/captive_audience.txt +++ b/forge-gui/res/cardsfolder/upcoming/captive_audience.txt @@ -1,4 +1,4 @@ -# -- THIS SCRIPT NEEDS REWRITING (non-functional) -- +# TODO: -- THIS SCRIPT NEEDS REWRITING (non-functional) -- Name:Captive Audience ManaCost:5 B R Types:Enchantment diff --git a/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt b/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt index 5925680ff5d..3fde626857d 100644 --- a/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt +++ b/forge-gui/res/cardsfolder/upcoming/rakdos_the_showstopper.txt @@ -7,6 +7,6 @@ K:Trample T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFlip | TriggerDescription$ When CARDNAME enters the battlefield, flip a coin for each creature that isn't a Demon, Dragons, or coins. Destroy each creature whose coin comes up tails. SVar:TrigFlip:DB$ FlipACoin | FlipUntilYouLose$ True | SaveNumFlipsToSVar$ X | LoseSubAbility$ DBDestroy SVar:DBDestroy:DB$ DestroyAll | ValidCards$ Creature.IsNotChosenType | References$ X -# -- THIS LINE NEEDS FIXING (doesn't reference the types correctly) -- +# TODO: -- THIS LINE NEEDS FIXING (doesn't reference the types correctly) -- SVar:X:Count$Valid Creature.isn Oracle:Flying, trample\nWhen Rakdos, the Showstopper enters the battlefield, flip a coin for each creature that isn't a Demon, Devil, or Imp. Destroy each creature whose coin comes up tails. diff --git a/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt b/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt index b372bbcb6fa..36747d0c27c 100644 --- a/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt +++ b/forge-gui/res/cardsfolder/upcoming/rumbling_ruin.txt @@ -5,5 +5,5 @@ PT:6/6 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME enters the battlefield, your number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. SVar:TrigEffect:DB$Effect | Name$ CARDNAME Effect | StaticAbilities$ KWPump SVar:KWPump:Mode$ Continuous | EffectZone$ Command | Affected$ Creature.YouCtrl+powerLTY | AddHiddenKeyword$ CARDNAME can't block. | Description$ Creatures your opponents control with power less than or equal to that number can't block this turn. -# -- THIS SCRIPT NEEDS FIXING (doesn't have the count var) -- +# TODO: -- THIS SCRIPT NEEDS FIXING (doesn't have the count var) -- Oracle:When Rumbling Ruin enters the battlefield, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt index fb1ecc53237..a171c4c0d33 100644 --- a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt +++ b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt @@ -2,7 +2,7 @@ Name:Smothering Tithe ManaCost:3 W Types:Enchantment T:Mode$ Drawn | ValidCard$ Card.OppOwn | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with flying{T}, Sacrifice this artifact: Add one mana of any color. -# -- THIS SCRIPT NEEDS FIXING (the Unless cost part isn't defined, token definition is odd below) +# TODO: -- THIS SCRIPT NEEDS FIXING (the Unless cost part isn't defined, token definition is odd below) SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenName$ Treasure | TokenTypes$ Artifact,Treasure | TokenOwner$ TriggeredPlayer | TokenColors$ Colorless | TokenImage$ c treasure | TokenAbilities$ ABTreasureMana | TokenAltImages$ c_treasure2,c_treasure3,c_treasure4 SVar:ABTreasureMana:DB$ Token | TokenAmount$ 1 | TokenName$ DeckHas:Ability$Token From 5901c6b66b4017e6a51f91be179e3fcf24a0131f Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 24 Jan 2019 08:38:11 +0300 Subject: [PATCH 04/54] - Restore AI SVars. --- forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt | 3 ++- forge-gui/res/cardsfolder/upcoming/thrash_threat.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt index fe24282b545..86a3ac8b876 100644 --- a/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt +++ b/forge-gui/res/cardsfolder/upcoming/smothering_tithe.txt @@ -2,5 +2,6 @@ Name:Smothering Tithe ManaCost:3 W Types:Enchantment T:Mode$ Drawn | ValidCard$ Card.OppOwn | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with flying{T}, Sacrifice this artifact: Add one mana of any color. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ TriggeredPlayer | LegacyImage$ c a treasure sac +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ TriggeredPlayer | LegacyImage$ c treasure +DeckHas:Ability$Token Oracle:Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color." diff --git a/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt b/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt index 14706116cf1..4f7b1c76af3 100644 --- a/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt +++ b/forge-gui/res/cardsfolder/upcoming/thrash_threat.txt @@ -13,4 +13,5 @@ Name:Threat ManaCost:2 R G Types:Sorcery A:SP$ Token | Cost$ 2 R G | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ rg_4_4_beast_trample | LegacyImage$ rg 4 4 beast trample rna | SpellDescription$ Create a 4/4 red and green Beast creature token with trample. +DeckHas:Ability$Token Oracle:Create a 4/4 red and green Beast creature token with trample. \ No newline at end of file From 96e61114000048bed3a9ac32fb07381b18a97729 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Wed, 23 Jan 2019 22:23:44 +0100 Subject: [PATCH 05/54] Riot: Make Riot Enchantment look into the future --- .../src/main/java/forge/game/GameAction.java | 28 ++++++++++ .../src/main/java/forge/game/card/Card.java | 11 +++- .../forge/game/keyword/KeywordCollection.java | 8 +++ .../forge/game/keyword/KeywordInstance.java | 26 ++++++++- .../forge/game/keyword/KeywordInterface.java | 1 + .../forge/game/keyword/KeywordsChange.java | 56 +++++++++++++++++-- .../forge/game/replacement/ReplaceMoved.java | 2 +- .../ai/simulation/GameSimulatorTest.java | 19 +++++++ .../match/input/InputSelectFromTwoLists.java | 2 +- 9 files changed, 142 insertions(+), 11 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 740f2d0c4af..1693ee24b07 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -29,6 +29,7 @@ import forge.game.ability.effects.AttachEffect; import forge.game.card.*; import forge.game.event.*; import forge.game.keyword.KeywordInterface; +import forge.game.keyword.KeywordsChange; import forge.game.player.GameLossReason; import forge.game.player.Player; import forge.game.replacement.ReplacementEffect; @@ -292,6 +293,33 @@ public class GameAction { copied.getOwner().addInboundToken(copied); } + if (toBattlefield) { + // HACK for making the RIOT enchantment look into the Future + // need to check the Keywords what it would have on the Battlefield + Card riotLKI = CardUtil.getLKICopy(copied); + riotLKI.setLastKnownZone(zoneTo); + CardCollection preList = new CardCollection(riotLKI); + checkStaticAbilities(false, Sets.newHashSet(riotLKI), preList); + + List changedTimeStamps = Lists.newArrayList(); + for(Map.Entry e : riotLKI.getChangedCardKeywords().entrySet()) { + if (!copied.hasChangedCardKeywords(e.getKey())) { + KeywordsChange o = e.getValue(); + o.setHostCard(copied); + for (KeywordInterface k : o.getKeywords()) { + for (ReplacementEffect re : k.getReplacements()) { + // this param need to be set, otherwise in ReplaceMoved it fails + re.getMapParams().put("BypassEtbCheck", "True"); + } + } + copied.addChangedCardKeywordsInternal(o, e.getKey()); + changedTimeStamps.add(e.getKey()); + } + } + + checkStaticAbilities(false); + } + Map repParams = Maps.newHashMap(); repParams.put("Event", "Moved"); repParams.put("Affected", copied); diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 8ded947cd48..43c55323e7d 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3404,6 +3404,15 @@ public class Card extends GameEntity implements Comparable { return change; } + public final boolean hasChangedCardKeywords(final long timestamp) { + return changedCardKeywords.containsKey(timestamp); + } + + public final void addChangedCardKeywordsInternal(final KeywordsChange change, final long timestamp) { + changedCardKeywords.put(timestamp, change); + updateKeywordsCache(currentState); + } + // Hidden keywords will be left out public final Collection getUnhiddenKeywords() { return getUnhiddenKeywords(currentState); @@ -5731,7 +5740,7 @@ public class Card extends GameEntity implements Comparable { public void setChangedCardKeywords(Map changedCardKeywords) { this.changedCardKeywords.clear(); for (Entry entry : changedCardKeywords.entrySet()) { - this.changedCardKeywords.put(entry.getKey(), entry.getValue()); + this.changedCardKeywords.put(entry.getKey(), entry.getValue().copy(this, true)); } } diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java b/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java index 98623cf6d72..e7c8f0ea745 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordCollection.java @@ -8,6 +8,8 @@ import java.util.Iterator; import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; +import forge.game.card.Card; + public class KeywordCollection implements Iterable, Serializable { private static final long serialVersionUID = -2882986558147844702L; @@ -151,6 +153,12 @@ public class KeywordCollection implements Iterable, Serializable { return map.get(keyword); } + public void setHostCard(final Card host) { + for (KeywordInterface k : map.values()) { + k.setHostCard(host); + } + } + @Override public Iterator iterator() { return new Iterator() { diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java index 6c0d1072085..33bfe77dd56 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java @@ -202,7 +202,7 @@ public abstract class KeywordInstance> implements K public Collection getStaticAbilities() { return staticAbilities; } - + /* * (non-Javadoc) * @see forge.game.keyword.KeywordInterface#copy() @@ -233,7 +233,7 @@ public abstract class KeywordInstance> implements K return result; } catch (final Exception ex) { - throw new RuntimeException("KeywordInstance : clone() error, " + ex); + throw new RuntimeException("KeywordInstance : clone() error", ex); } } @@ -252,4 +252,26 @@ public abstract class KeywordInstance> implements K public boolean redundant(Collection list) { return !list.isEmpty() && keyword.isMultipleRedundant; } + + /* (non-Javadoc) + * @see forge.game.keyword.KeywordInterface#setHostCard(forge.game.card.Card) + */ + @Override + public void setHostCard(Card host) { + for (SpellAbility sa : this.abilities) { + sa.setHostCard(host); + } + + for (Trigger tr : this.triggers) { + tr.setHostCard(host); + } + + for (ReplacementEffect re : this.replacements) { + re.setHostCard(host); + } + + for (StaticAbility sa : this.staticAbilities) { + sa.setHostCard(host); + } + } } diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java b/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java index 4830550f2b2..83ad9b87aa8 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInterface.java @@ -31,6 +31,7 @@ public interface KeywordInterface extends Cloneable { public void addSpellAbility(final SpellAbility s); public void addStaticAbility(final StaticAbility st); + public void setHostCard(final Card host); /** * @return the triggers diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java b/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java index 292741c323c..7b8453b05be 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java @@ -30,12 +30,11 @@ import forge.game.card.Card; *

* * @author Forge - * @version $Id: KeywordsChange.java 27095 2014-08-17 07:32:24Z elcnesh $ */ -public class KeywordsChange { - private final KeywordCollection keywords = new KeywordCollection(); - private final List removeKeywordInterfaces = Lists.newArrayList(); - private final List removeKeywords = Lists.newArrayList(); +public class KeywordsChange implements Cloneable { + private KeywordCollection keywords = new KeywordCollection(); + private List removeKeywordInterfaces = Lists.newArrayList(); + private List removeKeywords = Lists.newArrayList(); private boolean removeAllKeywords; private boolean removeIntrinsicKeywords; @@ -63,7 +62,7 @@ public class KeywordsChange { this.removeAllKeywords = removeAll; this.removeIntrinsicKeywords = removeIntrinsic; } - + public KeywordsChange( final Collection keywordList, final Collection removeKeywordInterfaces, @@ -172,4 +171,49 @@ public class KeywordsChange { removeIntrinsicKeywords = true; } } + + public void setHostCard(final Card host) { + keywords.setHostCard(host); + for (KeywordInterface k : removeKeywordInterfaces) { + k.setHostCard(host); + } + } + + public KeywordsChange copy(final Card host, final boolean lki) { + try { + KeywordsChange result = (KeywordsChange)super.clone(); + + result.keywords = new KeywordCollection(); + for (KeywordInterface ki : this.keywords.getValues()) { + result.keywords.insert(ki.copy(host, lki)); + } + + result.removeKeywords = Lists.newArrayList(removeKeywords); + + result.removeKeywordInterfaces = Lists.newArrayList(); + for (KeywordInterface ki : this.removeKeywordInterfaces) { + removeKeywordInterfaces.add(ki.copy(host, lki)); + } + + return result; + } catch (final Exception ex) { + throw new RuntimeException("KeywordsChange : clone() error", ex); + } + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("<+"); + sb.append(this.keywords); + sb.append("|-"); + sb.append(this.removeKeywordInterfaces); + sb.append("|-"); + sb.append(this.removeKeywords); + sb.append(">"); + return sb.toString(); + } } diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java b/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java index 963a7b0dd3e..d784653eee1 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java @@ -76,7 +76,7 @@ public class ReplaceMoved extends ReplacementEffect { return false; } - if (zt.equals(ZoneType.Battlefield) && getHostCard().equals(affected)) { + if (zt.equals(ZoneType.Battlefield) && getHostCard().equals(affected) && !hasParam("BypassEtbCheck")) { // would be an etb replacement effect that enters the battlefield Card lki = CardUtil.getLKICopy(affected); lki.setLastKnownZone(lki.getController().getZone(zt)); diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java index 01c455a35ea..2ec7fffc06a 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java @@ -1503,4 +1503,23 @@ public class GameSimulatorTest extends SimulationTestCase { } + public void testRiotEnchantment() { + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + + addCard("Rhythm of the Wild", p); + + Card goblin = addCardToZone("Zhur-Taa Goblin", p, ZoneType.Hand); + + addCard("Mountain", p); + addCard("Forest", p); + + SpellAbility goblinSA = goblin.getFirstSpellAbility(); + assertNotNull(goblinSA); + + GameSimulator sim = createSimulator(game, p); + int score = sim.simulateSpellAbility(goblinSA).value; + assertTrue(score > 0); + } } diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectFromTwoLists.java b/forge-gui/src/main/java/forge/match/input/InputSelectFromTwoLists.java index 5065b7ac111..90c6b717240 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectFromTwoLists.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectFromTwoLists.java @@ -69,7 +69,7 @@ public class InputSelectFromTwoLists extends InputSelectMa if ( valid1.contains(s) ) { selected1 = true; } if ( valid2.contains(s) ) { selected2 = true; } } - validChoices = selected1 ? ( selected2 ? FCollection.getEmpty() : valid2 ) : ( selected2 ? valid1 : validBoth ); + validChoices = selected1 ? ( selected2 ? FCollection.getEmpty() : valid2 ) : ( selected2 ? valid1 : validBoth ); setSelectables(); FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { From 1917871b98e0886e76c3d77d0147a5a96b93e067 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Thu, 24 Jan 2019 07:28:14 +0100 Subject: [PATCH 06/54] GameSimulatorTest: assert check for DoubleRiot --- .../java/forge/ai/simulation/GameSimulatorTest.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java index 2ec7fffc06a..fdd5c7f4d35 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java @@ -1508,9 +1508,11 @@ public class GameSimulatorTest extends SimulationTestCase { Player p = game.getPlayers().get(0); game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + final String goblinName = "Zhur-Taa Goblin"; + addCard("Rhythm of the Wild", p); - Card goblin = addCardToZone("Zhur-Taa Goblin", p, ZoneType.Hand); + Card goblin = addCardToZone(goblinName, p, ZoneType.Hand); addCard("Mountain", p); addCard("Forest", p); @@ -1521,5 +1523,13 @@ public class GameSimulatorTest extends SimulationTestCase { GameSimulator sim = createSimulator(game, p); int score = sim.simulateSpellAbility(goblinSA).value; assertTrue(score > 0); + + Game simGame = sim.getSimulatedGameState(); + + Card simGoblin = findCardWithName(simGame, goblinName); + + assertNotNull(simGoblin); + int effects = simGoblin.getCounters(CounterType.P1P1) + simGoblin.getKeywordMagnitude(Keyword.HASTE); + assertTrue(effects == 2); } } From 2eae26cefb08cbfbf82158838cabc0e27e4f8613 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Mon, 21 Jan 2019 16:40:55 +0000 Subject: [PATCH 07/54] TriggerHandler: Only real die can look back Rework Panharmonicon --- .../src/main/java/forge/game/card/Card.java | 3 +- .../forge/game/trigger/TriggerHandler.java | 70 +++++++++++-------- .../forge/game/trigger/TriggerWaiting.java | 5 +- .../cardsfolder/n/naban_dean_of_iteration.txt | 2 +- forge-gui/res/cardsfolder/p/panharmonicon.txt | 2 +- .../res/cardsfolder/upcoming/teysa_karlov.txt | 2 +- 6 files changed, 46 insertions(+), 38 deletions(-) diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 43c55323e7d..8f1343eeb31 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1465,7 +1465,8 @@ public class Card extends GameEntity implements Comparable { } } } - if (keyword.startsWith("CantBeCounteredBy")) { + if (keyword.startsWith("CantBeCounteredBy") || keyword.startsWith("Panharmonicon") + || keyword.startsWith("Dieharmonicon")) { final String[] p = keyword.split(":"); sbLong.append(p[2]).append("\r\n"); } else if (keyword.startsWith("etbCounter")) { diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index e08015d31df..31cfb4a1612 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -25,7 +25,9 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.effects.CharmEffect; import forge.game.card.Card; +import forge.game.card.CardLists; import forge.game.card.CardUtil; +import forge.game.keyword.KeywordInterface; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.Ability; @@ -376,11 +378,7 @@ public class TriggerHandler { // Static triggers for (final Trigger t : Lists.newArrayList(activeTriggers)) { if (t.isStatic() && canRunTrigger(t, mode, runParams)) { - int x = 1 + handlePanharmonicon(t, runParams); - - for (int i = 0; i < x; ++i) { - runSingleTrigger(t, runParams); - } + runSingleTrigger(t, runParams); checkStatics = true; } @@ -448,7 +446,7 @@ public class TriggerHandler { } } - int x = 1 + handlePanharmonicon(t, runParams);; + int x = 1 + handlePanharmonicon(t, runParams, player); for (int i = 0; i < x; ++i) { runSingleTrigger(t, runParams); @@ -692,45 +690,55 @@ public class TriggerHandler { } } - private int handlePanharmonicon(final Trigger t, final Map runParams) { - // Need to get the last info from the trigger host - final Card host = game.getChangeZoneLKIInfo(t.getHostCard()); - final Player p = host.getController(); + private int handlePanharmonicon(final Trigger t, final Map runParams, final Player p) { + Card host = t.getHostCard(); // not a changesZone trigger if (t.getMode() != TriggerType.ChangesZone) { return 0; } + // leave battlefield trigger, might be dying + if ("Battlefield".equals(t.getParam("Origin"))) { + // Need to get the last info from the trigger host + host = game.getChangeZoneLKIInfo(host); + } + // not a Permanent you control if (!host.isPermanent() || !host.isInZone(ZoneType.Battlefield)) { return 0; } int n = 0; - for (final String kw : p.getKeywords()) { - if (kw.startsWith("Panharmonicon")) { - // Enter the Battlefield Trigger - if (runParams.get("Destination") instanceof String) { - final String dest = (String) runParams.get("Destination"); - if ("Battlefield".equals(dest) && runParams.get("Card") instanceof Card) { - final Card card = (Card) runParams.get("Card"); - final String valid = kw.split(":")[1]; - if (card.isValid(valid.split(","), p, host, null)) { - n++; + // iterate over all cards + final List lastCards = CardLists.filterControlledBy(p.getGame().getLastStateBattlefield(), p); + for (final Card ck : lastCards) { + for (final KeywordInterface ki : ck.getKeywords()) { + final String kw = ki.getOriginal(); + if (kw.startsWith("Panharmonicon")) { + // Enter the Battlefield Trigger + if (runParams.get("Destination") instanceof String) { + final String dest = (String) runParams.get("Destination"); + if ("Battlefield".equals(dest) && runParams.get("Card") instanceof Card) { + final Card card = (Card) runParams.get("Card"); + final String valid = kw.split(":")[1]; + if (card.isValid(valid.split(","), p, ck, null)) { + n++; + } } } - } - } else if (kw.startsWith("Dieharmonicon")) { - // 700.4. The term dies means “is put into a graveyard from the battlefield.” - if (runParams.get("Origin") instanceof String) { - final String origin = (String) runParams.get("Origin"); - if ("Battlefield".equals(origin) && runParams.get("Destination") instanceof String) { - final String dest = (String) runParams.get("Destination"); - if ("Graveyard".equals(dest) && runParams.get("Card") instanceof Card) { - final Card card = (Card) runParams.get("Card"); - if (card.isCreature()) { - n++; + } else if (kw.startsWith("Dieharmonicon")) { + // 700.4. The term dies means “is put into a graveyard from the battlefield.” + if (runParams.get("Origin") instanceof String) { + final String origin = (String) runParams.get("Origin"); + if ("Battlefield".equals(origin) && runParams.get("Destination") instanceof String) { + final String dest = (String) runParams.get("Destination"); + if ("Graveyard".equals(dest) && runParams.get("Card") instanceof Card) { + final Card card = (Card) runParams.get("Card"); + final String valid = kw.split(":")[1]; + if (card.isValid(valid.split(","), p, ck, null)) { + n++; + } } } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerWaiting.java b/forge-game/src/main/java/forge/game/trigger/TriggerWaiting.java index 565ab2f0b57..0bf489d05fd 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerWaiting.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerWaiting.java @@ -13,7 +13,7 @@ public class TriggerWaiting { private Map params; private List triggers = null; - public TriggerWaiting(TriggerType m, Map p) { + public TriggerWaiting(TriggerType m, Map p) { mode = m; params = p; } @@ -25,7 +25,6 @@ public class TriggerWaiting { public Map getParams() { return params; } - public List getTriggers() { return triggers; @@ -35,7 +34,7 @@ public class TriggerWaiting { this.triggers = triggers; } - @Override + @Override public String toString() { return TextUtil.concatWithSpace("Waiting trigger:", mode.toString(),"with", params.toString()); } diff --git a/forge-gui/res/cardsfolder/n/naban_dean_of_iteration.txt b/forge-gui/res/cardsfolder/n/naban_dean_of_iteration.txt index 1b169abc441..e1606a06d8f 100644 --- a/forge-gui/res/cardsfolder/n/naban_dean_of_iteration.txt +++ b/forge-gui/res/cardsfolder/n/naban_dean_of_iteration.txt @@ -2,7 +2,7 @@ Name:Naban, Dean of Iteration ManaCost:1 U Types:Legendary Creature Human Wizard PT:2/1 -S:Mode$ Continuous | Affected$ You | AddKeyword$ Panharmonicon:Wizard.YouCtrl | Description$ If a Wizard entering the battlefield under your control causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. +K:Panharmonicon:Wizard.YouCtrl:If a Wizard entering the battlefield under your control causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. DeckHints:Type$Wizard SVar:Picture:http://www.wizards.com/global/images/magic/general/naban_dean_of_iteration.jpg Oracle:If a Wizard entering the battlefield under your control causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. diff --git a/forge-gui/res/cardsfolder/p/panharmonicon.txt b/forge-gui/res/cardsfolder/p/panharmonicon.txt index ebe29c22590..5cde6b7f7cb 100644 --- a/forge-gui/res/cardsfolder/p/panharmonicon.txt +++ b/forge-gui/res/cardsfolder/p/panharmonicon.txt @@ -1,6 +1,6 @@ Name:Panharmonicon ManaCost:4 Types:Artifact -S:Mode$ Continuous | Affected$ You | AddKeyword$ Panharmonicon:Creature,Artifact | Description$ If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. +K:Panharmonicon:Creature,Artifact:If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. SVar:Picture:http://www.wizards.com/global/images/magic/general/panharmonicon.jpg Oracle:If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. diff --git a/forge-gui/res/cardsfolder/upcoming/teysa_karlov.txt b/forge-gui/res/cardsfolder/upcoming/teysa_karlov.txt index cc63eea3839..bc52f882a8f 100644 --- a/forge-gui/res/cardsfolder/upcoming/teysa_karlov.txt +++ b/forge-gui/res/cardsfolder/upcoming/teysa_karlov.txt @@ -2,7 +2,7 @@ Name:Teysa Karlov ManaCost:2 W B Types:Legendary Creature Human Advisor PT:2/4 -S:Mode$ Continuous | Affected$ You | AddKeyword$ Dieharmonicon | Description$ If a creature dying causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. +K:Dieharmonicon:Creature:If a creature dying causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. S:Mode$ Continuous | Affected$ Creature.token+YouCtrl | AddKeyword$ Vigilance & Lifelink | Description$ Creature tokens you control have vigilance and lifelink. DeckHints:Ability$Token Oracle:If a creature dying causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.\nCreature tokens you control have vigilance and lifelink. From 7006c548a55e14058e2410d198a9cb091780dae9 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Tue, 22 Jan 2019 13:09:00 +0000 Subject: [PATCH 08/54] GameSimulatorTest: Teysa Karlov and Xathrid Necromancer --- .../ai/simulation/GameSimulatorTest.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java index fdd5c7f4d35..290f03a457c 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java @@ -1532,4 +1532,33 @@ public class GameSimulatorTest extends SimulationTestCase { int effects = simGoblin.getCounters(CounterType.P1P1) + simGoblin.getKeywordMagnitude(Keyword.HASTE); assertTrue(effects == 2); } + + public void testTeysaKarlovXathridNecromancer() { + // Teysa Karlov and Xathrid Necromancer dying at the same time makes 4 token + + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + + addCard("Teysa Karlov", p); + addCard("Xathrid Necromancer", p); + + for (int i = 0; i < 4; i++) { + addCardToZone("Plains", p, ZoneType.Battlefield); + } + + Card wrathOfGod = addCardToZone("Wrath of God", p, ZoneType.Hand); + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + + SpellAbility wrathSA = wrathOfGod.getFirstSpellAbility(); + assertNotNull(wrathSA); + + GameSimulator sim = createSimulator(game, p); + int score = sim.simulateSpellAbility(wrathSA).value; + assertTrue(score > 0); + Game simGame = sim.getSimulatedGameState(); + + int numZombies = countCardsWithName(simGame, "Zombie"); + assertTrue(numZombies == 4); + } } From b6019c630850e3c98011e686dcb8a3af821f2448 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Wed, 23 Jan 2019 08:08:56 +0100 Subject: [PATCH 09/54] GameSimulatorTest: second test for Teysa --- .../ai/simulation/GameSimulatorTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java index 290f03a457c..5493b7da670 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java @@ -1561,4 +1561,32 @@ public class GameSimulatorTest extends SimulationTestCase { int numZombies = countCardsWithName(simGame, "Zombie"); assertTrue(numZombies == 4); } + + public void testDoubleTeysaKarlovXathridNecromancer() { + // Teysa Karlov dieing because of Legendary rule will make Xathrid Necromancer trigger 3 times + + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + + addCard("Teysa Karlov", p); + addCard("Xathrid Necromancer", p); + + for (int i = 0; i < 3; i++) { + addCard("Plains", p); + } + addCard("Swamp", p); + + Card second = addCardToZone("Teysa Karlov", p, ZoneType.Hand); + + SpellAbility secondSA = second.getFirstSpellAbility(); + + GameSimulator sim = createSimulator(game, p); + int score = sim.simulateSpellAbility(secondSA).value; + assertTrue(score > 0); + Game simGame = sim.getSimulatedGameState(); + + int numZombies = countCardsWithName(simGame, "Zombie"); + assertTrue(numZombies == 3); + } } From 9778f9e3a014cbefdff0aeca1000bdb56e3a0ce8 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Thu, 24 Jan 2019 16:12:33 +0000 Subject: [PATCH 10/54] Teysa and Gitrog fixes --- .../java/forge/game/card/CardZoneTable.java | 36 ++++++ .../game/trigger/TriggerChangesZoneAll.java | 43 ++----- .../forge/game/trigger/TriggerHandler.java | 79 ++++++++----- .../ai/simulation/GameSimulatorTest.java | 107 ++++++++++++++++++ 4 files changed, 203 insertions(+), 62 deletions(-) diff --git a/forge-game/src/main/java/forge/game/card/CardZoneTable.java b/forge-game/src/main/java/forge/game/card/CardZoneTable.java index fbec5fa601e..720d5d5737b 100644 --- a/forge-game/src/main/java/forge/game/card/CardZoneTable.java +++ b/forge-game/src/main/java/forge/game/card/CardZoneTable.java @@ -11,6 +11,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Table; import forge.game.Game; +import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; @@ -45,4 +46,39 @@ public class CardZoneTable extends ForwardingTable origin, ZoneType destination, String valid, Card host, SpellAbility sa) { + CardCollection allCards = new CardCollection(); + if (destination != null) { + if (!containsColumn(destination)) { + return allCards; + } + } + if (origin != null) { + for (ZoneType z : origin) { + if (containsRow(z)) { + if (destination != null) { + allCards.addAll(row(z).get(destination)); + } else { + for (CardCollection c : row(z).values()) { + allCards.addAll(c); + } + } + } + } + } else if (destination != null) { + for (CardCollection c : column(destination).values()) { + allCards.addAll(c); + } + } else { + for (CardCollection c : values()) { + allCards.addAll(c); + } + } + + if (valid != null) { + allCards = CardLists.getValidCards(allCards, valid.split(","), host.getController(), host, sa); + } + return allCards; + } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerChangesZoneAll.java b/forge-game/src/main/java/forge/game/trigger/TriggerChangesZoneAll.java index 3651c3d9ae7..0993e8dae29 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerChangesZoneAll.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerChangesZoneAll.java @@ -42,48 +42,19 @@ public class TriggerChangesZoneAll extends Trigger { } private CardCollection filterCards(CardZoneTable table) { - CardCollection allCards = new CardCollection(); ZoneType destination = null; + List origin = null; - if (hasParam("Destination")) { - if (!getParam("Destination").equals("Any")) { - destination = ZoneType.valueOf(getParam("Destination")); - if (!table.containsColumn(destination)) { - return allCards; - } - } + if (hasParam("Destination") && !getParam("Destination").equals("Any")) { + destination = ZoneType.valueOf(getParam("Destination")); } if (hasParam("Origin") && !getParam("Origin").equals("Any")) { - if (getParam("Origin") == null) { - return allCards; - } - final List origin = ZoneType.listValueOf(getParam("Origin")); - for (ZoneType z : origin) { - if (table.containsRow(z)) { - if (destination != null) { - allCards.addAll(table.row(z).get(destination)); - } else { - for (CardCollection c : table.row(z).values()) { - allCards.addAll(c); - } - } - } - } - } else if (destination != null) { - for (CardCollection c : table.column(destination).values()) { - allCards.addAll(c); - } - } else { - for (CardCollection c : table.values()) { - allCards.addAll(c); - } + origin = ZoneType.listValueOf(getParam("Origin")); } - if (hasParam("ValidCards")) { - allCards = CardLists.getValidCards(allCards, getParam("ValidCards").split(","), - getHostCard().getController(), getHostCard(), null); - } - return allCards; + final String valid = this.getParamOrDefault("ValidCards", null); + + return table.filterCards(origin, destination, valid, getHostCard(), null); } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 31cfb4a1612..308b373411d 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -27,6 +27,7 @@ import forge.game.ability.effects.CharmEffect; import forge.game.card.Card; import forge.game.card.CardLists; import forge.game.card.CardUtil; +import forge.game.card.CardZoneTable; import forge.game.keyword.KeywordInterface; import forge.game.phase.PhaseType; import forge.game.player.Player; @@ -44,6 +45,7 @@ import io.sentry.event.BreadcrumbBuilder; import java.util.*; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -693,13 +695,14 @@ public class TriggerHandler { private int handlePanharmonicon(final Trigger t, final Map runParams, final Player p) { Card host = t.getHostCard(); - // not a changesZone trigger - if (t.getMode() != TriggerType.ChangesZone) { + // not a changesZone trigger or changesZoneAll + if (t.getMode() != TriggerType.ChangesZone && t.getMode() != TriggerType.ChangesZoneAll) { return 0; } // leave battlefield trigger, might be dying - if ("Battlefield".equals(t.getParam("Origin"))) { + // only real changeszone look back for this + if (t.getMode() == TriggerType.ChangesZone && "Battlefield".equals(t.getParam("Origin"))) { // Need to get the last info from the trigger host host = game.getChangeZoneLKIInfo(host); } @@ -710,30 +713,17 @@ public class TriggerHandler { } int n = 0; - // iterate over all cards - final List lastCards = CardLists.filterControlledBy(p.getGame().getLastStateBattlefield(), p); - for (final Card ck : lastCards) { - for (final KeywordInterface ki : ck.getKeywords()) { - final String kw = ki.getOriginal(); - if (kw.startsWith("Panharmonicon")) { - // Enter the Battlefield Trigger - if (runParams.get("Destination") instanceof String) { - final String dest = (String) runParams.get("Destination"); - if ("Battlefield".equals(dest) && runParams.get("Card") instanceof Card) { - final Card card = (Card) runParams.get("Card"); - final String valid = kw.split(":")[1]; - if (card.isValid(valid.split(","), p, ck, null)) { - n++; - } - } - } - } else if (kw.startsWith("Dieharmonicon")) { - // 700.4. The term dies means “is put into a graveyard from the battlefield.” - if (runParams.get("Origin") instanceof String) { - final String origin = (String) runParams.get("Origin"); - if ("Battlefield".equals(origin) && runParams.get("Destination") instanceof String) { + if (t.getMode() == TriggerType.ChangesZone) { + // iterate over all cards + final List lastCards = CardLists.filterControlledBy(p.getGame().getLastStateBattlefield(), p); + for (final Card ck : lastCards) { + for (final KeywordInterface ki : ck.getKeywords()) { + final String kw = ki.getOriginal(); + if (kw.startsWith("Panharmonicon")) { + // Enter the Battlefield Trigger + if (runParams.get("Destination") instanceof String) { final String dest = (String) runParams.get("Destination"); - if ("Graveyard".equals(dest) && runParams.get("Card") instanceof Card) { + if ("Battlefield".equals(dest) && runParams.get("Card") instanceof Card) { final Card card = (Card) runParams.get("Card"); final String valid = kw.split(":")[1]; if (card.isValid(valid.split(","), p, ck, null)) { @@ -741,6 +731,43 @@ public class TriggerHandler { } } } + } else if (kw.startsWith("Dieharmonicon")) { + // 700.4. The term dies means “is put into a graveyard from the battlefield.” + if (runParams.get("Origin") instanceof String) { + final String origin = (String) runParams.get("Origin"); + if ("Battlefield".equals(origin) && runParams.get("Destination") instanceof String) { + final String dest = (String) runParams.get("Destination"); + if ("Graveyard".equals(dest) && runParams.get("Card") instanceof Card) { + final Card card = (Card) runParams.get("Card"); + final String valid = kw.split(":")[1]; + if (card.isValid(valid.split(","), p, ck, null)) { + n++; + } + } + } + } + } + } + } + } else if (t.getMode() == TriggerType.ChangesZoneAll) { + final CardZoneTable table = (CardZoneTable) runParams.get("Cards"); + // iterate over all cards + for (final Card ck : p.getCardsIn(ZoneType.Battlefield)) { + for (final KeywordInterface ki : ck.getKeywords()) { + final String kw = ki.getOriginal(); + if (kw.startsWith("Panharmonicon")) { + // currently there is no ChangesZoneAll that would trigger on etb + final String valid = kw.split(":")[1]; + if (!table.filterCards(null, ZoneType.Battlefield, valid, ck, null).isEmpty()) { + n++; + } + } else if (kw.startsWith("Dieharmonicon")) { + // 700.4. The term dies means “is put into a graveyard from the battlefield.” + final String valid = kw.split(":")[1]; + if (!table.filterCards(ImmutableList.of(ZoneType.Battlefield), ZoneType.Graveyard, + valid, ck, null).isEmpty()) { + n++; + } } } } diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java index 5493b7da670..0d15d62f5f4 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java @@ -1589,4 +1589,111 @@ public class GameSimulatorTest extends SimulationTestCase { int numZombies = countCardsWithName(simGame, "Zombie"); assertTrue(numZombies == 3); } + + + public void testTeysaKarlovGitrogMonster() { + + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + + addCard("Teysa Karlov", p); + addCard("The Gitrog Monster", p); + addCard("Dryad Arbor", p); + + for (int i = 0; i < 4; i++) { + addCard("Plains", p); + addCardToZone("Plains", p, ZoneType.Library); + } + + Card armageddon = addCardToZone("Armageddon", p, ZoneType.Hand); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + + SpellAbility armageddonSA = armageddon.getFirstSpellAbility(); + + GameSimulator sim = createSimulator(game, p); + int score = sim.simulateSpellAbility(armageddonSA).value; + assertTrue(score > 0); + Game simGame = sim.getSimulatedGameState(); + + // Two cards drawn + assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 2); + } + + public void testTeysaKarlovGitrogMonsterGitrogDies() { + + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + + Card teysa = addCard("Teysa Karlov", p); + addCard("The Gitrog Monster", p); + addCard("Dryad Arbor", p); + + String indestructibilityName = "Indestructibility"; + Card indestructibility = addCard(indestructibilityName, p); + + indestructibility.attachToEntity(teysa); + + // update Indestructible state + game.getAction().checkStateEffects(true); + + for (int i = 0; i < 4; i++) { + addCard("Plains", p); + addCardToZone("Plains", p, ZoneType.Library); + } + + Card armageddon = addCardToZone("Wrath of God", p, ZoneType.Hand); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + + SpellAbility armageddonSA = armageddon.getFirstSpellAbility(); + + GameSimulator sim = createSimulator(game, p); + int score = sim.simulateSpellAbility(armageddonSA).value; + assertTrue(score > 0); + Game simGame = sim.getSimulatedGameState(); + + // One cards drawn + assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 1); + } + + public void testTeysaKarlovGitrogMonsterTeysaDies() { + + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p); + + addCard("Teysa Karlov", p); + Card gitrog = addCard("The Gitrog Monster", p); + addCard("Dryad Arbor", p); + + String indestructibilityName = "Indestructibility"; + Card indestructibility = addCard(indestructibilityName, p); + + indestructibility.attachToEntity(gitrog); + + // update Indestructible state + game.getAction().checkStateEffects(true); + + for (int i = 0; i < 4; i++) { + addCard("Plains", p); + addCardToZone("Plains", p, ZoneType.Library); + } + + Card armageddon = addCardToZone("Wrath of God", p, ZoneType.Hand); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + + SpellAbility armageddonSA = armageddon.getFirstSpellAbility(); + + GameSimulator sim = createSimulator(game, p); + int score = sim.simulateSpellAbility(armageddonSA).value; + assertTrue(score > 0); + Game simGame = sim.getSimulatedGameState(); + + // One cards drawn + assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 1); + } } From 4661a199829ff1633966f7db7cabf4b9e71eef41 Mon Sep 17 00:00:00 2001 From: Evan Murawski Date: Fri, 25 Jan 2019 04:53:36 +0000 Subject: [PATCH 11/54] DeckRecognizer: Recognize split card names with single slash --- forge-core/src/main/java/forge/deck/DeckRecognizer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/forge-core/src/main/java/forge/deck/DeckRecognizer.java b/forge-core/src/main/java/forge/deck/DeckRecognizer.java index a844ed270bb..0cae2a03261 100644 --- a/forge-core/src/main/java/forge/deck/DeckRecognizer.java +++ b/forge-core/src/main/java/forge/deck/DeckRecognizer.java @@ -102,6 +102,7 @@ public class DeckRecognizer { // Pattern.compile("(.*)[^A-Za-wyz]*\\s+([\\d]{1,2})"); private static final Pattern SEARCH_NUMBERS_IN_FRONT = Pattern.compile("([\\d]{1,2})[^A-Za-wyz]*\\s+(.*)"); //private static final Pattern READ_SEPARATED_EDITION = Pattern.compile("[[\\(\\{]([a-zA-Z0-9]){1,3})[]*\\s+(.*)"); + private static final Pattern SEARCH_SINGLE_SLASH = Pattern.compile("(?<=[^/])\\s*/\\s*(?=[^/])"); private final SetPreference useLastSet; private final ICardDatabase db; @@ -125,7 +126,10 @@ public class DeckRecognizer { return new Token(TokenType.Comment, 0, rawLine); } final char smartQuote = (char) 8217; - final String line = rawLine.trim().replace(smartQuote, '\''); + String line = rawLine.trim().replace(smartQuote, '\''); + + // Some websites export split card names with a single slash. Replace with double slash. + line = SEARCH_SINGLE_SLASH.matcher(line).replaceFirst(" // "); Token result = null; final Matcher foundNumbersInFront = DeckRecognizer.SEARCH_NUMBERS_IN_FRONT.matcher(line); From 76ebfa94605fee90d63bf28540f9b4992733837c Mon Sep 17 00:00:00 2001 From: Agetian Date: Fri, 25 Jan 2019 17:04:09 +0300 Subject: [PATCH 12/54] - Fix AI sealed booster generation for Ravnica Allegiance (use GRN basic lands). --- forge-gui/res/blockdata/blocks.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/blockdata/blocks.txt b/forge-gui/res/blockdata/blocks.txt index de26a42b8c2..bf2901ed696 100644 --- a/forge-gui/res/blockdata/blocks.txt +++ b/forge-gui/res/blockdata/blocks.txt @@ -78,4 +78,4 @@ Dominaria, 3/6/DOM, DOM Core Set 2019, 3/6/M19, M19 Guilds of Ravnica, 3/6/GRN, GRN Ultimate Masters, 3/6/M19, UMA -Ravnica Allegiance, 3/6/RNA, RNA \ No newline at end of file +Ravnica Allegiance, 3/6/GRN, RNA \ No newline at end of file From e3c9a40a17c2e64296a270dd75b6eb87492480db Mon Sep 17 00:00:00 2001 From: Agetian Date: Fri, 25 Jan 2019 17:17:40 +0300 Subject: [PATCH 13/54] - Use M19 lands as the default basic lands for GRN and RNA sealed/draft, since neither set has basic lands of its own in actual booster packs. --- forge-gui/res/blockdata/blocks.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/blockdata/blocks.txt b/forge-gui/res/blockdata/blocks.txt index bf2901ed696..c7822dda5ab 100644 --- a/forge-gui/res/blockdata/blocks.txt +++ b/forge-gui/res/blockdata/blocks.txt @@ -76,6 +76,6 @@ Iconic Masters, 3/6/XLN, IMA Masters 25, 3/6/XLN, A25 Dominaria, 3/6/DOM, DOM Core Set 2019, 3/6/M19, M19 -Guilds of Ravnica, 3/6/GRN, GRN +Guilds of Ravnica, 3/6/M19, GRN Ultimate Masters, 3/6/M19, UMA -Ravnica Allegiance, 3/6/GRN, RNA \ No newline at end of file +Ravnica Allegiance, 3/6/M19, RNA \ No newline at end of file From 7eedd04aa101921673cfafdedee066ea297a8824 Mon Sep 17 00:00:00 2001 From: Agetian Date: Fri, 25 Jan 2019 17:21:21 +0300 Subject: [PATCH 14/54] - Add basic lands definitions to Ravnica Allegiance. - Revert blocks.txt to use RNA for the land set. --- forge-gui/res/blockdata/blocks.txt | 4 ++-- forge-gui/res/editions/Ravnica Allegiance.txt | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/blockdata/blocks.txt b/forge-gui/res/blockdata/blocks.txt index c7822dda5ab..de26a42b8c2 100644 --- a/forge-gui/res/blockdata/blocks.txt +++ b/forge-gui/res/blockdata/blocks.txt @@ -76,6 +76,6 @@ Iconic Masters, 3/6/XLN, IMA Masters 25, 3/6/XLN, A25 Dominaria, 3/6/DOM, DOM Core Set 2019, 3/6/M19, M19 -Guilds of Ravnica, 3/6/M19, GRN +Guilds of Ravnica, 3/6/GRN, GRN Ultimate Masters, 3/6/M19, UMA -Ravnica Allegiance, 3/6/M19, RNA \ No newline at end of file +Ravnica Allegiance, 3/6/RNA, RNA \ No newline at end of file diff --git a/forge-gui/res/editions/Ravnica Allegiance.txt b/forge-gui/res/editions/Ravnica Allegiance.txt index bb56814ece6..7851c5f3446 100644 --- a/forge-gui/res/editions/Ravnica Allegiance.txt +++ b/forge-gui/res/editions/Ravnica Allegiance.txt @@ -268,6 +268,11 @@ Booster=10 Common:!fromSheet("RNA Secret Cards"), 3 Uncommon:!fromSheet("RNA Sec 257 C Simic Guildgate 258 C Simic Guildgate 259 R Stomping Ground +260 L Plains +261 L Island +262 L Swamp +263 L Mountain +264 L Forest 265 M Dovin, Architect of Law 266 C Elite Arrester 267 R Dovin's Dismissal From 66869377422d188e5ca704aaf0bd2ec5b5de732c Mon Sep 17 00:00:00 2001 From: Agetian Date: Fri, 25 Jan 2019 18:01:24 +0300 Subject: [PATCH 15/54] - Fix up the RNA printsheets a little bit (wrong card names, wrong set IDs) --- forge-gui/res/blockdata/printsheets.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/forge-gui/res/blockdata/printsheets.txt b/forge-gui/res/blockdata/printsheets.txt index aefbba16529..20e4ec7834f 100644 --- a/forge-gui/res/blockdata/printsheets.txt +++ b/forge-gui/res/blockdata/printsheets.txt @@ -1409,24 +1409,24 @@ Dimir Guildgate|GRN Boros Guildgate|GRN [RNA Lands] -10 Azorious Guildgate|GRN -10 Gruul Guildgate|GRN -10 Orzhov Guildgate|GRN -10 Rakdos Guildgate|GRN -10 Simic Guildgate|GRN +10 Azorius Guildgate|RNA +10 Gruul Guildgate|RNA +10 Orzhov Guildgate|RNA +10 Rakdos Guildgate|RNA +10 Simic Guildgate|RNA [RNA Secret Cards] -Dovin, Architecht of Law +Dovin, Architect of Law Elite Arrester Dovin's Dismissal Dovin's Automaton -Domri City Smasher +Domri, City Smasher Ragefire Charging War Boar Domri's Nodorog The Haunt of Hightower -Azorious Guildgate|GRN -Gruul Guildgate|GRN -Orzhov Guildgate|GRN -Rakdos Guildgate|GRN -Simic Guildgate|GRN \ No newline at end of file +Azorius Guildgate|RNA +Gruul Guildgate|RNA +Orzhov Guildgate|RNA +Rakdos Guildgate|RNA +Simic Guildgate|RNA \ No newline at end of file From 560dc572c299b35ac3ede92fa170d22ad5aae16c Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 26 Jan 2019 09:24:25 +0000 Subject: [PATCH 16/54] Charm rework --- .../main/java/forge/game/ability/effects/CharmEffect.java | 5 +++-- forge-game/src/main/java/forge/game/card/CardFactory.java | 5 ----- .../src/main/java/forge/game/trigger/TriggerHandler.java | 5 ++++- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index 88098689550..ef8dfcba924 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -150,14 +150,14 @@ public class CharmEffect extends SpellAbilityEffect { return ""; } - public static void makeChoices(SpellAbility sa) { + public static boolean makeChoices(SpellAbility sa) { //this resets all previous choices sa.setSubAbility(null); // Entwine does use all Choices if (sa.isEntwine()) { chainAbilities(sa, makePossibleOptions(sa)); - return; + return true; } final int num = sa.hasParam("CharmNumOnResolve") ? @@ -181,6 +181,7 @@ public class CharmEffect extends SpellAbilityEffect { List chosen = chooser.getController().chooseModeForAbility(sa, min, num, sa.hasParam("CanRepeatModes")); chainAbilities(sa, chosen); + return chosen != null && !chosen.isEmpty(); } private static void chainAbilities(SpellAbility sa, List chosen) { diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 9a9f08e1551..82db7497427 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -25,8 +25,6 @@ import forge.card.mana.ManaCost; import forge.game.Game; import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; -import forge.game.ability.ApiType; -import forge.game.ability.effects.CharmEffect; import forge.game.cost.Cost; import forge.game.player.Player; import forge.game.replacement.ReplacementHandler; @@ -680,9 +678,6 @@ public class CardFactory { } trig.setStackDescription(trig.toString()); - if (trig.getApi() == ApiType.Charm && !trig.isWrapper()) { - CharmEffect.makeChoices(trig); - } WrappedAbility wrapperAbility = new WrappedAbility(t, trig, ((WrappedAbility) sa).getDecider()); wrapperAbility.setTrigger(true); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 308b373411d..6d10443816a 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -636,7 +636,10 @@ public class TriggerHandler { sa.setStackDescription(sa.toString()); if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { - CharmEffect.makeChoices(sa); + if (!CharmEffect.makeChoices(sa)) { + // 603.3c If no mode is chosen, the ability is removed from the stack. + return; + } } Player decider = null; From b2616860c0776c328cf7fb247c46f54749f700f4 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Sat, 26 Jan 2019 13:28:55 +0100 Subject: [PATCH 17/54] Spell: fix casting opponent spells --- forge-game/src/main/java/forge/game/spellability/Spell.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/forge-game/src/main/java/forge/game/spellability/Spell.java b/forge-game/src/main/java/forge/game/spellability/Spell.java index 92879d67545..267a61fea8e 100644 --- a/forge-game/src/main/java/forge/game/spellability/Spell.java +++ b/forge-game/src/main/java/forge/game/spellability/Spell.java @@ -144,6 +144,8 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable if (lkicheck) { game.getAction().checkStaticAbilities(false); game.getTracker().unfreeze(); + // reset owner for lki + card.setController(null, 0); } if (!(isInstant || activator.canCastSorcery() || flash || getRestrictions().isInstantSpeed() From ed218b6e4c41479d901f44850ce3b8d3f0747ca6 Mon Sep 17 00:00:00 2001 From: tjtillmancoag Date: Sat, 26 Jan 2019 19:39:04 -0800 Subject: [PATCH 18/54] Fixed Amplifire (properly changes Power & Toughness), Consume (of Consecrate // Consume, works now), Final Payment (allows sacrifice of enchantment/creature as payment), Incongruity (fixed A:AB$ to A:SP$), Sentinel's Mark (gives Lifelink on Main phase trigger) Silhana Wayfinder (triggers on ETB) Smelt Ward Ignus (loses control of creature at EoT) Undercity's Embrace (no life amount in gainlife ability was causing crash on cast) --- forge-gui/res/cardsfolder/upcoming/amplifire.txt | 8 ++++++-- forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt | 5 ++--- forge-gui/res/cardsfolder/upcoming/final_payment.txt | 2 +- .../res/cardsfolder/upcoming/incubation_incongruity.txt | 2 +- forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt | 2 +- forge-gui/res/cardsfolder/upcoming/silhana_wayfinder.txt | 3 ++- forge-gui/res/cardsfolder/upcoming/smelt_ward_ignus.txt | 2 +- forge-gui/res/cardsfolder/upcoming/undercitys_embrace.txt | 2 +- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/amplifire.txt b/forge-gui/res/cardsfolder/upcoming/amplifire.txt index ce695f0c794..ec7e20c367f 100644 --- a/forge-gui/res/cardsfolder/upcoming/amplifire.txt +++ b/forge-gui/res/cardsfolder/upcoming/amplifire.txt @@ -3,6 +3,10 @@ ManaCost:2 R R Types:Creature Elemental PT:1/1 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDig | TriggerDescription$ At the beginning of your upkeep, reveal cards from the top of your library until you reveal a creature card. Until your next turn, CARDNAME's base power becomes twice that card's power and its toughness. Put the revealed cards on the bottom of your library in a random order. -SVar:TrigDig:DB$ DigUntil | Valid$ Creature | ValidDescription$ creature card | FoundDestination$ Library | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RememberFound$ True | SubAbility$ DBAnimate -SVar:DBAnimate:DB$ Animate | Power$ X | Toughness$ Y +SVar:TrigDig:DB$ DigUntil | Reveal$ True | Valid$ Creature | ValidDescription$ creature card | FoundDestination$ Exile | RevealedDestination$ Exile | RememberFound$ True | ImprintRevealed$ True | SubAbility$ DBAnimate +SVar:DBAnimate:DB$ Animate | Power$ X | Toughness$ Y | SubAbility$ DBMovetoLib +SVar:DBMovetoLib:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered,Card.IsImprinted | Origin$ Exile | Destination$ Library | RandomOrder$ True | LibraryPosition$ -1 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True +SVar:X:Remembered$CardPower/Times.2 +SVar:Y:Remembered$CardToughness/Times.2 Oracle:At the beginning of your upkeep, reveal cards from the top of your library until you reveal a creature card. Until your next turn, Amplifire's base power becomes twice that card's power and its base toughness becomes twice that card's toughness. Put the revealed cards on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt b/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt index 6f0ce2e9cdb..a995c978923 100644 --- a/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt +++ b/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt @@ -11,8 +11,7 @@ ALTERNATE Name:Consume ManaCost:2 W B Types:Sorcery -A:SP$ ChooseCard | Cost$ 2 W B | ValidTgts$ Player | Choices$ Creature.greatestPowerControlledByRemembered | Mandatory$ True | SubAbility$ DBSac -SVar:DBSac:DB$ Sacrifice | Defined$ Targeted | SacValid$ Card.ChosenCard | RememberSacrificed$ True | SacMessage$ the creature with the highest power | SubAbility$ DBGainLife +A:SP$ Sacrifice | Cost$ 2 W B | ValidTgts$ Player | SacValid$ Creature.greatestPower+TargetedPlayerCtrl | RememberSacrificed$ True | SacMessage$ Creature with greatest power among creatures you control | SubAbility$ DBGainLife | SpellDescription$ Target player sacrifices a creature with the greatest power among creatures they control. You gain life equal to its power. SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X -SVar:X:TargetedLKI$CardPower +SVar:X:RememberedLKI$CardPower Oracle:Target player sacrifices a creature with the greatest power among creatures they control. You gain life equal to its power. diff --git a/forge-gui/res/cardsfolder/upcoming/final_payment.txt b/forge-gui/res/cardsfolder/upcoming/final_payment.txt index b99e79bf6ff..bc63d05d707 100644 --- a/forge-gui/res/cardsfolder/upcoming/final_payment.txt +++ b/forge-gui/res/cardsfolder/upcoming/final_payment.txt @@ -1,6 +1,6 @@ Name:Final Payment ManaCost:W B Types:Instant -K:AlternateAdditionalCost:PayLife<5>:Sac<1/Creature,Enchantment> +K:AlternateAdditionalCost:PayLife<5>:Sac<1/Creature;Enchantment/creature or enchantment> A:SP$ Destroy | Cost$ W B | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Destroy target creature. Oracle:As an additional cost to cast this spell, pay 5 life or sacrifice a creature or enchantment.\nDestroy target creature. diff --git a/forge-gui/res/cardsfolder/upcoming/incubation_incongruity.txt b/forge-gui/res/cardsfolder/upcoming/incubation_incongruity.txt index 3814a3dbfcc..d6c71908766 100644 --- a/forge-gui/res/cardsfolder/upcoming/incubation_incongruity.txt +++ b/forge-gui/res/cardsfolder/upcoming/incubation_incongruity.txt @@ -11,6 +11,6 @@ ALTERNATE Name:Incongruity ManaCost:1 G U Types:Instant -A:AB$ ChangeZone | Cost$ 1 G U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken | SpellDescription$ Exile target creature. That creature’s controller creates a 3/3 green Frog Lizard creature token. +A:SP$ ChangeZone | Cost$ 1 G U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken | SpellDescription$ Exile target creature. That creature’s controller creates a 3/3 green Frog Lizard creature token. SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ TargetedController | TokenScript$ g_3_3_frog_lizard Oracle:Exile target creature. That creature’s controller creates a 3/3 green Frog Lizard creature token. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt b/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt index 0ab076fe3b1..5d6b7ac507e 100644 --- a/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt +++ b/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt @@ -6,5 +6,5 @@ K:Enchant creature A:SP$ Attach | Cost$ 1 W | ValidTgts$ Creature | AILogic$ Pump S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 1 | AddToughness$ 2 | AddKeyword$ Vigilance | Description$ Enchanted creature gets +1/+2 and has vigilance. T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | Condition$ Main1 | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. -SVar:TrigPump:DB$ Pump | Defined$ Enchanted | KW$ +SVar:TrigPump:DB$ Pump | Defined$ Enchanted | KW$ Lifelink Oracle:Flash\nEnchant creature\nEnchanted creature gets +1/+2 and has vigilance.\nAddendum — When Sentinel's Mark enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/silhana_wayfinder.txt b/forge-gui/res/cardsfolder/upcoming/silhana_wayfinder.txt index 8f001dc79ee..331db43d9ef 100644 --- a/forge-gui/res/cardsfolder/upcoming/silhana_wayfinder.txt +++ b/forge-gui/res/cardsfolder/upcoming/silhana_wayfinder.txt @@ -2,5 +2,6 @@ Name:Silhana Wayfinder ManaCost:1 G Types:Creature Elf Scout PT:2/1 -SVar:DBDig:DB$ Dig | DigNum$ 4 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Creature,Land | ForceRevealToController$ True | DestinationZone$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | ForceRevealToController$ True +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, look at the top four cards of your library. You may reveal a creature or land card from among them and put it on top of your library. Put the rest on the bottom of your library in a random order. +SVar:TrigDig:DB$ Dig | DigNum$ 4 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Creature,Land | ForceRevealToController$ True | DestinationZone$ Library | LibraryPosition$ 0 | RestRandomOrder$ True | ForceRevealToController$ True Oracle:When Silhana Wayfinder enters the battlefield, look at the top four cards of your library. You may reveal a creature or land card from among them and put it on top of your library. Put the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/upcoming/smelt_ward_ignus.txt b/forge-gui/res/cardsfolder/upcoming/smelt_ward_ignus.txt index b54b1e12310..6581226efc0 100644 --- a/forge-gui/res/cardsfolder/upcoming/smelt_ward_ignus.txt +++ b/forge-gui/res/cardsfolder/upcoming/smelt_ward_ignus.txt @@ -2,5 +2,5 @@ Name:Smelt-Ward Ignus ManaCost:1 R Types:Creature Elemental PT:2/1 -A:AB$ GainControl | Cost$ 2 R Sac<1/CARDNAME> | ValidTgts$ Creature.powerLE3 | TgtPrompt$ Select target creature with power 3 or less | Untap$ True | AddKWs$ Haste | SorcerySpeed$ True | SpellDescription$ Gain control of target creature with power 3 or less until end of turn. Untap that creature. It gains haste until end of turn. Activate this ability only any time you could cast a sorcery. +A:AB$ GainControl | Cost$ 2 R Sac<1/CARDNAME> | ValidTgts$ Creature.powerLE3 | LoseControl$ EOT | TgtPrompt$ Select target creature with power 3 or less | Untap$ True | AddKWs$ Haste | SorcerySpeed$ True | SpellDescription$ Gain control of target creature with power 3 or less until end of turn. Untap that creature. It gains haste until end of turn. Activate this ability only any time you could cast a sorcery. Oracle:{2}{R}, Sacrifice Smelt-Ward Ignus: Gain control of target creature with power 3 or less until end of turn. Untap that creature. It gains haste until end of turn. Activate this ability only any time you could cast a sorcery. diff --git a/forge-gui/res/cardsfolder/upcoming/undercitys_embrace.txt b/forge-gui/res/cardsfolder/upcoming/undercitys_embrace.txt index 528da6b040d..fd3a43144c6 100644 --- a/forge-gui/res/cardsfolder/upcoming/undercitys_embrace.txt +++ b/forge-gui/res/cardsfolder/upcoming/undercitys_embrace.txt @@ -2,6 +2,6 @@ Name:Undercity's Embrace ManaCost:2 B Types:Instant A:SP$ Sacrifice | Cost$ 2 B | ValidTgts$ Opponent | SacValid$ Creature | SacMessage$ Creature | SubAbility$ DBGainLife | SpellDescription$ Target opponent sacrifices a creature. If you control a creature with power 4 or greater, you gain 4 life. | StackDescription$ SpellDescription -SVar:DBGainLife:DB$ GainLife | Defined$ You | ConditionPresent$ Creature.YouCtrl+powerGE4 | ConditionCompare$ GE1 | StackDescription$ If you control a creature with power 4 or greater, you gain 4 life. +SVar:DBGainLife:DB$ GainLife | LifeAmount$ 4 | Defined$ You | ConditionPresent$ Creature.YouCtrl+powerGE4 | ConditionCompare$ GE1 | StackDescription$ If you control a creature with power 4 or greater, you gain 4 life. DeckHas:Ability$LifeGain Oracle:Target opponent sacrifices a creature. If you control a creature with power 4 or greater, you gain 4 life. From e604d9d0cbce2adabd38fbf180164905599fd10a Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 05:18:49 +0000 Subject: [PATCH 19/54] Update consecrate_consume.txt to add Cleanup Remembered --- forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt b/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt index a995c978923..66d5cf8dd0b 100644 --- a/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt +++ b/forge-gui/res/cardsfolder/upcoming/consecrate_consume.txt @@ -12,6 +12,7 @@ Name:Consume ManaCost:2 W B Types:Sorcery A:SP$ Sacrifice | Cost$ 2 W B | ValidTgts$ Player | SacValid$ Creature.greatestPower+TargetedPlayerCtrl | RememberSacrificed$ True | SacMessage$ Creature with greatest power among creatures you control | SubAbility$ DBGainLife | SpellDescription$ Target player sacrifices a creature with the greatest power among creatures they control. You gain life equal to its power. -SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X +SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X | References$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:RememberedLKI$CardPower Oracle:Target player sacrifices a creature with the greatest power among creatures they control. You gain life equal to its power. From e2ddcdda4d7de536ec56a3394f71670caefd73b1 Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Mon, 21 Jan 2019 11:40:36 -0500 Subject: [PATCH 20/54] stronger highlighting for selectable cards --- .../java/forge/view/arcane/CardPanel.java | 28 +++++++++++++------ .../forge/view/arcane/ScaledImagePanel.java | 9 +++++- .../main/java/forge/interfaces/IGuiGame.java | 1 + .../java/forge/match/AbstractGuiGame.java | 3 ++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java index 16339ea1602..d1e1e6f1953 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java @@ -253,6 +253,13 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl g2d.rotate(getTappedAngle(), cardXOffset + edgeOffset, (cardYOffset + cardHeight) - edgeOffset); } + boolean selectable = matchUI.isSelectable(getCard()); + if ( titleText!=null ) { // selectable cards have colored names + titleText.setForeground(selectable?Color.cyan:Color.white); + } + // if ( imagePanel != null ) { // if selecting, darken non-selectable cards - needs more refreshing to do right + // imagePanel.setBrightness(selectable?1.0f:(matchUI.isSelecting()?0.5f:1.0f)); + //} super.paint(g2d); } @@ -268,25 +275,21 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl final int cornerSize = noBorderPref && !cardImgHasAlpha ? 0 : Math.max(4, Math.round(cardWidth * CardPanel.ROUNDED_CORNER_SIZE)); final int offset = isTapped() && (!noBorderPref || cardImgHasAlpha) ? 1 : 0; - // Magenta outline for when card was chosen to pay + // Magenta outline for when card is chosen if (matchUI.isUsedToPay(getCard())) { g2d.setColor(Color.magenta); - final int n2 = Math.max(4, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); - g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); - } else if (matchUI.isSelectable(getCard())) { // Cyan outline for selectable cards - g2d.setColor(Color.cyan); - final int n2 = Math.max(4, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); + final int n2 = Math.max(1, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); } // Green outline for hover if (isSelected) { g2d.setColor(Color.green); - final int n = Math.max(4, Math.round(cardWidth * CardPanel.SELECTED_BORDER_SIZE)); - g2d.fillRoundRect(cardXOffset - n, (cardYOffset - n) + offset, cardWidth + (n * 2), cardHeight + (n * 2), cornerSize + n , cornerSize + n); + final int n = Math.max(1, Math.round(cardWidth * CardPanel.SELECTED_BORDER_SIZE)); + g2d.fillRoundRect(cardXOffset - n, (cardYOffset - n) + offset, cardWidth + (n * 2), cardHeight + (n * 2), cornerSize + n , cornerSize + n); } - // Black fill - (will become outline for white bordered cards) + // Black fill - (will become an outline for white bordered cards) g2d.setColor(Color.black); g2d.fillRoundRect(cardXOffset, cardYOffset + offset, cardWidth, cardHeight, cornerSize, cornerSize); @@ -309,6 +312,13 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl g2d.fillRoundRect(cardXOffset + ins, cardYOffset + ins, cardWidth - ins*2, cardHeight - ins*2, cornerSize-ins, cornerSize-ins); } } + + if (matchUI.isSelectable(getCard())) { // Replace border for selectable cards + g2d.setColor(Color.cyan); + // final int n2 = Math.max(2, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); + g2d.fillRoundRect(cardXOffset, (cardYOffset) + offset, cardWidth, cardHeight, cornerSize, cornerSize); + // g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); + } } private void drawManaCost(final Graphics g, final ManaCost cost, final int deltaY) { diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java index 26021b0f670..a9867f6db6c 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java @@ -20,6 +20,7 @@ package forge.view.arcane; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; +import java.awt.image.RescaleOp; /** *

@@ -37,6 +38,10 @@ public class ScaledImagePanel extends JPanel { * */ private volatile BufferedImage srcImage; + private float brightness = 1.0f; + public void setBrightness(final float bright) { + brightness = bright; + } /** *

@@ -127,7 +132,9 @@ public class ScaledImagePanel extends JPanel { } else { int x = (sz.width / 2) - (img.getWidth() / 2); int y = (sz.height / 2) - (img.getHeight() / 2); - g.drawImage(img, x, y, null); + Graphics2D g2d = (Graphics2D) g; + RescaleOp brighten = new RescaleOp(brightness,0,null); + g2d.drawImage(img, brighten, x, y); } } diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java index ec2c6994a0f..3c9b08f4679 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java @@ -159,6 +159,7 @@ public interface IGuiGame { void setUsedToPay(CardView card, boolean value); void setSelectables(final Iterable cards); void clearSelectables(); + boolean isSelecting(); void awaitNextInput(); void cancelAwaitNextInput(); diff --git a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java index e71e4ff0293..ed4a467e112 100644 --- a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java +++ b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java @@ -230,6 +230,9 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { public boolean isSelectable(final CardView card) { return selectableCards.contains(card); } + public boolean isSelecting() { + return !selectableCards.isEmpty(); + } /** Concede game, bring up WinLose UI. */ public boolean concede() { From 62316abf383f2c513b2b40cca230a615b58c60e8 Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Wed, 23 Jan 2019 02:35:58 -0500 Subject: [PATCH 21/54] darken non-selectable cards when selecting (needs work) --- .../java/forge/view/arcane/CardPanel.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java index d1e1e6f1953..280fb8c3905 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java @@ -253,14 +253,14 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl g2d.rotate(getTappedAngle(), cardXOffset + edgeOffset, (cardYOffset + cardHeight) - edgeOffset); } - boolean selectable = matchUI.isSelectable(getCard()); - if ( titleText!=null ) { // selectable cards have colored names - titleText.setForeground(selectable?Color.cyan:Color.white); + // System.out.println("Paint " + getCard() + " selecting " + matchUI.isSelecting()); + boolean nonselectable = matchUI.isSelecting() && !matchUI.isSelectable(getCard()); + if ( titleText!=null ) { // non-selectable cards have gray names + titleText.setForeground(nonselectable?Color.DARK_GRAY:Color.WHITE); } - // if ( imagePanel != null ) { // if selecting, darken non-selectable cards - needs more refreshing to do right - // imagePanel.setBrightness(selectable?1.0f:(matchUI.isSelecting()?0.5f:1.0f)); - //} - super.paint(g2d); + if ( imagePanel != null ) { // if selecting, darken non-selectable cards - needs more refreshing to do right + imagePanel.setBrightness(nonselectable?0.4f:1.0f); + } super.paint(g2d); } @Override @@ -304,7 +304,8 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl colorIsSet = true; } else if (ed != null && ed.isWhiteBorder() && state.getFoilIndex() == 0) { // Non-foil cards from white-bordered sets are drawn with white border - g2d.setColor(Color.WHITE); + // unless selecting and card is not selectable + g2d.setColor(matchUI.isSelecting()&&!matchUI.isSelectable(getCard())?Color.DARK_GRAY:Color.WHITE); colorIsSet = true; } if (colorIsSet) { @@ -313,11 +314,12 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl } } - if (matchUI.isSelectable(getCard())) { // Replace border for selectable cards - g2d.setColor(Color.cyan); - // final int n2 = Math.max(2, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); - g2d.fillRoundRect(cardXOffset, (cardYOffset) + offset, cardWidth, cardHeight, cornerSize, cornerSize); - // g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); + if (matchUI.isSelectable(getCard())) { // Replace border for selectable cards + g2d.setColor(Color.WHITE); + final int ins = 1; + g2d.fillRoundRect(cardXOffset+ins, cardYOffset+ins, cardWidth-ins*2, cardHeight-ins*2, cornerSize-ins, cornerSize-ins); + // final int n2 = Math.max(2, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); + // g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); } } @@ -368,6 +370,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl final boolean canShow = matchUI.mayView(card); final boolean showText = !imagePanel.hasImage() || !isAnimationPanel; + System.out.println("doLayout " + card); displayCardNameOverlay(showText && canShow && showCardNameOverlay(), imgSize, imgPos); displayPTOverlay(showText && (canShow || card.isFaceDown()) && showCardPowerOverlay(), imgSize, imgPos); displayCardIdOverlay(showText && canShow && showCardIdOverlay(), imgSize, imgPos); @@ -793,6 +796,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl return FModel.getPreferences().getPrefBoolean(preferenceName); } + // don't show overlays on non-selectable cards when selecting private boolean isShowingOverlays() { return isPreferenceEnabled(FPref.UI_SHOW_CARD_OVERLAYS) && card != null; } From 70f0f1108b14bd7ff5c465ec5b140bb9b2342c71 Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Sun, 27 Jan 2019 08:22:50 -0500 Subject: [PATCH 22/54] darken non-selectable cards during paintChildren --- .../java/forge/view/arcane/CardPanel.java | 31 ++++++++++--------- .../forge/view/arcane/ScaledImagePanel.java | 9 +----- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java index 280fb8c3905..7d0cbb2ce89 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java @@ -253,14 +253,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl g2d.rotate(getTappedAngle(), cardXOffset + edgeOffset, (cardYOffset + cardHeight) - edgeOffset); } - // System.out.println("Paint " + getCard() + " selecting " + matchUI.isSelecting()); - boolean nonselectable = matchUI.isSelecting() && !matchUI.isSelectable(getCard()); - if ( titleText!=null ) { // non-selectable cards have gray names - titleText.setForeground(nonselectable?Color.DARK_GRAY:Color.WHITE); - } - if ( imagePanel != null ) { // if selecting, darken non-selectable cards - needs more refreshing to do right - imagePanel.setBrightness(nonselectable?0.4f:1.0f); - } super.paint(g2d); + super.paint(g2d); } @Override @@ -304,8 +297,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl colorIsSet = true; } else if (ed != null && ed.isWhiteBorder() && state.getFoilIndex() == 0) { // Non-foil cards from white-bordered sets are drawn with white border - // unless selecting and card is not selectable - g2d.setColor(matchUI.isSelecting()&&!matchUI.isSelectable(getCard())?Color.DARK_GRAY:Color.WHITE); + g2d.setColor(Color.WHITE); colorIsSet = true; } if (colorIsSet) { @@ -314,12 +306,10 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl } } - if (matchUI.isSelectable(getCard())) { // Replace border for selectable cards + if (matchUI.isSelectable(getCard())) { // White border for selectable cards to further highlight them g2d.setColor(Color.WHITE); final int ins = 1; - g2d.fillRoundRect(cardXOffset+ins, cardYOffset+ins, cardWidth-ins*2, cardHeight-ins*2, cornerSize-ins, cornerSize-ins); - // final int n2 = Math.max(2, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE)); - // g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); + g2d.fillRoundRect(cardXOffset+ins, cardYOffset+ins, cardWidth-ins*2, cardHeight-ins*2, cornerSize-ins, cornerSize-ins); } } @@ -344,6 +334,19 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl drawFoilEffect(g, card, cardXOffset, cardYOffset, cardWidth, cardHeight, Math.round(cardWidth * BLACK_BORDER_SIZE)); } + + System.out.println("Painting " + getCard() + " selecting " + matchUI.isSelecting()); + boolean nonselectable = matchUI.isSelecting() && !matchUI.isSelectable(getCard()); + // if selecting, darken non-selectable cards - pfps - needs fixes to refreshing to do right + if ( nonselectable ) { + System.out.println("Paint nonselectable " + card); + boolean noBorderPref = !isPreferenceEnabled(FPref.UI_RENDER_BLACK_BORDERS); + boolean cardImgHasAlpha = imagePanel != null && imagePanel.getSrcImage() != null && imagePanel.getSrcImage().getColorModel().hasAlpha(); + final int cornerSize = noBorderPref && !cardImgHasAlpha ? 0 : Math.max(4, Math.round(cardWidth * CardPanel.ROUNDED_CORNER_SIZE)); + final int offset = isTapped() && (!noBorderPref || cardImgHasAlpha) ? 1 : 0; + g.setColor(new Color(0.0f,0.0f,0.0f,0.6f)); + g.fillRoundRect(cardXOffset, cardYOffset + offset, cardWidth, cardHeight, cornerSize, cornerSize); + } } public static void drawFoilEffect(final Graphics g, final CardView card2, final int x, final int y, final int width, final int height, final int borderSize) { diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java index a9867f6db6c..26021b0f670 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/ScaledImagePanel.java @@ -20,7 +20,6 @@ package forge.view.arcane; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; -import java.awt.image.RescaleOp; /** *

@@ -38,10 +37,6 @@ public class ScaledImagePanel extends JPanel { * */ private volatile BufferedImage srcImage; - private float brightness = 1.0f; - public void setBrightness(final float bright) { - brightness = bright; - } /** *

@@ -132,9 +127,7 @@ public class ScaledImagePanel extends JPanel { } else { int x = (sz.width / 2) - (img.getWidth() / 2); int y = (sz.height / 2) - (img.getHeight() / 2); - Graphics2D g2d = (Graphics2D) g; - RescaleOp brighten = new RescaleOp(brightness,0,null); - g2d.drawImage(img, brighten, x, y); + g.drawImage(img, x, y, null); } } From d9400fe0694ba6b58b0d18defbd5235dfbd7180a Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 17:55:04 +0000 Subject: [PATCH 23/54] Update rix_maadi_reveler.txt --- .../res/cardsfolder/upcoming/rix_maadi_reveler.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt b/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt index 7af42a6556d..cfd4bd2db5d 100644 --- a/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt +++ b/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt @@ -3,10 +3,10 @@ ManaCost:1 R Types:Creature Human Shaman PT:2/2 K:Flying -K:Morph:2 B R -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield, discard a card, then draw a card. If CARDNAME's Goblin cost was paid, instead discard your hand, then draw three cards. -SVar:TrigDiscard:DB$ Discard | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBDraw -SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 3 | SubAbility$ DBDiscard -SVar:DBDiscard:DB$ Discard | Mode$ Hand | Defined$ You | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | References$ X | SubAbility$ DBDraw -SVar:DBDraw +K:Spectacle:2 B R +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield, discard a card, then draw a card. If CARDNAME's spectacle cost was paid, instead discard your hand, then draw three cards. +SVar:TrigDiscard:DB$ Discard | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBDrawOne | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.spectacle | ConditionCompare$ EQ0 +SVar:DBDrawOne:DB$ Draw | Defined$ You | NumCards$ 1 | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.spectacle | ConditionCompare$ EQ0 | SubAbility$ DBDiscard +SVar:DBDiscard:DB$ Discard | Mode$ Hand | Defined$ You | SubAbility$ DBDrawThree | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.spectacle +SVar:DBDrawThree:DB$ Draw | Defined$ You | NumCards$ 3 | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.spectacle Oracle:Spectacle {2}{B}{R} (You may cast this spell for its spectacle cost rather than its mana cost if an opponent lost life this turn.)\nWhen Rix Maadi Reveler enters the battlefield, discard a card, then draw a card. If Rix Maadi Reveler's spectacle cost was paid, instead discard your hand, then draw three cards. From 79c3570bcc61dce96ac2643cfdaf198049f85da8 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 17:55:48 +0000 Subject: [PATCH 24/54] Update gutterbones.txt --- forge-gui/res/cardsfolder/upcoming/gutterbones.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/gutterbones.txt b/forge-gui/res/cardsfolder/upcoming/gutterbones.txt index 89207d77bf6..25cbbb43111 100644 --- a/forge-gui/res/cardsfolder/upcoming/gutterbones.txt +++ b/forge-gui/res/cardsfolder/upcoming/gutterbones.txt @@ -3,7 +3,6 @@ ManaCost:B Types:Creature Skeleton Warrior PT:2/1 K:CARDNAME enters the battlefield tapped. -A:AB$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Hand | ActivationZone$ Graveyard | OpponentTurn$ True | SubAbility$ DBEffect | SpellDescription$ Return CARDNAME from your graveyard to your hand. Activate this ability only during your turn and only if an opponent lost life this turn. -SVar:DBEffect:DB$ Effect | CheckSVar$ X | SVarCompare$ GE1 | References$ X | StaticAbilities$ MustAttack | SubAbility$ DBCleanup -SVar:RPrevent:Mode$ Continuous | EffectZone$ Command | Affected$ You | AddKeyword$ You only during your turn and only if an opponent lost life this turn. | Description$ Activate this ability only during your turn and only if an opponent +A:AB$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Hand | ActivationZone$ Graveyard | PlayerTurn$ True | CheckSVar$ X | References$ X | SpellDescription$ Return CARDNAME from your graveyard to your hand. Activate this ability only during your turn and only if an opponent lost life this turn. +SVar:X:Count$LifeOppsLostThisTurn Oracle:Gutterbones enters the battlefield tapped.\n{1}{B}: Return Gutterbones from your graveyard to your hand. Activate this ability only during your turn and only if an opponent lost life this turn. From 07324f63d90fb147759e4a36765826fb83844695 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 17:56:47 +0000 Subject: [PATCH 25/54] Update spawn_of_mayhem.txt --- forge-gui/res/cardsfolder/upcoming/spawn_of_mayhem.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/spawn_of_mayhem.txt b/forge-gui/res/cardsfolder/upcoming/spawn_of_mayhem.txt index 3d4b5725ea0..e1e05351ad4 100644 --- a/forge-gui/res/cardsfolder/upcoming/spawn_of_mayhem.txt +++ b/forge-gui/res/cardsfolder/upcoming/spawn_of_mayhem.txt @@ -6,7 +6,7 @@ K:Spectacle:1 B B K:Flying K:Trample T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDmg | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to each player. Then if you have 10 or less life, put a +1/+1 counter on CARDNAME. -SVar:TrigDmgOpp:DB$DealDamage | Defined$ Player | NumDmg$ 1 | SubAbility$ DBCounter +SVar:TrigDmg:DB$DealDamage | Defined$ Player | NumDmg$ 1 | SubAbility$ DBCounter SVar:DBCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ LE10 | References$ X SVar:X:Count$YourLifeTotal DeckHas:Ability$Counters From 3b21b2a6103bfdfc89edae5001150f691edabc43 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 17:58:28 +0000 Subject: [PATCH 26/54] Fix fireblade_artist dealing damage on sacrifice --- forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt index a75291fad70..109b188cb6b 100644 --- a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt +++ b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt @@ -4,6 +4,7 @@ Types:Creature Human Shaman PT:2/2 K:Haste T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, you may sacrifice a creature. When you do, CARDNAME deals 2 damage to target opponent or planeswalker. -SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 -SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 +SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 | RememberSacrificed$ True | SubAbility$ TrigDealDamage +SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | ConditionDefined$ Remembered | ConditionPresent$ Creature | ConditionCompare$ GE1 | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True Oracle:Haste\nAt the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker. From 4fa8fa399306e0e5e7f457c76c9de78d4ad8b811 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 18:04:06 +0000 Subject: [PATCH 27/54] Update sentinels_mark.txt --- forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt b/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt index 5d6b7ac507e..5a6c80a41b2 100644 --- a/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt +++ b/forge-gui/res/cardsfolder/upcoming/sentinels_mark.txt @@ -5,6 +5,6 @@ K:Flash K:Enchant creature A:SP$ Attach | Cost$ 1 W | ValidTgts$ Creature | AILogic$ Pump S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 1 | AddToughness$ 2 | AddKeyword$ Vigilance | Description$ Enchanted creature gets +1/+2 and has vigilance. -T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | Condition$ Main1 | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | Condition$ Main1,Main2 | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Enchanted | KW$ Lifelink Oracle:Flash\nEnchant creature\nEnchanted creature gets +1/+2 and has vigilance.\nAddendum — When Sentinel's Mark enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. From 54c5d3f344042901b6d460fbff7ac5528c6f1039 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 19:25:20 +0000 Subject: [PATCH 28/54] Fix Fireblade Artist to reflect "when you" sacrifice trigger (similar to Heart-Piercer Manticore) --- forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt index 109b188cb6b..34056eb8782 100644 --- a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt +++ b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt @@ -4,7 +4,7 @@ Types:Creature Human Shaman PT:2/2 K:Haste T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, you may sacrifice a creature. When you do, CARDNAME deals 2 damage to target opponent or planeswalker. -SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 | RememberSacrificed$ True | SubAbility$ TrigDealDamage -SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | ConditionDefined$ Remembered | ConditionPresent$ Creature | ConditionCompare$ GE1 | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 | SacrificeParam$ FirebladeArtist | AILogic$ ConsiderSac +T:Mode$ Sacrificed | ValidPlayer$ You | ValidCard$ Creature | CauseParam$ FirebladeArtist | Execute$ TrigDealDamage | Secondary$ True | TriggerDescription$ CARDNAME deals 2 damage to target opponent or planeswalker. +SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 Oracle:Haste\nAt the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker. From acdee9ff0ca580e6354ebf99b0a4ab0b36f1e2be Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 19:43:56 +0000 Subject: [PATCH 29/54] Update fireblade_artist.txt --- forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt index 34056eb8782..c2adafe9cb5 100644 --- a/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt +++ b/forge-gui/res/cardsfolder/upcoming/fireblade_artist.txt @@ -4,7 +4,8 @@ Types:Creature Human Shaman PT:2/2 K:Haste T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, you may sacrifice a creature. When you do, CARDNAME deals 2 damage to target opponent or planeswalker. -SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 | SacrificeParam$ FirebladeArtist | AILogic$ ConsiderSac -T:Mode$ Sacrificed | ValidPlayer$ You | ValidCard$ Creature | CauseParam$ FirebladeArtist | Execute$ TrigDealDamage | Secondary$ True | TriggerDescription$ CARDNAME deals 2 damage to target opponent or planeswalker. -SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 +SVar:TrigSacrifice:DB$ Sacrifice | Optional$ True | SacValid$ Creature | Amount$ 1 | RememberSacrificed$ True | SubAbility$ TrigImmediate +SVar:TrigImmediate:DB$ ImmediateTrigger | Execute$ TrigDealDamage | ConditionDefined$ Remembered | ConditionPresent$ Creature | ConditionCompare$ GE1 | TriggerDescription$ When you do, CARDNAME deals 2 damage to target opponent or planeswalker. +SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 2 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True Oracle:Haste\nAt the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker. From 625585f0057c9dd2c83151ec573a5349bffd9d5c Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 20:15:05 +0000 Subject: [PATCH 30/54] Fixed Scry 3 --- forge-gui/res/cardsfolder/upcoming/precognitive_perception.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/precognitive_perception.txt b/forge-gui/res/cardsfolder/upcoming/precognitive_perception.txt index 2bd4cc8757a..0b2a2ef5f7c 100644 --- a/forge-gui/res/cardsfolder/upcoming/precognitive_perception.txt +++ b/forge-gui/res/cardsfolder/upcoming/precognitive_perception.txt @@ -1,6 +1,6 @@ Name:Precognitive Perception ManaCost:3 U U Types:Instant -A:SP$ Scry | Cost$ 3 U U | NumCards$ 3 | ConditionPlayerTurn$ True | ConditionPhases$ Main1,Main2 | SubAbility$ DBDraw | SpellDescription$ Draw three cards.\nAddendum — If you cast this spell during your main phase, instead scry 3, then draw three cards. +A:SP$ Scry | Cost$ 3 U U | ScryNum$ 3 | ConditionPlayerTurn$ True | ConditionPhases$ Main1,Main2 | SubAbility$ DBDraw | SpellDescription$ Draw three cards.\nAddendum — If you cast this spell during your main phase, instead scry 3, then draw three cards. SVar:DBDraw:DB$ Draw | Cost$ 3 U U | NumCards$ 3 Oracle:Draw three cards.\nAddendum — If you cast this spell during your main phase, instead scry 3, then draw three cards. From 1dc8ef5244d670d58e5e6c5ed737078c8533410a Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 20:34:35 +0000 Subject: [PATCH 31/54] Fixed problem with self-exiling after trigger resolution (Hanmac) --- .../upcoming/lumbering_battlement.txt | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/lumbering_battlement.txt b/forge-gui/res/cardsfolder/upcoming/lumbering_battlement.txt index 0838ca63c67..9e3ec703e98 100644 --- a/forge-gui/res/cardsfolder/upcoming/lumbering_battlement.txt +++ b/forge-gui/res/cardsfolder/upcoming/lumbering_battlement.txt @@ -3,11 +3,21 @@ ManaCost:4 W Types:Creature Beast PT:4/5 K:Vigilance -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile any number of other nontoken creatures you control until it leaves the battlefield. -SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | ChangeType$ Creature.nonToken+Other+YouCtrl | TargetMin$ 0 | TargetMax$ X | References$ X | Mandatory$ True | SubAbility$ DBEffect -SVar:DBEffect:DB$ Effect | Triggers$ ComeBack | RememberObjects$ Remembered | ImprintCards$ Remembered | SVars$ TrigReturn,ExileSelf | ConditionPresent$ Card.IsRemembered | ConditionCompare$ GE1 -SVar: +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBChooseExile | TriggerDescription$ When CARDNAME enters the battlefield, exile any number of other nontoken creatures you control until it leaves the battlefield. +SVar:DBChooseExile:DB$ ChooseCard | Defined$ You | MinAmount$ 0 | Amount$ MaxTgts | References$ MaxTgts | Choices$ Creature.nonToken+Other+YouCtrl | ChoiceTitle$ Choose any number of other nontoken creatures you control | ChoiceZone$ Battlefield | SubAbility$ TrigExile +SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | Defined$ ChosenCard | SubAbility$ DBEffect +SVar:DBEffect:DB$ Effect | Triggers$ ComeBack | RememberObjects$ RememberedCard | ImprintCards$ Self | SVars$ TrigReturn,ExileSelf | ConditionPresent$ Card.Self | Duration$ Permanent | ForgetOnMoved$ Exile | SubAbility$ DBCleanup +SVar:ComeBack:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.IsImprinted | Execute$ TrigReturn | TriggerZones$ Command | TriggerController$ TriggeredCardController | Static$ True | TriggerDescription$ That creature is exiled until EFFECTSOURCE leaves the battlefield +SVar:TrigReturn:DB$ ChangeZoneAll | Origin$ Exile | Destination$ Battlefield | ChangeType$ Card.IsRemembered | SubAbility$ ExileSelf +SVar:ExileSelf:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self +SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True S:Mode$ Continuous | Affected$ Card.Self | AddPower$ X | AddToughness$ X | References$ X | Description$ CARDNAME gets +2/+2 for each card exiled with it. -SVar:X:Count$Valid Card.IsRemembered+namedCARDNAME/Times.2 +#Triggers to forget remembered on this +T:Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Exile | Destination$ Any | TriggerZones$ Battlefield | Static$ True | Execute$ TrigForget +SVar:TrigForget:DB$ Pump | ForgetObjects$ TriggeredCard +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Any | Static$ True | Execute$ TrigForgetAll +SVar:TrigForgetAll:DB$ Cleanup | ClearRemembered$ True +SVar:X:Count$ValidExile Card.IsRemembered+ExiledWithSource/Times.2 +SVar:MaxTgts:Count$Valid Creature.nonToken+Other+YouCtrl SVar:RemRandomDeck:True Oracle:Vigilance\nWhen Lumbering Battlement enters the battlefield, exile any number of other nontoken creatures you control until it leaves the battlefield.\nLumbering Battlement gets +2/+2 for each card exiled with it. From 8b7ace6d1c8e8b9131ce3e04f65be7bc51d4590c Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 21:45:52 +0000 Subject: [PATCH 32/54] Added TrigChangeZone to bounce it back, and CheckSVar to check if instant cast in Main Phase --- forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt b/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt index 72a7e9e4c1a..41757ebaac4 100644 --- a/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt +++ b/forge-gui/res/cardsfolder/upcoming/dovins_acuity.txt @@ -2,9 +2,10 @@ Name:Dovin's Acuity ManaCost:1 W U Types:Enchantment T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 2 life and draw a card. -T:Mode$ SpellCast | ValidCard$ Instant | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ Whenever you cast an instant spell during your main phase, you may return CARDNAME to its owner's hand. SVar:TrigGainLife:DB$GainLife | Defined$ You | LifeAmount$ 2 | SubAbility$ DBDraw SVar:DBDraw:DB$Draw | Defined$ You | NumCards$ 1 -SVar:X:Count$IfMainPhase +T:Mode$ SpellCast | ValidCard$ Instant | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | PlayerTurn$ True | CheckSVar$ X | SVarCompare$ GE1 | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ Whenever you cast an instant spell during your main phase, you may return CARDNAME to its owner's hand. +SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Battlefield | Destination$ Hand | Defined$ Self +SVar:X:Count$IfMainPhase.1.0 DeckHas:Ability$LifeGain Oracle:When Dovin's Acuity enters the battlefield, you gain 2 life and draw a card.\nWhenever you cast an instant spell during your main phase, you may return Dovin's Acuity to its owner's hand. From b23425ea9af6aa797a5868b0bda982280844a62e Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 22:37:18 +0000 Subject: [PATCH 33/54] Update bloodmist_infiltrator.txt --- forge-gui/res/cardsfolder/upcoming/bloodmist_infiltrator.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/bloodmist_infiltrator.txt b/forge-gui/res/cardsfolder/upcoming/bloodmist_infiltrator.txt index 595582978bd..564757411cf 100644 --- a/forge-gui/res/cardsfolder/upcoming/bloodmist_infiltrator.txt +++ b/forge-gui/res/cardsfolder/upcoming/bloodmist_infiltrator.txt @@ -3,7 +3,5 @@ ManaCost:2 B Types:Creature Vampire PT:3/1 T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks, you may sacrifice another creature. If you do, CARDNAME can't be blocked this turn. -SVar:TrigPump:AB$ Pump | Cost$ Sac<1/Creature.Other/another creature> | Defined$ Self | KW$ HIDDEN Unblockable | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | SubAbility$ DBCleanup | References$ X -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Remembered$Amount +SVar:TrigPump:AB$ Pump | Cost$ Sac<1/Creature.Other/another creature> | Defined$ Self | KW$ HIDDEN Unblockable Oracle:Whenever Bloodmist Infiltrator attacks, you may sacrifice another creature. If you do, Bloodmist Infiltrator can't be blocked this turn. From 0bfdfb78d3015be5af6c51d7b1e063e7ff042cab Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 22:43:34 +0000 Subject: [PATCH 34/54] Update ill_gotten_inheritance.txt --- .../cardsfolder/upcoming/ill_gotten_inheritance.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/ill_gotten_inheritance.txt b/forge-gui/res/cardsfolder/upcoming/ill_gotten_inheritance.txt index 5c3658aca13..85cf8828a10 100644 --- a/forge-gui/res/cardsfolder/upcoming/ill_gotten_inheritance.txt +++ b/forge-gui/res/cardsfolder/upcoming/ill_gotten_inheritance.txt @@ -1,9 +1,9 @@ Name:Ill-Gotten Inheritance ManaCost:3 B Types:Enchantment -T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDamageAll | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to each opponent and you gain 1 life. -SVar:TrigDealDamage:DB$ DamageAll | ValidPlayers$ Player.Opponent | NumDmg$ 1 | SubAbility$ DBGainLife -SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 -A:AB$ DealDamage | Cost$ 5 B Sac<1/CARDNAME> | ValidTgts$ Opponent | NumDmg$ 4 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 4 damage to target opponent and you gain 4 life. -SVar:DBGainLife:DB$GainLife | LifeAmount$ 4 +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to each opponent and you gain 1 life. +SVar:TrigDealDamage:DB$ DamageAll | ValidPlayers$ Player.Opponent | NumDmg$ 1 | SubAbility$ DBGainOneLife +SVar:DBGainOneLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 +A:AB$ DealDamage | Cost$ 5 B Sac<1/CARDNAME> | ValidTgts$ Opponent | NumDmg$ 4 | SubAbility$ DBGainFourLife | SpellDescription$ CARDNAME deals 4 damage to target opponent and you gain 4 life. +SVar:DBGainFourLife:DB$GainLife | Defined$ You | LifeAmount$ 4 Oracle:At the beginning of your upkeep, Ill-Gotten Inheritance deals 1 damage to each opponent and you gain 1 life.\n{5}{B}, Sacrifice Ill-Gotten Inheritance: It deals 4 damage to target opponent and you gain 4 life. From a1ad2208c8489c9928dab5bf176c47da3cd2ea9b Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 23:01:06 +0000 Subject: [PATCH 35/54] Update rix_maadi_reveler.txt --- forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt b/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt index cfd4bd2db5d..f7ceece6349 100644 --- a/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt +++ b/forge-gui/res/cardsfolder/upcoming/rix_maadi_reveler.txt @@ -2,7 +2,6 @@ Name:Rix Maadi Reveler ManaCost:1 R Types:Creature Human Shaman PT:2/2 -K:Flying K:Spectacle:2 B R T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield, discard a card, then draw a card. If CARDNAME's spectacle cost was paid, instead discard your hand, then draw three cards. SVar:TrigDiscard:DB$ Discard | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBDrawOne | ConditionDefined$ TriggeredCard | ConditionPresent$ Card.spectacle | ConditionCompare$ EQ0 From 766277673da1205454f2f3c08bf10e538d8fe6d1 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Sun, 27 Jan 2019 23:45:21 +0000 Subject: [PATCH 36/54] Update simic_locket.txt --- forge-gui/res/cardsfolder/upcoming/simic_locket.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/simic_locket.txt b/forge-gui/res/cardsfolder/upcoming/simic_locket.txt index 22025cfffd4..e7886996cae 100644 --- a/forge-gui/res/cardsfolder/upcoming/simic_locket.txt +++ b/forge-gui/res/cardsfolder/upcoming/simic_locket.txt @@ -2,7 +2,7 @@ Name:Simic Locket ManaCost:3 Types:Artifact A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}. -A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}. +A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}. AI:RemoveDeck:Random DeckNeeds:Color$Green | Blue A:AB$ Draw | Cost$ GU GU GU GU T Sac<1/CARDNAME> | NumCards$ 2 | SpellDescription$ Draw two cards. From 25003aa74e5a95e384ece291386dc823eeb02bae Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Sun, 27 Jan 2019 21:09:52 -0500 Subject: [PATCH 37/54] better way to schedule visual updates to non-selectable cards --- .../java/forge/screens/match/CMatchUI.java | 39 +++++++++++++++++++ .../java/forge/view/arcane/CardPanel.java | 7 +--- .../java/forge/view/arcane/FloatingZone.java | 5 +++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index db4efdbbee0..1e12acb4e9e 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -524,6 +524,45 @@ public final class CMatchUI } } + @Override + public void setSelectables(final Iterable cards) { + super.setSelectables(cards); + // update zones on tabletop and floating zones - non-selectable cards may be rendered differently + FThreads.invokeInEdtNowOrLater(new Runnable() { + @Override public final void run() { + for (final PlayerView p : getGameView().getPlayers()) { + if ( p.getCards(ZoneType.Battlefield) != null ) { + updateCards(p.getCards(ZoneType.Battlefield)); + } + if ( p.getCards(ZoneType.Hand) != null ) { + updateCards(p.getCards(ZoneType.Hand)); + } + } + FloatingZone.refreshAll(); + } + }); + } + + @Override + public void clearSelectables() { + super.clearSelectables(); + // update zones on tabletop and floating zones - non-selectable cards may be rendered differently + FThreads.invokeInEdtNowOrLater(new Runnable() { + @Override public final void run() { + for (final PlayerView p : getGameView().getPlayers()) { + if ( p.getCards(ZoneType.Battlefield) != null ) { + updateCards(p.getCards(ZoneType.Battlefield)); + } + if ( p.getCards(ZoneType.Hand) != null ) { + updateCards(p.getCards(ZoneType.Hand)); + } + } + FloatingZone.refreshAll(); + } + }); + } + + @Override public List getMenus() { return menus.getMenus(); diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java index 7d0cbb2ce89..8a7ee3c99c1 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java @@ -279,7 +279,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl if (isSelected) { g2d.setColor(Color.green); final int n = Math.max(1, Math.round(cardWidth * CardPanel.SELECTED_BORDER_SIZE)); - g2d.fillRoundRect(cardXOffset - n, (cardYOffset - n) + offset, cardWidth + (n * 2), cardHeight + (n * 2), cornerSize + n , cornerSize + n); + g2d.fillRoundRect(cardXOffset - n, (cardYOffset - n) + offset, cardWidth + (n * 2), cardHeight + (n * 2), cornerSize + n , cornerSize + n); } // Black fill - (will become an outline for white bordered cards) @@ -335,11 +335,9 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl cardWidth, cardHeight, Math.round(cardWidth * BLACK_BORDER_SIZE)); } - System.out.println("Painting " + getCard() + " selecting " + matchUI.isSelecting()); boolean nonselectable = matchUI.isSelecting() && !matchUI.isSelectable(getCard()); - // if selecting, darken non-selectable cards - pfps - needs fixes to refreshing to do right + // if selecting, darken non-selectable cards if ( nonselectable ) { - System.out.println("Paint nonselectable " + card); boolean noBorderPref = !isPreferenceEnabled(FPref.UI_RENDER_BLACK_BORDERS); boolean cardImgHasAlpha = imagePanel != null && imagePanel.getSrcImage() != null && imagePanel.getSrcImage().getColorModel().hasAlpha(); final int cornerSize = noBorderPref && !cardImgHasAlpha ? 0 : Math.max(4, Math.round(cardWidth * CardPanel.ROUNDED_CORNER_SIZE)); @@ -373,7 +371,6 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl final boolean canShow = matchUI.mayView(card); final boolean showText = !imagePanel.hasImage() || !isAnimationPanel; - System.out.println("doLayout " + card); displayCardNameOverlay(showText && canShow && showCardNameOverlay(), imgSize, imgPos); displayPTOverlay(showText && (canShow || card.isFaceDown()) && showCardPowerOverlay(), imgSize, imgPos); displayCardIdOverlay(showText && canShow && showCardIdOverlay(), imgSize, imgPos); diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingZone.java b/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingZone.java index d81af9fef88..616a7cce38c 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingZone.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/FloatingZone.java @@ -94,6 +94,11 @@ public class FloatingZone extends FloatingCardArea { } floatingAreas.clear(); } + public static void refreshAll() { + for (final FloatingZone cardArea : floatingAreas.values()) { + cardArea.refresh(); + } + } private final ZoneType zone; private PlayerView player; From 01c52667ad7fdb90cf1f30179bce04246a55409c Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 07:01:43 +0000 Subject: [PATCH 38/54] Update forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt, forge-gui/res/cardsfolder/r/raid_bombardment.txt, forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt, forge-gui/res/cardsfolder/upcoming/get_the_point.txt, forge-gui/res/cardsfolder/upcoming/haazda_officer.txt, forge-gui/res/cardsfolder/upcoming/lawmages_binding.txt, forge-gui/res/cardsfolder/upcoming/rubble_slinger.txt, forge-gui/res/cardsfolder/upcoming/rubblebelt_runner.txt, forge-gui/res/cardsfolder/upcoming/screaming_shield.txt, forge-gui/res/cardsfolder/upcoming/scuttlegator.txt, forge-gui/res/cardsfolder/upcoming/senate_griffin.txt, forge-gui/res/cardsfolder/upcoming/summary_judgment.txt, forge-gui/res/cardsfolder/upcoming/vizkopa_vampire.txt files --- forge-gui/res/cardsfolder/r/raid_bombardment.txt | 7 +++---- .../res/cardsfolder/upcoming/cavalcade_of_calamity.txt | 7 +++++++ forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/get_the_point.txt | 6 ++++++ forge-gui/res/cardsfolder/upcoming/haazda_officer.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/lawmages_binding.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/rubble_slinger.txt | 6 ++++++ forge-gui/res/cardsfolder/upcoming/rubblebelt_runner.txt | 6 ++++++ forge-gui/res/cardsfolder/upcoming/screaming_shield.txt | 7 +++++++ forge-gui/res/cardsfolder/upcoming/scuttlegator.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/senate_griffin.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/summary_judgment.txt | 6 ++++++ forge-gui/res/cardsfolder/upcoming/vizkopa_vampire.txt | 6 ++++++ 13 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/get_the_point.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/haazda_officer.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/lawmages_binding.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/rubble_slinger.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/rubblebelt_runner.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/screaming_shield.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/scuttlegator.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/senate_griffin.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/summary_judgment.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/vizkopa_vampire.txt diff --git a/forge-gui/res/cardsfolder/r/raid_bombardment.txt b/forge-gui/res/cardsfolder/r/raid_bombardment.txt index 2534b51ec7c..5cf328f2974 100644 --- a/forge-gui/res/cardsfolder/r/raid_bombardment.txt +++ b/forge-gui/res/cardsfolder/r/raid_bombardment.txt @@ -1,8 +1,7 @@ Name:Raid Bombardment ManaCost:2 R Types:Enchantment -T:Mode$ Attacks | ValidCard$ Creature.powerLE2+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever a creature you control with power 2 or less attacks, CARDNAME deals 1 damage to defending player. -SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredDefendingPlayer | NumDmg$ 1 +T:Mode$ Attacks | ValidCard$ Creature.powerLE2+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever a creature you control with power 2 or less attacks, CARDNAME deals 1 damage to the player or planeswalker that creature is attacking +SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredAttacked | NumDmg$ 1 SVar:PlayMain1:TRUE -SVar:Picture:http://www.wizards.com/global/images/magic/general/raid_bombardment.jpg -Oracle:Whenever a creature you control with power 2 or less attacks, Raid Bombardment deals 1 damage to defending player. +Oracle:Whenever a creature you control with power 2 or less attacks, Raid Bombardment deals 1 damage to the player or planeswalker that creature is attacking. diff --git a/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt b/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt new file mode 100644 index 00000000000..a4e5f920e7e --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt @@ -0,0 +1,7 @@ +Name:Cavalcade of Calamity +ManaCost:1 R +Types:Enchantment +T:Mode$ Attacks | ValidCard$ Creature.powerLE1+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever a creature you control with power 1 or less attacks, CARDNAME deals 1 damage to the player or planeswalker that creature is attacking +SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredAttacked | NumDmg$ 1 +SVar:PlayMain1:TRUE +Oracle:Whenever a creature you control with power 1 or less attacks, Cavalcade of Calamity deals 1 damage to the player or planeswalker that creature is attacking. diff --git a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt new file mode 100644 index 00000000000..4be78823eca --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt @@ -0,0 +1,8 @@ +Name:Forbidding Spirit +ManaCost:1 W W +Types:Creature Spirit Cleric +PT:3/3 +T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TempAttackTax | TriggerDescription$ When CARDNAME enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. +SVar:TempAttackTax:DB$ Effect | Name$ Forbidding Spirit Effect | StaticAbilities$ TempoCantAttack | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. +SVar:TempoCantAttack:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You,Planeswalker.YouCtrl | Cost$ 2 | Description$ Until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. +Oracle:When Forbidding Spirit enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. diff --git a/forge-gui/res/cardsfolder/upcoming/get_the_point.txt b/forge-gui/res/cardsfolder/upcoming/get_the_point.txt new file mode 100644 index 00000000000..1a09941bc97 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/get_the_point.txt @@ -0,0 +1,6 @@ +Name:Get the Point +ManaCost:3 B R +Types:Instant +A:SP$ Destroy | Cost$ 3 B R | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ DBScry | SpellDescription$ Destroy target creature. Scry 1. +SVar:DBScry:DB$ Scry | ScryNum$ 1 +Oracle:Destroy target creature. Scry 1. diff --git a/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt b/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt new file mode 100644 index 00000000000..0890f2ade76 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt @@ -0,0 +1,8 @@ +Name:Haazda Officer +ManaCost:2 W +Types:Creature Human Soldier +PT:3/2 +T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, target creature you control gets +1/+1 until end of turn. +SVar:TrigPump:DB$Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | NumAtt$ 1 | NumDef$ 1 +SVar:PlayMain1:TRUE +Oracle:When Haazda Officer enters the battlefield, target creature you control gets +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/lawmages_binding.txt b/forge-gui/res/cardsfolder/upcoming/lawmages_binding.txt new file mode 100644 index 00000000000..3c5087d6bc5 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/lawmages_binding.txt @@ -0,0 +1,8 @@ +Name:Lawmage's Binding +ManaCost:1 W U +Types:Enchantment Aura +K:Flash +K:Enchant creature +A:SP$ Attach | Cost$ 1 W U | ValidTgts$ Creature | AILogic$ Curse +S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. & CARDNAME's activated abilities can't be activated. | Description$ Enchanted creature can't attack or block and its activated abilities can't be activated. +Oracle:Flash\nEnchant creature\nEnchanted creature can't attack or block, and its activated abilities can't be activated. diff --git a/forge-gui/res/cardsfolder/upcoming/rubble_slinger.txt b/forge-gui/res/cardsfolder/upcoming/rubble_slinger.txt new file mode 100644 index 00000000000..bfa37840636 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/rubble_slinger.txt @@ -0,0 +1,6 @@ +Name:Rubble Slinger +ManaCost:2 RG +Types:Creature Human Warrior +PT:2/3 +K:Reach +Oracle:Reach diff --git a/forge-gui/res/cardsfolder/upcoming/rubblebelt_runner.txt b/forge-gui/res/cardsfolder/upcoming/rubblebelt_runner.txt new file mode 100644 index 00000000000..6c88e9b0745 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/rubblebelt_runner.txt @@ -0,0 +1,6 @@ +Name:Rubblebelt Runner +ManaCost:1 R G +Types:Creature Viashino Warrior +PT:3/3 +K:CantBeBlockedBy Creature.token +Oracle:Rubblebelt Runner can’t be blocked by creature tokens. diff --git a/forge-gui/res/cardsfolder/upcoming/screaming_shield.txt b/forge-gui/res/cardsfolder/upcoming/screaming_shield.txt new file mode 100644 index 00000000000..f0f80e0a52e --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/screaming_shield.txt @@ -0,0 +1,7 @@ +Name:Screaming Shield +ManaCost:1 +Types:Artifact Equipment +K:Equip:3 +S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddToughness$ 3 | AddAbility$ Mill | Description$ Equipped creature gets +0/+3 and has "{2}, {T}: Target player puts the top three cards of their library into their graveyard." +SVar:Mill:AB$ Mill | Cost$ 2 T | NumCards$ 3 | ValidTgts$ Player | TgtPrompt$ Choose a player | SpellDescription$ Target player puts the top three cards of their library into their graveyard. +Oracle:Equipped creature gets +0/+3 and has "{2}, {T}: Target player puts the top three cards of their library into their graveyard."\nEquip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/upcoming/scuttlegator.txt b/forge-gui/res/cardsfolder/upcoming/scuttlegator.txt new file mode 100644 index 00000000000..19a4f959cab --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/scuttlegator.txt @@ -0,0 +1,8 @@ +Name:Scuttlegator +ManaCost:4 GU GU +Types:Creature Crab Turtle Crocodile +PT:6/6 +K:Defender +K:Adapt:3:6 GU GU +S:Mode$ Continuous | Affected$ Card.Self+counters_GE1_P1P1 | AddHiddenKeyword$ CARDNAME can attack as though it didn't have defender. | Description$ As long as CARDNAME has a +1/+1 counter on it, it can attack as though it didn’t have defender. +Oracle:Defender\n{6}{G/U}{G/U}: Adapt 3. (If this creature has no +1/+1 counters on it, put two +1/+1 counters on it.)\nAs long as Scuttlegator has a +1/+1 counter on it, it can attack as though it didn’t have defender. diff --git a/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt b/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt new file mode 100644 index 00000000000..c7193c112b9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt @@ -0,0 +1,8 @@ +Name:Senate Griffin +ManaCost:2 UW UW +Types:Creature Griffin +PT:3/2 +K:Flying +T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ DBScry | TriggerDescription$ When CARDNAME etners the battlefield, scry 1. +SVar:DBScry:DB$ Scry | ScryNum$ 1 +Oracle:Flying.\nWhen Senate Griffin enters the battlefield, scry 1. diff --git a/forge-gui/res/cardsfolder/upcoming/summary_judgment.txt b/forge-gui/res/cardsfolder/upcoming/summary_judgment.txt new file mode 100644 index 00000000000..605dc72faa4 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/summary_judgment.txt @@ -0,0 +1,6 @@ +Name:Summary Judgment +ManaCost:1 W +Types:Instant +A:SP$ DealDamage | Cost$ 1 W | ValidTgts$ Creature.tapped | NumDmg$ X | References$ X | TgtPrompt$ Select target tapped creature | SpellDescription$ CARDNAME deals 3 damage to target tapped creature. If you cast this spell during your main phase, CARDNAME deals 5 damage to that creature instead. +SVar:X:Count$IfMainPhase.5.3 +Oracle:Summary Judgment deals 3 damage to target tapped creature.\nAddendum — If you cast this spell during your main phase, it deals 5 damage to that creature instead. diff --git a/forge-gui/res/cardsfolder/upcoming/vizkopa_vampire.txt b/forge-gui/res/cardsfolder/upcoming/vizkopa_vampire.txt new file mode 100644 index 00000000000..c14766555ab --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/vizkopa_vampire.txt @@ -0,0 +1,6 @@ +Name:Vizkopa Vampire +ManaCost:2 WB +Types:Creature Vampire +PT:3/1 +K:Lifelink +Oracle:Lifelink From 89757b9677a1c955cb160af31432b1bdf06dec67 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 07:04:13 +0000 Subject: [PATCH 39/54] Update forge-gui/res/cardsfolder/upcoming/footlight_fiend.txt --- forge-gui/res/cardsfolder/upcoming/footlight_fiend.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/footlight_fiend.txt diff --git a/forge-gui/res/cardsfolder/upcoming/footlight_fiend.txt b/forge-gui/res/cardsfolder/upcoming/footlight_fiend.txt new file mode 100644 index 00000000000..d5476eccf58 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/footlight_fiend.txt @@ -0,0 +1,7 @@ +Name:Footlight Fiend +ManaCost:BR +Types:Creature Devil +PT:1/1 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDealDamage | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, it deals 1 damage to any target. +SVar:TrigDealDamage:DB$DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 +Oracle:When Footlight Fiend dies, it deals 1 damage to any target. From e1ceed159f17edb8f9e938b938b68c0ab4c083d8 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 07:08:05 +0000 Subject: [PATCH 40/54] Update forge-gui/res/cardsfolder/upcoming/elite_arrester.txt, forge-gui/res/cardsfolder/upcoming/clamor_shaman.txt files --- forge-gui/res/cardsfolder/upcoming/clamor_shaman.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/elite_arrester.txt | 7 +++++++ 2 files changed, 15 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/clamor_shaman.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/elite_arrester.txt diff --git a/forge-gui/res/cardsfolder/upcoming/clamor_shaman.txt b/forge-gui/res/cardsfolder/upcoming/clamor_shaman.txt new file mode 100644 index 00000000000..64148416e73 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/clamor_shaman.txt @@ -0,0 +1,8 @@ +Name:Clamor Shaman +ManaCost:2 R +Types:Creature Shaman +PT:1/1 +K:Riot +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCanNotBlock | TriggerDescription$ Whenever CARDNAME attacks, target creature an opponent controls can't block this turn. +SVar:TrigCanNotBlock:DB$ Pump | ValidTgts$ Creature.OppCtrl | KW$ HIDDEN CARDNAME can't block. | TgtPrompt$ Select target creature an opponent controls | IsCurse$ True +Oracle:Riot (This creature enters the battlefield with your choice of a +1/+1 counter or haste.)\nWhenever Clamor Shaman attacks, target creature an opponent controls can’t block this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/elite_arrester.txt b/forge-gui/res/cardsfolder/upcoming/elite_arrester.txt new file mode 100644 index 00000000000..67442dfa407 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/elite_arrester.txt @@ -0,0 +1,7 @@ +Name:Elite Arrester +ManaCost:W +Types:Creature Human Soldier +PT:0/3 +A:AB$ Tap | Cost$ 1 U T | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Tap target creature. +SVar:NonCombatPriority:5 +Oracle:{1}{U}, {T}: Tap target creature. From a462d3424953d70ceee4b9aa935318a1fc7b7e2a Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 07:38:32 +0000 Subject: [PATCH 41/54] Update forge-gui/res/cardsfolder/upcoming/charging_war_boar.txt, forge-gui/res/cardsfolder/upcoming/cindervines.txt files --- forge-gui/res/cardsfolder/upcoming/charging_war_boar.txt | 8 ++++++++ forge-gui/res/cardsfolder/upcoming/cindervines.txt | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/charging_war_boar.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/cindervines.txt diff --git a/forge-gui/res/cardsfolder/upcoming/charging_war_boar.txt b/forge-gui/res/cardsfolder/upcoming/charging_war_boar.txt new file mode 100644 index 00000000000..120a77a72d7 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/charging_war_boar.txt @@ -0,0 +1,8 @@ +Name:Charging War Boar +ManaCost:1 R G +Types:Creature Boar +PT:3/1 +K:Haste +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Trample | AddPower$ 1 | AddToughness$ 1 | IsPresent$ Planeswalker.Domri+YouCtrl | Description$ As long as you control a Domri planeswalker, CARDNAME gets +1/+1 and has trample. +SVar:BuffedBy:Domri +Oracle:Haste (This creature can attack and {T} as soon as it comes under your control.)\nAs long as you control a Domri planeswalker, Charging War Boar gets +1/+1 and has trample. (It can deal excess damage to the player or planeswalker it’s attacking.) diff --git a/forge-gui/res/cardsfolder/upcoming/cindervines.txt b/forge-gui/res/cardsfolder/upcoming/cindervines.txt new file mode 100644 index 00000000000..5d0b5133500 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/cindervines.txt @@ -0,0 +1,8 @@ +Name:Cindervines +ManaCost:R G +Types:Enchantment +T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigDealOneDamage | TriggerDescription$ Whenever an opponent casts a noncreature spell, CARDNAME deals 1 damage to that player. +SVar:TrigDealOneDamage:DB$DealDamage | Defined$ TriggeredActivator | NumDmg$ 1 +A:AB$ Destroy | Cost$ 1 Sac<1/CARDNAME> | ValidTgt$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | Subability$ DBDealTwoDamage | SpellDescription$ Destroy target artifact or enchantment. CARDNAME deals 2 damage to that permanent’s controller. +SVar:DBDealTwoDamage:DB$ DealDamage | Defined$ TargetedController | NumDmg$ 2 +Oracle:Whenever an opponent casts a noncreature spell, Cindervines deals 1 damage to that player.\n{1}, Sacrifice Cindervines: Destroy target artifact or enchantment. Cindervines deals 2 damage to that permanent’s controller. From 1c9a515bb3911b4abd5eccafb02062ab4812440d Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 07:47:55 +0000 Subject: [PATCH 42/54] Update forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt --- forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt diff --git a/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt b/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt new file mode 100644 index 00000000000..bb227a66cff --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt @@ -0,0 +1,9 @@ +Name:Domri's Nodorog +ManaCost:3 R G +Types:Creature Beast +PT:5/2 +K:Trample +T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. +SVar:TrigSearch:DB$ ChangeZone | Origin$ Library,Graveyard | Destination$ Hand | ChangeType$ Card.namedDomri; City Smasher | ChangeNum$ 1 | Optional$ True +DeckHints:Name$Domri, City Smasher +Oracle:Trample\nWhen Domri’s Nodorog enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. From 7c98ed75be1651ed557eb9b08a8e68659adaaa7a Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 08:02:07 +0000 Subject: [PATCH 43/54] Update forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt, forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt, forge-gui/res/cardsfolder/upcoming/haazda_officer.txt, forge-gui/res/cardsfolder/upcoming/senate_griffin.txt files --- forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt | 2 +- forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt | 2 +- forge-gui/res/cardsfolder/upcoming/haazda_officer.txt | 2 +- forge-gui/res/cardsfolder/upcoming/senate_griffin.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt b/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt index bb227a66cff..b823c2265fe 100644 --- a/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt +++ b/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt @@ -3,7 +3,7 @@ ManaCost:3 R G Types:Creature Beast PT:5/2 K:Trample -T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. SVar:TrigSearch:DB$ ChangeZone | Origin$ Library,Graveyard | Destination$ Hand | ChangeType$ Card.namedDomri; City Smasher | ChangeNum$ 1 | Optional$ True DeckHints:Name$Domri, City Smasher Oracle:Trample\nWhen Domri’s Nodorog enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. diff --git a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt index 4be78823eca..510834864df 100644 --- a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt +++ b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt @@ -2,7 +2,7 @@ Name:Forbidding Spirit ManaCost:1 W W Types:Creature Spirit Cleric PT:3/3 -T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TempAttackTax | TriggerDescription$ When CARDNAME enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TempAttackTax | TriggerDescription$ When CARDNAME enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. SVar:TempAttackTax:DB$ Effect | Name$ Forbidding Spirit Effect | StaticAbilities$ TempoCantAttack | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. SVar:TempoCantAttack:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You,Planeswalker.YouCtrl | Cost$ 2 | Description$ Until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. Oracle:When Forbidding Spirit enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. diff --git a/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt b/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt index 0890f2ade76..abf54ae1465 100644 --- a/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt +++ b/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt @@ -2,7 +2,7 @@ Name:Haazda Officer ManaCost:2 W Types:Creature Human Soldier PT:3/2 -T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, target creature you control gets +1/+1 until end of turn. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, target creature you control gets +1/+1 until end of turn. SVar:TrigPump:DB$Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | NumAtt$ 1 | NumDef$ 1 SVar:PlayMain1:TRUE Oracle:When Haazda Officer enters the battlefield, target creature you control gets +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt b/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt index c7193c112b9..d0d603912aa 100644 --- a/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt +++ b/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt @@ -3,6 +3,6 @@ ManaCost:2 UW UW Types:Creature Griffin PT:3/2 K:Flying -T:Mode$ ChangeZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ DBScry | TriggerDescription$ When CARDNAME etners the battlefield, scry 1. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ DBScry | TriggerDescription$ When CARDNAME etners the battlefield, scry 1. SVar:DBScry:DB$ Scry | ScryNum$ 1 Oracle:Flying.\nWhen Senate Griffin enters the battlefield, scry 1. From b08ce490577930fe26d3f16cc25795411210747d Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 08:07:43 +0000 Subject: [PATCH 44/54] Update forge-gui/res/cardsfolder/upcoming/senate_griffin.txt, forge-gui/res/cardsfolder/upcoming/haazda_officer.txt, forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt, forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt files --- forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt | 2 +- forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt | 2 +- forge-gui/res/cardsfolder/upcoming/haazda_officer.txt | 2 +- forge-gui/res/cardsfolder/upcoming/senate_griffin.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt b/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt index b823c2265fe..1ab1297832a 100644 --- a/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt +++ b/forge-gui/res/cardsfolder/upcoming/domris_nodorog.txt @@ -3,7 +3,7 @@ ManaCost:3 R G Types:Creature Beast PT:5/2 K:Trample -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. SVar:TrigSearch:DB$ ChangeZone | Origin$ Library,Graveyard | Destination$ Hand | ChangeType$ Card.namedDomri; City Smasher | ChangeNum$ 1 | Optional$ True DeckHints:Name$Domri, City Smasher Oracle:Trample\nWhen Domri’s Nodorog enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. diff --git a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt index 510834864df..ab1a4292b5a 100644 --- a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt +++ b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt @@ -2,7 +2,7 @@ Name:Forbidding Spirit ManaCost:1 W W Types:Creature Spirit Cleric PT:3/3 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TempAttackTax | TriggerDescription$ When CARDNAME enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TempAttackTax | TriggerDescription$ When CARDNAME enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. SVar:TempAttackTax:DB$ Effect | Name$ Forbidding Spirit Effect | StaticAbilities$ TempoCantAttack | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. SVar:TempoCantAttack:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You,Planeswalker.YouCtrl | Cost$ 2 | Description$ Until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. Oracle:When Forbidding Spirit enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. diff --git a/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt b/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt index abf54ae1465..1599c582e1a 100644 --- a/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt +++ b/forge-gui/res/cardsfolder/upcoming/haazda_officer.txt @@ -2,7 +2,7 @@ Name:Haazda Officer ManaCost:2 W Types:Creature Human Soldier PT:3/2 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, target creature you control gets +1/+1 until end of turn. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, target creature you control gets +1/+1 until end of turn. SVar:TrigPump:DB$Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | NumAtt$ 1 | NumDef$ 1 SVar:PlayMain1:TRUE Oracle:When Haazda Officer enters the battlefield, target creature you control gets +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt b/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt index d0d603912aa..3b01e0b0c7a 100644 --- a/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt +++ b/forge-gui/res/cardsfolder/upcoming/senate_griffin.txt @@ -3,6 +3,6 @@ ManaCost:2 UW UW Types:Creature Griffin PT:3/2 K:Flying -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ DBScry | TriggerDescription$ When CARDNAME etners the battlefield, scry 1. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBScry | TriggerDescription$ When CARDNAME etners the battlefield, scry 1. SVar:DBScry:DB$ Scry | ScryNum$ 1 Oracle:Flying.\nWhen Senate Griffin enters the battlefield, scry 1. From 5e94c6c8d31e536ec346e634186be8b479cc1267 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 08:27:47 +0000 Subject: [PATCH 45/54] Update forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt --- forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt index ab1a4292b5a..37885dd2d0e 100644 --- a/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt +++ b/forge-gui/res/cardsfolder/upcoming/forbidding_spirit.txt @@ -4,5 +4,5 @@ Types:Creature Spirit Cleric PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TempAttackTax | TriggerDescription$ When CARDNAME enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. SVar:TempAttackTax:DB$ Effect | Name$ Forbidding Spirit Effect | StaticAbilities$ TempoCantAttack | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. -SVar:TempoCantAttack:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You,Planeswalker.YouCtrl | Cost$ 2 | Description$ Until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. +SVar:TempoCantAttack:Mode$ CantAttackUnless | EffectZone$ Command | ValidCard$ Creature | Target$ You,Planeswalker.YouCtrl | Cost$ 2 | Description$ Until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. Oracle:When Forbidding Spirit enters the battlefield, until your next turn, creatures can’t attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. From 763cb3d08e9943ca2f3e5bd6d27b13190c8695dd Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 08:30:23 +0000 Subject: [PATCH 46/54] Update forge-gui/res/cardsfolder/upcoming/shimmer_of_possibility.txt --- forge-gui/res/cardsfolder/upcoming/shimmer_of_possibility.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/shimmer_of_possibility.txt b/forge-gui/res/cardsfolder/upcoming/shimmer_of_possibility.txt index f554272ecf9..ab6ac18b898 100644 --- a/forge-gui/res/cardsfolder/upcoming/shimmer_of_possibility.txt +++ b/forge-gui/res/cardsfolder/upcoming/shimmer_of_possibility.txt @@ -1,5 +1,5 @@ Name:Shimmer of Possibility ManaCost:1 U Types:Sorcery -A:SP$ Dig | Cost$ 1 U | DigNum$ 4 | ChangeNum$ 1 | SpellDescription$ Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order. +A:SP$ Dig | Cost$ 1 U | DigNum$ 4 | ChangeNum$ 1 | RestRandomOrder$ True | SpellDescription$ Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order. Oracle:Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order. From f8bf8c7f28446947669ec4a0aaca38bb230dd22c Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 08:41:26 +0000 Subject: [PATCH 47/54] Update forge-gui/res/cardsfolder/upcoming/cindervines.txt --- forge-gui/res/cardsfolder/upcoming/cindervines.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/cindervines.txt b/forge-gui/res/cardsfolder/upcoming/cindervines.txt index 5d0b5133500..c323277874d 100644 --- a/forge-gui/res/cardsfolder/upcoming/cindervines.txt +++ b/forge-gui/res/cardsfolder/upcoming/cindervines.txt @@ -3,6 +3,6 @@ ManaCost:R G Types:Enchantment T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigDealOneDamage | TriggerDescription$ Whenever an opponent casts a noncreature spell, CARDNAME deals 1 damage to that player. SVar:TrigDealOneDamage:DB$DealDamage | Defined$ TriggeredActivator | NumDmg$ 1 -A:AB$ Destroy | Cost$ 1 Sac<1/CARDNAME> | ValidTgt$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | Subability$ DBDealTwoDamage | SpellDescription$ Destroy target artifact or enchantment. CARDNAME deals 2 damage to that permanent’s controller. +A:AB$ Destroy | Cost$ 1 Sac<1/CARDNAME> | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | Subability$ DBDealTwoDamage | SpellDescription$ Destroy target artifact or enchantment. CARDNAME deals 2 damage to that permanent’s controller. SVar:DBDealTwoDamage:DB$ DealDamage | Defined$ TargetedController | NumDmg$ 2 Oracle:Whenever an opponent casts a noncreature spell, Cindervines deals 1 damage to that player.\n{1}, Sacrifice Cindervines: Destroy target artifact or enchantment. Cindervines deals 2 damage to that permanent’s controller. From 1ba1226661753124552fa0544afa0a17270c997e Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Mon, 28 Jan 2019 05:53:38 -0500 Subject: [PATCH 48/54] refresh hand floating zone when hand is updated --- .../src/main/java/forge/screens/match/CMatchUI.java | 1 + 1 file changed, 1 insertion(+) diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 1e12acb4e9e..5df40f54120 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -397,6 +397,7 @@ public final class CMatchUI case Hand: updateHand = true; updateZones = true; + FloatingZone.refresh(owner, zone); break; default: updateZones = true; From 104aaa12558c70585d5eb502b0f9cae53f92a75b Mon Sep 17 00:00:00 2001 From: Agetian Date: Mon, 28 Jan 2019 15:22:06 +0300 Subject: [PATCH 49/54] - Added puzzle PS_RNA0a (RNA Prerelease Puzzle) --- forge-gui/res/puzzle/PS_RNA0a.pzl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 forge-gui/res/puzzle/PS_RNA0a.pzl diff --git a/forge-gui/res/puzzle/PS_RNA0a.pzl b/forge-gui/res/puzzle/PS_RNA0a.pzl new file mode 100644 index 00000000000..f26949aa65c --- /dev/null +++ b/forge-gui/res/puzzle/PS_RNA0a.pzl @@ -0,0 +1,17 @@ +[metadata] +Name:Possibility Storm - Ravnica Allegiance #00a (Prerelease Puzzle) +URL:http://www.possibilitystorm.com/wp-content/uploads/2019/01/097.-RNA002.jpg +Goal:Win +Turns:1 +Difficulty:Rare +Description:Win this turn. You have three other Growth-Chamber Guardians in your deck (in addition to the one in your hand). +[state] +humanlife=20 +ailife=7 +turn=1 +activeplayer=human +activephase=MAIN1 +humanhand=Grotesque Demise;Ancient Animus;Bedevil;Growth-Chamber Guardian +humanlibrary=Growth-Chamber Guardian;Growth-Chamber Guardian;Growth-Chamber Guardian +humanbattlefield=Rhythm of the Wild;Rhythm of the Wild;Piston-Fist Cyclops|NoETBTrigs;Mausoleum Harpy|NoETBTrigs;Dragon Egg|NoETBTrigs;Blood Crypt|NoETBTrigs;Blood Crypt|NoETBTrigs;Blood Crypt|NoETBTrigs;Overgrown Tomb|NoETBTrigs;Overgrown Tomb|NoETBTrigs;Overgrown Tomb|NoETBTrigs +aibattlefield=Goring Ceratops;Goblin Chainwhirler;Goblin Chainwhirler From 4b8584376dae6544051d2fcbe08f2d2e7f63ad2c Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 17:27:48 +0000 Subject: [PATCH 50/54] Update forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt --- forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt b/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt index a4e5f920e7e..90dc2bd6971 100644 --- a/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt +++ b/forge-gui/res/cardsfolder/upcoming/cavalcade_of_calamity.txt @@ -2,6 +2,6 @@ Name:Cavalcade of Calamity ManaCost:1 R Types:Enchantment T:Mode$ Attacks | ValidCard$ Creature.powerLE1+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever a creature you control with power 1 or less attacks, CARDNAME deals 1 damage to the player or planeswalker that creature is attacking -SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredAttacked | NumDmg$ 1 +SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredDefender | NumDmg$ 1 SVar:PlayMain1:TRUE Oracle:Whenever a creature you control with power 1 or less attacks, Cavalcade of Calamity deals 1 damage to the player or planeswalker that creature is attacking. From dbe212065dfef7f1c5af54fdb24185309b3861b2 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 17:44:21 +0000 Subject: [PATCH 51/54] Update forge-gui/res/cardsfolder/r/raid_bombardment.txt --- forge-gui/res/cardsfolder/r/raid_bombardment.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/r/raid_bombardment.txt b/forge-gui/res/cardsfolder/r/raid_bombardment.txt index 5cf328f2974..58fd1ccbdf2 100644 --- a/forge-gui/res/cardsfolder/r/raid_bombardment.txt +++ b/forge-gui/res/cardsfolder/r/raid_bombardment.txt @@ -2,6 +2,6 @@ Name:Raid Bombardment ManaCost:2 R Types:Enchantment T:Mode$ Attacks | ValidCard$ Creature.powerLE2+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever a creature you control with power 2 or less attacks, CARDNAME deals 1 damage to the player or planeswalker that creature is attacking -SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredAttacked | NumDmg$ 1 +SVar:TrigDamage:DB$DealDamage | Defined$ TriggeredDefender | NumDmg$ 1 SVar:PlayMain1:TRUE Oracle:Whenever a creature you control with power 2 or less attacks, Raid Bombardment deals 1 damage to the player or planeswalker that creature is attacking. From e0b463c6ea55540ef0223f7ee29491d884950328 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 18:03:00 +0000 Subject: [PATCH 52/54] Update forge-gui/res/cardsfolder/upcoming/cindervines.txt --- forge-gui/res/cardsfolder/upcoming/cindervines.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/cindervines.txt b/forge-gui/res/cardsfolder/upcoming/cindervines.txt index c323277874d..9025de38615 100644 --- a/forge-gui/res/cardsfolder/upcoming/cindervines.txt +++ b/forge-gui/res/cardsfolder/upcoming/cindervines.txt @@ -3,6 +3,6 @@ ManaCost:R G Types:Enchantment T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigDealOneDamage | TriggerDescription$ Whenever an opponent casts a noncreature spell, CARDNAME deals 1 damage to that player. SVar:TrigDealOneDamage:DB$DealDamage | Defined$ TriggeredActivator | NumDmg$ 1 -A:AB$ Destroy | Cost$ 1 Sac<1/CARDNAME> | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | Subability$ DBDealTwoDamage | SpellDescription$ Destroy target artifact or enchantment. CARDNAME deals 2 damage to that permanent’s controller. +A:AB$ Destroy | Cost$ 1 Sac<1/CARDNAME> | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SubAbility$ DBDealTwoDamage | SpellDescription$ Destroy target artifact or enchantment. CARDNAME deals 2 damage to that permanent’s controller. SVar:DBDealTwoDamage:DB$ DealDamage | Defined$ TargetedController | NumDmg$ 2 Oracle:Whenever an opponent casts a noncreature spell, Cindervines deals 1 damage to that player.\n{1}, Sacrifice Cindervines: Destroy target artifact or enchantment. Cindervines deals 2 damage to that permanent’s controller. From 5bd9f324e024d770421171c72c01644b7e257ed2 Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 18:09:35 +0000 Subject: [PATCH 53/54] Update forge-gui/res/cardsfolder/upcoming/dovins_dismissal.txt --- forge-gui/res/cardsfolder/upcoming/dovins_dismissal.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/dovins_dismissal.txt diff --git a/forge-gui/res/cardsfolder/upcoming/dovins_dismissal.txt b/forge-gui/res/cardsfolder/upcoming/dovins_dismissal.txt new file mode 100644 index 00000000000..603c0fa17af --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/dovins_dismissal.txt @@ -0,0 +1,7 @@ +Name:Dovin's Dismissal +ManaCost:2 W U +Types:Instant +A:SP$ ChangeZone | Cost$ 2 W U | ValidTgts$ Creature.tapped | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target tapped creature | Origin$ Battlefield | Destination$ Library | LibraryPosition$ 0 | SubAbility$ DBSearch | SpellDescription$ Put up to one target tapped creature on top of its owner's library. You may search your library and/or graveyard for a card named Dovin, Architect of Law, reveal it, and put it into your hand. If you search your library this way, shuffle it. +SVar:DBSearch:DB$ ChangeZone | Origin$ Library,Graveyard | Destination$ Hand | ChangeType$ Card.namedDovin; Architect of Law | ChangeNum$ 1 | Optional$ True +DeckNeeds:Name$Dovin, Architect of Law +Oracle:Put up to one target tapped creature on top of its owner’s library. You may search your library and/or graveyard for a card named Dovin, Architect of Law, reveal it, and put it into your hand. If you search your library this way, shuffle it. From d8da15d8aef1259e536d7c30409945ca2716905f Mon Sep 17 00:00:00 2001 From: "T.J. Tillman" Date: Mon, 28 Jan 2019 19:58:23 +0000 Subject: [PATCH 54/54] Update forge-gui/res/cardsfolder/upcoming/dovin_architect_of_law.txt --- .../cardsfolder/upcoming/dovin_architect_of_law.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/dovin_architect_of_law.txt diff --git a/forge-gui/res/cardsfolder/upcoming/dovin_architect_of_law.txt b/forge-gui/res/cardsfolder/upcoming/dovin_architect_of_law.txt new file mode 100644 index 00000000000..cd0a8f42060 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/dovin_architect_of_law.txt @@ -0,0 +1,11 @@ +Name:Dovin, Architect of Law +ManaCost:4 W U +Types:Legendary Planeswalker Dovin +Loyalty:5 +A:AB$ GainLife | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Defined$ You | LifeAmount$ 2 | SubAbility$ DBDraw | SpellDescription$ You gain 2 life and draw a card. +SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 +A:AB$ Tap | Cost$ SubCounter<1/LOYALTY> | ValidTgts$ Creature | TgtPrompt$ Choose target creature to tap. | Planeswalker$ True | SubAbility$ DovinPump | SpellDescription$ Tap target creature. It doesn't untap during its controller's next untap step. +SVar:DovinPump:DB$ Pump | Defined$ Targeted | Permanent$ True | KW$ HIDDEN This card doesn't untap during your next untap step. +A:AB$ TapAll | Cost$ SubCounter<9/LOYALTY> | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | ValidCards$ Permanent | Planeswalker$ True | SubAbility$ NoUntap | SpellDescription$ Tap all permanents target opponent controls. That player skips their next untap step. +SVar:NoUntap:DB$ Pump | Defined$ TargetedPlayer | IsCurse$ True | KW$ Skip your next untap step. | Permanent$ True +Oracle:+1: You gain 2 life and draw a card.\n−1: Tap target creature. It doesn’t untap during its controller’s next untap step.\n−9: Tap all permanents target opponent controls. That player skips their next untap step.