From 0bc50c313c6e84398d32532cb1abb290cb85ed7c Mon Sep 17 00:00:00 2001 From: paulsnoops Date: Fri, 6 Jan 2023 08:49:04 +0000 Subject: [PATCH 01/37] Formats update: Add DMR --- forge-gui/res/formats/Archived/Legacy/2023-01-13.txt | 8 ++++++++ forge-gui/res/formats/Archived/Vintage/2023-01-13.txt | 9 +++++++++ forge-gui/res/formats/Sanctioned/Legacy.txt | 2 +- forge-gui/res/formats/Sanctioned/Vintage.txt | 2 +- 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 forge-gui/res/formats/Archived/Legacy/2023-01-13.txt create mode 100644 forge-gui/res/formats/Archived/Vintage/2023-01-13.txt diff --git a/forge-gui/res/formats/Archived/Legacy/2023-01-13.txt b/forge-gui/res/formats/Archived/Legacy/2023-01-13.txt new file mode 100644 index 00000000000..333b95ab4fc --- /dev/null +++ b/forge-gui/res/formats/Archived/Legacy/2023-01-13.txt @@ -0,0 +1,8 @@ +[format] +Name:Legacy (DMR) +Type:Archived +Subtype:Legacy +Effective:2023-01-13 +Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, HOU, C17, XLN, DDT, IMA, V17, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD, DMR +Banned:Advantageous Proclamation; Adriana's Valor; Amulet of Quoz; Ancestral Recall; Arcum's Astrolabe; Assemble the Rank and Vile; Backup Plan; Balance; Bazaar of Baghdad; Black Lotus; Brago's Favor; Bronze Tablet; Channel; Chaos Orb; Cleanse; Contract from Below; Crusade; Darkpact; Deathrite Shaman; Demonic Attorney; Demonic Consultation; Demonic Tutor; Dig Through Time; Double Stroke; Dreadhorde Arcanist; Earthcraft; Echoing Boon; Emissary's Ploy; Falling Star; Fastbond; Flash; Frantic Search; Gitaxian Probe; Goblin Recruiter; Gush; Hermit Druid; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Imperial Seal; Imprison; Incendiary Dissent; Invoke Prejudice; Iterative Analysis; Jeweled Bird; Jihad; Library of Alexandria; Lurrus of the Dream-Den; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Mind's Desire; Mishra's Workshop; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Muzzio's Preparations; Mystical Tutor; Natural Unity; Necropotence; Oath of Druids; Oko, Thief of Crowns; Power Play; Pradesh Gypsies; Ragavan, Nimble Pilferer; Rebirth; Secret Summoning; Secrets of Paradise; Sensei's Divining Top; Sentinel Dispatch; Shahrazad; Skullclamp; Sol Ring; Sovereign's Realm; Stone-Throwing Devils; Strip Mine; Summoner's Bond; Survival of the Fittest; Tempest Efreet; Time Vault; Time Walk; Timetwister; Timmerian Fiends; Tinker; Tolarian Academy; Treasure Cruise; Underworld Breach; Unexpected Potential; Vampiric Tutor; Weight Advantage; Wheel of Fortune; Windfall; Worldknit; Wrenn and Six; Yawgmoth's Bargain; Yawgmoth's Will; Zirda, the Dawnwaker +Additional:Arvinox, the Mind Flail; Blanka, Ferocious Friend; Bjorna, Nightfall Alchemist; Cecily, Haunted Mage; Chief Jim Hopper; Chun-Li, Countless Kicks; Daryl, Hunter of Walkers; Dhalsim, Pliable Pacifist; Dustin, Gadget Genius; E. Honda, Sumo Champion; Eleven, the Mage; Elmar, Ulvenwald Informant; Glenn, the Voice of Calm; Guile, Sonic Soldier; Hargilde, Kindly Runechanter; Havengul Laboratory; Ken, Burning Brawler; Lucas, the Sharpshooter; Max, the Daredevil; Michonne, Ruthless Survivor; Mike, the Dungeon Master; Mind Flayer, the Shadow; Negan, the Cold-Blooded; Othelm, Sigardian Outcast; Rick, Steadfast Leader; Ryu, World Warrior; Sophina, Spearsage Deserter; Wernog, Rider's Chaplain; Will the Wise; Zangief, the Red Cyclone diff --git a/forge-gui/res/formats/Archived/Vintage/2023-01-13.txt b/forge-gui/res/formats/Archived/Vintage/2023-01-13.txt new file mode 100644 index 00000000000..343a0caeff6 --- /dev/null +++ b/forge-gui/res/formats/Archived/Vintage/2023-01-13.txt @@ -0,0 +1,9 @@ +[format] +Name:Vintage (DMR) +Type:Archived +Subtype:Vintage +Effective:2023-01-13 +Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, HOU, C17, XLN, DDT, IMA, V17, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD, DMR +Restricted:Ancestral Recall; Balance; Black Lotus; Brainstorm; Chalice of the Void; Channel; Demonic Consultation; Demonic Tutor; Dig Through Time; Flash; Gitaxian Probe; Golgari Grave-Troll; Gush; Imperial Seal; Karn, the Great Creator; Library of Alexandria; Lion's Eye Diamond; Lodestone Golem; Lotus Petal; Mana Crypt; Mana Vault; Memory Jar; Mental Misstep; Merchant Scroll; Mind's Desire; Monastery Mentor; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystic Forge; Mystical Tutor; Narset, Parter of Veils; Necropotence; Ponder; Sol Ring; Strip Mine; Thorn of Amethyst; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Trinisphere; Vampiric Tutor; Wheel of Fortune; Windfall; Yawgmoth's Will +Banned:Adriana's Valor; Advantageous Proclamation; Amulet of Quoz; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Bronze Tablet; Chaos Orb; Cleanse; Contract from Below; Crusade; Darkpact; Demonic Attorney; Double Stroke; Echoing Boon; Emissary's Ploy; Falling Star; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Imprison; Incendiary Dissent; Invoke Prejudice; Iterative Analysis; Jeweled Bird; Jihad; Muzzio's Preparations; Natural Unity; Power Play; Pradesh Gypsies; Rebirth; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Shahrazad; Sovereign's Realm; Stone-Throwing Devils; Summoner's Bond; Tempest Efreet; Timmerian Fiends; Unexpected Potential; Weight Advantage; Worldknit +Additional:Arvinox, the Mind Flail; Blanka, Ferocious Friend; Bjorna, Nightfall Alchemist; Cecily, Haunted Mage; Chief Jim Hopper; Chun-Li, Countless Kicks; Daryl, Hunter of Walkers; Dhalsim, Pliable Pacifist; Dustin, Gadget Genius; E. Honda, Sumo Champion; Eleven, the Mage; Elmar, Ulvenwald Informant; Glenn, the Voice of Calm; Guile, Sonic Soldier; Hargilde, Kindly Runechanter; Havengul Laboratory; Ken, Burning Brawler; Lucas, the Sharpshooter; Max, the Daredevil; Michonne, Ruthless Survivor; Mike, the Dungeon Master; Mind Flayer, the Shadow; Negan, the Cold-Blooded; Othelm, Sigardian Outcast; Rick, Steadfast Leader; Ryu, World Warrior; Sophina, Spearsage Deserter; Wernog, Rider's Chaplain; Will the Wise; Zangief, the Red Cyclone diff --git a/forge-gui/res/formats/Sanctioned/Legacy.txt b/forge-gui/res/formats/Sanctioned/Legacy.txt index d4417bd86d0..d4bb3870224 100644 --- a/forge-gui/res/formats/Sanctioned/Legacy.txt +++ b/forge-gui/res/formats/Sanctioned/Legacy.txt @@ -3,5 +3,5 @@ Name:Legacy Order:105 Subtype:Legacy Type:Sanctioned -Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, HOU, C17, XLN, DDT, IMA, V17, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, SLD, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, SLX, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD +Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, HOU, C17, XLN, DDT, IMA, V17, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, SLD, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, SLX, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD, DMR Banned:Advantageous Proclamation; Adriana's Valor; Amulet of Quoz; Ancestral Recall; Arcum's Astrolabe; Assemble the Rank and Vile; Backup Plan; Balance; Bazaar of Baghdad; Black Lotus; Brago's Favor; Bronze Tablet; Channel; Chaos Orb; Cleanse; Contract from Below; Crusade; Darkpact; Deathrite Shaman; Demonic Attorney; Demonic Consultation; Demonic Tutor; Dig Through Time; Double Stroke; Dreadhorde Arcanist; Earthcraft; Echoing Boon; Emissary's Ploy; Falling Star; Fastbond; Flash; Frantic Search; Gitaxian Probe; Goblin Recruiter; Gush; Hermit Druid; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Imperial Seal; Imprison; Incendiary Dissent; Invoke Prejudice; Iterative Analysis; Jeweled Bird; Jihad; Library of Alexandria; Lurrus of the Dream-Den; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Mind's Desire; Mishra's Workshop; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Muzzio's Preparations; Mystical Tutor; Natural Unity; Necropotence; Oath of Druids; Oko, Thief of Crowns; Power Play; Pradesh Gypsies; Ragavan, Nimble Pilferer; Rebirth; Secret Summoning; Secrets of Paradise; Sensei's Divining Top; Sentinel Dispatch; Shahrazad; Skullclamp; Sol Ring; Sovereign's Realm; Stone-Throwing Devils; Strip Mine; Summoner's Bond; Survival of the Fittest; Tempest Efreet; Time Vault; Time Walk; Timetwister; Timmerian Fiends; Tinker; Tolarian Academy; Treasure Cruise; Underworld Breach; Unexpected Potential; Vampiric Tutor; Weight Advantage; Wheel of Fortune; Windfall; Worldknit; Wrenn and Six; Yawgmoth's Bargain; Yawgmoth's Will; Zirda, the Dawnwaker diff --git a/forge-gui/res/formats/Sanctioned/Vintage.txt b/forge-gui/res/formats/Sanctioned/Vintage.txt index 2c9ffdb5309..718514b02d3 100644 --- a/forge-gui/res/formats/Sanctioned/Vintage.txt +++ b/forge-gui/res/formats/Sanctioned/Vintage.txt @@ -3,6 +3,6 @@ Name:Vintage Order:104 Subtype:Vintage Type:Sanctioned -Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, HOU, C17, XLN, DDT, IMA, V17, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, SLD, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, SLX, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD +Sets:LEA, LEB, 2ED, ARN, ATQ, 3ED, LEG, DRC94, DRK, PHPR, FEM, 4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, POR, WTH, TMP, STH, EXO, PO2, USG, ATH, ULG, 6ED, UDS, S99, PTK, MMQ, BRB, NMS, S00, PCY, BTD, INV, PLS, 7ED, APC, ODY, DKM, TOR, JUD, ONS, LGN, SCG, 8ED, MRD, DST, 5DN, CHK, BOK, SOK, 9ED, RAV, GPT, DIS, CSP, TSP, TSB, PLC, FUT, 10E, MED, LRW, DD1, MOR, SHM, EVE, DRB, ME2, ALA, DD2, CFX, DDC, ARB, M10, TD0, FVE, ME3, ZEN, DDD, PDS, WWK, DDE, ROE, DPA, M11, FVR, DDF, SOM, TD1, PD2, ME4, MBS, DDG, NPH, TD2, COM, M12, FVL, DDH, ISD, PD3, DKA, DDI, AVR, M13, V12, DDJ, RTR, CM1, GTC, DDK, DGM, MMA, M14, V13, DDL, THS, C13, BNG, DDM, JOU, MD1, CNS, VMA, M15, V14, DDN, KTK, C14, DVD, EVG, GVL, JVC, FRF, UGF, DDO, DTK, TPR, MM2, ORI, V15, DDP, BFZ, EXP, C15, PZ1, OGW, DDQ, SOI, W16, EMA, EMN, V16, CN2, DDR, KLD, MPS_KLD, C16, PZ2, AER, MM3, DDS, AKH, MPS_AKH, W17, CMA, HOU, C17, XLN, DDT, IMA, V17, RIX, A25, DDU, DOM, CM2, BBD, SS1, GS1, M19, C18, GRN, MPS_GRN, GK1, G18, GNT, UMA, RNA, MPS_RNA, GK2, WAR, MPS_WAR, MH1, SS2, M20, C19, ELD, MB1, GN2, SLD, THB, IKO, C20, SS3, M21, JMP, 2XM, ZNR, ZNE, ZNC, CMR, CC1, KHM, KHC, TSR, STX, STA, C21, MH2, H1R, AFR, AFC, MID, MIC, VOW, VOC, DBL, CC2, NEO, NEC, SNC, NCC, SLX, CLB, 2X2, DMU, DMC, 40K, UNF, GN3, BRO, BRC, BRR, BOT, J22, SCD, DMR Restricted:Ancestral Recall; Balance; Black Lotus; Brainstorm; Chalice of the Void; Channel; Demonic Consultation; Demonic Tutor; Dig Through Time; Flash; Gitaxian Probe; Golgari Grave-Troll; Gush; Imperial Seal; Karn, the Great Creator; Library of Alexandria; Lion's Eye Diamond; Lodestone Golem; Lotus Petal; Mana Crypt; Mana Vault; Memory Jar; Mental Misstep; Merchant Scroll; Mind's Desire; Monastery Mentor; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystic Forge; Mystical Tutor; Narset, Parter of Veils; Necropotence; Ponder; Sol Ring; Strip Mine; Thorn of Amethyst; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Trinisphere; Vampiric Tutor; Wheel of Fortune; Windfall; Yawgmoth's Will Banned:Adriana's Valor; Advantageous Proclamation; Amulet of Quoz; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Bronze Tablet; Chaos Orb; Cleanse; Contract from Below; Crusade; Darkpact; Demonic Attorney; Double Stroke; Echoing Boon; Emissary's Ploy; Falling Star; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Imprison; Incendiary Dissent; Invoke Prejudice; Iterative Analysis; Jeweled Bird; Jihad; Muzzio's Preparations; Natural Unity; Power Play; Pradesh Gypsies; Rebirth; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Shahrazad; Sovereign's Realm; Stone-Throwing Devils; Summoner's Bond; Tempest Efreet; Timmerian Fiends; Unexpected Potential; Weight Advantage; Worldknit From 70a062afd3c5735761f0f7769c7cee83ab841141 Mon Sep 17 00:00:00 2001 From: paulsnoops Date: Fri, 6 Jan 2023 09:08:00 +0000 Subject: [PATCH 02/37] Edition update: PH21 --- forge-gui/res/editions/2021 Heroes of the Realm.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/forge-gui/res/editions/2021 Heroes of the Realm.txt b/forge-gui/res/editions/2021 Heroes of the Realm.txt index 95f6cfe360d..a3ed44fe505 100644 --- a/forge-gui/res/editions/2021 Heroes of the Realm.txt +++ b/forge-gui/res/editions/2021 Heroes of the Realm.txt @@ -7,5 +7,6 @@ ScryfallCode=PH21 [cards] 1 M Andrios, Roaming Explorer @Borja Pindado +2 M Arteeoh, Dread Scavenger @Zoltan Boros 3 M Byode, Inverse Sun @Dominik Mayer 4 M Ersta, Friend to All @Winona Nelson From 794fc11ab16763203672da0812f24eab5e33e4c3 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Fri, 6 Jan 2023 22:17:38 +0100 Subject: [PATCH 03/37] Rework UntilHostLeavesPlay timing --- .../src/main/java/forge/game/GameAction.java | 27 ++++++++++--------- .../game/zone/PlayerZoneBattlefield.java | 10 ------- forge-gui/res/cardsfolder/a/animate_dead.txt | 2 +- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index df67f6bf4c6..a51816f5ff4 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -579,6 +579,12 @@ public class GameAction { c.setZone(zoneTo); } + if (fromBattlefield) { + // order here is important so it doesn't unattach cards that might have returned from UntilHostLeavesPlay + unattachCardLeavingBattlefield(copied); + c.runLeavesPlayCommands(); + } + // do ETB counters after zone add if (!suppress && toBattlefield && !copied.getEtbCounters().isEmpty()) { game.getTriggerHandler().registerActiveTrigger(copied, false); @@ -706,7 +712,6 @@ public class GameAction { copied.setState(CardStateName.Original, true); } - unattachCardLeavingBattlefield(copied); } else if (toBattlefield) { for (Player p : game.getPlayers()) { copied.getDamageHistory().setNotAttackedSinceLastUpkeepOf(p); @@ -982,9 +987,15 @@ public class GameAction { if (c.isInZone(ZoneType.Stack)) { c.getGame().getStack().remove(c); } + + final Zone z = c.getZone(); // in some corner cases there's no zone yet (copied spell that failed targeting) - if (c.getZone() != null) { - c.getZone().remove(c); + if (z != null) { + z.remove(c); + if (z.is(ZoneType.Battlefield)) { + c.runLeavesPlayCommands(); + } + } // CR 603.6c other players LTB triggers should work @@ -1045,20 +1056,13 @@ public class GameAction { } game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - for (Player p : game.getPlayers()) { - ((PlayerZoneBattlefield) p.getZone(ZoneType.Battlefield)).setTriggers(false); - } - - final int tiz = c.getTurnInZone(); oldBattlefield.remove(c); newBattlefield.add(c); - c.setSickness(true); if (game.getPhaseHandler().inCombat()) { game.getCombat().removeFromCombat(c); } - c.setTurnInZone(tiz); c.setCameUnderControlSinceLastUpkeep(true); final Map runParams = AbilityKey.mapFromCard(c); @@ -1066,9 +1070,6 @@ public class GameAction { game.getTriggerHandler().runTrigger(TriggerType.ChangesController, runParams, false); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); - for (Player p : game.getPlayers()) { - ((PlayerZoneBattlefield) p.getZone(ZoneType.Battlefield)).setTriggers(true); - } c.runChangeControllerCommands(); } diff --git a/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java b/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java index 4bbddf21e57..8011a36b88a 100644 --- a/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java +++ b/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java @@ -65,16 +65,6 @@ public class PlayerZoneBattlefield extends PlayerZone { } } - /** {@inheritDoc} */ - @Override - public final void remove(final Card c) { - super.remove(c); - - if (trigger) { - c.runLeavesPlayCommands(); - } - } - public final void setTriggers(final boolean b) { trigger = b; } diff --git a/forge-gui/res/cardsfolder/a/animate_dead.txt b/forge-gui/res/cardsfolder/a/animate_dead.txt index 378e22d60dc..c4d9b77523b 100644 --- a/forge-gui/res/cardsfolder/a/animate_dead.txt +++ b/forge-gui/res/cardsfolder/a/animate_dead.txt @@ -8,7 +8,7 @@ SVar:TrigReanimate:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield SVar:DBAnimate:DB$ Animate | Defined$ Self | OverwriteSpells$ True | Abilities$ NewAttach | Keywords$ Enchant creature put onto the battlefield with CARDNAME | RemoveKeywords$ Enchant creature card in a graveyard | Duration$ Permanent | SubAbility$ DBAttach SVar:DBAttach:DB$ Attach | Defined$ Remembered SVar:NewAttach:SP$ Attach | Cost$ 1 B | ValidTgts$ Creature.IsRemembered | AILogic$ Pump -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigSacrifice | TriggerDescription$ When Animate Dead leaves the battlefield, that creature's controller sacrifices it. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigSacrifice | TriggerDescription$ When CARDNAME leaves the battlefield, that creature's controller sacrifices it. SVar:TrigSacrifice:DB$ Destroy | Sacrifice$ True | Defined$ DirectRemembered | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ -1 | Description$ Enchanted creature gets -1/-0. From c23bf249f5f5e063b4b9410d62395f66ad2ac3f3 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Fri, 6 Jan 2023 22:57:52 +0100 Subject: [PATCH 04/37] Trigger fix --- forge-game/src/main/java/forge/game/zone/MagicStack.java | 2 +- forge-gui/res/cardsfolder/a/animate_dead.txt | 9 +++++---- forge-gui/res/cardsfolder/d/dance_of_the_dead.txt | 9 +++++---- forge-gui/res/cardsfolder/n/necromancy.txt | 9 +++++---- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index 857b7d5b0d4..4f26ab23c1f 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -857,7 +857,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable Date: Sat, 7 Jan 2023 13:34:12 +0100 Subject: [PATCH 05/37] update --- .../res/cardsfolder/upcoming/argentum_masticore.txt | 13 +++++++++++++ .../upcoming/kethek_crucible_goliath.txt | 9 +++++++++ .../cardsfolder/upcoming/migloz_maze_crusher.txt | 10 ++++++++++ .../cardsfolder/upcoming/mindsplice_apparatus.txt | 11 +++++++++++ .../res/cardsfolder/upcoming/zenith_chronicler.txt | 7 +++++++ 5 files changed, 50 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/kethek_crucible_goliath.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt diff --git a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt new file mode 100644 index 00000000000..b48cc1e5c6a --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt @@ -0,0 +1,13 @@ +Name:Argentum Masticore +ManaCost:5 +Types:Artifact Creature Phyrexian Masticore +PT:5/5 +K:First strike +K:Protection:Card.MultiColor:Protection from multicolored +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you discard a card. When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. +SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | SubAbility$ TrigImmediateTrig +SVar:TrigImmediateTrig:DB$ ImmediateTrigger | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card +SVar:X:Discarded$CardManaCost +DeckHas:Ability$Discard|Sacrifice +Oracle:First strike, protection from multicolored\nAt the beginning of your upkeep, sacrifice Argentum Masticore unless you discard a card\nWhen you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/kethek_crucible_goliath.txt b/forge-gui/res/cardsfolder/upcoming/kethek_crucible_goliath.txt new file mode 100644 index 00000000000..ce0048c32a0 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/kethek_crucible_goliath.txt @@ -0,0 +1,9 @@ +Name:Kethek, Crucible Goliath +ManaCost:2 R B +Types:Legendary Creature Phyrexian Beast +PT:4/4 +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your end step, you may sacrifice another creature. If you do, reveal cards from the top of your library until you reveal a nonlegendary creature card with lesser mana value, put it onto the battlefield, then put the rest on the bottom of your library in a random order. +SVar:TrigSac:AB$ DigUntil | Cost$ Sac<1/Creature.Other/another creature> | Defined$ You | Valid$ Card.Creature+nonLegendary+cmcLTX | FoundDestination$ Battlefield | RevealedDestination$ Library | RestRandomOrder$ True +SVar:X:Sacrificed$CardManaCost +DeckHas:Ability$Sacrifice +Oracle:At the beginning of your end step, you may sacrifice another creature. If you do, reveal cards from the top of your library until you reveal a nonlegendary creature card with lesser mana value, put it onto the battlefield, then put the rest on the bottom of your library in a random order. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt b/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt new file mode 100644 index 00000000000..3564563ac96 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt @@ -0,0 +1,10 @@ +Name:Migloz, Maze Crusher +ManaCost:1 R G +Types:Legendary Creature Phyrexian Beast +PT:4/4 +K:etbCounter:OIL:5 +A:AB$ Pump | Cost$ 1 SubCounter<1/OIL> | Defined$ Self | KW$ Vigilance & Menace | SpellDescription$ It gains vigilance and menace until end of turn. +A:AB$ Pump | Cost$ 2 SubCounter<2/OIL> | Defined$ Self | NumAtt$ 2 | NumDef$ 2 | SpellDescription$ It gets +2/+2 until end of turn. +A:AB$ Destroy | Cost$ 3 SubCounter<3/OIL> | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. +DeckHas:Ability$Counters +Oracle:Migloz, Maze Crusher enters the battlefield with five oil counters on it.\n{1}, Remove an oil counter from Migloz: It gains vigilance and menace until end of turn.\n{2}, Remove two oil counters from Migloz: It gets +2/+2 until end of turn.\n{3}, Remove three oil counters from Migloz: Destroy target artifact or enchantment. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt b/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt new file mode 100644 index 00000000000..aa42080bf7d --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt @@ -0,0 +1,11 @@ +Name:Mindsplice Apparatus +ManaCost:3 U +Types:Artifact +K:Flash +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCounter | TriggerDescription$ At the beginning of your upkeep, put an oil counter on CARDNAME. +SVar:TrigCounter:DB$ PutCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1 +S:Mode$ ReduceCost | ValidCard$ Instant,Sorcery | Type$ Spell | Activator$ You | Amount$ X | Description$ Instant and sorcery spells you cast cost 1 less to cast for each oil counter on CARDNAME. +SVar:X:Count$CardCounters.OIL +DeckHas:Ability$Counters +DeckHints:Type$Instant|Sorcery +Oracle:At the beginning of your upkeep, put an oil counter on Mindsplice Apparatus.\nInstant and sorcery spells you cast cost 1 less to cast for each oil counter on Mindsplice Apparatus. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt b/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt new file mode 100644 index 00000000000..e3a9237a46f --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt @@ -0,0 +1,7 @@ +Name:Zenith Chronicler +ManaCost:2 +Types:Artifact Creature Phyrexian Construct +PT:3/1 +T:Mode$ SpellCast | ValidCard$ Card.MultiColor | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | Execute$ TrigDraw | TriggerDescription$ Whenever a player casts their first multicolored spell each turn, each other player draws a card. +SVar:TrigDraw:DB$ Draw | Defined$ TriggeredCardOpponent +Oracle:Whenever a player casts their first multicolored spell each turn, each other player draws a card. \ No newline at end of file From 960b2531a3130a400f88a23740214ea155197ec9 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Sat, 7 Jan 2023 14:17:25 +0100 Subject: [PATCH 06/37] update --- .../res/cardsfolder/upcoming/argentum_masticore.txt | 9 +++++---- .../res/cardsfolder/upcoming/mindsplice_apparatus.txt | 2 +- forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt index b48cc1e5c6a..9586ddfb88d 100644 --- a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt +++ b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt @@ -5,9 +5,10 @@ PT:5/5 K:First strike K:Protection:Card.MultiColor:Protection from multicolored T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you discard a card. When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. -SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | SubAbility$ TrigImmediateTrig -SVar:TrigImmediateTrig:DB$ ImmediateTrigger | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. -SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card -SVar:X:Discarded$CardManaCost +SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | RememberObjects$ Discarded | SubAbility$ TrigImmediateTrig +SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:TriggeredRemembered$CardManaCost DeckHas:Ability$Discard|Sacrifice Oracle:First strike, protection from multicolored\nAt the beginning of your upkeep, sacrifice Argentum Masticore unless you discard a card\nWhen you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt b/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt index aa42080bf7d..a35114952b8 100644 --- a/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt +++ b/forge-gui/res/cardsfolder/upcoming/mindsplice_apparatus.txt @@ -8,4 +8,4 @@ S:Mode$ ReduceCost | ValidCard$ Instant,Sorcery | Type$ Spell | Activator$ You | SVar:X:Count$CardCounters.OIL DeckHas:Ability$Counters DeckHints:Type$Instant|Sorcery -Oracle:At the beginning of your upkeep, put an oil counter on Mindsplice Apparatus.\nInstant and sorcery spells you cast cost 1 less to cast for each oil counter on Mindsplice Apparatus. \ No newline at end of file +Oracle:Flash\nAt the beginning of your upkeep, put an oil counter on Mindsplice Apparatus.\nInstant and sorcery spells you cast cost 1 less to cast for each oil counter on Mindsplice Apparatus. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt b/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt index e3a9237a46f..1c71f96b130 100644 --- a/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt +++ b/forge-gui/res/cardsfolder/upcoming/zenith_chronicler.txt @@ -3,5 +3,5 @@ ManaCost:2 Types:Artifact Creature Phyrexian Construct PT:3/1 T:Mode$ SpellCast | ValidCard$ Card.MultiColor | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | Execute$ TrigDraw | TriggerDescription$ Whenever a player casts their first multicolored spell each turn, each other player draws a card. -SVar:TrigDraw:DB$ Draw | Defined$ TriggeredCardOpponent +SVar:TrigDraw:DB$ Draw | Defined$ NonTriggeredCardController Oracle:Whenever a player casts their first multicolored spell each turn, each other player draws a card. \ No newline at end of file From c88caf6dbf0aba25ef9bb66a6dbde50c4d0a5fec Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Sat, 7 Jan 2023 14:21:29 +0100 Subject: [PATCH 07/37] Update argentum_masticore.txt --- forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt index 9586ddfb88d..837bce62865 100644 --- a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt +++ b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt @@ -5,8 +5,8 @@ PT:5/5 K:First strike K:Protection:Card.MultiColor:Protection from multicolored T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you discard a card. When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. -SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | RememberObjects$ Discarded | SubAbility$ TrigImmediateTrig -SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. +SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | SubAbility$ TrigImmediateTrig +SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | RememberObjects$ Discarded | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:TriggeredRemembered$CardManaCost From 2ee9d3f355d2d3bb38f53165b0e20fc9a8bc1100 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Sat, 7 Jan 2023 14:32:44 +0100 Subject: [PATCH 08/37] Update argentum_masticore.txt --- forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt index 837bce62865..0ec4b698fc3 100644 --- a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt +++ b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt @@ -5,10 +5,9 @@ PT:5/5 K:First strike K:Protection:Card.MultiColor:Protection from multicolored T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you discard a card. When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. -SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | SubAbility$ TrigImmediateTrig +SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | RememberObjects$ Discarded | SubAbility$ TrigImmediateTrig SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | RememberObjects$ Discarded | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. -SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:TriggeredRemembered$CardManaCost +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card +SVar:X:TriggerRemembered$CardManaCost DeckHas:Ability$Discard|Sacrifice Oracle:First strike, protection from multicolored\nAt the beginning of your upkeep, sacrifice Argentum Masticore unless you discard a card\nWhen you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. \ No newline at end of file From faf0f3f1fd5de4d81dc4eee635ffebccd84af89b Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:31:30 +0100 Subject: [PATCH 09/37] PH21 Arteeoh, Dread Scaveneger (#2211) * Create arteeoh_dread_scavenger.txt * Update arteeoh_dread_scavenger.txt * Update arteeoh_dread_scavenger.txt * Update arteeoh_dread_scavenger.txt * Update arteeoh_dread_scavenger.txt * Update arteeoh_dread_scavenger.txt * Update arteeoh_dread_scavenger.txt --- .../upcoming/arteeoh_dread_scavenger.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/arteeoh_dread_scavenger.txt diff --git a/forge-gui/res/cardsfolder/upcoming/arteeoh_dread_scavenger.txt b/forge-gui/res/cardsfolder/upcoming/arteeoh_dread_scavenger.txt new file mode 100644 index 00000000000..3171f634429 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/arteeoh_dread_scavenger.txt @@ -0,0 +1,14 @@ +Name:Arteeoh, Dread Scavenger +ManaCost:1 B G U +Types:Legendary Artifact Creature Robot +PT:3/3 +K:Flying +K:Deathtouch +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigExchange | TriggerDescription$ Whenever NICKNAME deals combat damage to a player, you may exchange control of two other target artifacts. When you do, create a token that's a copy of target artifact you don't control, except it's a 1/1 green Squirrel creature token in addition to its other colors and types. +SVar:TrigExchange:DB$ ExchangeControl | RememberExchanged$ True | ValidTgts$ Artifact.Other | TargetMin$ 2 | TargetMax$ 2 | TgtPrompt$ Choose two other target artifacts | Optional$ True | AILogic$ TrigTwoTargets | SubAbility$ TrigImmediateTrig +SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE2 | SubAbility$ DBCleanup | Execute$ TrigToken | TriggerDescription$ When you do, create a token that's a copy of target artifact you don't control, except it's a 1/1 green Squirrel creature token in addition to its other colors and types. +SVar:TrigToken:DB$ CopyPermanent | ValidTgts$ Artifact.YouDontCtrl | TgtPrompt$ Select target artifact you don't control | SetPower$ 1 | SetToughness$ 1 | AddColors$ Green | AddTypes$ Creature & Squirrel +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +DeckHas:Ability$Token & Type$Squirrel +AI:RemoveDeck:Random +Oracle:Flying, deathtouch\nWhenever Arteeoh deals combat damage to a player, you may exchange control of two other target artifacts. When you do, create a token that's a copy of target artifact you don't control, except it's a 1/1 green Squirrel creature token in addition to its other colors and types. From 4432de4df0754177b37a19549d5051250deede88 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Sat, 7 Jan 2023 15:41:34 +0100 Subject: [PATCH 10/37] Update migloz_maze_crusher.txt --- .../res/cardsfolder/upcoming/migloz_maze_crusher.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt b/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt index 3564563ac96..c0547163bfc 100644 --- a/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt +++ b/forge-gui/res/cardsfolder/upcoming/migloz_maze_crusher.txt @@ -3,8 +3,8 @@ ManaCost:1 R G Types:Legendary Creature Phyrexian Beast PT:4/4 K:etbCounter:OIL:5 -A:AB$ Pump | Cost$ 1 SubCounter<1/OIL> | Defined$ Self | KW$ Vigilance & Menace | SpellDescription$ It gains vigilance and menace until end of turn. -A:AB$ Pump | Cost$ 2 SubCounter<2/OIL> | Defined$ Self | NumAtt$ 2 | NumDef$ 2 | SpellDescription$ It gets +2/+2 until end of turn. -A:AB$ Destroy | Cost$ 3 SubCounter<3/OIL> | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. +A:AB$ Pump | Cost$ 1 SubCounter<1/OIL/NICKNAME> | Defined$ Self | KW$ Vigilance & Menace | SpellDescription$ It gains vigilance and menace until end of turn. +A:AB$ Pump | Cost$ 2 SubCounter<2/OIL/NICKNAME> | Defined$ Self | NumAtt$ 2 | NumDef$ 2 | SpellDescription$ It gets +2/+2 until end of turn. +A:AB$ Destroy | Cost$ 3 SubCounter<3/OIL/NICKNAME> | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. DeckHas:Ability$Counters -Oracle:Migloz, Maze Crusher enters the battlefield with five oil counters on it.\n{1}, Remove an oil counter from Migloz: It gains vigilance and menace until end of turn.\n{2}, Remove two oil counters from Migloz: It gets +2/+2 until end of turn.\n{3}, Remove three oil counters from Migloz: Destroy target artifact or enchantment. \ No newline at end of file +Oracle:Migloz, Maze Crusher enters the battlefield with five oil counters on it.\n{1}, Remove an oil counter from Migloz: It gains vigilance and menace until end of turn.\n{2}, Remove two oil counters from Migloz: It gets +2/+2 until end of turn.\n{3}, Remove three oil counters from Migloz: Destroy target artifact or enchantment. From 87c79300d9c4fb095f3a4fcb9170d2d2854066fc Mon Sep 17 00:00:00 2001 From: tool4ever Date: Sat, 7 Jan 2023 16:41:11 +0000 Subject: [PATCH 11/37] Update argentum_masticore.txt --- forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt index 0ec4b698fc3..d74028da427 100644 --- a/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt +++ b/forge-gui/res/cardsfolder/upcoming/argentum_masticore.txt @@ -5,9 +5,9 @@ PT:5/5 K:First strike K:Protection:Card.MultiColor:Protection from multicolored T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you discard a card. When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. -SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice {c:Self}. | RememberObjects$ Discarded | SubAbility$ TrigImmediateTrig -SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | RememberObjects$ Discarded | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. +SVar:TrigSacrifice:DB$ Sacrifice | UnlessCost$ Discard<1/Card> | UnlessPayer$ You | OrString$ Sacrifice it. | SubAbility$ TrigImmediateTrig +SVar:TrigImmediateTrig:DB$ ImmediateTrigger | ConditionDefined$ Discarded | ConditionPresent$ Card | ConditionCompare$ GE1 | RememberObjects$ Discarded | Execute$ TrigDestroy | TriggerDescription$ When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent.nonLand+cmcLEX+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls with mana value less or equal to the discarded card SVar:X:TriggerRemembered$CardManaCost DeckHas:Ability$Discard|Sacrifice -Oracle:First strike, protection from multicolored\nAt the beginning of your upkeep, sacrifice Argentum Masticore unless you discard a card\nWhen you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. \ No newline at end of file +Oracle:First strike, protection from multicolored\nAt the beginning of your upkeep, sacrifice Argentum Masticore unless you discard a card. When you discard a card this way, destroy target nonland permanent an opponent controls with mana value less than or equal to the mana value of the discarded card. From fb3f14db7153cdec9eac0276cc73117b8ca51918 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sun, 8 Jan 2023 21:13:58 +0100 Subject: [PATCH 12/37] ONE: Toxic Keyword (#2213) * ONE: Toxic Keyword * more scripts * Proliferate Trigger * add proliferate trigger * ~ add Toxic to ai part * ~ more toxic cards * add Venser Corpse Puppet * ~ fix jiang * ~ fix venser * predictPoisonFromTriggers Toxic+Double Strike --- .../java/forge/ai/ComputerUtilCombat.java | 9 +++-- .../effects/CountersProliferateEffect.java | 4 +++ .../src/main/java/forge/game/card/Card.java | 2 +- .../main/java/forge/game/keyword/Keyword.java | 1 + .../main/java/forge/game/player/Player.java | 11 +++++- .../game/trigger/TriggerProliferate.java | 36 +++++++++++++++++++ .../java/forge/game/trigger/TriggerType.java | 1 + forge-gui/res/cardsfolder/b/bitterblossom.txt | 6 ++-- forge-gui/res/cardsfolder/j/jiang_yanggu.txt | 2 +- .../cardsfolder/upcoming/blightbelly_rat.txt | 10 ++++++ .../upcoming/ezuri_stalker_of_spheres.txt | 12 +++++++ forge-gui/res/cardsfolder/upcoming/mirrex.txt | 8 +++++ .../res/cardsfolder/upcoming/myr_convert.txt | 7 ++++ .../upcoming/necrogen_rotpriest.txt | 9 +++++ .../res/cardsfolder/upcoming/skrelvs_hive.txt | 9 +++++ .../upcoming/venser_corpse_puppet.txt | 12 +++++++ forge-gui/res/lists/TypeLists.txt | 2 ++ .../b_1_1_bird_flying_noblock.txt | 2 +- .../c_0_1_a_goblin_construct_noblock_ping.txt | 2 +- .../c_1_1_a_phyrexian_mite_toxic_noblock.txt | 7 ++++ .../tokenscripts/c_4_4_a_robot_noblock.txt | 2 +- .../res/tokenscripts/r_1_1_goblin_noblock.txt | 2 +- .../r_1_1_pirate_noblock_all_attack.txt | 2 +- .../res/tokenscripts/r_1_1_satyr_noblock.txt | 2 +- .../res/tokenscripts/the_hollow_sentinel.txt | 5 +++ 25 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/trigger/TriggerProliferate.java create mode 100644 forge-gui/res/cardsfolder/upcoming/blightbelly_rat.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/ezuri_stalker_of_spheres.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/mirrex.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/myr_convert.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/necrogen_rotpriest.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/skrelvs_hive.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/venser_corpse_puppet.txt create mode 100644 forge-gui/res/tokenscripts/c_1_1_a_phyrexian_mite_toxic_noblock.txt create mode 100644 forge-gui/res/tokenscripts/the_hollow_sentinel.txt diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index 52cb5e0a24c..9c2a70d78dd 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -2475,11 +2475,14 @@ public class ComputerUtilCombat { } } poison += pd; - if (pd > 0 && attacker.hasDoubleStrike()) { - poison += pd; - } // TODO: Predict replacement effects for counters (doubled, reduced, additional counters, etc.) } + // intern toxic effect + poison += attacker.getKeywordMagnitude(Keyword.TOXIC); + } + if (attacker.hasDoubleStrike()) + { + poison *= 2; } return poison; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersProliferateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersProliferateEffect.java index 257894cfce3..8df0bad7d57 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersProliferateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersProliferateEffect.java @@ -5,6 +5,7 @@ import java.util.List; import forge.game.Game; import forge.game.GameEntity; import forge.game.GameEntityCounterTable; +import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardLists; @@ -14,6 +15,7 @@ import forge.game.player.Player; import forge.game.player.PlayerController; import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; +import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; import forge.util.Localizer; import forge.util.collect.FCollection; @@ -52,5 +54,7 @@ public class CountersProliferateEffect extends SpellAbilityEffect { } } table.replaceCounterEffect(game, sa, true); + + game.getTriggerHandler().runTrigger(TriggerType.Proliferate, AbilityKey.mapFromPlayer(p), false); } } 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 ad4f65c5634..108b89f684f 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2251,7 +2251,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { || keyword.startsWith("Fabricate") || keyword.startsWith("Soulshift") || keyword.startsWith("Bushido") || keyword.startsWith("Crew") || keyword.startsWith("Tribute") || keyword.startsWith("Absorb") || keyword.startsWith("Graft") || keyword.startsWith("Fading") || keyword.startsWith("Vanishing") - || keyword.startsWith("Afterlife") || keyword.startsWith("Hideaway") + || keyword.startsWith("Afterlife") || keyword.startsWith("Hideaway") || keyword.startsWith("Toxic") || keyword.startsWith("Afflict") || keyword.startsWith ("Poisonous") || keyword.startsWith("Rampage") || keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")) { final String[] k = keyword.split(":"); diff --git a/forge-game/src/main/java/forge/game/keyword/Keyword.java b/forge-game/src/main/java/forge/game/keyword/Keyword.java index 5be70fcf882..3d88989568e 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -170,6 +170,7 @@ public enum Keyword { SURGE("Surge", KeywordWithCost.class, false, "You may cast this spell for its surge cost if you or a teammate has cast another spell this turn."), SUSPEND("Suspend", Suspend.class, false, "Rather than cast this card from your hand, you may pay %s and exile it with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost."), TOTEM_ARMOR("Totem armor", SimpleKeyword.class, true, "If enchanted permanent would be destroyed, instead remove all damage marked on it and destroy this Aura."), + TOXIC("Toxic", KeywordWithAmount.class, false, "Players dealt combat damage by this creature also get {%d:poison counter}."), TRAINING("Training", SimpleKeyword.class, false, "Whenever this creature attacks with another creature with greater power, put a +1/+1 counter on this creature."), TRAMPLE("Trample", Trample.class, true, "This creature can deal excess combat damage to the player or planeswalker it's attacking."), TRANSFIGURE("Transfigure", KeywordWithCost.class, false, "%s, Sacrifice this creature: Search your library for a creature card with the same mana value as this creature and put that card onto the battlefield, then shuffle. Transfigure only as a sorcery."), diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 747fb5dfc9b..448f0f6c859 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -671,8 +671,9 @@ public class Player extends GameEntity implements Comparable { boolean infect = source.hasKeyword(Keyword.INFECT) || hasKeyword("All damage is dealt to you as though its source had infect."); + int poisonCounters = 0; if (infect) { - addPoisonCounters(amount, source.getController(), counterTable); + poisonCounters += amount; } else if (!hasKeyword("Damage doesn't cause you to lose life.")) { // rule 118.2. Damage dealt to a player normally causes that player to lose that much life. @@ -684,6 +685,14 @@ public class Player extends GameEntity implements Comparable { } } + if (isCombat) { + poisonCounters += source.getKeywordMagnitude(Keyword.TOXIC); + } + + if (poisonCounters > 0) { + addPoisonCounters(poisonCounters, source.getController(), counterTable); + } + //Oathbreaker, Tiny Leaders, and Brawl ignore commander damage rule if (source.isCommander() && isCombat && !this.getGame().getRules().hasAppliedVariant(GameType.Oathbreaker) diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerProliferate.java b/forge-game/src/main/java/forge/game/trigger/TriggerProliferate.java new file mode 100644 index 00000000000..7e222fb7ad1 --- /dev/null +++ b/forge-game/src/main/java/forge/game/trigger/TriggerProliferate.java @@ -0,0 +1,36 @@ +package forge.game.trigger; + +import java.util.Map; + +import forge.game.ability.AbilityKey; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; +import forge.util.Localizer; + +public class TriggerProliferate extends Trigger { + + public TriggerProliferate(Map params, Card host, boolean intrinsic) { + super(params, host, intrinsic); + } + + @Override + public boolean performTest(Map runParams) { + if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) { + return false; + } + return true; + } + + @Override + public void setTriggeringObjects(SpellAbility sa, Map runParams) { + sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player); + } + + @Override + public String getImportantStackObjects(SpellAbility sa) { + StringBuilder sb = new StringBuilder(); + sb.append(Localizer.getInstance().getMessage("lblPlayer")).append(": ").append(sa.getTriggeringObject(AbilityKey.Player)); + return sb.toString(); + } + +} diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java index 4b1e72b1d43..a4d3dd98c15 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java @@ -94,6 +94,7 @@ public enum TriggerType { PlanarDice(TriggerPlanarDice.class), PlaneswalkedFrom(TriggerPlaneswalkedFrom.class), PlaneswalkedTo(TriggerPlaneswalkedTo.class), + Proliferate(TriggerProliferate.class), Regenerated(TriggerRegenerated.class), Revealed(TriggerRevealed.class), RolledDie(TriggerRolledDie.class), diff --git a/forge-gui/res/cardsfolder/b/bitterblossom.txt b/forge-gui/res/cardsfolder/b/bitterblossom.txt index c50f09c0bec..558327bc384 100644 --- a/forge-gui/res/cardsfolder/b/bitterblossom.txt +++ b/forge-gui/res/cardsfolder/b/bitterblossom.txt @@ -1,8 +1,8 @@ Name:Bitterblossom ManaCost:1 B Types:Tribal Enchantment Faerie -T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, you lose 1 life and create a 1/1 black Faerie Rogue creature token with flying. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_1_1_faerie_rogue_flying | TokenOwner$ You | SubAbility$ DB -SVar:DB:DB$ LoseLife | LifeAmount$ 1 +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ At the beginning of your upkeep, you lose 1 life and create a 1/1 black Faerie Rogue creature token with flying. +SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 1 | SubAbility$ DBToken +SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_1_1_faerie_rogue_flying | TokenOwner$ You SVar:AICastPreference:NeverCastIfLifeBelow$ 4 Oracle:At the beginning of your upkeep, you lose 1 life and create a 1/1 black Faerie Rogue creature token with flying. diff --git a/forge-gui/res/cardsfolder/j/jiang_yanggu.txt b/forge-gui/res/cardsfolder/j/jiang_yanggu.txt index 6326bb80453..52168119fe5 100644 --- a/forge-gui/res/cardsfolder/j/jiang_yanggu.txt +++ b/forge-gui/res/cardsfolder/j/jiang_yanggu.txt @@ -3,7 +3,7 @@ ManaCost:4 G Types:Legendary Planeswalker Yanggu Loyalty:4 A:AB$ Pump | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ Target creature gets +2/+2 until end of turn. -A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ mowu | TokenOwner$ You | SpellDescription$ If you don't control a creature named Mowu, create Mowu, a legendary 3/3 green Dog creature token. | IsPresent$ Creature.YouCtrl+namedMowu | PresentCompare$ EQ0 +A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ mowu | TokenOwner$ You | SpellDescription$ If you don't control a creature named Mowu, create Mowu, a legendary 3/3 green Dog creature token. | ConditionPresent$ Creature.YouCtrl+namedMowu | ConditionCompare$ EQ0 A:AB$ Pump | Cost$ SubCounter<5/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | NumDef$ +X | KW$ Trample | SpellDescription$ Until end of turn, target creature gains trample and gets +X/+X, where X is the number of lands you control. SVar:X:Count$TypeYouCtrl.Land Oracle:[+1]: Target creature gets +2/+2 until end of turn.\n[-1]: If you don't control a creature named Mowu, create Mowu, a legendary 3/3 green Dog creature token.\n[-5]: Until end of turn, target creature gains trample and gets +X/+X, where X is the number of lands you control. diff --git a/forge-gui/res/cardsfolder/upcoming/blightbelly_rat.txt b/forge-gui/res/cardsfolder/upcoming/blightbelly_rat.txt new file mode 100644 index 00000000000..fd631c141f0 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/blightbelly_rat.txt @@ -0,0 +1,10 @@ +Name:Blightbelly Rat +ManaCost:1 B +Types:Creature Phyrexian Rat +PT:2/2 +K:Toxic:1 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigProliferate | TriggerDescription$ When CARDNAME dies, proliferate. +SVar:TrigProliferate:DB$ Proliferate +DeckHas:Ability$Proliferate +DeckNeeds:Ability$Counters +Oracle:Toxic 1 (Players dealt combat damage by this creature also get a poison counter.)\nWhen Blightbelly Rat dies, proliferate. diff --git a/forge-gui/res/cardsfolder/upcoming/ezuri_stalker_of_spheres.txt b/forge-gui/res/cardsfolder/upcoming/ezuri_stalker_of_spheres.txt new file mode 100644 index 00000000000..eaff2fbce65 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/ezuri_stalker_of_spheres.txt @@ -0,0 +1,12 @@ +Name:Ezuri, Stalker of Spheres +ManaCost:2 G U +Types:Legendary Creature Phyrexian Elf Warrior +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigProliferate | TriggerDescription$ When CARDNAME enters the battlefield, you may pay {3}. If you do, proliferate twice. +SVar:TrigProliferate:AB$ Proliferate | Cost$ 3 | SubAbility$ TrigProliferate2 +SVar:TrigProliferate2:DB$ Proliferate +T:Mode$ Proliferate | ValidPlayer$ You | Execute$ TrigDraw | TriggerDescription$ Whenever you proliferate, draw a card. +SVar:TrigDraw:DB$ Draw +DeckHas:Ability$Proliferate|Counters +DeckNeeds:Ability$Counters +Oracle:When Ezuri, Stalker of Spheres enters the battlefield, you may pay {3}. If you do, proliferate twice.\nWhenever you proliferate, draw a card. diff --git a/forge-gui/res/cardsfolder/upcoming/mirrex.txt b/forge-gui/res/cardsfolder/upcoming/mirrex.txt new file mode 100644 index 00000000000..8d9c6522ad8 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/mirrex.txt @@ -0,0 +1,8 @@ +Name:Mirrex +ManaCost:no cost +Types:Land Sphere +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Mana | Cost$ T | Produced$ Any | IsPresent$ Card.Self+ThisTurnEntered | SpellDescription$ Add one mana of any color. Activate only if CARDNAME entered the battlefield this turn. +A:AB$ Token | Cost$ 3 T | TokenScript$ c_1_1_a_phyrexian_mite_toxic_noblock | TokenOwner$ You | SpellDescription$ Create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block." (Players dealt combat damage by it also get a poison counter.) +DeckHas:Ability$Token & Type$Phyrexian|Mite|Artifact +Oracle:{T}: Add {C}.\n{T}: Add one mana of any color. Activate only if Mirrex entered the battlefield this turn.\n{3},{T}: Create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block." (Players dealt combat damage by it also get a poison counter.) diff --git a/forge-gui/res/cardsfolder/upcoming/myr_convert.txt b/forge-gui/res/cardsfolder/upcoming/myr_convert.txt new file mode 100644 index 00000000000..67f26b2af91 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/myr_convert.txt @@ -0,0 +1,7 @@ +Name:Myr Convert +ManaCost:2 +Types:Artifact Creature Phyrexian Myr +PT:2/1 +K:Toxic:1 +A:AB$ Mana | Cost$ T PayLife<2> | Produced$ Any | SpellDescription$ Add one mana of any color. +Oracle:Toxic 1 (Players dealt combat damage by this creature also get a poison counter.)\nT, Pay 2 life: Add one mana of any color. diff --git a/forge-gui/res/cardsfolder/upcoming/necrogen_rotpriest.txt b/forge-gui/res/cardsfolder/upcoming/necrogen_rotpriest.txt new file mode 100644 index 00000000000..ca46e761d55 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/necrogen_rotpriest.txt @@ -0,0 +1,9 @@ +Name:Necrogen Rotpriest +ManaCost:2 B G +Types:Creature Phyrexian Zombie Cleric +PT:1/5 +K:Toxic:2 +T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl+withToxic | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigPoison | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature you control with toxic deals combat damage to a player, that player gets an additional poison counter. +SVar:TrigPoison:DB$ Poison | Defined$ TriggeredTarget | Num$ 1 +A:AB$ Pump | Cost$ 1 B G | ValidTgts$ Creature.YouCtrl+withToxic | TgtPrompt$ Select target creature you control with toxic | KW$ Deathtouch | SpellDescription$ Target creature you control with toxic gains deathtouch until end of turn. +Oracle:Toxic 2 (Players dealt combat damage by this creature also get two poison counters.)\nWhenever a creature you control with toxic deals combat damage to a player, that player gets an additional poison counter.\n1BG: Target creature you control with toxic gains deathtouch until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/skrelvs_hive.txt b/forge-gui/res/cardsfolder/upcoming/skrelvs_hive.txt new file mode 100644 index 00000000000..3e5fd260b57 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/skrelvs_hive.txt @@ -0,0 +1,9 @@ +Name:Skrelv's Hive +ManaCost:1 W +Types:Enchantment +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ At the beginning of your upkeep, you lose 1 life and create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block." +SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 1 | SubAbility$ DBToken +SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_a_phyrexian_mite_toxic_noblock | TokenOwner$ You +S:Mode$ Continuous | Affected$ Creature.YouCtrl+withToxic | AddKeyword$ Lifelink | CheckSVar$ X | SVarCompare$ GE3 | Description$ Corrupted - As long as an opponent has three or more poison counters, creatures you control with toxic have lifelink. +SVar:X:PlayerCountOpponents$HighestPoisonCounters +Oracle:At the beginning of your upkeep, you lose 1 life and create a 1/1 colorless Phyrexian Mite artifact creature token with toxic 1 and "This creature can't block."\nCorrupted - As long as an opponent has three or more poison counters, creatures you control with toxic have lifelink. diff --git a/forge-gui/res/cardsfolder/upcoming/venser_corpse_puppet.txt b/forge-gui/res/cardsfolder/upcoming/venser_corpse_puppet.txt new file mode 100644 index 00000000000..f7e2c9a0a21 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/venser_corpse_puppet.txt @@ -0,0 +1,12 @@ +Name:Venser, Corpse Puppet +ManaCost:U B +Types:Legendary Creature Phyrexian Zombie Wizard +PT:1/3 +K:Lifelink +K:Toxic:1 +T:Mode$ Proliferate | ValidPlayer$ You | Execute$ TrigChoose | TriggerDescription$ Whenever you proliferate, ABILITY +SVar:TrigChoose:DB$ Charm | Choices$ DBToken,DBPump +SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ the_hollow_sentinel | TokenOwner$ You | ConditionPresent$ Creature.YouCtrl+namedThe Hollow Sentinel | ConditionCompare$ EQ0 | SpellDescription$ If you don't control a creature named The Hollow Sentinel, create The Hollow Sentinel, a legendary 3/3 colorless Phyrexian Golem artifact creature token. +SVar:DBPump:DB$ Pump | ValidTgts$ Creature.Artifact+YouCtrl | TgtPrompt$ Select target artifact creature you control | KW$ Flying & Lifelink | SpellDescription$ Target artifact creature you control gains flying and lifelink until end of turn. +Oracle:Lifelink, toxic 1\nWhenever you proliferate, choose one -\n• If you don't control a creature named The Hollow Sentinel, create The Hollow Sentinel, a legendary 3/3 colorless Phyrexian Golem artifact creature token.\n• Target artifact creature you control gains flying and lifelink until end of turn. + diff --git a/forge-gui/res/lists/TypeLists.txt b/forge-gui/res/lists/TypeLists.txt index 0545bc9ac8d..8a34fff13a6 100644 --- a/forge-gui/res/lists/TypeLists.txt +++ b/forge-gui/res/lists/TypeLists.txt @@ -11,6 +11,7 @@ Lair Locus Mine Power-Plant +Sphere:Spheres Tower Urza's [CreatureTypes] @@ -166,6 +167,7 @@ Merfolk:Merfolk Metathran:Metathrans Minion:Minions Minotaur:Minotaurs +Mite:Mites Mole:Moles Monger:Mongers Mongoose:Mongooses diff --git a/forge-gui/res/tokenscripts/b_1_1_bird_flying_noblock.txt b/forge-gui/res/tokenscripts/b_1_1_bird_flying_noblock.txt index d58af864fe8..f49bffd1af5 100644 --- a/forge-gui/res/tokenscripts/b_1_1_bird_flying_noblock.txt +++ b/forge-gui/res/tokenscripts/b_1_1_bird_flying_noblock.txt @@ -4,5 +4,5 @@ Types:Creature Bird Colors:black PT:1/1 K:Flying -K:CARDNAME can't block. +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block. Oracle:Flying\nThis creature can't block. diff --git a/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt b/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt index 8e65f8f8dcf..d30a50564b8 100644 --- a/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt +++ b/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt @@ -2,7 +2,7 @@ Name:Goblin Construct Token ManaCost:no cost PT:0/1 Types:Artifact Creature Goblin Construct -K:CARDNAME can't block. +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigDealDamage | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to you. SVar:TrigDealDamage:DB$ DealDamage | Defined$ You | NumDmg$ 1 Oracle:This creature can't block.\nAt the beginning of your upkeep, this creature deals 1 damage to you. diff --git a/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_mite_toxic_noblock.txt b/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_mite_toxic_noblock.txt new file mode 100644 index 00000000000..7264cb4331d --- /dev/null +++ b/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_mite_toxic_noblock.txt @@ -0,0 +1,7 @@ +Name:Phyrexian Mite Token +ManaCost:no cost +Types:Artifact Creature Phyrexian Mite +PT:1/1 +K:Toxic:1 +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block +Oracle:Toxic 1\nThis creature can't block. diff --git a/forge-gui/res/tokenscripts/c_4_4_a_robot_noblock.txt b/forge-gui/res/tokenscripts/c_4_4_a_robot_noblock.txt index b4ea8013349..273498f40aa 100644 --- a/forge-gui/res/tokenscripts/c_4_4_a_robot_noblock.txt +++ b/forge-gui/res/tokenscripts/c_4_4_a_robot_noblock.txt @@ -2,5 +2,5 @@ Name:Robot Token ManaCost:no cost Types:Artifact Creature Robot PT:4/4 -S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block. Oracle:This creature can't block. diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt b/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt index 47e58f1539d..2bb0fca11dc 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt @@ -3,5 +3,5 @@ ManaCost:no cost Types:Creature Goblin Colors:red PT:1/1 -K:CARDNAME can't block. +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block. Oracle:This creature can't block. diff --git a/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt b/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt index 0c94b4a02d0..9f91d686ef7 100644 --- a/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt +++ b/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt @@ -3,6 +3,6 @@ ManaCost:no cost Types:Creature Pirate Colors:red PT:1/1 -K:CARDNAME can't block. +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block. S:Mode$ MustAttack | ValidCreature$ Creature.YouCtrl | Description$ Creatures you control attack each combat if able. Oracle:This creature can't block.\nCreatures you control attack each combat if able. diff --git a/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt b/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt index 3311f4fca39..2a9daf4f9ce 100644 --- a/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt +++ b/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt @@ -3,5 +3,5 @@ ManaCost:no cost Types:Creature Satyr Colors:red PT:1/1 -K:CARDNAME can't block. +S:Mode$ CantBlockBy | ValidBlocker$ Creature.Self | Description$ CARDNAME can't block. Oracle:This creature can't block. diff --git a/forge-gui/res/tokenscripts/the_hollow_sentinel.txt b/forge-gui/res/tokenscripts/the_hollow_sentinel.txt new file mode 100644 index 00000000000..cbeafadc11c --- /dev/null +++ b/forge-gui/res/tokenscripts/the_hollow_sentinel.txt @@ -0,0 +1,5 @@ +Name:The Hollow Sentinel +ManaCost:no cost +Types:Legendary Creature Phyrexian Golem +PT:3/3 +Oracle: From f783d5a198a1eb8dce60ab08505e824f474301c0 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sun, 8 Jan 2023 23:14:47 +0100 Subject: [PATCH 13/37] Performance: improve deduping --- .../src/main/java/forge/ai/AiController.java | 3 ++- .../main/java/forge/ai/ComputerUtilCard.java | 19 +++++++++++++++++++ .../java/forge/ai/ComputerUtilCombat.java | 5 ++--- .../main/java/forge/ai/CreatureEvaluator.java | 3 +++ .../src/main/java/forge/ai/GameState.java | 4 +--- .../ai/simulation/MultiTargetSelector.java | 2 +- .../ai/simulation/SpellAbilityPicker.java | 14 ++------------ .../game/ability/effects/MutateEffect.java | 4 +--- .../src/main/java/forge/game/card/Card.java | 3 ++- 9 files changed, 33 insertions(+), 24 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 9c1cc7cd8aa..2b97b75890d 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1646,7 +1646,8 @@ public class AiController { } private final SpellAbility getSpellAbilityToPlay() { - final CardCollection cards = ComputerUtilAbility.getAvailableCards(game, player); + CardCollection cards = ComputerUtilAbility.getAvailableCards(game, player); + cards = ComputerUtilCard.dedupeCards(cards); List saList = Lists.newArrayList(); SpellAbility top = null; diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index a20541c243b..fb2b0eddda3 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -2052,6 +2052,25 @@ public class ComputerUtilCard { return false; } + public static CardCollection dedupeCards(CardCollection cc) { + CardCollection deduped = new CardCollection(); + for (Card c : cc) { + boolean unique = true; + if (c.isInZone(ZoneType.Hand)) { + for (Card d : deduped) { + if (d.isInZone(ZoneType.Hand) && d.getOwner().equals(c.getOwner()) && d.getName().equals(c.getName())) { + unique = false; + break; + } + } + } + if (unique) { + deduped.add(c); + } + } + return deduped; + } + // Determine if the AI has an AI:RemoveDeck:All or an AI:RemoveDeck:Random hint specified. // Includes a NPE guard on getRules() which might otherwise be tripped on some cards (e.g. tokens). public static boolean isCardRemAIDeck(final Card card) { diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index 9c2a70d78dd..a1428d824b3 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -200,8 +200,8 @@ public class ComputerUtilCombat { return 0; } - damage += predictPowerBonusOfAttacker(attacker, null, combat, withoutAbilities); if (!attacker.hasKeyword(Keyword.INFECT)) { + damage += predictPowerBonusOfAttacker(attacker, null, combat, withoutAbilities); sum = predictDamageTo(attacked, damage, attacker, true); if (attacker.hasDoubleStrike()) { sum *= 2; @@ -2480,8 +2480,7 @@ public class ComputerUtilCombat { // intern toxic effect poison += attacker.getKeywordMagnitude(Keyword.TOXIC); } - if (attacker.hasDoubleStrike()) - { + if (attacker.hasDoubleStrike()) { poison *= 2; } return poison; diff --git a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java index 56e456da584..6fa75e8fcab 100644 --- a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java @@ -116,6 +116,9 @@ public class CreatureEvaluator implements Function { else if (c.hasKeyword(Keyword.WITHER)) { value += addValue(power * 10, "Wither"); } + else if (c.hasKeyword(Keyword.TOXIC)) { + value += addValue(power * 10, "Toxic"); + } value += addValue(c.getKeywordMagnitude(Keyword.RAMPAGE), "rampage"); value += addValue(c.getKeywordMagnitude(Keyword.AFFLICT) * 5, "afflict"); } diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index 49d9697ce9f..1054469a22d 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -1066,9 +1066,7 @@ public abstract class GameState { } top.addMergedCard(bottom); - if (top.getMutatedTimestamp() != -1) { - top.removeCloneState(top.getMutatedTimestamp()); - } + top.removeMutatedStates(); final long ts = game.getNextTimestamp(); top.setMutatedTimestamp(ts); diff --git a/forge-ai/src/main/java/forge/ai/simulation/MultiTargetSelector.java b/forge-ai/src/main/java/forge/ai/simulation/MultiTargetSelector.java index 5e09ddb8f9a..00e5ad45e48 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/MultiTargetSelector.java +++ b/forge-ai/src/main/java/forge/ai/simulation/MultiTargetSelector.java @@ -73,7 +73,7 @@ public class MultiTargetSelector { public void reset() { for (PossibleTargetSelector selector : selectors) { - selector.reset(); + selector.reset(); } currentIndex = -1; } diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java index e02e90c6be6..d570d012de1 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java @@ -2,7 +2,6 @@ package forge.ai.simulation; import forge.util.MyRandom; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.Set; @@ -10,6 +9,7 @@ import java.util.Set; import forge.ai.AiPlayDecision; import forge.ai.ComputerUtil; import forge.ai.ComputerUtilAbility; +import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCost; import forge.ai.ability.ChangeZoneAi; import forge.ai.ability.ExploreAi; @@ -66,8 +66,8 @@ public class SpellAbilityPicker { private List getCandidateSpellsAndAbilities() { CardCollection cards = ComputerUtilAbility.getAvailableCards(game, player); + cards = ComputerUtilCard.dedupeCards(cards); List all = ComputerUtilAbility.getSpellAbilities(cards, player); - HashMap landsDeDupe = new HashMap<>(); List candidateSAs = ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player); int writeIndex = 0; for (int i = 0; i < candidateSAs.size(); i++) { @@ -75,16 +75,6 @@ public class SpellAbilityPicker { if (sa.isManaAbility()) { continue; } - // Skip identical lands. - if (sa instanceof LandAbility) { - Card land = sa.getHostCard(); - Card previousLand = landsDeDupe.get(sa.getHostCard().getName()); - if (previousLand != null && previousLand.getZone() == land.getZone() && - previousLand.getOwner() == land.getOwner()) { - continue; - } - landsDeDupe.put(land.getName(), land); - } sa.setActivatingPlayer(player, true); AiPlayDecision opinion = canPlayAndPayForSim(sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/MutateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MutateEffect.java index 75fd27dd8ba..155d5bb282c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MutateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MutateEffect.java @@ -66,9 +66,7 @@ public class MutateEffect extends SpellAbilityEffect { } // First remove current mutated states - if (target.getMutatedTimestamp() != -1) { - target.removeCloneState(target.getMutatedTimestamp()); - } + target.removeMutatedStates(); // Now add all abilities from bottom cards final Long ts = game.getNextTimestamp(); target.setMutatedTimestamp(ts); 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 108b89f684f..2968877d344 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1240,7 +1240,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final void removeMutatedStates() { - if (getMutatedTimestamp() != -1) { + if (isMutated()) { removeCloneState(getMutatedTimestamp()); } } @@ -5801,6 +5801,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } return getCastSA().isMadness(); } + public boolean wasDiscarded() { return discarded; } public void setDiscarded(boolean state) { discarded = state; } From 58fcee689fdbbc69b72247c06538d9c30cdc7c00 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sun, 8 Jan 2023 23:15:53 +0100 Subject: [PATCH 14/37] Fix cards --- .../main/java/forge/ai/simulation/SpellAbilityPicker.java | 3 +-- forge-gui/res/cardsfolder/c/curse_of_echoes.txt | 2 +- forge-gui/res/cardsfolder/h/hive_mind.txt | 2 +- forge-gui/res/cardsfolder/j/jodah_the_unifier.txt | 7 ++++--- forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java index d570d012de1..f7481bbbcb6 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java @@ -70,8 +70,7 @@ public class SpellAbilityPicker { List all = ComputerUtilAbility.getSpellAbilities(cards, player); List candidateSAs = ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player); int writeIndex = 0; - for (int i = 0; i < candidateSAs.size(); i++) { - SpellAbility sa = candidateSAs.get(i); + for (SpellAbility sa : candidateSAs) { if (sa.isManaAbility()) { continue; } diff --git a/forge-gui/res/cardsfolder/c/curse_of_echoes.txt b/forge-gui/res/cardsfolder/c/curse_of_echoes.txt index eef1bc4543a..dd618478059 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_echoes.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_echoes.txt @@ -4,6 +4,6 @@ Types:Enchantment Aura Curse K:Enchant player A:SP$ Attach | Cost$ 4 U | ValidTgts$ Player | AILogic$ Curse T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ Player.EnchantedBy | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player casts an instant or sorcery spell, each other player may copy that spell and may choose new targets for the copy they control. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredCardOpponent | Optional$ True | MayChooseTarget$ True +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ NonTriggeredCardController | Optional$ True | MayChooseTarget$ True AI:RemoveDeck:All Oracle:Enchant player\nWhenever enchanted player casts an instant or sorcery spell, each other player may copy that spell and may choose new targets for the copy they control. diff --git a/forge-gui/res/cardsfolder/h/hive_mind.txt b/forge-gui/res/cardsfolder/h/hive_mind.txt index 79398e76958..227bad5bddd 100644 --- a/forge-gui/res/cardsfolder/h/hive_mind.txt +++ b/forge-gui/res/cardsfolder/h/hive_mind.txt @@ -2,6 +2,6 @@ Name:Hive Mind ManaCost:5 U Types:Enchantment T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ Player | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player casts an instant or sorcery spell, each other player copies that spell. Each of those players may choose new targets for their copy. -SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ TriggeredCardOpponent | MayChooseTarget$ True +SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ NonTriggeredCardController | MayChooseTarget$ True AI:RemoveDeck:Random Oracle:Whenever a player casts an instant or sorcery spell, each other player copies that spell. Each of those players may choose new targets for their copy. diff --git a/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt b/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt index e3f5870f2ef..cc0397b5cb8 100644 --- a/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt +++ b/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt @@ -4,9 +4,10 @@ Types:Legendary Creature Human Wizard PT:5/5 S:Mode$ Continuous | Affected$ Creature.Legendary+YouCtrl | AddPower$ X | AddToughness$ X | Description$ Legendary creatures you control get +X/+X, where X is the number of legendary creatures you control. T:Mode$ SpellCast | ValidCard$ Card.Legendary+wasCastFromYourHandByYou | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ DBDigUntil | TriggerDescription$ Whenever you cast a legendary spell from your hand, exile cards from the top of your library until you exile a legendary nonland card with lesser mana value. You may cast that card without paying its mana cost. Put the rest on the bottom of your library in a random order. -SVar:DBDigUntil:DB$ DigUntil | Defined$ You | Valid$ Card.nonLand+Legendary+cmcLTY | FoundDestination$ Exile | RevealedDestination$ Library| RememberFound$ True | RestRandomOrder$ True | SubAbility$ DBPlay -SVar:DBPlay:DB$ Play | Defined$ Remembered | ValidSA$ Spell | WithoutManaCost$ True | Optional$ True | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:DBDigUntil:DB$ DigUntil | Defined$ You | Valid$ Card.nonLand+Legendary+cmcLTY | FoundDestination$ Exile | RevealedDestination$ Exile | ImprintFound$ True | RememberRevealed$ True +SVar:DBPlay:DB$ Play | Defined$ Imprinted | ValidSA$ Spell | WithoutManaCost$ True | Optional$ True | SubAbility$ DBChange +SVar:DBChange:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Exile | Destination$ Library | RandomOrder$ True | LibraryPosition$ -1 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True SVar:X:Count$Valid Creature.Legendary+YouCtrl SVar:Y:TriggeredCard$CardManaCost DeckHints:Type$Legendary diff --git a/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt b/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt index e54cafb56e6..41c71cfe484 100644 --- a/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt +++ b/forge-gui/res/cardsfolder/m/moritte_of_the_frost.txt @@ -4,7 +4,7 @@ Types:Legendary Snow Creature Shapeshifter PT:0/0 K:Changeling K:ETBReplacement:Copy:DBCopy:Optional -SVar:DBCopy:DB$ Clone | Choices$ Permanent.Other+YouCtrl | AddTypes$ Legendary & Snow | SubAbility$ DBConditionEffect | AddKeywords$ Changeling | SpellDescription$ You may have Moritte of the Frost enter the battlefield as a copy of a permanent you control, except it's legendary and snow in addition to its other types and, if it's a creature, it enters with two additional +1/+1 counters on it and has changeling. +SVar:DBCopy:DB$ Clone | Choices$ Permanent.Other+YouCtrl | AddTypes$ Legendary & Snow | SubAbility$ DBConditionEffect | AddKeywords$ Changeling | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of a permanent you control, except it's legendary and snow in addition to its other types and, if it's a creature, it enters with two additional +1/+1 counters on it and has changeling. SVar:DBConditionEffect:DB$ Effect | RememberObjects$ Self | Name$ Moritte of the Frost Effect | ReplacementEffects$ ETBCreat SVar:ETBCreat:Event$ Moved | ValidCard$ Creature.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated | Description$ If it's a creature, it enters with two additional +1/+1 counters on it. SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ 2 | SubAbility$ DBExile From 830d0afba2c1998ce6cccd6eb18c5fb96a8ece99 Mon Sep 17 00:00:00 2001 From: TRT <> Date: Mon, 9 Jan 2023 08:22:29 +0100 Subject: [PATCH 15/37] Clean up --- forge-ai/src/main/java/forge/ai/ComputerUtilCard.java | 3 +++ forge-ai/src/main/java/forge/ai/CreatureEvaluator.java | 8 +++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index fb2b0eddda3..4ea030507c0 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -2053,6 +2053,9 @@ public class ComputerUtilCard { } public static CardCollection dedupeCards(CardCollection cc) { + if (cc.size() <= 1) { + return cc; + } CardCollection deduped = new CardCollection(); for (Card c : cc) { boolean unique = true; diff --git a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java index 6fa75e8fcab..aac52cdaa9d 100644 --- a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java @@ -114,13 +114,11 @@ public class CreatureEvaluator implements Function { value += addValue(power * 15, "infect"); } else if (c.hasKeyword(Keyword.WITHER)) { - value += addValue(power * 10, "Wither"); + value += addValue(power * 10, "wither"); } - else if (c.hasKeyword(Keyword.TOXIC)) { - value += addValue(power * 10, "Toxic"); - } - value += addValue(c.getKeywordMagnitude(Keyword.RAMPAGE), "rampage"); + value += addValue(c.getKeywordMagnitude(Keyword.TOXIC) * 5, "toxic"); value += addValue(c.getKeywordMagnitude(Keyword.AFFLICT) * 5, "afflict"); + value += addValue(c.getKeywordMagnitude(Keyword.RAMPAGE), "rampage"); } value += addValue(c.getKeywordMagnitude(Keyword.ANNIHILATOR) * 50, "eldrazi"); From 217ec8e3fe87c647fbcde64b5e2db435802d75e7 Mon Sep 17 00:00:00 2001 From: TRT <> Date: Mon, 9 Jan 2023 09:38:38 +0100 Subject: [PATCH 16/37] Fix NPE --- .../gamemodes/match/input/InputSelectEntitiesFromList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectEntitiesFromList.java b/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectEntitiesFromList.java index ed593159fe1..16a1d35f574 100644 --- a/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectEntitiesFromList.java +++ b/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectEntitiesFromList.java @@ -124,7 +124,7 @@ public class InputSelectEntitiesFromList extends InputSele ? String.format(message, selected.size()) : String.format(message, max - selected.size())); - if (sa != null && sa.hasParam("Crew")) { + if (sa != null && sa.hasParam("Crew") && sa.getPayCosts().hasSpecificCostType(CostTapType.class)) { msg.append("\nCrewing: "). append(CardLists.getTotalPower((FCollection)getSelected(), true, true)). append(" / ").append(TextUtil.fastReplace(sa.getPayCosts().getCostPartByType(CostTapType.class).getType(), "Creature.Other+withTotalPowerGE", "")); From fc53c3ab840a9bfe99e49c81971cd6877f3fe9ad Mon Sep 17 00:00:00 2001 From: TRT <> Date: Mon, 9 Jan 2023 11:55:57 +0100 Subject: [PATCH 17/37] Fix card --- forge-gui/res/cardsfolder/j/jodah_the_unifier.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt b/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt index cc0397b5cb8..f61fa77b8f2 100644 --- a/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt +++ b/forge-gui/res/cardsfolder/j/jodah_the_unifier.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Wizard PT:5/5 S:Mode$ Continuous | Affected$ Creature.Legendary+YouCtrl | AddPower$ X | AddToughness$ X | Description$ Legendary creatures you control get +X/+X, where X is the number of legendary creatures you control. T:Mode$ SpellCast | ValidCard$ Card.Legendary+wasCastFromYourHandByYou | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ DBDigUntil | TriggerDescription$ Whenever you cast a legendary spell from your hand, exile cards from the top of your library until you exile a legendary nonland card with lesser mana value. You may cast that card without paying its mana cost. Put the rest on the bottom of your library in a random order. -SVar:DBDigUntil:DB$ DigUntil | Defined$ You | Valid$ Card.nonLand+Legendary+cmcLTY | FoundDestination$ Exile | RevealedDestination$ Exile | ImprintFound$ True | RememberRevealed$ True +SVar:DBDigUntil:DB$ DigUntil | Defined$ You | Valid$ Card.nonLand+Legendary+cmcLTY | FoundDestination$ Exile | RevealedDestination$ Exile | ImprintFound$ True | RememberRevealed$ True | SubAbility$ DBPlay SVar:DBPlay:DB$ Play | Defined$ Imprinted | ValidSA$ Spell | WithoutManaCost$ True | Optional$ True | SubAbility$ DBChange SVar:DBChange:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Exile | Destination$ Library | RandomOrder$ True | LibraryPosition$ -1 | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True From 49fb4cf218066a1ed8090112cc173bc6aeebfdb1 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Mon, 9 Jan 2023 12:11:31 +0100 Subject: [PATCH 18/37] ONE 5 sphere cards (#2215) * update * update * update * Update monument_to_perfection.txt --- .../res/cardsfolder/upcoming/monument_to_perfection.txt | 9 +++++++++ .../res/cardsfolder/upcoming/the_monumental_facade.txt | 8 ++++++++ .../res/cardsfolder/upcoming/the_mycosynth_gardens.txt | 9 +++++++++ forge-gui/res/cardsfolder/upcoming/the_seedcore.txt | 9 +++++++++ 4 files changed, 35 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/monument_to_perfection.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/the_monumental_facade.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/the_mycosynth_gardens.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/the_seedcore.txt diff --git a/forge-gui/res/cardsfolder/upcoming/monument_to_perfection.txt b/forge-gui/res/cardsfolder/upcoming/monument_to_perfection.txt new file mode 100644 index 00000000000..5eda4d14777 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/monument_to_perfection.txt @@ -0,0 +1,9 @@ +Name:Monument to Perfection +ManaCost:2 +Types:Artifact +A:AB$ ChangeZone | Cost$ 3 T | Origin$ Library | Destination$ Hand | ChangeType$ Land.Basic,Land.Locus,Land.Sphere | ChangeTypeDesc$ basic, Sphere, or Locus land card | SpellDescription$ Search your library for a basic, Sphere, or Locus land card, reveal it, put it into your hand, then shuffle. +A:AB$ Animate | Cost$ 3 | CheckSVar$ CountAll | SVarCompare$ GE9 | Power$ 9 | Toughness$ 9 | Types$ Artifact,Creature,Phyrexian,Construct | RemoveAllAbilities$ True | Defined$ Self | Keywords$ Indestructible & Toxic:9 | Duration$ Permanent | SpellDescription$ CARDNAME becomes a 9/9 Phyrexian Construct artifact creature, loses all abilities, and gains indestructible and toxic 9. Activate only if there are nine or more lands with different names among the basic, Sphere, and Locus lands you control. +SVar:CountAll:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield+Basic,Land.YouCtrl+inZoneBattlefield+Sphere,Land.YouCtrl+inZoneBattlefield+Locus +DeckNeeds:Type$Locus|Sphere +DeckHas:Type$Phyrexian|Construct|Artifact +Oracle:{3},{T}: Search your library for a basic, Sphere, or Locus land card, reveal it, put it into your hand, then shuffle.\n{3}: Monument to Perfection becomes a 9/9 Phyrexian Construct artifact creature, loses all abilities, and gains indestructible and toxic 9. Activate only if there are nine or more lands with different names among the basic, Sphere, and Locus lands you control. diff --git a/forge-gui/res/cardsfolder/upcoming/the_monumental_facade.txt b/forge-gui/res/cardsfolder/upcoming/the_monumental_facade.txt new file mode 100644 index 00000000000..6eaf08b34d9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/the_monumental_facade.txt @@ -0,0 +1,8 @@ +Name:The Monumental Facade +ManaCost:no cost +Types:Land Sphere +K:etbCounter:OIL:5 +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ PutCounter | Cost$ T SubCounter<1/OIL> | ValidTgts$ Artifact.YouCtrl,Creature.YouCtrl | TgtPrompt$ Select target Artifact of Creature you control | SorcerySpeed$ True | CounterType$ OIL | SpellDescription$ Put an oil counter on target artifact or creature you control. Activate only as a sorcery. +DeckHas:Ability$Counters +Oracle:The Monumental Facade enters the battlefield with five oil counters on it.\n{T}: Add {C}.\n{T}, Remove an oil counter from The Monumental Facade: Put an oil counter on target artifact or creature you control. Activate only as a sorcery. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/the_mycosynth_gardens.txt b/forge-gui/res/cardsfolder/upcoming/the_mycosynth_gardens.txt new file mode 100644 index 00000000000..7ab9cd7c146 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/the_mycosynth_gardens.txt @@ -0,0 +1,9 @@ +Name:The Mycosynth Gardens +ManaCost:no cost +Types:Land Sphere +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Mana | Cost$ 1 T | Produced$ Any | SpellDescription$ Add one mana of any color. +A:AB$ Clone | Cost$ X T | ValidTgts$ Artifact.YouCtrl+cmcEQX+nonToken | TgtPrompt$ Select target nontoken artifact you control | SpellDescription$ CARDNAME becomes a copy of target nontoken artifact you control with mana value X. +SVar:X:Count$xPaid +DeckHints:Type$Artifact +Oracle:{T}: Add {C}.\n{1}, {T}: Add one mana of any color.\n{X}, {T}: The Mycosynth Gardens becomes a copy of target nontoken artifact you control with mana value X. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/the_seedcore.txt b/forge-gui/res/cardsfolder/upcoming/the_seedcore.txt new file mode 100644 index 00000000000..02660202b47 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/the_seedcore.txt @@ -0,0 +1,9 @@ +Name:The Seedcore +ManaCost:no cost +Types:Land Sphere +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Mana | Cost$ T | Produced$ Any | RestrictValid$ Spell.Creature+Phyrexian | SpellDescription$ Add one mana of any color. Spend this mana only to cast Phyrexian creature spells. +A:AB$ Pump | Cost$ T | PrecostDesc$ Corrupted — | CheckSVar$ X | SVarCompare$ GE3 | ValidTgts$ Creature.powerEQ1+toughnessEQ1 | TgtPrompt$ Select target 1/1 creature | NumAtt$ +2 | NumDef$ +1 | SpellDescription$ Target 1/1 creature gets +2/+1 until end of turn. Activate only if an opponent has three or more poison counters. +SVar:X:PlayerCountOpponents$HighestPoisonCounters +DeckNeeds:Type$Phyrexian +Oracle:{T}: Add {C}.\n{T}: Add one mana of any color. Spend this mana only to cast Phyrexian creature spells.\nCorrupted - {T}: Target 1/1 creature gets +2/+1 until end of turn. Activate only if an opponent has three or more poison counters. \ No newline at end of file From 0d33400ec33632bc8a29ed1e7439c9e7af566250 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:47:49 +0100 Subject: [PATCH 19/37] update --- .../cardsfolder/upcoming/archfiend_of_the_dross.txt | 13 +++++++++++++ .../cardsfolder/upcoming/black_suns_twilight.txt | 8 ++++++++ .../res/cardsfolder/upcoming/conduit_of_worlds.txt | 8 ++++++++ .../cardsfolder/upcoming/encroaching_mycosynth.txt | 5 +++++ .../upcoming/geth_thane_of_contracts.txt | 10 ++++++++++ 5 files changed, 44 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt diff --git a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt new file mode 100644 index 00000000000..f10bff7d020 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt @@ -0,0 +1,13 @@ +Name:Archfiend of the Dross +ManaCost:2 B +Types:Creature Phyrexian Demon +PT:6/6 +K:Flying +K:etbCounter:OIL:4 +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemoveCtr | TriggerDescription$ At the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game. +SVar:TrigRemoveCtr:DB$ RemoveCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1 | SubAbility$ LoseGame +SVar:LoseGame:DB$ LoseGame | Defined$ You | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_OIL +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.OppCtrl | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Whenever a creature an opponent controls dies, its controller loses 2 life. +SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ TriggeredCardController +DeckHas:Ability$Counters +Oracle:Flying\nArchfiend of the Dross enters the battlefield with four oil counters on it.\nAt the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game.\nWhenever a creature an opponent controls dies, its controller loses 2 life. diff --git a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt new file mode 100644 index 00000000000..99feb932ea9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt @@ -0,0 +1,8 @@ +Name:Black Sun's Twilight +ManaCost:X B +Types:Instant +A:SP$ Pump | ValidTgts$ Creature | TgtPrompt$ Select up to one target creature | TargetMin$ 0 | TargetMax$ 1 | NumAtt$ -X | NumDef$ -X | IsCurse$ True | SubAbility$ DBReanimate | SpellDescription$ Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. +SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | TgtPrompt$ Choose target creature card with mana value X | ValidTgts$ Creature.YouOwn+cmcEQX +SVar:X:Count$xPaid +DeckNeeds:Ability$Graveyard +Oracle:Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt new file mode 100644 index 00000000000..93693c82916 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -0,0 +1,8 @@ +Name:Conduit of Worlds +ManaCost:2 G G +Types:Artifact +S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. +S:Mode$ CantBeCast | ValidCard$ Card.nonArtifact | Caster$ Player | NumLimitEachTurn$ 1 | Description$ Each player who has cast a nonartifact spell this turn can't cast additional nonartifact spells. +SVar:X:Count$ThisTurnCast_Creature.ActivePlayerCtrl +DeckHints:Ability$Graveyard|Mill|Dredge +Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt b/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt new file mode 100644 index 00000000000..e2437d02d45 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt @@ -0,0 +1,5 @@ +Name:Encroaching Mycosynth +ManaCost:3 U +Types:Artifact +S:Mode$ Continuous | Affected$ Permanent.nonLand+YouCtrl | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | AddType$ Artifact | Description$ Nonland permanents you control are artifacts in addition to their other types The same is true for permanent spells you control and nonland permanent cards you own that aren't on the battlefield. +Oracle:Nonland permanents you control are artifacts in addition to their other types The same is true for permanent spells you control and nonland permanent cards you own that aren't on the battlefield. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt b/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt new file mode 100644 index 00000000000..3575e78fd48 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt @@ -0,0 +1,10 @@ +Name:Geth, Thane of Contracts +ManaCost:1 B B +Types:Legendary Creature Phyrexian Zombie +PT:3/4 +S:Mode$ Continuous | Affected$ Creature.Other+YouCtrl | AddPower$ -1 | AddToughness$ -1 | Description$ Other creatures you control get -1/-1. +A:AB$ ChangeZone | Cost$ 1 B B T | Origin$ Graveyard | SorcerySpeed$ True | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature in your graveyard | SubAbility$ DBPump | SpellDescription$Return target creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead of putting it anywhere else." Activate only as a sorcery. +SVar:DBPump:DB$ Pump | LeaveBattlefield$ Exile | Defined$ Targeted | Duration$ Permanent +DeckHints:Ability$Graveyard|Mill|Dredge +DeckHas:Ability$Graveyard +Oracle:Other creatures you control get -1/-1.\n{1}{B}{B}, {T}: Return target creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead of putting it anywhere else." Activate only as a sorcery. \ No newline at end of file From f96a701f959cd1de096f83e5df5aacba56950ebf Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Mon, 9 Jan 2023 22:39:17 +0100 Subject: [PATCH 20/37] update --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index 93693c82916..5ea058dd950 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,7 +2,10 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -S:Mode$ CantBeCast | ValidCard$ Card.nonArtifact | Caster$ Player | NumLimitEachTurn$ 1 | Description$ Each player who has cast a nonartifact spell this turn can't cast additional nonartifact spells. -SVar:X:Count$ThisTurnCast_Creature.ActivePlayerCtrl +A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouCtrl | PumpZone$ Graveyard | TargetPrompt$ Choose a creature card in your graveyard | RememberTargets$ True | SubAbility$ DBPlay | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +SVar:DBPlay:DB$ Play | Defined$ Targeted | ValidSA$ Spell | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect +SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | StaticAbilities$ STCantBeCast +SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. +SVar:X:Count$ThisTurnCast_Spell.YouCtrl DeckHints:Ability$Graveyard|Mill|Dredge Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. \ No newline at end of file From 3fe7bf64e117e06c1fa4b845553484875f6527c9 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Mon, 9 Jan 2023 23:01:33 +0100 Subject: [PATCH 21/37] update --- forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt | 2 +- forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt | 2 +- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt index f10bff7d020..97637f2ee56 100644 --- a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt +++ b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt @@ -6,7 +6,7 @@ K:Flying K:etbCounter:OIL:4 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemoveCtr | TriggerDescription$ At the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game. SVar:TrigRemoveCtr:DB$ RemoveCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1 | SubAbility$ LoseGame -SVar:LoseGame:DB$ LoseGame | Defined$ You | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_OIL +SVar:LoseGame:DB$ LosesGame | Defined$ You | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_OIL T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.OppCtrl | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Whenever a creature an opponent controls dies, its controller loses 2 life. SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ TriggeredCardController DeckHas:Ability$Counters diff --git a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt index 99feb932ea9..09d2a65701f 100644 --- a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt +++ b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt @@ -2,7 +2,7 @@ Name:Black Sun's Twilight ManaCost:X B Types:Instant A:SP$ Pump | ValidTgts$ Creature | TgtPrompt$ Select up to one target creature | TargetMin$ 0 | TargetMax$ 1 | NumAtt$ -X | NumDef$ -X | IsCurse$ True | SubAbility$ DBReanimate | SpellDescription$ Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. -SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | TgtPrompt$ Choose target creature card with mana value X | ValidTgts$ Creature.YouOwn+cmcEQX +SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | Hidden$ True | ChangeType$ Creature.YouOwn+cmcLEX SVar:X:Count$xPaid DeckNeeds:Ability$Graveyard Oracle:Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index 5ea058dd950..81744201136 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,9 +2,9 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouCtrl | PumpZone$ Graveyard | TargetPrompt$ Choose a creature card in your graveyard | RememberTargets$ True | SubAbility$ DBPlay | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | ImprintTargets$ True | SubAbility$ DBPlay | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. SVar:DBPlay:DB$ Play | Defined$ Targeted | ValidSA$ Spell | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect -SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | StaticAbilities$ STCantBeCast +SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. SVar:X:Count$ThisTurnCast_Spell.YouCtrl DeckHints:Ability$Graveyard|Mill|Dredge From 8250082c224334dd1fd0d72dc6557e417eaacb20 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Tue, 10 Jan 2023 07:20:37 +0800 Subject: [PATCH 22/37] Update necromancy.txt Fix typo --- forge-gui/res/cardsfolder/n/necromancy.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/n/necromancy.txt b/forge-gui/res/cardsfolder/n/necromancy.txt index 24538975dfc..8fe9a3e8c17 100644 --- a/forge-gui/res/cardsfolder/n/necromancy.txt +++ b/forge-gui/res/cardsfolder/n/necromancy.txt @@ -8,7 +8,7 @@ SVar:Aurify:DB$ Animate | IsPresent$ Card.Self | Types$ Aura | OverwriteSpells$ SVar:NewAttach:SP$ Attach | Cost$ 2 B | ValidTgts$ Creature.IsRemembered | AILogic$ Pump | SubAbility$ DBDelay SVar:DBDelay:DB$ DelayedTrigger | Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Execute$ TrigSacrifice | RememberObjects$ RememberedLKI | TriggerDescription$ When CARDNAME leaves the battlefield, that creature's controller sacrifices it. SVar:NecromAttach:DB$ Attach | Defined$ Remembered -SVar:TrigSac:DB$ Destroy | Sacrifice$ True | Defined$ DirectRemembered +SVar:TrigSacrifice:DB$ Destroy | Sacrifice$ True | Defined$ DirectRemembered T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ DBCleanup | Static$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:NeedsToPlayVar:Y GE1 From 5feb79a0afa125c23e6234cfa96f233ba3d0720f Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 10:31:56 +0100 Subject: [PATCH 23/37] update --- .../res/cardsfolder/upcoming/black_suns_twilight.txt | 2 +- .../res/cardsfolder/upcoming/bloated_contaminator.txt | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt diff --git a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt index 09d2a65701f..7ce74a1bbf4 100644 --- a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt +++ b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt @@ -2,7 +2,7 @@ Name:Black Sun's Twilight ManaCost:X B Types:Instant A:SP$ Pump | ValidTgts$ Creature | TgtPrompt$ Select up to one target creature | TargetMin$ 0 | TargetMax$ 1 | NumAtt$ -X | NumDef$ -X | IsCurse$ True | SubAbility$ DBReanimate | SpellDescription$ Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. -SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | Hidden$ True | ChangeType$ Creature.YouOwn+cmcLEX +SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | Chooser$ You | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | Hidden$ True | ChangeType$ Creature.YouOwn+cmcLEX SVar:X:Count$xPaid DeckNeeds:Ability$Graveyard Oracle:Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt b/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt new file mode 100644 index 00000000000..463bfcd3d7d --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt @@ -0,0 +1,11 @@ +Name:Bloated Contaminator +ManaCost:2 G +Types:Creature Phyrexian Beast +PT:4/4 +K:Trample +K:Toxic:1 +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigProliferate | TriggerDescription$ Whenever CARDNAME deals combat damage to a player or dies, proliferate. +SVar:TrigProliferate:DB$ Proliferate +DeckHas:Ability$Proliferate +DeckHints:Type$Planeswalker & Ability$Counters +Oracle:Trample\nToxic 1\nWhenever Bloated Contaminator deals combat damage to a player, proliferate. \ No newline at end of file From 09043d1c008e31efa4842a11485e4cdf7d504382 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 10:33:01 +0100 Subject: [PATCH 24/37] Delete conduit_of_worlds.txt --- .../res/cardsfolder/upcoming/conduit_of_worlds.txt | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt deleted file mode 100644 index 81744201136..00000000000 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ /dev/null @@ -1,11 +0,0 @@ -Name:Conduit of Worlds -ManaCost:2 G G -Types:Artifact -S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | ImprintTargets$ True | SubAbility$ DBPlay | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. -SVar:DBPlay:DB$ Play | Defined$ Targeted | ValidSA$ Spell | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect -SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast -SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. -SVar:X:Count$ThisTurnCast_Spell.YouCtrl -DeckHints:Ability$Graveyard|Mill|Dredge -Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. \ No newline at end of file From 70fe54c2555327c117c2112513c15a080a6f4ee8 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 12:10:12 +0100 Subject: [PATCH 25/37] update --- .../res/cardsfolder/upcoming/conduit_of_worlds.txt | 11 +++++++++++ .../res/cardsfolder/upcoming/evolved_spinoderm.txt | 13 +++++++++++++ .../res/cardsfolder/upcoming/glissa_sunslayer.txt | 13 +++++++++++++ .../upcoming/graaz_unstoppable_juggernaut.txt | 8 ++++++++ .../cardsfolder/upcoming/karumonix_the_rat_king.txt | 10 ++++++++++ .../res/cardsfolder/upcoming/kemba_kha_enduring.txt | 11 +++++++++++ .../upcoming/malcator_purity_overseer.txt | 11 +++++++++++ 7 files changed, 77 insertions(+) create mode 100644 forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/graaz_unstoppable_juggernaut.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt new file mode 100644 index 00000000000..95964b09d4e --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -0,0 +1,11 @@ +Name:Conduit of Worlds +ManaCost:2 G G +Types:Artifact +S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. +A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | SubAbility$ DBPlay | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +SVar:DBPlay:DB$ Play | Defined$ Targeted | ValidSA$ Spell | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect +SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast +SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. +SVar:X:Count$ThisTurnCast_Spell.YouCtrl +DeckHints:Ability$Graveyard|Mill|Dredge +Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt b/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt new file mode 100644 index 00000000000..1dc5ed942b7 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt @@ -0,0 +1,13 @@ +Name:Evolved Spinoderm +ManaCost:2 G G +Types:Creature Phyrexian Beast +PT:5/5 +K:etbCounter:OIL:4 +S:Mode$ Continuous | Affected$ Creature.Self+counters_LE2_OIL | AddKeyword$ Trample | Description$ CARDNAME has trample as long as it has two or fewer oil counters on it. Otherwise, it has hexproof. +S:Mode$ Continuous | Affected$ Creature.Self+counters_GT2_OIL | AddKeyword$ Hexproof +S:Mode$ Continuous | Affected$ Creature.Self | AddPower$ -2 | AddToughness$ -1 +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemoveCtr | TriggerDescription$ At the beginning of your upkeep, remove an oil counter from CARDNAME. Then if it has no oil counters on it, sacrifice it. +SVar:TrigRemoveCtr:DB$ RemoveCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1 | SubAbility$ DBSacrifice +SVar:DBSacrifice:DB$ Sacrifice | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_OIL +DeckHas:Ability$Counters +Oracle:Evolved Spinoderm enters the battlefield with four oil counters on it.\nEvolved Spinoderm has trample as long as it has two or fewer oil counters on it. Otherwise, it has hexproof.\nAt the beginning of your upkeep, remove an oil counter from Evolved Spinoderm. Then if it has no oil counters on it, sacrifice it. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt b/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt new file mode 100644 index 00000000000..6fa43e30f27 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt @@ -0,0 +1,13 @@ +Name:Glissa Sunslayer +ManaCost:1 B G +Types:Legendary Creature Phyrexian Zombie Elf +PT:3/3 +K:First strike +K:Deathtouch +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, ABILITY +SVar:TrigCharm:DB$ Charm | Choices$ DBDraw,DBDestroy,DBRemove +SVar:DBDraw:DB$ Draw | SubAbility$ DBLoseLife | SpellDescription$ You draw a card and you lose 1 life. +SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 1 +SVar:DBDestroy:DB$ Destroy | ValidTgts$ Enchantment | SpellDescription$ Destroy target enchantment. +SVar:DBRemove:DB$ RemoveCounter | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ 3 | SpellDescription$ Remove up to three counters from target permanent. +Oracle:Whenever Glissa Sunslayer deals combat damage to a player, choose one —\n• You draw a card and you lose 1 life.\n• Destroy target enchantment.\n• Remove up to three counters from target permanent. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/graaz_unstoppable_juggernaut.txt b/forge-gui/res/cardsfolder/upcoming/graaz_unstoppable_juggernaut.txt new file mode 100644 index 00000000000..d6e1c1d7c7b --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/graaz_unstoppable_juggernaut.txt @@ -0,0 +1,8 @@ +Name:Graaz, Unstoppable Juggernaut +ManaCost:8 +Types:Legendary Artifact Creature Juggernaut +PT:7/5 +S:Mode$ MustAttack | ValidCreature$ Juggernaut.YouCtrl | Description$ Juggernauts you control attack each combat if able. +S:Mode$ CantBlockBy | ValidAttacker$ Juggernaut.YouCtrl | ValidBlocker$ Creature.Wall | Description$ Juggernauts you control can't be blocked by Walls. +S:Mode$ Continuous | Affected$ Creature.Other+YouCtrl | AffectedZone$ Battlefield | SetPower$ 5 | SetToughness$ 3 | AddType$ Juggernaut | Description$ Other creatures you control have base power and toughness 5/3 and are Juggernauts in addition to their other creature types. +Oracle:Juggernauts you control attack each combat if able.\nJuggernauts you control can't be blocked by Walls.\nOther creatures you control have base power and toughness 5/3 and are Juggernauts in addition to their other creature types. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt b/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt new file mode 100644 index 00000000000..b05781e8408 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt @@ -0,0 +1,10 @@ +Name:Karumonix, the Rat King +ManaCost:1 B B +Types:Legendary Creature Phyrexian Rat +PT:3/3 +K:Toxic:1 +S:Mode$ Continuous | Affected$ Creature.Rat+YouCtrl+Other | AddKeyword$ Toxic:1 | Description$ Other Rats you control have toxic 1. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ When NICKNAME enters the battlefield, look at the top five cards of your library. You may reveal any number of Rat cards from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in a random order. +SVar:TrigDig:DB$ Dig | DigNum$ 5 | AnyNumber$ True | ChangeValid$ Creature.Rat | RestRandomOrder$ True +DeckNeeds:Type$Rat +Oracle:Toxic 1\nOther Rats you control have toxic 1.\nWhen Karumonix enters the battlefield, look at the top five cards of your library. You may reveal any number of Rat cards from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in a random order. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt b/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt new file mode 100644 index 00000000000..cb7b99e7c35 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt @@ -0,0 +1,11 @@ +Name:Kemba, Kha Enduring +ManaCost:1 W +Types:Creature Cat Cleric +PT:2/2 +T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.Other+Cat+YouCtrl | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigAttach | TriggerDescription$ Whenever CARDNAME or another Cat enters the battlefield under your control, attach up to one target Equipment you control to that creature. +SVar:TrigAttach:DB$ Attach | Defined$ TriggeredCard | Object$ Targeted | ValidTgts$ Equipment.YouCtrl | TgtPrompt$ Select target Equipment you control. | TargetMin$ 0 | TargetMax$ 1 +S:Mode$ Continuous | Affected$ Creature.YouCtrl+equipped | AddPower$ 1 | AddToughness$ 1 | Description$ Equipped creatures you control get +1/+1. +A:AB$ Token | Cost$ 3 W W | TokenScript$ w_2_2_cat | TokenAmount$ 1 | TokenOwner$ You | SpellDescription$ Create a 2/2 white Cat creature token. +DeckNeeds:Type$Equipment +DeckHas:Ability$Token +Oracle:Whenever Kemba, Kha Enduring or another Cat enters the battlefield under your control, attach up to one target Equipment you control to that creature.\nEquipped creatures you control get +1/+1.\n{3}{W}{W}: Create a 2/2 white Cat creature token. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt b/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt new file mode 100644 index 00000000000..e70d8c70b5a --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt @@ -0,0 +1,11 @@ +Name:Malcator, Purity Overseer +ManaCost:1 W U +Types:Creature Phyrexian Elephant Wizard +PT:1/1 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ TriggerDescription$ When CARDNAME enters the battlefield, create a 3/3 colorless Phyrexian Golem artifact creature token. +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE3 | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, if three or more artifacts entered the battlefield under your control this turn, create a 3/3 colorless Phyrexian Golem artifact creature token. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_phyrexian_golem | TokenOwner$ You +SVar:X:Count$ThisTurnEntered_Battlefield_Artifact.YouCtrl +DeckHas:Ability$Token & Type$Golem +DeckHints:Type$Artifact +Oracle:When Malcator, Purity Overseer enters the battlefield, create a 3/3 colorless Phyrexian Golem artifact creature token.\nAt the beginning of your end step, if three or more artifacts entered the battlefield under your control this turn, create a 3/3 colorless Phyrexian Golem artifact creature token. \ No newline at end of file From 9fed4432a1250b043c25d14d8dd044f6a4ae0601 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 12:18:49 +0100 Subject: [PATCH 26/37] update --- .../res/cardsfolder/upcoming/archfiend_of_the_dross.txt | 4 ++-- forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt | 2 +- forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt | 2 +- .../res/cardsfolder/upcoming/encroaching_mycosynth.txt | 4 ++-- .../res/cardsfolder/upcoming/geth_thane_of_contracts.txt | 6 ++++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt index 97637f2ee56..28f3a2241bd 100644 --- a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt +++ b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt @@ -4,10 +4,10 @@ Types:Creature Phyrexian Demon PT:6/6 K:Flying K:etbCounter:OIL:4 -T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemoveCtr | TriggerDescription$ At the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game. +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemoveCtr | TriggerDescription$ At the beginning of your upkeep, remove an oil counter from CARDNAME. Then if it has no oil counters on it, you lose the game. SVar:TrigRemoveCtr:DB$ RemoveCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1 | SubAbility$ LoseGame SVar:LoseGame:DB$ LosesGame | Defined$ You | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_OIL T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.OppCtrl | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Whenever a creature an opponent controls dies, its controller loses 2 life. SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ TriggeredCardController DeckHas:Ability$Counters -Oracle:Flying\nArchfiend of the Dross enters the battlefield with four oil counters on it.\nAt the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game.\nWhenever a creature an opponent controls dies, its controller loses 2 life. +Oracle:Flying\nArchfiend of the Dross enters the battlefield with four oil counters on it.\nAt the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game.\nWhenever a creature an opponent controls dies, its controller loses 2 life. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt index 7ce74a1bbf4..ed024929696 100644 --- a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt +++ b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt @@ -2,7 +2,7 @@ Name:Black Sun's Twilight ManaCost:X B Types:Instant A:SP$ Pump | ValidTgts$ Creature | TgtPrompt$ Select up to one target creature | TargetMin$ 0 | TargetMax$ 1 | NumAtt$ -X | NumDef$ -X | IsCurse$ True | SubAbility$ DBReanimate | SpellDescription$ Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. -SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | Chooser$ You | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | Hidden$ True | ChangeType$ Creature.YouOwn+cmcLEX +SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | Chooser$ You | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | Hidden$ True | Tapped$ True | ChangeType$ Creature.YouOwn+cmcLEX SVar:X:Count$xPaid DeckNeeds:Ability$Graveyard Oracle:Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt b/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt index 463bfcd3d7d..4a0380de4c7 100644 --- a/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt +++ b/forge-gui/res/cardsfolder/upcoming/bloated_contaminator.txt @@ -4,7 +4,7 @@ Types:Creature Phyrexian Beast PT:4/4 K:Trample K:Toxic:1 -T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigProliferate | TriggerDescription$ Whenever CARDNAME deals combat damage to a player or dies, proliferate. +T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigProliferate | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, proliferate. SVar:TrigProliferate:DB$ Proliferate DeckHas:Ability$Proliferate DeckHints:Type$Planeswalker & Ability$Counters diff --git a/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt b/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt index e2437d02d45..85295a2d0c1 100644 --- a/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt +++ b/forge-gui/res/cardsfolder/upcoming/encroaching_mycosynth.txt @@ -1,5 +1,5 @@ Name:Encroaching Mycosynth ManaCost:3 U Types:Artifact -S:Mode$ Continuous | Affected$ Permanent.nonLand+YouCtrl | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | AddType$ Artifact | Description$ Nonland permanents you control are artifacts in addition to their other types The same is true for permanent spells you control and nonland permanent cards you own that aren't on the battlefield. -Oracle:Nonland permanents you control are artifacts in addition to their other types The same is true for permanent spells you control and nonland permanent cards you own that aren't on the battlefield. \ No newline at end of file +S:Mode$ Continuous | Affected$ Permanent.nonLand+YouCtrl | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | AddType$ Artifact | Description$ Nonland permanents you control are artifacts in addition to their other types. The same is true for permanent spells you control and nonland permanent cards you own that aren't on the battlefield. +Oracle:Nonland permanents you control are artifacts in addition to their other types. The same is true for permanent spells you control and nonland permanent cards you own that aren't on the battlefield. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt b/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt index 3575e78fd48..9ee4b2d15f7 100644 --- a/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt +++ b/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt @@ -3,8 +3,10 @@ ManaCost:1 B B Types:Legendary Creature Phyrexian Zombie PT:3/4 S:Mode$ Continuous | Affected$ Creature.Other+YouCtrl | AddPower$ -1 | AddToughness$ -1 | Description$ Other creatures you control get -1/-1. -A:AB$ ChangeZone | Cost$ 1 B B T | Origin$ Graveyard | SorcerySpeed$ True | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature in your graveyard | SubAbility$ DBPump | SpellDescription$Return target creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead of putting it anywhere else." Activate only as a sorcery. -SVar:DBPump:DB$ Pump | LeaveBattlefield$ Exile | Defined$ Targeted | Duration$ Permanent +A:AB$ ChangeZone | Cost$ 1 B B T | Origin$ Graveyard | SorcerySpeed$ True | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature in your graveyard | SubAbility$ DBAnimate | SpellDescription$ Return target creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead of putting it anywhere else." Activate only as a sorcery. +SVar:DBAnimate:DB$ Animate | Replacements$ ReplaceLeaves | Defined$ Targeted | Duration$ Permanent +SVar:ReplaceLeaves:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | ValidCard$ Card.Self | ReplaceWith$ Exile | Description$ If this creature would leave the battlefield, exile it instead. +SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard DeckHints:Ability$Graveyard|Mill|Dredge DeckHas:Ability$Graveyard Oracle:Other creatures you control get -1/-1.\n{1}{B}{B}, {T}: Return target creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead of putting it anywhere else." Activate only as a sorcery. \ No newline at end of file From 913c7b2d9336312d2d9aebff9ede3ef08f1cc770 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 12:29:38 +0100 Subject: [PATCH 27/37] Update evolved_spinoderm.txt --- forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt b/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt index 1dc5ed942b7..bcfbbe088a6 100644 --- a/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt +++ b/forge-gui/res/cardsfolder/upcoming/evolved_spinoderm.txt @@ -5,9 +5,8 @@ PT:5/5 K:etbCounter:OIL:4 S:Mode$ Continuous | Affected$ Creature.Self+counters_LE2_OIL | AddKeyword$ Trample | Description$ CARDNAME has trample as long as it has two or fewer oil counters on it. Otherwise, it has hexproof. S:Mode$ Continuous | Affected$ Creature.Self+counters_GT2_OIL | AddKeyword$ Hexproof -S:Mode$ Continuous | Affected$ Creature.Self | AddPower$ -2 | AddToughness$ -1 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemoveCtr | TriggerDescription$ At the beginning of your upkeep, remove an oil counter from CARDNAME. Then if it has no oil counters on it, sacrifice it. SVar:TrigRemoveCtr:DB$ RemoveCounter | Defined$ Self | CounterType$ OIL | CounterNum$ 1 | SubAbility$ DBSacrifice SVar:DBSacrifice:DB$ Sacrifice | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_OIL DeckHas:Ability$Counters -Oracle:Evolved Spinoderm enters the battlefield with four oil counters on it.\nEvolved Spinoderm has trample as long as it has two or fewer oil counters on it. Otherwise, it has hexproof.\nAt the beginning of your upkeep, remove an oil counter from Evolved Spinoderm. Then if it has no oil counters on it, sacrifice it. \ No newline at end of file +Oracle:Evolved Spinoderm enters the battlefield with four oil counters on it.\nEvolved Spinoderm has trample as long as it has two or fewer oil counters on it. Otherwise, it has hexproof.\nAt the beginning of your upkeep, remove an oil counter from Evolved Spinoderm. Then if it has no oil counters on it, sacrifice it. From 1202a4f0f379ac4ddf713f7cbf6407fb191b1478 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:04:39 +0100 Subject: [PATCH 28/37] Update conduit_of_worlds.txt --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index 95964b09d4e..d7f02c90b77 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,8 +2,8 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | SubAbility$ DBPlay | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. -SVar:DBPlay:DB$ Play | Defined$ Targeted | ValidSA$ Spell | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect +A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | SubAbility$ DBPlay | ImprintTargets$ True | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +SVar:DBPlay:DB$ Play | Defined$ Imprinted | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. SVar:X:Count$ThisTurnCast_Spell.YouCtrl From b24d6b1b22717683ab389513fd46a53a81adcf46 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:06:19 +0100 Subject: [PATCH 29/37] Update conduit_of_worlds.txt --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index d7f02c90b77..7a392091253 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -4,8 +4,9 @@ Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | SubAbility$ DBPlay | ImprintTargets$ True | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. SVar:DBPlay:DB$ Play | Defined$ Imprinted | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect -SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast +SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. SVar:X:Count$ThisTurnCast_Spell.YouCtrl DeckHints:Ability$Graveyard|Mill|Dredge -Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. \ No newline at end of file +Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. From 132df49fe4469f96e59594181ae04c8bb5faefba Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:27:29 +0100 Subject: [PATCH 30/37] Update conduit_of_worlds.txt --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index d7f02c90b77..639e31343af 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,8 +2,7 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Pump | Cost$ T | Defined$ You | SorcerySpeed$ True | ValidTgts$ Permanent.nonLand+YouOwn | PumpZone$ Graveyard | TgtZone$ Graveyard | TgtPrompt$ Choose a creature card in your graveyard | SubAbility$ DBPlay | ImprintTargets$ True | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. -SVar:DBPlay:DB$ Play | Defined$ Imprinted | ConditionCheckSVar$ X | CondtionSVarCompare$ EQ0 | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect +A:AB$ Play | Cost$ T | Defined$ Targeted | SorcerySpeed$ True | TgtPrompt$ Choose a creature card in your graveyard | CheckSVar$ X | SVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect |SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. SVar:X:Count$ThisTurnCast_Spell.YouCtrl From f45447b8169f5dbcfc0331f4e8f88ab91b0c8565 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:29:03 +0100 Subject: [PATCH 31/37] Update conduit_of_worlds.txt --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index 639e31343af..0370b637243 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,9 +2,10 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Play | Cost$ T | Defined$ Targeted | SorcerySpeed$ True | TgtPrompt$ Choose a creature card in your graveyard | CheckSVar$ X | SVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect |SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. -SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast +A:AB$ Play | Cost$ T | Defined$ Targeted | ValidSA$ Spell | SorcerySpeed$ True | TgtPrompt$ Choose a creature card in your graveyard | CheckSVar$ X | SVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect |SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast | SubAbility$ DBCleanup SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Count$ThisTurnCast_Spell.YouCtrl DeckHints:Ability$Graveyard|Mill|Dredge -Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. \ No newline at end of file +Oracle:You may play lands from your graveyard.\n{T}: Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. From 8680630d4b49274835e1b8efcf98c9ea5134403b Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 15:38:39 +0100 Subject: [PATCH 32/37] Update conduit_of_worlds.txt --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index 0370b637243..abcc646a5fe 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,7 +2,7 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Play | Cost$ T | Defined$ Targeted | ValidSA$ Spell | SorcerySpeed$ True | TgtPrompt$ Choose a creature card in your graveyard | CheckSVar$ X | SVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect |SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +A:AB$ Play | Cost$ T | ValidSA$ Spell | SorcerySpeed$ True | TgtPrompt$ Choose a creature card in your graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast | SubAbility$ DBCleanup SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True From 73a9c83b05c6dad467c7e8ee5508836744ca2cec Mon Sep 17 00:00:00 2001 From: Northmoc <103371817+Northmoc@users.noreply.github.com> Date: Tue, 10 Jan 2023 09:55:00 -0500 Subject: [PATCH 33/37] ONE: Elesh Norn, Mother of Machines and support (#2179) * elesh_norn_mother_of_machines.txt * StaticAbilityDisableTriggers.java --- .../src/main/java/forge/ai/AiController.java | 12 +- .../java/forge/game/GlobalRuleChange.java | 2 - .../java/forge/game/ability/AbilityKey.java | 1 + .../StaticAbilityDisableTriggers.java | 127 ++++++++++++++++++ .../StaticAbilityPanharmonicon.java | 8 +- .../game/trigger/TriggerAbilityTriggered.java | 2 +- .../forge/game/trigger/TriggerHandler.java | 75 +---------- .../ai/simulation/GameSimulationTest.java | 37 +++++ forge-gui/res/cardsfolder/h/hushbringer.txt | 5 +- .../res/cardsfolder/h/hushwing_gryff.txt | 2 +- .../res/cardsfolder/t/tocatli_honor_guard.txt | 3 +- forge-gui/res/cardsfolder/t/torpor_orb.txt | 2 +- .../elesh_norn_mother_of_machines.txt | 8 ++ 13 files changed, 198 insertions(+), 86 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/staticability/StaticAbilityDisableTriggers.java create mode 100644 forge-gui/res/cardsfolder/upcoming/elesh_norn_mother_of_machines.txt diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 2b97b75890d..0c862cd8d87 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -54,6 +54,7 @@ import forge.game.replacement.ReplacementLayer; import forge.game.replacement.ReplacementType; import forge.game.spellability.*; import forge.game.staticability.StaticAbility; +import forge.game.staticability.StaticAbilityDisableTriggers; import forge.game.staticability.StaticAbilityMustTarget; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerType; @@ -262,11 +263,6 @@ public class AiController { } } - if (card.isCreature() - && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers)) { - return api == null; - } - boolean rightapi = false; // Trigger play improvements @@ -281,6 +277,12 @@ public class AiController { continue; } + final Map runParams = AbilityKey.mapFromCard(tr.getHostCard()); + runParams.put(AbilityKey.Destination, ZoneType.Battlefield.name()); + if (StaticAbilityDisableTriggers.disabled(game, tr, runParams)) { + return api == null; + } + if (tr.hasParam("ValidCard")) { String validCard = tr.getParam("ValidCard"); if (!validCard.contains("Self")) { diff --git a/forge-game/src/main/java/forge/game/GlobalRuleChange.java b/forge-game/src/main/java/forge/game/GlobalRuleChange.java index ef364c1b354..26480436bba 100644 --- a/forge-game/src/main/java/forge/game/GlobalRuleChange.java +++ b/forge-game/src/main/java/forge/game/GlobalRuleChange.java @@ -25,8 +25,6 @@ public enum GlobalRuleChange { alwaysWither ("All damage is dealt as though its source had wither."), attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."), manaBurn ("A player losing unspent mana causes that player to lose that much life."), - noCreatureETBTriggers ("Creatures entering the battlefield don't cause abilities to trigger."), - noCreatureDyingTriggers ("Creatures dying don't cause abilities to trigger."), noNight ("It can't become night."), /* onlyOneAttackerATurn ("No more than one creature can attack each turn."), */ onlyOneAttackerACombat ("No more than one creature can attack each combat."), diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index 72c85a515f5..c03300096ab 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -31,6 +31,7 @@ public enum AbilityKey { CastSA("CastSA"), Card("Card"), Cards("Cards"), + CardsFiltered("CardsFiltered"), CardLKI("CardLKI"), Cause("Cause"), Causer("Causer"), diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityDisableTriggers.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityDisableTriggers.java new file mode 100644 index 00000000000..efeee10ec00 --- /dev/null +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityDisableTriggers.java @@ -0,0 +1,127 @@ +package forge.game.staticability; + +import com.google.common.base.Predicates; +import com.google.common.collect.Table.Cell; + +import forge.game.Game; +import forge.game.card.*; +import forge.game.ability.AbilityKey; +import forge.game.trigger.Trigger; +import forge.game.trigger.TriggerType; +import forge.game.zone.ZoneType; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.Map; + +public class StaticAbilityDisableTriggers { + + static String MODE = "DisableTriggers"; + + public static boolean disabled(final Game game, final Trigger regtrig, final Map runParams) { + CardCollectionView cardList = null; + // if LTB look back + if ((regtrig.getMode() == TriggerType.ChangesZone || regtrig.getMode() == TriggerType.ChangesZoneAll) && "Battlefield".equals(regtrig.getParam("Origin"))) { + if (runParams.containsKey(AbilityKey.LastStateBattlefield)) { + cardList = (CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield); + } + if (cardList == null) { + cardList = game.getLastStateBattlefield(); + } + } else { + cardList = game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES); + } + + for (final Card ca : cardList) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } + + if (isDisabled(stAb, regtrig, runParams)) { + return true; + } + } + } + return false; + } + + public static boolean isDisabled(final StaticAbility stAb, final Trigger regtrig, final Map runParams) { + final TriggerType trigMode = regtrig.getMode(); + + // CR 603.2e + if (stAb.hasParam("ValidCard") && regtrig.getSpawningAbility() != null) { + return false; + } + + if (!stAb.matchesValidParam("ValidCard", regtrig.getHostCard())) { + return false; + } + + if (stAb.hasParam("ValidMode")) { + if (!ArrayUtils.contains(stAb.getParam("ValidMode").split(","), trigMode.toString())) { + return false; + } + } + + if (trigMode.equals(TriggerType.ChangesZone)) { + // Cause of the trigger – the card changing zones + if (!stAb.matchesValidParam("ValidCause", runParams.get(AbilityKey.Card))) { + return false; + } + if (!stAb.matchesValidParam("Destination", runParams.get(AbilityKey.Destination))) { + return false; + } + if (!stAb.matchesValidParam("Origin", runParams.get(AbilityKey.Origin))) { + return false; + } + if ("Graveyard".equals(runParams.get(AbilityKey.Destination)) + && "Battlefield".equals(runParams.get(AbilityKey.Origin))) { + // Allow triggered ability of a dying creature that triggers + // only when that creature is put into a graveyard from anywhere + if ("Card.Self".equals(regtrig.getParam("ValidCard")) + && (!regtrig.hasParam("Origin") || "Any".equals(regtrig.getParam("Origin")))) { + return false; + } + } + } else if (trigMode.equals(TriggerType.ChangesZoneAll)) { + final String origin = stAb.getParam("Origin"); + final String destination = stAb.getParam("Destination"); + // check if some causes were already ignored by a different ability, then the forbidden causes will be combined + CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.CardsFiltered); + if (table == null) { + table = (CardZoneTable) runParams.get(AbilityKey.Cards); + } + CardZoneTable filtered = new CardZoneTable(); + boolean possiblyDisabled = false; + + // purge all forbidden causes from table + for (Cell cell : table.cellSet()) { + CardCollection changers = cell.getValue(); + if ((origin == null || cell.getRowKey() == ZoneType.valueOf(origin)) && + (destination == null || cell.getColumnKey() == ZoneType.valueOf(destination))) { + changers = CardLists.filter(changers, Predicates.not(CardPredicates.restriction(stAb.getParam("ValidCause").split(","), stAb.getHostCard().getController(), stAb.getHostCard(), stAb))); + // static will match some of the causes + if (changers.size() < cell.getValue().size()) { + possiblyDisabled = true; + } + } + filtered.put(cell.getRowKey(), cell.getColumnKey(), changers); + } + + if (!possiblyDisabled) { + return false; + } + + // test if trigger would still fire when ignoring forbidden causes + final Map runParamsFiltered = AbilityKey.newMap(runParams); + runParamsFiltered.put(AbilityKey.Cards, filtered); + if (regtrig.performTest(runParamsFiltered)) { + // store the filtered Cards because Panharmonicon shouldn't see the others + runParams.put(AbilityKey.CardsFiltered, filtered); + + return false; + } + } + return true; + } +} diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityPanharmonicon.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityPanharmonicon.java index 00ee0ccc414..377a2ac608d 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityPanharmonicon.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityPanharmonicon.java @@ -37,7 +37,7 @@ public class StaticAbilityPanharmonicon { CardCollectionView cardList = null; // if LTB look back - if (t.getMode() == TriggerType.ChangesZone && "Battlefield".equals(t.getParam("Origin"))) { + if ((t.getMode() == TriggerType.ChangesZone || t.getMode() == TriggerType.ChangesZoneAll) && "Battlefield".equals(t.getParam("Origin"))) { if (runParams.containsKey(AbilityKey.LastStateBattlefield)) { cardList = (CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield); } @@ -102,7 +102,11 @@ public class StaticAbilityPanharmonicon { // Check if the cards have a trigger at all final String origin = stAb.getParam("Origin"); final String destination = stAb.getParam("Destination"); - final CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards); + // check if some causes were ignored + CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.CardsFiltered); + if (table == null) { + table = (CardZoneTable) runParams.get(AbilityKey.Cards); + } if (table.filterCards(origin == null ? null : ImmutableList.of(ZoneType.smartValueOf(origin)), ZoneType.smartValueOf(destination), stAb.getParam("ValidCause"), card, stAb).isEmpty()) { return false; diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerAbilityTriggered.java b/forge-game/src/main/java/forge/game/trigger/TriggerAbilityTriggered.java index e3fa7bf0946..e17b405baf6 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerAbilityTriggered.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerAbilityTriggered.java @@ -83,7 +83,7 @@ public class TriggerAbilityTriggered extends Trigger { if (!matchesValidParam("ValidCause", causes)) { return false; } - + if (hasParam("TriggeredOwnAbility") && "True".equals(getParam("TriggeredOwnAbility")) && !Iterables.contains(causes, source)) { return false; } 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 7f33bc8604a..be0b3aa8c1e 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -19,18 +19,15 @@ package forge.game.trigger; import java.util.*; -import com.google.common.base.Predicates; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimaps; -import com.google.common.collect.Table.Cell; import forge.game.CardTraitBase; import forge.game.CardTraitPredicates; import forge.game.Game; -import forge.game.GlobalRuleChange; import forge.game.IHasSVars; import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityKey; @@ -39,6 +36,7 @@ import forge.game.card.*; import forge.game.player.Player; import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; +import forge.game.staticability.StaticAbilityDisableTriggers; import forge.game.staticability.StaticAbilityPanharmonicon; import forge.game.zone.Zone; import forge.game.zone.ZoneType; @@ -445,74 +443,9 @@ public class TriggerHandler { } } - // Torpor Orb check - if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers) - && !regtrig.isStatic()) { - if (mode.equals(TriggerType.ChangesZone)) { - if (runParams.get(AbilityKey.Destination) instanceof String) { - final String dest = (String) runParams.get(AbilityKey.Destination); - if (dest.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) { - final Card card = (Card) runParams.get(AbilityKey.Card); - if (card.isCreature()) { - return false; - } - } - } - } else if (mode.equals(TriggerType.ChangesZoneAll)) { - CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards); - // find out if any other cards would still trigger it - boolean found = false; - for (Cell cell : table.cellSet()) { - // this currently assumes the table will not contain multiple destinations - // however with some effects (e.g. Goblin Welder) that should indeed be the case - // once Forge handles that correctly this section needs to account for that - // (by doing a closer check of the triggered ability first) - if (cell.getColumnKey() != ZoneType.Battlefield) { - found = true; - } else if (Iterables.any(cell.getValue(), Predicates.not(CardPredicates.isType("Creature")))) { - found = true; - } - if (found) break; - } - if (!found) { - return false; - } - } - } // Torpor Orb check - - if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureDyingTriggers) - && !regtrig.isStatic()) { - if (mode.equals(TriggerType.ChangesZone)) { - if (runParams.get(AbilityKey.Destination) instanceof String && runParams.get(AbilityKey.Origin) instanceof String) { - final String dest = (String) runParams.get(AbilityKey.Destination); - final String origin = (String) runParams.get(AbilityKey.Origin); - if (dest.equals("Graveyard") && origin.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) { - // It will trigger if the ability is of a dying creature that triggers only when that creature is put into a graveyard from anywhere - if (!"Card.Self".equals(regtrig.getParam("ValidCard")) || (regtrig.hasParam("Origin") && !"Any".equals(regtrig.getParam("Origin")))) { - final Card card = (Card) runParams.get(AbilityKey.Card); - if (card.isCreature()) { - return false; - } - } - } - } - } else if (mode.equals(TriggerType.ChangesZoneAll)) { - CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards); - boolean found = false; - for (Cell cell : table.cellSet()) { - if (cell.getRowKey() != ZoneType.Battlefield) { - found = true; - } else if (cell.getColumnKey() != ZoneType.Graveyard) { - found = true; - } else if (Iterables.any(cell.getValue(), Predicates.not(CardPredicates.isType("Creature")))) { - found = true; - } - if (found) break; - } - if (!found) { - return false; - } - } + // check if any static abilities are disabling the trigger (Torpor Orb and the like) + if (!regtrig.isStatic() && StaticAbilityDisableTriggers.disabled(game, regtrig, runParams)) { + return false; } return true; } diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java index 3355b6f10b7..066583e4366 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java @@ -2495,4 +2495,41 @@ public class GameSimulationTest extends SimulationTest { AssertJUnit.assertNotNull(simMentor); AssertJUnit.assertEquals(1, simMentor.getCounters(CounterEnumType.P1P1)); } + + @Test + public void testHushbringer() { + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + + addCard("Naban, Dean of Iteration", p); + addCard("Hushbringer", p); + addCard("Ingenious Artillerist", p); + + // both ETB together and Artillerist should still trigger from the non-creature + addCardToZone("Spellbook", p, ZoneType.Library); + // whereas Naban doesn't see Memnarch to double the trigger + addCardToZone("Memnarch", p, ZoneType.Library); + + addCard("Forest", p); + addCard("Forest", p); + addCard("Island", p); + addCard("Island", p); + addCard("Island", p); + addCard("Mountain", p); + addCard("Mountain", p); + + Card genesis = addCardToZone("Genesis Ultimatum", p, ZoneType.Hand); + + SpellAbility genesisSA = genesis.getFirstSpellAbility(); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + game.getAction().checkStateEffects(true); + + GameSimulator sim = createSimulator(game, p); + sim.simulateSpellAbility(genesisSA); + Game simGame = sim.getSimulatedGameState(); + + // 2 damage dealt for 2 artifacts + AssertJUnit.assertEquals(18, simGame.getPlayers().get(1).getLife()); + } } diff --git a/forge-gui/res/cardsfolder/h/hushbringer.txt b/forge-gui/res/cardsfolder/h/hushbringer.txt index 3fc0204661c..3265bc793d8 100644 --- a/forge-gui/res/cardsfolder/h/hushbringer.txt +++ b/forge-gui/res/cardsfolder/h/hushbringer.txt @@ -4,7 +4,8 @@ Types:Creature Faerie PT:1/2 K:Flying K:Lifelink -S:Mode$ Continuous | GlobalRule$ Creatures entering the battlefield don't cause abilities to trigger. | Description$ Creatures entering the battlefield or dying don't cause abilities to trigger. -S:Mode$ Continuous | GlobalRule$ Creatures dying don't cause abilities to trigger. | Secondary$ True | Description$ Creatures entering the battlefield or dying don't cause abilities to trigger. +S:Mode$ DisableTriggers | ValidCause$ Creature | ValidMode$ ChangesZone,ChangesZoneAll | Destination$ Battlefield | Description$ Creatures entering the battlefield or dying don't cause abilities to trigger. +S:Mode$ DisableTriggers | ValidCause$ Creature | ValidMode$ ChangesZone,ChangesZoneAll | Origin$ Battlefield | Destination$ Graveyard | Secondary$ True | Description$ Creatures entering the battlefield or dying don't cause abilities to trigger. AI:RemoveDeck:Random +DeckHas:Ability$LifeGain Oracle:Flying, lifelink\nCreatures entering the battlefield or dying don't cause abilities to trigger. diff --git a/forge-gui/res/cardsfolder/h/hushwing_gryff.txt b/forge-gui/res/cardsfolder/h/hushwing_gryff.txt index ab0d71c5894..6aa9a77b09e 100644 --- a/forge-gui/res/cardsfolder/h/hushwing_gryff.txt +++ b/forge-gui/res/cardsfolder/h/hushwing_gryff.txt @@ -4,6 +4,6 @@ Types:Creature Hippogriff PT:2/1 K:Flash K:Flying -S:Mode$ Continuous | GlobalRule$ Creatures entering the battlefield don't cause abilities to trigger. | Description$ Creatures entering the battlefield don't cause abilities to trigger. +S:Mode$ DisableTriggers | ValidCause$ Creature | ValidMode$ ChangesZone,ChangesZoneAll | Destination$ Battlefield | Description$ Creatures entering the battlefield don't cause abilities to trigger. AI:RemoveDeck:Random Oracle:Flash\nFlying\nCreatures entering the battlefield don't cause abilities to trigger. diff --git a/forge-gui/res/cardsfolder/t/tocatli_honor_guard.txt b/forge-gui/res/cardsfolder/t/tocatli_honor_guard.txt index da597558dc2..3a490f3aa6a 100644 --- a/forge-gui/res/cardsfolder/t/tocatli_honor_guard.txt +++ b/forge-gui/res/cardsfolder/t/tocatli_honor_guard.txt @@ -2,5 +2,6 @@ Name:Tocatli Honor Guard ManaCost:1 W Types:Creature Human Soldier PT:1/3 -S:Mode$ Continuous | GlobalRule$ Creatures entering the battlefield don't cause abilities to trigger. | Description$ Creatures entering the battlefield don't cause abilities to trigger. +S:Mode$ DisableTriggers | ValidCause$ Creature | ValidMode$ ChangesZone,ChangesZoneAll | Destination$ Battlefield | Description$ Creatures entering the battlefield don't cause abilities to trigger. +AI:RemoveDeck:Random Oracle:Creatures entering the battlefield don't cause abilities to trigger. diff --git a/forge-gui/res/cardsfolder/t/torpor_orb.txt b/forge-gui/res/cardsfolder/t/torpor_orb.txt index a71f3ba25b7..6afd7bfab0f 100644 --- a/forge-gui/res/cardsfolder/t/torpor_orb.txt +++ b/forge-gui/res/cardsfolder/t/torpor_orb.txt @@ -1,7 +1,7 @@ Name:Torpor Orb ManaCost:2 Types:Artifact -S:Mode$ Continuous | GlobalRule$ Creatures entering the battlefield don't cause abilities to trigger. | Description$ Creatures entering the battlefield don't cause abilities to trigger. +S:Mode$ DisableTriggers | ValidCause$ Creature | ValidMode$ ChangesZone,ChangesZoneAll | Destination$ Battlefield | Description$ Creatures entering the battlefield don't cause abilities to trigger. SVar:NonStackingEffect:True AI:RemoveDeck:Random Oracle:Creatures entering the battlefield don't cause abilities to trigger. diff --git a/forge-gui/res/cardsfolder/upcoming/elesh_norn_mother_of_machines.txt b/forge-gui/res/cardsfolder/upcoming/elesh_norn_mother_of_machines.txt new file mode 100644 index 00000000000..9d3236ba682 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/elesh_norn_mother_of_machines.txt @@ -0,0 +1,8 @@ +Name:Elesh Norn, Mother of Machines +ManaCost:4 W +Types:Legendary Creature Phyrexian Praetor +PT:4/7 +K:Vigilance +S:Mode$ Panharmonicon | ValidMode$ ChangesZone,ChangesZoneAll | ValidCard$ Permanent.YouCtrl | ValidCause$ Permanent | Destination$ Battlefield | Description$ If a permanent entering the battlefield under your control causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. +S:Mode$ DisableTriggers | ValidCause$ Permanent | ValidMode$ ChangesZone,ChangesZoneAll | Destination$ Battlefield | ValidCard$ Permanent.OppCtrl | Description$ Permanents entering the battlefield don't cause abilities of permanents your opponents control to trigger. +Oracle:Vigilance\nIf a permanent entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.\nPermanents entering the battlefield don't cause abilities of permanents your opponents control to trigger. From dd3423572898429e1498ef5c1c50b62a568b875a Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:31:17 +0100 Subject: [PATCH 34/37] update --- forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt | 1 + forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt | 2 +- forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt index 28f3a2241bd..f4a204470e0 100644 --- a/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt +++ b/forge-gui/res/cardsfolder/upcoming/archfiend_of_the_dross.txt @@ -10,4 +10,5 @@ SVar:LoseGame:DB$ LosesGame | Defined$ You | ConditionDefined$ Self | ConditionP T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.OppCtrl | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ Whenever a creature an opponent controls dies, its controller loses 2 life. SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ TriggeredCardController DeckHas:Ability$Counters +AI:RemoveDeck:Random Oracle:Flying\nArchfiend of the Dross enters the battlefield with four oil counters on it.\nAt the beginning of your upkeep, remove an oil counter from Archfiend of the Dross. Then if it has no oil counters on it, you lose the game.\nWhenever a creature an opponent controls dies, its controller loses 2 life. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt index ed024929696..d55498242ce 100644 --- a/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt +++ b/forge-gui/res/cardsfolder/upcoming/black_suns_twilight.txt @@ -4,5 +4,5 @@ Types:Instant A:SP$ Pump | ValidTgts$ Creature | TgtPrompt$ Select up to one target creature | TargetMin$ 0 | TargetMax$ 1 | NumAtt$ -X | NumDef$ -X | IsCurse$ True | SubAbility$ DBReanimate | SpellDescription$ Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. SVar:DBReanimate:DB$ ChangeZone | Origin$ Graveyard | Chooser$ You | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5 | Destination$ Battlefield | Hidden$ True | Tapped$ True | ChangeType$ Creature.YouOwn+cmcLEX SVar:X:Count$xPaid -DeckNeeds:Ability$Graveyard +DeckHas:Ability$Graveyard Oracle:Up to one target creature gets -X/-X until end of turn. If X is 5 or more, return a creature card with mana value X or less from your graveyard to the battlefield tapped. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt b/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt index 9ee4b2d15f7..fc68119799d 100644 --- a/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt +++ b/forge-gui/res/cardsfolder/upcoming/geth_thane_of_contracts.txt @@ -7,6 +7,6 @@ A:AB$ ChangeZone | Cost$ 1 B B T | Origin$ Graveyard | SorcerySpeed$ True | Dest SVar:DBAnimate:DB$ Animate | Replacements$ ReplaceLeaves | Defined$ Targeted | Duration$ Permanent SVar:ReplaceLeaves:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | ValidCard$ Card.Self | ReplaceWith$ Exile | Description$ If this creature would leave the battlefield, exile it instead. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard -DeckHints:Ability$Graveyard|Mill|Dredge +DeckHints:Ability$Graveyard|Mill|Dredge|Sacrifice DeckHas:Ability$Graveyard Oracle:Other creatures you control get -1/-1.\n{1}{B}{B}, {T}: Return target creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead of putting it anywhere else." Activate only as a sorcery. \ No newline at end of file From 8912bcb2cba592e0eb3063cca5863e2f7dfaaaf2 Mon Sep 17 00:00:00 2001 From: Simisays <67333662+Simisays@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:34:51 +0100 Subject: [PATCH 35/37] update --- forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt | 2 +- forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt | 2 +- forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt | 4 ++-- forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt | 2 +- .../res/cardsfolder/upcoming/malcator_purity_overseer.txt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt index abcc646a5fe..f45e4e31ee3 100644 --- a/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt +++ b/forge-gui/res/cardsfolder/upcoming/conduit_of_worlds.txt @@ -2,7 +2,7 @@ Name:Conduit of Worlds ManaCost:2 G G Types:Artifact S:Mode$ Continuous | Affected$ Land.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands from your graveyard. -A:AB$ Play | Cost$ T | ValidSA$ Spell | SorcerySpeed$ True | TgtPrompt$ Choose a creature card in your graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. +A:AB$ Play | Cost$ T | ValidSA$ Spell | SorcerySpeed$ True | TgtPrompt$ Choose target nonland permanent card in your graveyard | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ0 | TgtZone$ Graveyard | ValidTgts$ Permanent.nonLand+YouOwn | RememberPlayed$ True | Optional$ True | SubAbility$ DBEffect | SpellDescription$ Choose target nonland permanent card in your graveyard. If you haven't cast a spell this turn, you may cast that card. If you do, you can't cast additional spells this turn. Activate only as a sorcery. SVar:DBEffect:DB$ Effect | Name$ Conduit of Worlds's Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | StaticAbilities$ STCantBeCast | SubAbility$ DBCleanup SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ You | Description$ You can't cast additional spells this turn. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt b/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt index 6fa43e30f27..96a92193828 100644 --- a/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt +++ b/forge-gui/res/cardsfolder/upcoming/glissa_sunslayer.txt @@ -10,4 +10,4 @@ SVar:DBDraw:DB$ Draw | SubAbility$ DBLoseLife | SpellDescription$ You draw a car SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 1 SVar:DBDestroy:DB$ Destroy | ValidTgts$ Enchantment | SpellDescription$ Destroy target enchantment. SVar:DBRemove:DB$ RemoveCounter | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ 3 | SpellDescription$ Remove up to three counters from target permanent. -Oracle:Whenever Glissa Sunslayer deals combat damage to a player, choose one —\n• You draw a card and you lose 1 life.\n• Destroy target enchantment.\n• Remove up to three counters from target permanent. \ No newline at end of file +Oracle:First strike, deathtouch\nWhenever Glissa Sunslayer deals combat damage to a player, choose one —\n• You draw a card and you lose 1 life.\n• Destroy target enchantment.\n• Remove up to three counters from target permanent. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt b/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt index b05781e8408..9ba5deffb8c 100644 --- a/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt +++ b/forge-gui/res/cardsfolder/upcoming/karumonix_the_rat_king.txt @@ -3,8 +3,8 @@ ManaCost:1 B B Types:Legendary Creature Phyrexian Rat PT:3/3 K:Toxic:1 -S:Mode$ Continuous | Affected$ Creature.Rat+YouCtrl+Other | AddKeyword$ Toxic:1 | Description$ Other Rats you control have toxic 1. +S:Mode$ Continuous | Affected$ Rat.YouCtrl+Other | AddKeyword$ Toxic:1 | Description$ Other Rats you control have toxic 1. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ When NICKNAME enters the battlefield, look at the top five cards of your library. You may reveal any number of Rat cards from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in a random order. -SVar:TrigDig:DB$ Dig | DigNum$ 5 | AnyNumber$ True | ChangeValid$ Creature.Rat | RestRandomOrder$ True +SVar:TrigDig:DB$ Dig | DigNum$ 5 | AnyNumber$ True | ChangeValid$ Rat | RestRandomOrder$ True DeckNeeds:Type$Rat Oracle:Toxic 1\nOther Rats you control have toxic 1.\nWhen Karumonix enters the battlefield, look at the top five cards of your library. You may reveal any number of Rat cards from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in a random order. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt b/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt index cb7b99e7c35..7917bb03d44 100644 --- a/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt +++ b/forge-gui/res/cardsfolder/upcoming/kemba_kha_enduring.txt @@ -3,7 +3,7 @@ ManaCost:1 W Types:Creature Cat Cleric PT:2/2 T:Mode$ ChangesZone | ValidCard$ Card.Self,Creature.Other+Cat+YouCtrl | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigAttach | TriggerDescription$ Whenever CARDNAME or another Cat enters the battlefield under your control, attach up to one target Equipment you control to that creature. -SVar:TrigAttach:DB$ Attach | Defined$ TriggeredCard | Object$ Targeted | ValidTgts$ Equipment.YouCtrl | TgtPrompt$ Select target Equipment you control. | TargetMin$ 0 | TargetMax$ 1 +SVar:TrigAttach:DB$ Attach | Defined$ TriggeredCard | Object$ Targeted | ValidTgts$ Equipment.YouCtrl | TgtPrompt$ Select up to one target Equipment you control | TargetMin$ 0 | TargetMax$ 1 S:Mode$ Continuous | Affected$ Creature.YouCtrl+equipped | AddPower$ 1 | AddToughness$ 1 | Description$ Equipped creatures you control get +1/+1. A:AB$ Token | Cost$ 3 W W | TokenScript$ w_2_2_cat | TokenAmount$ 1 | TokenOwner$ You | SpellDescription$ Create a 2/2 white Cat creature token. DeckNeeds:Type$Equipment diff --git a/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt b/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt index e70d8c70b5a..83d86655aa4 100644 --- a/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt +++ b/forge-gui/res/cardsfolder/upcoming/malcator_purity_overseer.txt @@ -6,6 +6,6 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE3 | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, if three or more artifacts entered the battlefield under your control this turn, create a 3/3 colorless Phyrexian Golem artifact creature token. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_3_3_a_phyrexian_golem | TokenOwner$ You SVar:X:Count$ThisTurnEntered_Battlefield_Artifact.YouCtrl -DeckHas:Ability$Token & Type$Golem +DeckHas:Ability$Token & Type$Golem|Artifact DeckHints:Type$Artifact Oracle:When Malcator, Purity Overseer enters the battlefield, create a 3/3 colorless Phyrexian Golem artifact creature token.\nAt the beginning of your end step, if three or more artifacts entered the battlefield under your control this turn, create a 3/3 colorless Phyrexian Golem artifact creature token. \ No newline at end of file From af2fd2cc111771486861675d450c7306c3b8c811 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 11 Jan 2023 02:53:03 +0800 Subject: [PATCH 36/37] Update tamiyo_compleated_sage.txt - closes #2226 --- forge-gui/res/cardsfolder/t/tamiyo_compleated_sage.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/t/tamiyo_compleated_sage.txt b/forge-gui/res/cardsfolder/t/tamiyo_compleated_sage.txt index 0c8b707251b..963bea784d3 100644 --- a/forge-gui/res/cardsfolder/t/tamiyo_compleated_sage.txt +++ b/forge-gui/res/cardsfolder/t/tamiyo_compleated_sage.txt @@ -5,7 +5,7 @@ Loyalty:5 K:Compleated A:AB$ Tap | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Artifact,Creature | TgtPrompt$ Select up to one target artifact or creature | TargetMin$ 0 | TargetMax$ 1 | SubAbility$ DBPump | SpellDescription$ Tap up to one target artifact or creature. It doesn't untap during its controller's next untap step. SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ HIDDEN This card doesn't untap during your next untap step. | Duration$ Permanent -A:AB$ ChangeZone | Cost$ SubCounter | Planeswalker$ True | ValidTgts$ Permanent.nonLand+cmcEQX | TgtPrompt$ Select target nonland permanent card with mana value X | AILogic$ BestCard | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBCopy | SpellDescription$ Exile target nonland permanent card with mana value X from your graveyard. +A:AB$ ChangeZone | Cost$ SubCounter | Planeswalker$ True | ValidTgts$ Permanent.nonLand+cmcEQX+YouCtrl | TgtPrompt$ Select target nonland permanent card with mana value X | AILogic$ BestCard | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBCopy | SpellDescription$ Exile target nonland permanent card with mana value X from your graveyard. SVar:DBCopy:DB$ CopyPermanent | Defined$ Targeted | SpellDescription$ Create a token that's a copy of that card. SVar:X:Count$xPaid A:AB$ Token | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | TokenScript$ tamiyos_notebook | SpellDescription$ Create Tamiyo's Notebook, a legendary colorless artifact token with "Spells you cast cost {2} less to cast" and "{T}: Draw a card." From 876668c3709591c9e7fef2569590e9eeab2665e4 Mon Sep 17 00:00:00 2001 From: tool4ever Date: Wed, 11 Jan 2023 12:06:12 +0100 Subject: [PATCH 37/37] Fix Stack Overflow (#2228) * Fix cards * Fix Stack Overflow * Performance fix Co-authored-by: tool4EvEr Co-authored-by: TRT <> --- .../src/main/java/forge/ai/ComputerUtil.java | 32 +++++++++++++------ .../java/forge/ai/ComputerUtilCombat.java | 21 ++++++------ .../main/java/forge/ai/ComputerUtilCost.java | 9 +++--- .../main/java/forge/ai/ComputerUtilMana.java | 14 ++++---- .../game/ability/SpellAbilityEffect.java | 10 +++--- .../main/java/forge/game/cost/CostExert.java | 1 - .../forge/game/cost/CostPutCardToLib.java | 3 +- .../cardsfolder/f/flayer_of_the_hatebound.txt | 2 +- .../cardsfolder/p/phyrexian_dragon_engine.txt | 2 +- 9 files changed, 53 insertions(+), 41 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index 8ab5228fc26..abfc9e97348 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -33,6 +33,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import forge.ai.AiCardMemory.MemorySet; import forge.ai.ability.ChooseGenericEffectAi; import forge.ai.ability.ProtectAi; import forge.ai.ability.TokenAi; @@ -449,14 +450,27 @@ public class ComputerUtil { } // try everything when about to die - if (game.getPhaseHandler().getPhase().equals(PhaseType.COMBAT_DECLARE_BLOCKERS) - && ComputerUtilCombat.lifeInSeriousDanger(ai, game.getCombat())) { - final CardCollection nonCreatures = CardLists.getNotType(typeList, "Creature"); - if (!nonCreatures.isEmpty()) { - return ComputerUtilCard.getWorstAI(nonCreatures); - } else if (!typeList.isEmpty()) { - // TODO make sure survival is possible in case the creature blocks a trampler - return ComputerUtilCard.getWorstAI(typeList); + if (game.getPhaseHandler().getPhase().equals(PhaseType.COMBAT_DECLARE_BLOCKERS)) { + // in some rare situations the call to lifeInDanger could lead us back here, this will prevent an overflow + boolean preventReturn = sa != null && sa.isManaAbility(); + if (preventReturn) { + AiCardMemory.rememberCard(ai, sa.getHostCard(), MemorySet.HELD_MANA_SOURCES_FOR_NEXT_SPELL); + } + + boolean danger = ComputerUtilCombat.lifeInSeriousDanger(ai, game.getCombat()); + + if (preventReturn) { + AiCardMemory.forgetCard(ai, sa.getHostCard(), MemorySet.HELD_MANA_SOURCES_FOR_NEXT_SPELL); + } + + if (danger) { + final CardCollection nonCreatures = CardLists.getNotType(typeList, "Creature"); + if (!nonCreatures.isEmpty()) { + return ComputerUtilCard.getWorstAI(nonCreatures); + } else if (!typeList.isEmpty()) { + // TODO make sure survival is possible in case the creature blocks a trampler + return ComputerUtilCard.getWorstAI(typeList); + } } } } @@ -609,7 +623,7 @@ public class ComputerUtil { int count = 0; while (count < amount) { - Card prefCard = getCardPreference(ai, source, "SacCost", typeList); + Card prefCard = getCardPreference(ai, source, "SacCost", typeList, ability); if (prefCard == null) { prefCard = ComputerUtilCard.getWorstAI(typeList); } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index a1428d824b3..656645992f4 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -328,10 +328,10 @@ public class ComputerUtilCombat { if (blockers.size() == 0 || StaticAbilityAssignCombatDamageAsUnblocked.assignCombatDamageAsUnblocked(attacker)) { unblocked.add(attacker); - } else if (attacker.hasKeyword(Keyword.TRAMPLE) - && getAttack(attacker) > totalShieldDamage(attacker, blockers)) { - if (!attacker.hasKeyword(Keyword.INFECT)) { - damage += getAttack(attacker) - totalShieldDamage(attacker, blockers); + } else if (attacker.hasKeyword(Keyword.TRAMPLE) && !attacker.hasKeyword(Keyword.INFECT)) { + int dmgAfterShielding = getAttack(attacker) - totalShieldDamage(attacker, blockers); + if (dmgAfterShielding > 0) { + damage += dmgAfterShielding; } } } @@ -369,13 +369,14 @@ public class ComputerUtilCombat { if (blockers.size() == 0 || StaticAbilityAssignCombatDamageAsUnblocked.assignCombatDamageAsUnblocked(attacker)) { unblocked.add(attacker); - } else if (attacker.hasKeyword(Keyword.TRAMPLE) - && getAttack(attacker) > totalShieldDamage(attacker, blockers)) { + } else if (attacker.hasKeyword(Keyword.TRAMPLE)) { int trampleDamage = getAttack(attacker) - totalShieldDamage(attacker, blockers); - if (attacker.hasKeyword(Keyword.INFECT)) { - poison += trampleDamage; + if (trampleDamage > 0) { + if (attacker.hasKeyword(Keyword.INFECT)) { + poison += trampleDamage; + } + poison += predictPoisonFromTriggers(attacker, ai, trampleDamage); } - poison += predictPoisonFromTriggers(attacker, ai, trampleDamage); } } @@ -686,7 +687,7 @@ public class ComputerUtilCombat { final int defenderDefense = blocker.getLethalDamage() - flankingMagnitude + defBushidoMagnitude; return defenderDefense; - } // shieldDamage + } // For AI safety measures like Regeneration /** diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index 4cb075b9e10..4717a910bb6 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -234,7 +234,7 @@ public class ComputerUtilCost { return true; } - public static boolean checkForManaSacrificeCost(final Player ai, final Cost cost, final Card source, final SpellAbility sourceAbility, final boolean effect) { + public static boolean checkForManaSacrificeCost(final Player ai, final Cost cost, final SpellAbility sourceAbility, final boolean effect) { // TODO cheating via autopay can still happen, need to get the real ai player from controlledBy if (cost == null || !ai.isAI()) { return true; @@ -247,18 +247,17 @@ public class ComputerUtilCost { exclude.addAll(AiCardMemory.getMemorySet(ai, MemorySet.PAYS_SAC_COST)); } if (part.payCostFromSource()) { - list.add(source); + list.add(sourceAbility.getHostCard()); } else if (part.getType().equals("OriginalHost")) { list.add(sourceAbility.getOriginalHost()); } else if (part.getAmount().equals("All")) { // Does the AI want to use Sacrifice All? return false; } else { - final String amount = part.getAmount(); Integer c = part.convertAmount(); if (c == null) { - c = AbilityUtils.calculateAmount(source, amount, sourceAbility); + c = part.getAbilityAmount(sourceAbility); } final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); CardCollectionView choices = aic.chooseSacrificeType(part.getType(), sourceAbility, effect, c, exclude); @@ -636,7 +635,7 @@ public class ComputerUtilCost { return ComputerUtilMana.canPayManaCost(sa, player, extraManaNeeded, effect) && CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa); - } // canPayCost() + } public static boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, FCollectionView payers) { final Card source = sa.getHostCard(); diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index 87cc9c397b7..05414e0dcfa 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -316,10 +316,6 @@ public class ComputerUtilMana { continue; } - if (!ComputerUtilCost.checkForManaSacrificeCost(ai, ma.getPayCosts(), ma.getHostCard(), ma, ma.isTrigger())) { - continue; - } - if (sa.getApi() == ApiType.Animate) { // For abilities like Genju of the Cedars, make sure that we're not activating the aura ability by tapping the enchanted card for mana if (saHost.isAura() && "Enchanted".equals(sa.getParam("Defined")) @@ -381,9 +377,15 @@ public class ComputerUtilMana { continue; } - if (canPayShardWithSpellAbility(toPay, ai, paymentChoice, sa, checkCosts, cost.getXManaCostPaidByColor())) { - return paymentChoice; + if (!canPayShardWithSpellAbility(toPay, ai, paymentChoice, sa, checkCosts, cost.getXManaCostPaidByColor())) { + continue; } + + if (!ComputerUtilCost.checkForManaSacrificeCost(ai, ma.getPayCosts(), ma, ma.isTrigger())) { + continue; + } + + return paymentChoice; } return null; } diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 0bf5d8306fc..f46d837bc99 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -118,12 +118,10 @@ public abstract class SpellAbilityEffect { int amount = AbilityUtils.calculateAmount(sa.getHostCard(), svar, sa); sb.append(" "); sb.append(TextUtil.enclosedParen(TextUtil.concatNoSpace(svar,"=",String.valueOf(amount)))); - } else { - if (sa.costHasManaX()) { - int amount = sa.getXManaCostPaid() == null ? 0 : sa.getXManaCostPaid(); - sb.append(" "); - sb.append(TextUtil.enclosedParen(TextUtil.concatNoSpace("X","=",String.valueOf(amount)))); - } + } else if (sa.costHasManaX()) { + int amount = sa.getXManaCostPaid() == null ? 0 : sa.getXManaCostPaid(); + sb.append(" "); + sb.append(TextUtil.enclosedParen(TextUtil.concatNoSpace("X","=",String.valueOf(amount)))); } String currentName = CardTranslation.getTranslatedName(sa.getHostCard().getName()); diff --git a/forge-game/src/main/java/forge/game/cost/CostExert.java b/forge-game/src/main/java/forge/game/cost/CostExert.java index 4e4fae78cae..bec43cc5c5f 100644 --- a/forge-game/src/main/java/forge/game/cost/CostExert.java +++ b/forge-game/src/main/java/forge/game/cost/CostExert.java @@ -88,7 +88,6 @@ public class CostExert extends CostPartWithList { typeList = CardLists.getValidCards(typeList, this.getType().split(";"), payer, source, ability); final int amount = this.getAbilityAmount(ability); - return needsAnnoucement || (typeList.size() >= amount); } diff --git a/forge-game/src/main/java/forge/game/cost/CostPutCardToLib.java b/forge-game/src/main/java/forge/game/cost/CostPutCardToLib.java index ecb924a950c..04a18c68094 100644 --- a/forge-game/src/main/java/forge/game/cost/CostPutCardToLib.java +++ b/forge-game/src/main/java/forge/game/cost/CostPutCardToLib.java @@ -82,7 +82,6 @@ public class CostPutCardToLib extends CostPartWithList { sb.append(Cost.convertAmountTypeToWords(i, getAmount(), desc)); } - if (sameZone) { sb.append(" from the same ").append(from); } else if (!this.payCostFromSource()) { @@ -137,7 +136,7 @@ public class CostPutCardToLib extends CostPartWithList { } typeList = CardLists.getValidCards(typeList, getType().split(";"), payer, source, ability); - + if (typeList.size() < i) { return false; } diff --git a/forge-gui/res/cardsfolder/f/flayer_of_the_hatebound.txt b/forge-gui/res/cardsfolder/f/flayer_of_the_hatebound.txt index 55b891c10d7..7938a3b13f6 100644 --- a/forge-gui/res/cardsfolder/f/flayer_of_the_hatebound.txt +++ b/forge-gui/res/cardsfolder/f/flayer_of_the_hatebound.txt @@ -3,7 +3,7 @@ ManaCost:5 R Types:Creature Devil PT:4/2 K:Undying -T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Card.Self,Creature.YouOwn+Other | Execute$ ReanimateDmg | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield from your graveyard, that creature deals damage equal to its power to any target. +T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Card.Self+YouOwn,Creature.YouOwn+Other | Execute$ ReanimateDmg | TriggerDescription$ Whenever CARDNAME or another creature enters the battlefield from your graveyard, that creature deals damage equal to its power to any target. SVar:ReanimateDmg:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | DamageSource$ TriggeredCard | NumDmg$ Damage SVar:Damage:TriggeredCard$CardPower Oracle:Undying (When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.)\nWhenever Flayer of the Hatebound or another creature enters the battlefield from your graveyard, that creature deals damage equal to its power to any target. diff --git a/forge-gui/res/cardsfolder/p/phyrexian_dragon_engine.txt b/forge-gui/res/cardsfolder/p/phyrexian_dragon_engine.txt index 7bc76146457..cd7bae2cef4 100644 --- a/forge-gui/res/cardsfolder/p/phyrexian_dragon_engine.txt +++ b/forge-gui/res/cardsfolder/p/phyrexian_dragon_engine.txt @@ -3,7 +3,7 @@ ManaCost:3 Types:Artifact Creature Phyrexian Dragon PT:2/2 K:Double Strike -T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | OptionalDecider$ You | TriggerZones$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield from your graveyard, you may discard your hand. If you do, draw three cards. +T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Battlefield | OptionalDecider$ You | TriggerZones$ Battlefield | ValidCard$ Card.Self+YouOwn | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield from your graveyard, you may discard your hand. If you do, draw three cards. SVar:TrigDiscard:DB$ Discard | Mode$ Hand | Defined$ You | SubAbility$ DBDraw SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 3 K:Unearth:3 R R