diff --git a/.gitignore b/.gitignore index d60de4860ca..15d874097cc 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ Mage.Tests/Mage.log Mage.Tests/watchdog.log # Mage +*.log Mage/target # Mage.Updater @@ -91,7 +92,7 @@ Mage.Verify/AllCards.json.zip Mage.Verify/AllSets.json.zip Mage.Verify/AllCards.json Mage.Verify/AllSets.json -/db +Mage.Verify/db releases Utils/author.txt diff --git a/.travis.yml b/.travis.yml index a5d7bdc1f5a..7862dd752a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,3 +3,10 @@ dist: trusty language: java before_install: - echo "MAVEN_OPTS='-Xmx2g'" > ~/.mavenrc +# addons: +# sonarcloud: +# organization: "magefree" +# token: +# secure: SONAR_TOKEN +# script: +# - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml index 776034c3ba5..5be94dfac9c 100644 --- a/Mage.Client/pom.xml +++ b/Mage.Client/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 org.mage diff --git a/Mage.Client/release/sample-decks/2013/Standard/DailyMTG Reconstructed - Sliving the good Life/Douglas Scheinberg's Séance Combo.dck b/Mage.Client/release/sample-decks/2013/Standard/DailyMTG Reconstructed - Sliving the good Life/Douglas Scheinberg's Seance Combo.dck similarity index 96% rename from Mage.Client/release/sample-decks/2013/Standard/DailyMTG Reconstructed - Sliving the good Life/Douglas Scheinberg's Séance Combo.dck rename to Mage.Client/release/sample-decks/2013/Standard/DailyMTG Reconstructed - Sliving the good Life/Douglas Scheinberg's Seance Combo.dck index 6cb6e9d096e..a11ea95c633 100644 --- a/Mage.Client/release/sample-decks/2013/Standard/DailyMTG Reconstructed - Sliving the good Life/Douglas Scheinberg's Séance Combo.dck +++ b/Mage.Client/release/sample-decks/2013/Standard/DailyMTG Reconstructed - Sliving the good Life/Douglas Scheinberg's Seance Combo.dck @@ -1,22 +1,22 @@ -NAME:Douglas Scheinberg's Séance Combo -1 [AVR:42] Alchemist's Apprentice -4 [RTR:1] Angel of Serenity -1 [ISD:68] Mirror-Mad Phantasm -2 [ISD:248] Sulfur Falls -4 [RTR:249] Transguild Promenade -3 [RTR:247] Steam Vents -1 [AVR:1] Angel of Glory's Rise -4 [ISD:122] Unburial Rites -4 [RTR:201] Supreme Verdict -1 [ISD:55] Forbidden Alchemy -1 [ISD:61] Laboratory Maniac -3 [ISD:238] Clifftop Retreat -3 [ISD:43] Armored Skaab -2 [GTC:245] Sacred Foundry -4 [M13:69] Sphinx of Uthuun -3 [M13:225] Glacial Fortress -4 [RTR:172] Izzet Charm -2 [AVR:229] Slayers' Stronghold -2 [AVR:226] Cavern of Souls -4 [DKA:87] Faithless Looting -4 [RTR:241] Hallowed Fountain +NAME:Douglas Scheinberg's Séance Combo +1 [AVR:42] Alchemist's Apprentice +4 [RTR:1] Angel of Serenity +1 [ISD:68] Mirror-Mad Phantasm +2 [ISD:248] Sulfur Falls +4 [RTR:249] Transguild Promenade +3 [RTR:247] Steam Vents +1 [AVR:1] Angel of Glory's Rise +4 [ISD:122] Unburial Rites +4 [RTR:201] Supreme Verdict +1 [ISD:55] Forbidden Alchemy +1 [ISD:61] Laboratory Maniac +3 [ISD:238] Clifftop Retreat +3 [ISD:43] Armored Skaab +2 [GTC:245] Sacred Foundry +4 [M13:69] Sphinx of Uthuun +3 [M13:225] Glacial Fortress +4 [RTR:172] Izzet Charm +2 [AVR:229] Slayers' Stronghold +2 [AVR:226] Cavern of Souls +4 [DKA:87] Faithless Looting +4 [RTR:241] Hallowed Fountain diff --git a/Mage.Client/release/sample-decks/2013/Standard/GP Guadalajara (May 26)/Emmanuel Ramírez's Reanimator.dck b/Mage.Client/release/sample-decks/2013/Standard/GP Guadalajara (May 26)/Emmanuel Ramirez's Reanimator.dck similarity index 96% rename from Mage.Client/release/sample-decks/2013/Standard/GP Guadalajara (May 26)/Emmanuel Ramírez's Reanimator.dck rename to Mage.Client/release/sample-decks/2013/Standard/GP Guadalajara (May 26)/Emmanuel Ramirez's Reanimator.dck index db9096fb72d..c8bf400e7de 100644 --- a/Mage.Client/release/sample-decks/2013/Standard/GP Guadalajara (May 26)/Emmanuel Ramírez's Reanimator.dck +++ b/Mage.Client/release/sample-decks/2013/Standard/GP Guadalajara (May 26)/Emmanuel Ramirez's Reanimator.dck @@ -1,31 +1,31 @@ -NAME:Emmanuel Ramírez's Reanimator -4 [ISD:170] Avacyn's Pilgrim -2 [ISD:249] Woodland Cemetery -3 [M13:159] Acidic Slime -3 [ISD:196] Mulch -1 [ISD:239] Gavony Township -3 [ISD:15] Fiend Hunter -3 [RTR:1] Angel of Serenity -2 [AVR:226] Cavern of Souls -4 [AVR:32] Restoration Angel -2 [ISD:242] Isolated Chapel -4 [RTR:248] Temple Garden -4 [RTR:243] Overgrown Tomb -3 [M13:160] Arbor Elf -4 [M13:193] Thragtusk -2 [DGM:103] Sin Collector -4 [RTR:165] Grisly Salvage -3 [M13:229] Sunpetal Grove -3 [RTR:270] Forest -2 [GTC:242] Godless Shrine -4 [ISD:122] Unburial Rites -SB: 1 [RTR:148] Centaur Healer -SB: 2 [DKA:17] Ray of Revelation -SB: 1 [M13:159] Acidic Slime -SB: 2 [ISD:181] Garruk Relentless -SB: 2 [RTR:141] Abrupt Decay -SB: 1 [ISD:15] Fiend Hunter -SB: 2 [RTR:213] Deathrite Shaman -SB: 1 [DGM:103] Sin Collector -SB: 2 [RTR:178] Loxodon Smiter -SB: 1 [ISD:115] Sever the Bloodline +NAME:Emmanuel Ramírez's Reanimator +4 [ISD:170] Avacyn's Pilgrim +2 [ISD:249] Woodland Cemetery +3 [M13:159] Acidic Slime +3 [ISD:196] Mulch +1 [ISD:239] Gavony Township +3 [ISD:15] Fiend Hunter +3 [RTR:1] Angel of Serenity +2 [AVR:226] Cavern of Souls +4 [AVR:32] Restoration Angel +2 [ISD:242] Isolated Chapel +4 [RTR:248] Temple Garden +4 [RTR:243] Overgrown Tomb +3 [M13:160] Arbor Elf +4 [M13:193] Thragtusk +2 [DGM:103] Sin Collector +4 [RTR:165] Grisly Salvage +3 [M13:229] Sunpetal Grove +3 [RTR:270] Forest +2 [GTC:242] Godless Shrine +4 [ISD:122] Unburial Rites +SB: 1 [RTR:148] Centaur Healer +SB: 2 [DKA:17] Ray of Revelation +SB: 1 [M13:159] Acidic Slime +SB: 2 [ISD:181] Garruk Relentless +SB: 2 [RTR:141] Abrupt Decay +SB: 1 [ISD:15] Fiend Hunter +SB: 2 [RTR:213] Deathrite Shaman +SB: 1 [DGM:103] Sin Collector +SB: 2 [RTR:178] Loxodon Smiter +SB: 1 [ISD:115] Sever the Bloodline diff --git a/Mage.Client/release/sample-decks/2013/Standard/GP Quebec City/Frédéric Mercier's Esper Control.dck b/Mage.Client/release/sample-decks/2013/Standard/GP Quebec City/Frederic Mercier's Esper Control.dck similarity index 96% rename from Mage.Client/release/sample-decks/2013/Standard/GP Quebec City/Frédéric Mercier's Esper Control.dck rename to Mage.Client/release/sample-decks/2013/Standard/GP Quebec City/Frederic Mercier's Esper Control.dck index 40acc0590eb..70622a3155f 100644 --- a/Mage.Client/release/sample-decks/2013/Standard/GP Quebec City/Frédéric Mercier's Esper Control.dck +++ b/Mage.Client/release/sample-decks/2013/Standard/GP Quebec City/Frederic Mercier's Esper Control.dck @@ -1,33 +1,33 @@ -NAME:Frédéric Mercier's Esper Control -2 [M13:26] Planar Cleansing -1 [RTR:250] Plains -4 [M13:225] Glacial Fortress -2 [GTC:63] Devour Flesh -4 [ISD:83] Think Twice -4 [RTR:145] Azorius Charm -2 [ISD:78] Snapcaster Mage -2 [GTC:249] Watery Grave -1 [RTR:82] Ultimate Price -1 [RTR:156] Dramatic Rescue -2 [GPT:157] Godless Shrine -3 [AVR:32] Restoration Angel -4 [M13:43] Augur of Bolas -4 [ISD:242] Isolated Chapel -4 [RTR:201] Supreme Verdict -2 [MIR:61] Dissipate -1 [RTR:256] Island -1 [RTR:255] Island -4 [ISD:245] Nephalia Drownyard -4 [RTR:241] Hallowed Fountain -4 [M13:223] Drowned Catacomb -4 [RTR:200] Sphinx's Revelation -SB: 1 [WWK:26] Dispel -SB: 3 [AVR:104] Gloom Surgeon -SB: 2 [M11:96] Duress -SB: 2 [ISD:236] Witchbane Orb -SB: 1 [RTR:18] Rest in Peace -SB: 1 [RTR:36] Dispel -SB: 1 [SOK:158] Pithing Needle -SB: 1 [RTR:47] Psychic Spiral -SB: 2 [M13:56] Jace, Memory Adept -SB: 1 [M12:69] Negate +NAME:Frédéric Mercier's Esper Control +2 [M13:26] Planar Cleansing +1 [RTR:250] Plains +4 [M13:225] Glacial Fortress +2 [GTC:63] Devour Flesh +4 [ISD:83] Think Twice +4 [RTR:145] Azorius Charm +2 [ISD:78] Snapcaster Mage +2 [GTC:249] Watery Grave +1 [RTR:82] Ultimate Price +1 [RTR:156] Dramatic Rescue +2 [GPT:157] Godless Shrine +3 [AVR:32] Restoration Angel +4 [M13:43] Augur of Bolas +4 [ISD:242] Isolated Chapel +4 [RTR:201] Supreme Verdict +2 [MIR:61] Dissipate +1 [RTR:256] Island +1 [RTR:255] Island +4 [ISD:245] Nephalia Drownyard +4 [RTR:241] Hallowed Fountain +4 [M13:223] Drowned Catacomb +4 [RTR:200] Sphinx's Revelation +SB: 1 [WWK:26] Dispel +SB: 3 [AVR:104] Gloom Surgeon +SB: 2 [M11:96] Duress +SB: 2 [ISD:236] Witchbane Orb +SB: 1 [RTR:18] Rest in Peace +SB: 1 [RTR:36] Dispel +SB: 1 [SOK:158] Pithing Needle +SB: 1 [RTR:47] Psychic Spiral +SB: 2 [M13:56] Jace, Memory Adept +SB: 1 [M12:69] Negate diff --git a/Mage.Client/release/sample-decks/2013/Standard/GP Verona/Jérémy Dezani's Jund Midrange.dck b/Mage.Client/release/sample-decks/2013/Standard/GP Verona/Jeremy Dezani's Jund Midrange.dck similarity index 96% rename from Mage.Client/release/sample-decks/2013/Standard/GP Verona/Jérémy Dezani's Jund Midrange.dck rename to Mage.Client/release/sample-decks/2013/Standard/GP Verona/Jeremy Dezani's Jund Midrange.dck index 3a4b62e0147..e5e32ee185a 100644 --- a/Mage.Client/release/sample-decks/2013/Standard/GP Verona/Jérémy Dezani's Jund Midrange.dck +++ b/Mage.Client/release/sample-decks/2013/Standard/GP Verona/Jeremy Dezani's Jund Midrange.dck @@ -1,36 +1,36 @@ -NAME:Jérémy Dezani's Jund Midrange -4 [M13:170] Farseek -3 [AVR:129] Bonfire of the Damned -1 [DKA:76] Tragic Slip -4 [ISD:249] Woodland Cemetery -2 [RTR:141] Abrupt Decay -3 [ISD:105] Liliana of the Veil -3 [M13:222] Dragonskull Summit -1 [RTR:82] Ultimate Price -2 [ISD:243] Kessig Wolf Run -1 [M13:217] Staff of Nin -1 [M13:101] Murder -4 [GTC:247] Stomping Ground -3 [ISD:215] Olivia Voldaren -2 [M13:174] Garruk, Primal Hunter -2 [RTR:188] Rakdos's Return -4 [DKA:140] Huntmaster of the Fells -4 [RTR:243] Overgrown Tomb -2 [M13:160] Arbor Elf -4 [M13:193] Thragtusk -4 [RTR:238] Blood Crypt -2 [M13:228] Rootbound Crag -1 [RTR:101] Mizzium Mortars -1 [RTR:157] Dreadbore -2 [RTR:270] Forest -SB: 1 [RTR:188] Rakdos's Return -SB: 1 [AVR:129] Bonfire of the Damned -SB: 1 [DKA:76] Tragic Slip -SB: 2 [M13:159] Acidic Slime -SB: 1 [RTR:141] Abrupt Decay -SB: 1 [DKA:149] Grafdigger's Cage -SB: 2 [M13:90] Duress -SB: 1 [M13:219] Tormod's Crypt -SB: 3 [RTR:197] Slaughter Games -SB: 1 [RTR:101] Mizzium Mortars -SB: 1 [AVR:149] Pillar of Flame +NAME:Jérémy Dezani's Jund Midrange +4 [M13:170] Farseek +3 [AVR:129] Bonfire of the Damned +1 [DKA:76] Tragic Slip +4 [ISD:249] Woodland Cemetery +2 [RTR:141] Abrupt Decay +3 [ISD:105] Liliana of the Veil +3 [M13:222] Dragonskull Summit +1 [RTR:82] Ultimate Price +2 [ISD:243] Kessig Wolf Run +1 [M13:217] Staff of Nin +1 [M13:101] Murder +4 [GTC:247] Stomping Ground +3 [ISD:215] Olivia Voldaren +2 [M13:174] Garruk, Primal Hunter +2 [RTR:188] Rakdos's Return +4 [DKA:140] Huntmaster of the Fells +4 [RTR:243] Overgrown Tomb +2 [M13:160] Arbor Elf +4 [M13:193] Thragtusk +4 [RTR:238] Blood Crypt +2 [M13:228] Rootbound Crag +1 [RTR:101] Mizzium Mortars +1 [RTR:157] Dreadbore +2 [RTR:270] Forest +SB: 1 [RTR:188] Rakdos's Return +SB: 1 [AVR:129] Bonfire of the Damned +SB: 1 [DKA:76] Tragic Slip +SB: 2 [M13:159] Acidic Slime +SB: 1 [RTR:141] Abrupt Decay +SB: 1 [DKA:149] Grafdigger's Cage +SB: 2 [M13:90] Duress +SB: 1 [M13:219] Tormod's Crypt +SB: 3 [RTR:197] Slaughter Games +SB: 1 [RTR:101] Mizzium Mortars +SB: 1 [AVR:149] Pillar of Flame diff --git a/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Philipp Schönegger's Miracles.dck b/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Philipp Schonegger's Miracles.dck similarity index 96% rename from Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Philipp Schönegger's Miracles.dck rename to Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Philipp Schonegger's Miracles.dck index 1959f8d1e65..791dfa7183a 100644 --- a/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Philipp Schönegger's Miracles.dck +++ b/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Philipp Schonegger's Miracles.dck @@ -1,32 +1,32 @@ -NAME:Philipp Schönegger's Miracles -4 [C13:341] Island -4 [CHK:268] Sensei's Divining Top -4 [ONS:316] Flooded Strand -2 [AVR:20] Entreat the Angels -3 [WWK:31] Jace, the Mind Sculptor -3 [ISD:78] Snapcaster Mage -4 [ALL:42] Force of Will -2 [ZEN:211] Arid Mesa -2 [M12:73] Ponder -1 [MMA:70] Vendilion Clique -4 [CMD:40] Brainstorm -1 [LEG:248] Karakas -2 [7ED:67] Counterspell -3 [CSP:31] Counterbalance -4 [AVR:38] Terminus -4 [ZEN:223] Scalding Tarn -2 [ZEN:67] Spell Pierce -2 [C13:337] Plains -2 [3ED:306] Volcanic Island -3 [3ED:304] Tundra -4 [DDF:22] Swords to Plowshares -SB: 1 [5ED:262] Pyroblast -SB: 1 [AVR:20] Entreat the Angels -SB: 3 [CMD:46] Flusterstorm -SB: 2 [4ED:236] Red Elemental Blast -SB: 1 [TSB:6] Disenchant -SB: 2 [MMA:204] Engineered Explosives -SB: 1 [7ED:67] Counterspell -SB: 1 [RTR:201] Supreme Verdict -SB: 1 [MMA:70] Vendilion Clique -SB: 2 [RTR:18] Rest in Peace +NAME:Philipp Schönegger's Miracles +4 [C13:341] Island +4 [CHK:268] Sensei's Divining Top +4 [ONS:316] Flooded Strand +2 [AVR:20] Entreat the Angels +3 [WWK:31] Jace, the Mind Sculptor +3 [ISD:78] Snapcaster Mage +4 [ALL:42] Force of Will +2 [ZEN:211] Arid Mesa +2 [M12:73] Ponder +1 [MMA:70] Vendilion Clique +4 [CMD:40] Brainstorm +1 [LEG:248] Karakas +2 [7ED:67] Counterspell +3 [CSP:31] Counterbalance +4 [AVR:38] Terminus +4 [ZEN:223] Scalding Tarn +2 [ZEN:67] Spell Pierce +2 [C13:337] Plains +2 [3ED:306] Volcanic Island +3 [3ED:304] Tundra +4 [DDF:22] Swords to Plowshares +SB: 1 [5ED:262] Pyroblast +SB: 1 [AVR:20] Entreat the Angels +SB: 3 [CMD:46] Flusterstorm +SB: 2 [4ED:236] Red Elemental Blast +SB: 1 [TSB:6] Disenchant +SB: 2 [MMA:204] Engineered Explosives +SB: 1 [7ED:67] Counterspell +SB: 1 [RTR:201] Supreme Verdict +SB: 1 [MMA:70] Vendilion Clique +SB: 2 [RTR:18] Rest in Peace diff --git a/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Stefan Böttcher's Deathblade.dck b/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Stefan Bottcher's Deathblade.dck similarity index 96% rename from Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Stefan Böttcher's Deathblade.dck rename to Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Stefan Bottcher's Deathblade.dck index eeb9e9c7815..668d8ad15d7 100644 --- a/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Stefan Böttcher's Deathblade.dck +++ b/Mage.Client/release/sample-decks/2014/Legacy/GP Paris/Stefan Bottcher's Deathblade.dck @@ -1,42 +1,42 @@ -NAME:Stefan Böttcher's Deathblade -1 [WWK:134] Creeping Tar Pit -4 [RTR:213] Deathrite Shaman -1 [AVR:20] Entreat the Angels -2 [C13:63] True-Name Nemesis -2 [WWK:31] Jace, the Mind Sculptor -3 [ISD:78] Snapcaster Mage -3 [MMA:75] Dark Confidant -1 [MMA:70] Vendilion Clique -1 [NPH:130] Batterskull -1 [ARB:85] Zealous Persecution -4 [CMD:40] Brainstorm -2 [THS:107] Thoughtseize -1 [MMA:204] Engineered Explosives -1 [BOK:163] Umezawa's Jitte -1 [3ED:298] Scrubland -1 [C13:337] Plains -3 [3ED:305] Underground Sea -3 [3ED:304] Tundra -4 [DDF:22] Swords to Plowshares -1 [3ED:303] Tropical Island -1 [C13:341] Island -3 [ONS:316] Flooded Strand -1 [C13:345] Swamp -1 [ZEN:219] Marsh Flats -2 [TMP:340] Wasteland -1 [LEG:248] Karakas -1 [MMA:219] Academy Ruins -1 [7ED:67] Counterspell -3 [ONS:321] Polluted Delta -3 [ZEN:67] Spell Pierce -3 [WWK:20] Stoneforge Mystic -SB: 1 [ISD:105] Liliana of the Veil -SB: 1 [RTR:155] Detention Sphere -SB: 3 [ALL:42] Force of Will -SB: 1 [RTR:201] Supreme Verdict -SB: 3 [M11:21] Leyline of Sanctity -SB: 1 [MBS:138] Sword of Feast and Famine -SB: 2 [NPH:74] Surgical Extraction -SB: 1 [THS:65] Swan Song -SB: 1 [MMA:213] Relic of Progenitus -SB: 1 [NMS:111] Reverent Silence +NAME:Stefan Böttcher's Deathblade +1 [WWK:134] Creeping Tar Pit +4 [RTR:213] Deathrite Shaman +1 [AVR:20] Entreat the Angels +2 [C13:63] True-Name Nemesis +2 [WWK:31] Jace, the Mind Sculptor +3 [ISD:78] Snapcaster Mage +3 [MMA:75] Dark Confidant +1 [MMA:70] Vendilion Clique +1 [NPH:130] Batterskull +1 [ARB:85] Zealous Persecution +4 [CMD:40] Brainstorm +2 [THS:107] Thoughtseize +1 [MMA:204] Engineered Explosives +1 [BOK:163] Umezawa's Jitte +1 [3ED:298] Scrubland +1 [C13:337] Plains +3 [3ED:305] Underground Sea +3 [3ED:304] Tundra +4 [DDF:22] Swords to Plowshares +1 [3ED:303] Tropical Island +1 [C13:341] Island +3 [ONS:316] Flooded Strand +1 [C13:345] Swamp +1 [ZEN:219] Marsh Flats +2 [TMP:340] Wasteland +1 [LEG:248] Karakas +1 [MMA:219] Academy Ruins +1 [7ED:67] Counterspell +3 [ONS:321] Polluted Delta +3 [ZEN:67] Spell Pierce +3 [WWK:20] Stoneforge Mystic +SB: 1 [ISD:105] Liliana of the Veil +SB: 1 [RTR:155] Detention Sphere +SB: 3 [ALL:42] Force of Will +SB: 1 [RTR:201] Supreme Verdict +SB: 3 [M11:21] Leyline of Sanctity +SB: 1 [MBS:138] Sword of Feast and Famine +SB: 2 [NPH:74] Surgical Extraction +SB: 1 [THS:65] Swan Song +SB: 1 [MMA:213] Relic of Progenitus +SB: 1 [NMS:111] Reverent Silence diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index d0f3ebde883..1fa1ee81a29 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -3,6 +3,8 @@ package mage.client; import mage.cards.action.ActionCallback; import mage.cards.decks.Deck; import mage.cards.repository.CardRepository; +import mage.cards.repository.ExpansionRepository; +import mage.cards.repository.RepositoryUtil; import mage.client.cards.BigCard; import mage.client.chat.ChatPanelBasic; import mage.client.components.*; @@ -212,6 +214,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { LOGGER.fatal(null, ex); } + RepositoryUtil.bootstrapLocalDb(); ManaSymbols.loadImages(); Plugins.instance.loadPlugins(); @@ -281,7 +284,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { if (Plugins.instance.isCounterPluginLoaded()) { int i = Plugins.instance.getGamesPlayed(); - JLabel label = new JLabel(" Games played: " + String.valueOf(i)); + JLabel label = new JLabel(" Games played: " + i); desktopPane.add(label, JLayeredPane.DEFAULT_LAYER + 1); label.setVisible(true); label.setForeground(Color.white); @@ -717,6 +720,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { boolean autoConnectParamValue = startUser != null || Boolean.parseBoolean(PREFS.get("autoConnect", "false")); boolean status = false; if (autoConnectParamValue) { + LOGGER.info("Auto-connecting to " + MagePreferences.getServerAddress()); status = performConnect(false); } return status; @@ -739,6 +743,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { currentConnection.setPassword(password); currentConnection.setHost(server); currentConnection.setPort(port); + // force to redownload db on updates + boolean redownloadDatabase = (ExpansionRepository.instance.getSetByCode("GRN") == null || CardRepository.instance.findCard("Island") == null); + currentConnection.setForceDBComparison(redownloadDatabase); String allMAC = ""; try { allMAC = Connection.getMAC(); @@ -1160,7 +1167,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { /** * @param args the command line arguments */ - public static void main(final String args[]) { + public static void main(final String[] args) { // Workaround for #451 System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); LOGGER.info("Starting MAGE client version " + VERSION); diff --git a/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java b/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java index df8cbd65ec4..8645e5f3de1 100644 --- a/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java +++ b/Mage.Client/src/main/java/mage/client/components/ext/dlg/impl/StackDialog.java @@ -85,11 +85,6 @@ public class StackDialog extends IDialogPanel { jTitle.setFont(new Font("Dialog", Font.BOLD, 14)); jTitle.setText("Current stack: "); - /*jTitle2 = new CustomLabel(); - jTitle2.setBounds(new Rectangle(5, 5 + SettingsManager.getInstance().getCardSize().height + 30, 129, 20)); - jTitle2.setFont(new Font("Dialog", Font.BOLD, 14)); - jTitle2.setText("Spell targets:");*/ - this.setLayout(null); jLayeredPane.setLayout(null); diff --git a/Mage.Client/src/main/java/mage/client/constants/Constants.java b/Mage.Client/src/main/java/mage/client/constants/Constants.java index 3b1ba14dd68..54d74f36997 100644 --- a/Mage.Client/src/main/java/mage/client/constants/Constants.java +++ b/Mage.Client/src/main/java/mage/client/constants/Constants.java @@ -94,7 +94,6 @@ public final class Constants { public interface IO { String DEFAULT_IMAGES_DIR = "plugins" + File.separator + "images" + File.separator; - String IMAGE_PROPERTIES_FILE = "image.url.properties"; } public enum DeckEditorMode { diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java index 7935854a1ba..5fd75a8e53a 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java @@ -253,7 +253,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene predicates.add(new ColorPredicate(ObjectColor.WHITE)); } if (this.tbColorless.isSelected()) { - predicates.add(new ColorlessPredicate()); + predicates.add(ColorlessPredicate.instance); } filter.add(Predicates.or(predicates)); diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index 182be367ebd..29ef276b9a7 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -14,7 +14,6 @@ import mage.cards.Sets; import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; import mage.cards.decks.importer.DeckImporter; -import mage.cards.decks.importer.DeckImporterUtil; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.client.MageFrame; @@ -798,7 +797,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { - newDeck = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath(), errorMessages), true, true); + newDeck = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages), true, true); processAndShowImportErrors(errorMessages); if (newDeck != null) { @@ -831,7 +830,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { - deckToAppend = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath(), errorMessages), true, true); + deckToAppend = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages), true, true); processAndShowImportErrors(errorMessages); if (deckToAppend != null) { @@ -878,7 +877,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { Deck newDeck = null; StringBuilder errorMessages = new StringBuilder(); - newDeck = Deck.load(DeckImporterUtil.importDeck(file.getPath(), errorMessages), true, true); + newDeck = Deck.load(DeckImporter.importDeckFromFile(file.getPath(), errorMessages), true, true); processAndShowImportErrors(errorMessages); if (newDeck != null) { @@ -977,7 +976,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { File file = fcImportDeck.getSelectedFile(); MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); try { - DeckImporter importer = DeckImporterUtil.getDeckImporter(file.getPath()); + DeckImporter importer = DeckImporter.getDeckImporter(file.getPath()); if (importer != null) { StringBuilder errorMessages = new StringBuilder(); @@ -1048,7 +1047,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { try { MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); String path = DeckGenerator.generateDeck(); - deck = Deck.load(DeckImporterUtil.importDeck(path), true, true); + deck = Deck.load(DeckImporter.importDeckFromFile(path), true, true); } catch (GameException ex) { JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading generated deck", JOptionPane.ERROR_MESSAGE); } catch (DeckGeneratorException ex) { @@ -1120,7 +1119,12 @@ class ImportFilter extends FileFilter { ext = s.substring(i + 1).toLowerCase(Locale.ENGLISH); } if (ext != null) { - if (ext.toLowerCase(Locale.ENGLISH).equals("dec") || ext.toLowerCase(Locale.ENGLISH).equals("mwdeck") || ext.toLowerCase(Locale.ENGLISH).equals("txt") || ext.toLowerCase(Locale.ENGLISH).equals("dek")) { + if (ext.toLowerCase(Locale.ENGLISH).equals("dec") + || ext.toLowerCase(Locale.ENGLISH).equals("mwdeck") + || ext.toLowerCase(Locale.ENGLISH).equals("txt") + || ext.toLowerCase(Locale.ENGLISH).equals("dek") + || ext.toLowerCase(Locale.ENGLISH).equals("cod") + || ext.toLowerCase(Locale.ENGLISH).equals("o8d")) { return true; } } @@ -1129,7 +1133,7 @@ class ImportFilter extends FileFilter { @Override public String getDescription() { - return "*.dec | *.mwDeck | *.txt | *.dek"; + return "*.dec | *.mwDeck | *.txt | *.dek | *.cod | *.o8d"; } } diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/collection/viewer/MageBook.java b/Mage.Client/src/main/java/mage/client/deckeditor/collection/viewer/MageBook.java index 7749b95c800..a9dce7c5390 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/collection/viewer/MageBook.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/collection/viewer/MageBook.java @@ -1,20 +1,5 @@ - package mage.client.deckeditor.collection.viewer; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.FileNotFoundException; -import java.io.InputStream; -import static java.lang.Math.min; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.UUID; -import javax.imageio.ImageIO; -import javax.swing.*; import mage.cards.*; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; @@ -24,12 +9,13 @@ import mage.client.MageFrame; import mage.client.cards.BigCard; import mage.client.components.HoverButton; import mage.client.plugins.impl.Plugins; -import mage.client.util.*; +import mage.client.util.Config; +import mage.client.util.ImageHelper; +import mage.client.util.NaturalOrderCardNumberComparator; import mage.client.util.audio.AudioManager; import mage.client.util.sets.ConstructedFormats; import mage.components.ImagePanel; import mage.components.ImagePanelStyle; -import mage.constants.Rarity; import mage.game.command.Emblem; import mage.game.command.Plane; import mage.game.permanent.PermanentToken; @@ -41,6 +27,19 @@ import mage.view.PlaneView; import org.apache.log4j.Logger; import org.mage.card.arcane.ManaSymbols; import org.mage.plugins.card.images.CardDownloadData; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.*; + +import static java.lang.Math.min; import static org.mage.plugins.card.images.DownloadPicturesService.getTokenCardUrls; /** @@ -307,25 +306,33 @@ public class MageBook extends JComponent { // Already have numTokens tokens presented. Appending the emblems to the end of these. numTokens = numTokens % conf.CARDS_PER_PAGE; if (numTokens < conf.CARDS_PER_PAGE / 2) { + // page 1 with tokens for (int z = 0; z < numTokens && z < conf.CARDS_PER_PAGE / 2; z++) { rectangle = CardPosition.translatePosition(z, rectangle, conf); } } else { + // page 2 with tokens rectangle.setLocation(second_page_x, OFFSET_Y); for (int z = 0; z < numTokens - conf.CARDS_PER_PAGE / 2; z++) { rectangle = CardPosition.translatePosition(z, rectangle, conf); } } + // page 1 with emblems after tokens int lastI = 0; + boolean needContinueFromPage1 = false; for (int i = 0; i < size && i + numTokens < conf.CARDS_PER_PAGE / 2; i++) { Emblem emblem = emblems.get(i); addEmblem(emblem, bigCard, null, rectangle); rectangle = CardPosition.translatePosition(i + numTokens, rectangle, conf); lastI++; + needContinueFromPage1 = true; } - rectangle.setLocation(second_page_x, OFFSET_Y); + // page 2 with emblems after tokens + if (needContinueFromPage1) { + rectangle.setLocation(second_page_x, OFFSET_Y); + } if (size + numTokens > conf.CARDS_PER_PAGE / 2) { for (int i = lastI; i < size && i + numTokens < conf.CARDS_PER_PAGE; i++) { Emblem emblem = emblems.get(i); @@ -354,25 +361,33 @@ public class MageBook extends JComponent { numTokensEmblems = numTokensEmblems % conf.CARDS_PER_PAGE; if (numTokensEmblems < conf.CARDS_PER_PAGE / 2) { + // page 1 with tokens/emblems for (int z = 0; z < numTokensEmblems && z < conf.CARDS_PER_PAGE / 2; z++) { rectangle = CardPosition.translatePosition(z, rectangle, conf); } } else { + // page 2 with tokens/emblems rectangle.setLocation(second_page_x, OFFSET_Y); for (int z = 0; z < numTokensEmblems - conf.CARDS_PER_PAGE / 2; z++) { rectangle = CardPosition.translatePosition(z, rectangle, conf); } } + // page 1 with planes after tokens/emblems int lastI = 0; + boolean needContinueFromPage1 = false; for (int i = 0; i < size && i + numTokensEmblems < conf.CARDS_PER_PAGE / 2; i++) { Plane plane = planes.get(i); addPlane(plane, bigCard, null, rectangle); rectangle = CardPosition.translatePosition(i + numTokensEmblems, rectangle, conf); lastI++; + needContinueFromPage1 = true; } - rectangle.setLocation(second_page_x, OFFSET_Y); + // page 2 with planes after tokens/emblems + if (needContinueFromPage1) { + rectangle.setLocation(second_page_x, OFFSET_Y); + } if (size + numTokensEmblems > conf.CARDS_PER_PAGE / 2) { for (int i = lastI; i < size && i + numTokensEmblems < conf.CARDS_PER_PAGE; i++) { Plane plane = planes.get(i); @@ -602,13 +617,13 @@ public class MageBook extends JComponent { } } } - + int totalTokens = getTotalNumTokens(set); int start = 0; if (!(page * conf.CARDS_PER_PAGE <= totalTokens && (page + 1) * conf.CARDS_PER_PAGE >= totalTokens)) { start = page * conf.CARDS_PER_PAGE - totalTokens; } - + int end = emblems.size(); if ((page + 1) * conf.CARDS_PER_PAGE < totalTokens + emblems.size()) { end = (page + 1) * conf.CARDS_PER_PAGE - totalTokens; @@ -659,7 +674,7 @@ public class MageBook extends JComponent { } } } - + int totalTokens = getTotalNumTokens(set); int totalTokensEmblems = totalTokens + getTotalNumEmblems(set); int start = 0; @@ -667,7 +682,7 @@ public class MageBook extends JComponent { start = page * conf.CARDS_PER_PAGE - totalTokensEmblems; pageRight.setVisible(true); } - + int end = planes.size(); if ((page + 1) * conf.CARDS_PER_PAGE < totalTokensEmblems + planes.size()) { end = (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems; diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form index c1ef452cc22..99de56d11bb 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form @@ -3,9 +3,6 @@
- - - @@ -26,30 +23,26 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + - + + + + + + + + + + + @@ -57,82 +50,58 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + - + - - + + @@ -152,49 +121,27 @@ + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + + @@ -205,10 +152,11 @@ + - + @@ -289,86 +237,23 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + - - + + @@ -420,5 +305,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index 981d34781e2..7d932d99e50 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -5,43 +5,11 @@ */ package mage.client.dialog; -import java.awt.Cursor; -import java.awt.event.ActionListener; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.InputStreamReader; -import java.io.Writer; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JLayeredPane; -import javax.swing.JOptionPane; -import javax.swing.SwingWorker; - import mage.cards.repository.CardRepository; +import mage.cards.repository.ExpansionRepository; import mage.choices.Choice; import mage.choices.ChoiceImpl; import mage.client.MageFrame; -import static mage.client.dialog.PreferencesDialog.KEY_CONNECTION_URL_SERVER_LIST; -import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_AUTO_CONNECT; -import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_FLAG; import mage.client.preference.MagePreferences; import mage.client.util.Config; import mage.client.util.gui.countryBox.CountryItemEditor; @@ -50,6 +18,20 @@ import mage.remote.Connection; import mage.utils.StreamUtils; import org.apache.log4j.Logger; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionListener; +import java.io.*; +import java.net.*; +import java.util.List; +import java.util.*; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static mage.client.dialog.PreferencesDialog.*; + /** * @author BetaSteward_at_googlemail.com */ @@ -123,10 +105,6 @@ public class ConnectDialog extends MageDialog { private void initComponents() { lblServer = new javax.swing.JLabel(); - txtServer = new javax.swing.JTextField(); - btnFind = new javax.swing.JButton(); - lblPort = new javax.swing.JLabel(); - txtPort = new javax.swing.JTextField(); lblUserName = new javax.swing.JLabel(); txtUserName = new javax.swing.JTextField(); lblPassword = new javax.swing.JLabel(); @@ -140,47 +118,41 @@ public class ConnectDialog extends MageDialog { lblStatus = new javax.swing.JLabel(); btnRegister = new javax.swing.JButton(); btnForgotPassword = new javax.swing.JButton(); - btnFind1 = new javax.swing.JButton(); - btnFind2 = new javax.swing.JButton(); - btnFind3 = new javax.swing.JButton(); lblFastConnect = new javax.swing.JLabel(); panelFlag = new javax.swing.JPanel(); cbFlag = new mage.client.util.gui.countryBox.CountryComboBox(); filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(4, 0), new java.awt.Dimension(5, 32767)); btnFlagSearch = new javax.swing.JButton(); + panelFast = new javax.swing.JPanel(); + btnFindMain = new javax.swing.JButton(); + btnFindLocal = new javax.swing.JButton(); + btnFindBeta = new javax.swing.JButton(); + btnFindUs = new javax.swing.JButton(); + btnFindOther = new javax.swing.JButton(); + panelServer = new javax.swing.JPanel(); + txtServer = new javax.swing.JTextField(); + txtPort = new javax.swing.JTextField(); + lblPort = new javax.swing.JLabel(); + btnCheckStatus = new javax.swing.JButton(); + filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 50), new java.awt.Dimension(0, 50), new java.awt.Dimension(32767, 50)); setTitle("Connect to server"); - setNormalBounds(new java.awt.Rectangle(100, 100, 410, 307)); + lblServer.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); lblServer.setLabelFor(txtServer); - lblServer.setText("Server:"); - - btnFind.setText("Find..."); - btnFind.setToolTipText("Shows the list of public servers"); - btnFind.setName("findServerBtn"); // NOI18N - btnFind.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - findPublicServerActionPerformed(evt); - } - }); - - lblPort.setLabelFor(txtPort); - lblPort.setText("Port:"); - - txtPort.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyTyped(java.awt.event.KeyEvent evt) { - ConnectDialog.this.keyTyped(evt); - } - }); + lblServer.setText("Server name:"); + lblUserName.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); lblUserName.setLabelFor(txtUserName); - lblUserName.setText("User name:"); + lblUserName.setText("Username:"); + lblPassword.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); lblPassword.setLabelFor(txtPassword); lblPassword.setText("Password:"); + lblFlag.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); lblFlag.setLabelFor(txtUserName); - lblFlag.setText("User flag:"); + lblFlag.setText("User's flag:"); chkAutoConnect.setText("Automatically connect to this server next time"); chkAutoConnect.setToolTipText("If active this connect dialog will not be shown if you choose to connect.
\nInstead XMage tries to connect to the last server you were connected to."); @@ -241,55 +213,12 @@ public class ConnectDialog extends MageDialog { } }); - btnFind1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/de.png"))); // NOI18N - btnFind1.setText("X"); - btnFind1.setToolTipText("Connect to xmage.de (Europe, most popular)"); - btnFind1.setActionCommand("connectXmageDe"); - btnFind1.setAlignmentY(0.0F); - btnFind1.setMargin(new java.awt.Insets(2, 2, 2, 2)); - btnFind1.setMaximumSize(new java.awt.Dimension(42, 23)); - btnFind1.setMinimumSize(new java.awt.Dimension(42, 23)); - btnFind1.setName("connectXmageDeBtn"); // NOI18N - btnFind1.setPreferredSize(new java.awt.Dimension(23, 23)); - btnFind1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - connectXmageDe(evt); - } - }); - - btnFind2.setText("L"); - btnFind2.setToolTipText("Connect to localhost (local server)"); - btnFind2.setActionCommand("connectLocalhost"); - btnFind2.setAlignmentY(0.0F); - btnFind2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - btnFind2.setMargin(new java.awt.Insets(2, 2, 2, 2)); - btnFind2.setName("connectLocalhostBtn"); // NOI18N - btnFind2.setPreferredSize(new java.awt.Dimension(23, 23)); - btnFind2.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - connectLocalhost(evt); - } - }); - - btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N - btnFind3.setText("P"); - btnFind3.setToolTipText("Connect to mtg.powersofwar.com (USA)"); - btnFind3.setActionCommand("connectXmageus"); - btnFind3.setAlignmentY(0.0F); - btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2)); - btnFind3.setName("connectXmageusBtn"); // NOI18N - btnFind3.setPreferredSize(new java.awt.Dimension(23, 23)); - btnFind3.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - connectXmageus(evt); - } - }); - - lblFastConnect.setLabelFor(btnFind1); - lblFastConnect.setText("Fast connect to:"); + lblFastConnect.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblFastConnect.setLabelFor(btnFindMain); + lblFastConnect.setText("Connect to:"); lblFastConnect.setName(""); // NOI18N - panelFlag.setPreferredSize(new java.awt.Dimension(189, 30)); + panelFlag.setMinimumSize(new java.awt.Dimension(50, 33)); panelFlag.setLayout(new javax.swing.BoxLayout(panelFlag, javax.swing.BoxLayout.LINE_AXIS)); cbFlag.setEditable(true); @@ -311,109 +240,232 @@ public class ConnectDialog extends MageDialog { }); panelFlag.add(btnFlagSearch); + btnFindMain.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/de.png"))); // NOI18N + btnFindMain.setText("X"); + btnFindMain.setToolTipText("Connect to xmage.de (Europe, most popular, registration needs)"); + btnFindMain.setActionCommand("connectXmageDe"); + btnFindMain.setAlignmentY(0.0F); + btnFindMain.setMargin(new java.awt.Insets(2, 2, 2, 2)); + btnFindMain.setMaximumSize(new java.awt.Dimension(42, 23)); + btnFindMain.setMinimumSize(new java.awt.Dimension(42, 23)); + btnFindMain.setName("connectXmageDeBtn"); // NOI18N + btnFindMain.setPreferredSize(new java.awt.Dimension(23, 23)); + btnFindMain.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + connectXmageDe(evt); + } + }); + + btnFindLocal.setText("LOCAL"); + btnFindLocal.setToolTipText("Connect to localhost (local server)"); + btnFindLocal.setActionCommand("connectLocalhost"); + btnFindLocal.setAlignmentY(0.0F); + btnFindLocal.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnFindLocal.setMargin(new java.awt.Insets(2, 2, 2, 2)); + btnFindLocal.setName("connectLocalhostBtn"); // NOI18N + btnFindLocal.setPreferredSize(new java.awt.Dimension(23, 23)); + btnFindLocal.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + connectLocalhost(evt); + } + }); + + btnFindBeta.setText("BETA"); + btnFindBeta.setToolTipText("Connect to BETA server (use any username without registration)"); + btnFindBeta.setAlignmentY(0.0F); + btnFindBeta.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnFindBeta.setMargin(new java.awt.Insets(2, 2, 2, 2)); + btnFindBeta.setPreferredSize(new java.awt.Dimension(23, 23)); + btnFindBeta.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnFindBetaconnectLocalhost(evt); + } + }); + + btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N + btnFindUs.setText("P"); + btnFindUs.setToolTipText("Connect to mtg.powersofwar.com (USA, use any username without registration)"); + btnFindUs.setActionCommand("connectXmageus"); + btnFindUs.setAlignmentY(0.0F); + btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2)); + btnFindUs.setName("connectXmageusBtn"); // NOI18N + btnFindUs.setPreferredSize(new java.awt.Dimension(23, 23)); + btnFindUs.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + connectXmageus(evt); + } + }); + + btnFindOther.setText("Other servers..."); + btnFindOther.setToolTipText("Choose server from full servers list"); + btnFindOther.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnFindOther.setName("findServerBtn"); // NOI18N + btnFindOther.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + findPublicServerActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelFastLayout = new javax.swing.GroupLayout(panelFast); + panelFast.setLayout(panelFastLayout); + panelFastLayout.setHorizontalGroup( + panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelFastLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnFindOther, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, 0)) + ); + panelFastLayout.setVerticalGroup( + panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelFastLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnFindOther)) + .addGap(0, 0, 0)) + ); + + txtPort.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + ConnectDialog.this.keyTyped(evt); + } + }); + + lblPort.setLabelFor(txtPort); + lblPort.setText("Port:"); + + btnCheckStatus.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/world.png"))); // NOI18N + btnCheckStatus.setText("Check online status"); + btnCheckStatus.setToolTipText("Go to servers online statuses page"); + btnCheckStatus.setAlignmentY(0.0F); + btnCheckStatus.setMargin(new java.awt.Insets(2, 2, 2, 2)); + btnCheckStatus.setPreferredSize(new java.awt.Dimension(23, 23)); + btnCheckStatus.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCheckStatusActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelServerLayout = new javax.swing.GroupLayout(panelServer); + panelServer.setLayout(panelServerLayout); + panelServerLayout.setHorizontalGroup( + panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelServerLayout.createSequentialGroup() + .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblPort) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 141, Short.MAX_VALUE) + .addGap(0, 0, 0)) + ); + panelServerLayout.setVerticalGroup( + panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelServerLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblPort) + .addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(29, 29, 29) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblPort) - .addComponent(lblServer))) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(lblFlag))) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblUserName) - .addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING)))) - .addGap(0, 0, 0) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(jProxySettingsButton) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(panelFlag, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(txtServer, javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtUserName, javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtPassword, javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE) - .addComponent(lblFastConnect) + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(lblUserName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jProxySettingsButton) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtUserName) + .addComponent(txtPassword) + .addComponent(panelFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnFind1, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGap(0, 0, 0) - .addComponent(btnFind))) - .addContainerGap()) + .addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) ); layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblServer) - .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnFind)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblPort) - .addComponent(btnFind1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFastConnect)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblUserName)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblPassword)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(chkAutoConnect) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(chkForceUpdateDB) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jProxySettingsButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addGroup(layout.createSequentialGroup() - .addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(23, 23, 23)) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(txtPassword) + .addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addComponent(filler2, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(chkAutoConnect) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(chkForceUpdateDB) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jProxySettingsButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(layout.createSequentialGroup() + .addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(23, 23, 23)) ); + lblFastConnect.getAccessibleContext().setAccessibleName("Fast connect to:"); + pack(); }// //GEN-END:initComponents @@ -456,7 +508,8 @@ public class ConnectDialog extends MageDialog { connection.setPort(Integer.valueOf(this.txtPort.getText().trim())); connection.setUsername(this.txtUserName.getText().trim()); connection.setPassword(this.txtPassword.getText().trim()); - boolean redownloadDatabase = CardRepository.instance.findCard("Island") == null; + // force to redownload db + boolean redownloadDatabase = (ExpansionRepository.instance.getSetByCode("GRN") == null || CardRepository.instance.findCard("Island") == null); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected() || redownloadDatabase); String allMAC = ""; try { @@ -676,8 +729,7 @@ public class ConnectDialog extends MageDialog { this.txtPort.setText("17171"); // Update userName and password according to the chosen server. this.txtUserName.setText(MagePreferences.getUserName(serverAddress)); - this.txtPassword.setText(MagePreferences.getPassword(serverAddress)); - + this.txtPassword.setText(MagePreferences.getPassword(serverAddress)); // TODO add your handling code here: }//GEN-LAST:event_btnFind1findPublicServerActionPerformed private void connectLocalhost(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFind2findPublicServerActionPerformed @@ -699,10 +751,33 @@ public class ConnectDialog extends MageDialog { this.txtPassword.setText(MagePreferences.getPassword(serverAddress)); } + private void connectBeta(java.awt.event.ActionEvent evt) { + String serverAddress = "xmage.today"; + this.txtServer.setText(serverAddress); + this.txtPort.setText("17171"); + // Update userName and password according to the chosen server. + this.txtUserName.setText(MagePreferences.getUserName(serverAddress)); + this.txtPassword.setText(MagePreferences.getPassword(serverAddress)); + } + private void btnFlagSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFlagSearchActionPerformed doFastFlagSearch(); }//GEN-LAST:event_btnFlagSearchActionPerformed + private void btnFindBetaconnectLocalhost(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindBetaconnectLocalhost + connectBeta(evt); + }//GEN-LAST:event_btnFindBetaconnectLocalhost + + private void btnCheckStatusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckStatusActionPerformed + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(new URI("http://xmageservers.online/")); + } catch (Exception e) { + // + } + } + }//GEN-LAST:event_btnCheckStatusActionPerformed + private void doFastFlagSearch() { Choice choice = new ChoiceImpl(false); @@ -748,11 +823,13 @@ public class ConnectDialog extends MageDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnCancel; + private javax.swing.JButton btnCheckStatus; private javax.swing.JButton btnConnect; - private javax.swing.JButton btnFind; - private javax.swing.JButton btnFind1; - private javax.swing.JButton btnFind2; - private javax.swing.JButton btnFind3; + private javax.swing.JButton btnFindBeta; + private javax.swing.JButton btnFindLocal; + private javax.swing.JButton btnFindMain; + private javax.swing.JButton btnFindOther; + private javax.swing.JButton btnFindUs; private javax.swing.JButton btnFlagSearch; private javax.swing.JButton btnForgotPassword; private javax.swing.JButton btnRegister; @@ -760,6 +837,7 @@ public class ConnectDialog extends MageDialog { private javax.swing.JCheckBox chkAutoConnect; private javax.swing.JCheckBox chkForceUpdateDB; private javax.swing.Box.Filler filler1; + private javax.swing.Box.Filler filler2; private javax.swing.JButton jProxySettingsButton; private javax.swing.JLabel lblFastConnect; private javax.swing.JLabel lblFlag; @@ -768,7 +846,9 @@ public class ConnectDialog extends MageDialog { private javax.swing.JLabel lblServer; private javax.swing.JLabel lblStatus; private javax.swing.JLabel lblUserName; + private javax.swing.JPanel panelFast; private javax.swing.JPanel panelFlag; + private javax.swing.JPanel panelServer; private javax.swing.JPasswordField txtPassword; private javax.swing.JTextField txtPort; private javax.swing.JTextField txtServer; diff --git a/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java index a16a7bbccd0..5d4e19e7642 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java @@ -1,7 +1,7 @@ package mage.client.dialog; -import mage.cards.decks.importer.DeckImporterUtil; +import mage.cards.decks.importer.DeckImporter; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.players.PlayerType; @@ -119,9 +119,9 @@ public class JoinTableDialog extends MageDialog { try { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD_JOIN, txtPassword.getText()); if (isTournament) { - joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporterUtil.importDeck(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText()); + joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText()); } else { - joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporterUtil.importDeck(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText()); + joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText()); } } catch (Exception ex) { diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java index c47059ed798..e4ad14fbaef 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -7,7 +7,8 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import javax.swing.*; -import mage.cards.decks.importer.DeckImporterUtil; + +import mage.cards.decks.importer.DeckImporter; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.client.components.MageComponents; @@ -425,7 +426,7 @@ public class NewTableDialog extends MageDialog { table.getTableId(), this.player1Panel.getPlayerName(), PlayerType.HUMAN, 1, - DeckImporterUtil.importDeck(this.player1Panel.getDeckFile()), + DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()), this.txtPassword.getText())) { for (TablePlayerPanel player : players) { if (player.getPlayerType() != PlayerType.HUMAN) { diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index fef9bdab407..bba0ef95006 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -18,7 +18,7 @@ import java.util.UUID; import javax.swing.*; import javax.swing.filechooser.FileFilter; import mage.cards.decks.Deck; -import mage.cards.decks.importer.DeckImporterUtil; +import mage.cards.decks.importer.DeckImporter; import mage.cards.repository.ExpansionInfo; import mage.cards.repository.ExpansionRepository; import mage.client.MageFrame; @@ -557,7 +557,7 @@ public class NewTournamentDialog extends MageDialog { if (!(cubeFromDeckFilename.isEmpty())) { Deck cubeFromDeck = new Deck(); try { - cubeFromDeck = Deck.load(DeckImporterUtil.importDeck(cubeFromDeckFilename), true, true); + cubeFromDeck = Deck.load(DeckImporter.importDeckFromFile(cubeFromDeckFilename), true, true); } catch (GameException e1) { JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); } @@ -631,11 +631,11 @@ public class NewTournamentDialog extends MageDialog { table.getTableId(), this.player1Panel.getPlayerName(), PlayerType.HUMAN, 1, - DeckImporterUtil.importDeck(this.player1Panel.getDeckFile()), + DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()), tOptions.getPassword())) { for (TournamentPlayerPanel player : players) { if (player.getPlayerType().getSelectedItem() != PlayerType.HUMAN) { - if (!player.joinTournamentTable(roomId, table.getTableId(), DeckImporterUtil.importDeck(this.player1Panel.getDeckFile()))) { + if (!player.joinTournamentTable(roomId, table.getTableId(), DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()))) { // error message must be send by sever SessionHandler.removeTable(roomId, table.getTableId()); table = null; diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java index 42541329f91..57ced4260ea 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java @@ -20,7 +20,8 @@ import javax.swing.JPopupMenu; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.MenuSelectionManager; import javax.swing.event.ChangeListener; -import mage.cards.decks.importer.DeckImporterUtil; + +import mage.cards.decks.importer.DeckImporter; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.client.cards.BigCard; @@ -569,7 +570,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { } private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) { - SessionHandler.cheat(gameId, playerId, DeckImporterUtil.importDeck("cheat.dck")); + SessionHandler.cheat(gameId, playerId, DeckImporter.importDeckFromFile("cheat.dck")); } public boolean isSmallMode() { diff --git a/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java b/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java index d18df6ef694..99d0dae1098 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java @@ -8,7 +8,7 @@ package mage.client.table; -import mage.cards.decks.importer.DeckImporterUtil; +import mage.cards.decks.importer.DeckImporter; import mage.client.SessionHandler; import mage.client.util.Config; import mage.client.util.Event; @@ -53,7 +53,7 @@ public class TablePlayerPanel extends javax.swing.JPanel { public boolean joinTable(UUID roomId, UUID tableId) throws IOException, ClassNotFoundException { if (this.cbPlayerType.getSelectedItem() != PlayerType.HUMAN) { - return SessionHandler.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), (PlayerType) this.cbPlayerType.getSelectedItem(), this.newPlayerPanel.getLevel(), DeckImporterUtil.importDeck(this.newPlayerPanel.getDeckFile()), ""); + return SessionHandler.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), (PlayerType) this.cbPlayerType.getSelectedItem(), this.newPlayerPanel.getLevel(), DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), ""); } return true; } diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index 7bbd6816add..7652a5040b5 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -1,6 +1,6 @@ package mage.client.table; -import mage.cards.decks.importer.DeckImporterUtil; +import mage.cards.decks.importer.DeckImporter; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.client.chat.ChatPanelBasic; @@ -1263,8 +1263,8 @@ public class TablesPanel extends javax.swing.JPanel { options.setBannedUsers(IgnoreList.ignoreList(serverAddress)); table = SessionHandler.createTable(roomId, options); - SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, DeckImporterUtil.importDeck("test.dck"), ""); - SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, DeckImporterUtil.importDeck("test.dck"), ""); + SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile("test.dck"), ""); + SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, DeckImporter.importDeckFromFile("test.dck"), ""); SessionHandler.startMatch(roomId, table.getTableId()); } catch (HeadlessException ex) { handleError(ex); diff --git a/Mage.Client/src/main/java/mage/client/table/TablesUtil.java b/Mage.Client/src/main/java/mage/client/table/TablesUtil.java index 475be3d2f96..bdb6bc363bc 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesUtil.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesUtil.java @@ -18,6 +18,8 @@ public class TablesUtil { searchId = ((TablesTableModel) table.getModel()).findTableAndGameInfoByRow(row); } else if (table.getModel() instanceof MatchesTableModel) { searchId = ((MatchesTableModel) table.getModel()).findTableAndGameInfoByRow(row); + } else if (table.getModel() instanceof TournamentMatchesTableModel) { + searchId = ((TournamentMatchesTableModel) table.getModel()).findTableAndGameInfoByRow(row); } else { logger.error("Not supported tables model " + table.getModel().getClass().toString()); } @@ -31,6 +33,8 @@ public class TablesUtil { row = ((TablesTableModel) tableModel).findRowByTableAndGameInfo(searchId); } else if (tableModel instanceof MatchesTableModel) { row = ((MatchesTableModel) tableModel).findRowByTableAndGameInfo(searchId); + } else if (tableModel instanceof TournamentMatchesTableModel) { + row = ((TournamentMatchesTableModel) tableModel).findRowByTableAndGameInfo(searchId); } else { logger.error("Not supported tables model " + tableModel.getClass().toString()); } diff --git a/Mage.Client/src/main/java/mage/client/table/TournamentMatchesTableModel.java b/Mage.Client/src/main/java/mage/client/table/TournamentMatchesTableModel.java new file mode 100644 index 00000000000..288a5c70f7e --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/table/TournamentMatchesTableModel.java @@ -0,0 +1,116 @@ +package mage.client.table; + +import mage.view.RoundView; +import mage.view.TournamentGameView; +import mage.view.TournamentView; + +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.List; + +/** + * @author JayDi85 + */ +public class TournamentMatchesTableModel extends AbstractTableModel { + public static final int ACTION_COLUMN = 4; // column the action is located + + private final String[] columnNames = new String[]{"Round Number", "Players", "State", "Result", "Action"}; + private TournamentGameView[] games = new TournamentGameView[0]; + private boolean watchingAllowed; + + public void loadData(TournamentView tournament) { + List views = new ArrayList<>(); + watchingAllowed = tournament.isWatchingAllowed(); + for (RoundView round : tournament.getRounds()) { + for (TournamentGameView game : round.getGames()) { + views.add(game); + } + } + games = views.toArray(new TournamentGameView[0]); + this.fireTableDataChanged(); + } + + public String getTableAndGameInfo(int row) { + return this.games[row].getTableId().toString() + ";" + games[row].toString(); + } + + public String findTableAndGameInfoByRow(int row) { + if (row >= 0 && row < this.games.length) { + return getTableAndGameInfo(row); + } else { + return null; + } + } + + public int findRowByTableAndGameInfo(String tableAndGame) { + for (int i = 0; i < this.games.length; i++) { + String rowID = this.games[i].getTableId().toString() + ";" + this.games[i].toString(); + if (tableAndGame.equals(rowID)) { + return i; + } + } + return -1; + } + + @Override + public int getRowCount() { + return games.length; + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int arg0, int arg1) { + switch (arg1) { + case 0: + return Integer.toString(games[arg0].getRoundNum()); + case 1: + return games[arg0].getPlayers(); + case 2: + return games[arg0].getState(); + case 3: + return games[arg0].getResult(); + case 4: +// if (games[arg0].getState().equals("Finished")) { +// return "Replay"; +// } + if (watchingAllowed && games[arg0].getState().startsWith("Dueling")) { + return "Watch"; + } + return ""; + case 5: + return games[arg0].getTableId().toString(); + case 6: + return games[arg0].getMatchId().toString(); + case 7: + return games[arg0].getGameId().toString(); + + } + return ""; + } + + @Override + public String getColumnName(int columnIndex) { + String colName = ""; + + if (columnIndex <= getColumnCount()) { + colName = columnNames[columnIndex]; + } + + return colName; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == ACTION_COLUMN; + } + +} \ No newline at end of file diff --git a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java index bdafa112a59..19eeb84fdbc 100644 --- a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java +++ b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java @@ -5,12 +5,16 @@ import mage.client.SessionHandler; import mage.client.chat.ChatPanelBasic; import mage.client.dialog.PreferencesDialog; import mage.client.table.TablesButtonColumn; +import mage.client.table.TablesUtil; +import mage.client.table.TournamentMatchesTableModel; import mage.client.util.Format; import mage.client.util.GUISizeHelper; import mage.client.util.gui.TableUtil; import mage.client.util.gui.countryBox.CountryCellRenderer; import mage.constants.PlayerAction; -import mage.view.*; +import mage.view.TournamentPlayerView; +import mage.view.TournamentView; +import mage.view.UserRequestMessage; import org.apache.log4j.Logger; import javax.swing.*; @@ -18,7 +22,6 @@ import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.text.DateFormat; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -74,7 +77,11 @@ public class TournamentPanel extends javax.swing.JPanel { Action action = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { - int modelRow = Integer.valueOf(e.getActionCommand()); + String searchID = e.getActionCommand(); + int modelRow = TablesUtil.findTableRowFromSearchId(matchesModel, searchID); + if (modelRow == -1) { + return; + } String state = (String) tableMatches.getValueAt(modelRow, tableMatches.convertColumnIndexToView(2)); String actionText = (String) tableMatches.getValueAt(modelRow, tableMatches.convertColumnIndexToView(TournamentMatchesTableModel.ACTION_COLUMN)); @@ -132,7 +139,7 @@ public class TournamentPanel extends javax.swing.JPanel { private void saveDividerLocations() { // save panel sizes and divider locations. Rectangle rec = MageFrame.getDesktop().getBounds(); - String sb = Double.toString(rec.getWidth()) + 'x' + Double.toString(rec.getHeight()); + String sb = Double.toString(rec.getWidth()) + 'x' + rec.getHeight(); PreferencesDialog.saveValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, sb); PreferencesDialog.saveValue(PreferencesDialog.KEY_TOURNAMENT_DIVIDER_LOCATION_1, Integer.toString(this.jSplitPane1.getDividerLocation())); PreferencesDialog.saveValue(PreferencesDialog.KEY_TOURNAMENT_DIVIDER_LOCATION_2, Integer.toString(this.jSplitPane2.getDividerLocation())); @@ -142,7 +149,7 @@ public class TournamentPanel extends javax.swing.JPanel { Rectangle rec = MageFrame.getDesktop().getBounds(); if (rec != null) { String size = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, null); - String sb = Double.toString(rec.getWidth()) + 'x' + Double.toString(rec.getHeight()); + String sb = Double.toString(rec.getWidth()) + 'x' + rec.getHeight(); // use divider positions only if screen size is the same as it was the time the settings were saved if (size != null && size.equals(sb)) { String location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_TOURNAMENT_DIVIDER_LOCATION_1, null); @@ -585,88 +592,6 @@ class TournamentPlayersTableModel extends AbstractTableModel { } -class TournamentMatchesTableModel extends AbstractTableModel { - - public static final int ACTION_COLUMN = 4; // column the action is located - - private final String[] columnNames = new String[]{"Round Number", "Players", "State", "Result", "Action"}; - private TournamentGameView[] games = new TournamentGameView[0]; - private boolean watchingAllowed; - - public void loadData(TournamentView tournament) { - List views = new ArrayList<>(); - watchingAllowed = tournament.isWatchingAllowed(); - for (RoundView round : tournament.getRounds()) { - for (TournamentGameView game : round.getGames()) { - views.add(game); - } - } - games = views.toArray(new TournamentGameView[0]); - this.fireTableDataChanged(); - } - - @Override - public int getRowCount() { - return games.length; - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int arg0, int arg1) { - switch (arg1) { - case 0: - return Integer.toString(games[arg0].getRoundNum()); - case 1: - return games[arg0].getPlayers(); - case 2: - return games[arg0].getState(); - case 3: - return games[arg0].getResult(); - case 4: -// if (games[arg0].getState().equals("Finished")) { -// return "Replay"; -// } - if (watchingAllowed && games[arg0].getState().startsWith("Dueling")) { - return "Watch"; - } - return ""; - case 5: - return games[arg0].getTableId().toString(); - case 6: - return games[arg0].getMatchId().toString(); - case 7: - return games[arg0].getGameId().toString(); - - } - return ""; - } - - @Override - public String getColumnName(int columnIndex) { - String colName = ""; - - if (columnIndex <= getColumnCount()) { - colName = columnNames[columnIndex]; - } - - return colName; - } - - @Override - public Class getColumnClass(int columnIndex) { - return String.class; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return columnIndex == ACTION_COLUMN; - } - -} class UpdateTournamentTask extends SwingWorker { @@ -709,4 +634,4 @@ class UpdateTournamentTask extends SwingWorker { } } -} +} \ No newline at end of file diff --git a/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java b/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java index fe22935c6e8..45864841500 100644 --- a/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java +++ b/Mage.Client/src/main/java/mage/client/util/gui/FastSearchUtil.java @@ -1,17 +1,15 @@ package mage.client.util.gui; import mage.choices.ChoiceImpl; +import mage.client.dialog.CheckBoxList; import mage.client.dialog.PickCheckBoxDialog; import mage.client.dialog.PickChoiceDialog; -import mage.client.dialog.CheckBoxList; - import javax.swing.*; import java.util.HashMap; import java.util.Map; /** - * * @author JayDi85 */ public class FastSearchUtil { @@ -19,27 +17,28 @@ public class FastSearchUtil { public static String DEFAULT_EXPANSION_SEARCH_MESSAGE = "Select set or expansion"; public static String DEFAULT_EXPANSION_TOOLTIP_MESSAGE = "Fast search set or expansion"; - public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage){ + public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage) { showFastSearchForStringComboBox(combo, chooseMessage, 300, 500); } /** * Show fast choice modal dialog with incremental searching for any string combobox components - * @param combo combobox control with default data model + * + * @param combo combobox control with default data model * @param chooseMessage caption message for dialog */ - public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage, int windowWidth, int windowHeight){ + public static void showFastSearchForStringComboBox(JComboBox combo, String chooseMessage, int windowWidth, int windowHeight) { // fast search/choice dialog for string combobox mage.choices.Choice choice = new ChoiceImpl(false); // collect data from expansion combobox (String) - DefaultComboBoxModel comboModel = (DefaultComboBoxModel)combo.getModel(); + DefaultComboBoxModel comboModel = (DefaultComboBoxModel) combo.getModel(); Map choiceItems = new HashMap<>(comboModel.getSize()); Map choiceSorting = new HashMap<>(comboModel.getSize()); String item; - for(int i = 0; i < comboModel.getSize(); i++){ + for (int i = 0; i < comboModel.getSize(); i++) { item = comboModel.getElementAt(i).toString(); choiceItems.put(item, item); choiceSorting.put(item, i); // need so sorting @@ -57,35 +56,36 @@ public class FastSearchUtil { PickChoiceDialog dlg = new PickChoiceDialog(); dlg.setWindowSize(windowWidth, windowHeight); dlg.showDialog(choice, needSelectValue); - if(choice.isChosen()){ + if (choice.isChosen()) { item = choice.getChoiceKey(); // compatible select for object's models (use setSelectedIndex instead setSelectedObject) - for(int i = 0; i < comboModel.getSize(); i++){ - if(comboModel.getElementAt(i).toString().equals(item)){ + for (int i = 0; i < comboModel.getSize(); i++) { + if (comboModel.getElementAt(i).toString().equals(item)) { combo.setSelectedIndex(i); } } } } - + /** * Show fast choice modal dialog with incremental searching for any string CheckBoxList components - * @param combo CheckBoxList control with default data model + * + * @param combo CheckBoxList control with default data model * @param chooseMessage caption message for dialog */ - public static void showFastSearchForStringComboBox(CheckBoxList combo, String chooseMessage){ + public static void showFastSearchForStringComboBox(CheckBoxList combo, String chooseMessage) { // fast search/choice dialog for string combobox mage.choices.Choice choice = new ChoiceImpl(false); // collect data from expansion combobox (String) - DefaultListModel comboModel = (DefaultListModel)combo.getModel(); + DefaultListModel comboModel = (DefaultListModel) combo.getModel(); Map choiceItems = new HashMap<>(comboModel.getSize()); Map choiceSorting = new HashMap<>(comboModel.getSize()); String item; - for(int i = 0; i < comboModel.size(); i++){ + for (int i = 0; i < comboModel.size(); i++) { item = comboModel.getElementAt(i).toString(); choiceItems.put(item, item); choiceSorting.put(item, i); // need so sorting @@ -96,21 +96,22 @@ public class FastSearchUtil { choice.setMessage(chooseMessage); // current selection value restore - String needSelectValue; - needSelectValue = comboModel.firstElement().toString(); + String needSelectValue = null; + if (comboModel.size() > 0) { + needSelectValue = comboModel.firstElement().toString(); + } // ask for new value - - PickCheckBoxDialog dlg = new PickCheckBoxDialog(combo); + PickCheckBoxDialog dlg = new PickCheckBoxDialog(combo); dlg.setWindowSize(300, 500); dlg.showDialog(choice, needSelectValue); - if(choice.isChosen()){ + if (choice.isChosen()) { item = choice.getChoiceKey(); // compatible select for object's models (use setSelectedIndex instead setSelectedObject) - for(int i = 0; i < comboModel.getSize(); i++){ - if(comboModel.getElementAt(i).toString().equals(item)){ + for (int i = 0; i < comboModel.getSize(); i++) { + if (comboModel.getElementAt(i).toString().equals(item)) { combo.setSelectedIndex(i); } } diff --git a/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java b/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java index ad1351b7f89..ae4a93b343c 100644 --- a/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java +++ b/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java @@ -1,17 +1,13 @@ package mage.client.util.sets; -import java.util.ArrayList; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import mage.cards.repository.ExpansionInfo; import mage.cards.repository.ExpansionRepository; +import mage.cards.repository.RepositoryEvent; import mage.constants.SetType; -import static mage.constants.SetType.EXPANSION; -import static mage.constants.SetType.SUPPLEMENTAL; import mage.deck.Standard; +import mage.game.events.Listener; + +import java.util.*; /** * Utility class for constructed formats (expansions and other editions). @@ -26,11 +22,36 @@ public final class ConstructedFormats { public static final String FRONTIER = "- Frontier"; public static final String MODERN = "- Modern"; public static final String VINTAGE_LEGACY = "- Vintage / Legacy"; + public static final String JOKE = "- Joke Sets"; public static final String CUSTOM = "- Custom"; public static final Standard STANDARD_CARDS = new Standard(); + // Attention -Month is 0 Based so Feb = 1 for example. // + private static final Date extendedDate = new GregorianCalendar(2009, 7, 20).getTime(); + private static final Date frontierDate = new GregorianCalendar(2014, 6, 17).getTime(); + private static final Date modernDate = new GregorianCalendar(2003, 6, 20).getTime(); + + // for all sets just return empty list + private static final List all = new ArrayList<>(); + private static final Map> underlyingSetCodesPerFormat = new HashMap<>(); private static final List formats = new ArrayList<>(); + private static final Listener setsDbListener; + + static { + buildLists(); + + // auto-update sets list on changes + setsDbListener = new Listener() { + @Override + public void event(RepositoryEvent event) { + if (event.getEventType().equals(RepositoryEvent.RepositoryEventType.DB_UPDATED)) { + buildLists(); + } + } + }; + ExpansionRepository.instance.subscribe(setsDbListener); + } private ConstructedFormats() { } @@ -57,12 +78,13 @@ public final class ConstructedFormats { } } - private static void buildLists() { + public static void buildLists() { underlyingSetCodesPerFormat.put(STANDARD, new ArrayList<>()); underlyingSetCodesPerFormat.put(EXTENDED, new ArrayList<>()); underlyingSetCodesPerFormat.put(FRONTIER, new ArrayList<>()); underlyingSetCodesPerFormat.put(MODERN, new ArrayList<>()); underlyingSetCodesPerFormat.put(VINTAGE_LEGACY, new ArrayList<>()); + underlyingSetCodesPerFormat.put(JOKE, new ArrayList<>()); underlyingSetCodesPerFormat.put(CUSTOM, new ArrayList<>()); final Map expansionInfo = new HashMap<>(); formats.clear(); // prevent NPE on sorting if this is not the first try @@ -85,6 +107,10 @@ public final class ConstructedFormats { underlyingSetCodesPerFormat.get(CUSTOM).add(set.getCode()); continue; } + if (set.getType() == SetType.JOKESET) { + underlyingSetCodesPerFormat.get(JOKE).add(set.getCode()); + continue; + } underlyingSetCodesPerFormat.get(VINTAGE_LEGACY).add(set.getCode()); if (set.getType() == SetType.CORE || set.getType() == SetType.EXPANSION || set.getType() == SetType.SUPPLEMENTAL_STANDARD_LEGAL) { if (STANDARD_CARDS.getSetCodes().contains(set.getCode())) { @@ -211,12 +237,12 @@ public final class ConstructedFormats { }); if (!formats.isEmpty()) { formats.add(0, CUSTOM); + formats.add(0, JOKE); formats.add(0, VINTAGE_LEGACY); formats.add(0, MODERN); - formats.add(0, EXTENDED); formats.add(0, FRONTIER); + formats.add(0, EXTENDED); formats.add(0, STANDARD); - } formats.add(0, ALL); } @@ -224,15 +250,4 @@ public final class ConstructedFormats { private static String getBlockDisplayName(String blockName) { return "* " + blockName + " Block"; } - // Attention -Month is 0 Based so Feb = 1 for example. - private static final Date extendedDate = new GregorianCalendar(2009, 7, 20).getTime(); - private static final Date frontierDate = new GregorianCalendar(2014, 6, 17).getTime(); - private static final Date modernDate = new GregorianCalendar(2003, 6, 20).getTime(); - - // for all sets just return empty list - private static final List all = new ArrayList<>(); - - static { - buildLists(); - } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java index df290687c19..f8216028bae 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java @@ -1,4 +1,3 @@ - package org.mage.plugins.card.dl.sources; import org.apache.log4j.Logger; @@ -59,7 +58,7 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { return null; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java index 8fb85388bf5..758f38881ef 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java @@ -6,11 +6,11 @@ import org.mage.plugins.card.images.CardDownloadData; import java.util.ArrayList; /** - * @author North + * @author North, JayDi85 */ public interface CardImageSource { - CardImageUrls generateURL(CardDownloadData card) throws Exception; + CardImageUrls generateCardUrl(CardDownloadData card) throws Exception; CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception; @@ -53,7 +53,11 @@ public interface CardImageSource { return true; } - default boolean isImageProvided(String setCode, String cardName) { + default boolean isCardImageProvided(String setCode, String cardName) { + return false; + } + + default boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { return false; } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java index 0fc6561b978..766208bdf11 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java @@ -1,6 +1,10 @@ package org.mage.plugins.card.dl.sources; -import java.awt.Toolkit; +import mage.cards.Sets; +import org.mage.plugins.card.images.CardDownloadData; + +import javax.swing.*; +import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.io.IOException; @@ -10,12 +14,8 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.swing.JOptionPane; -import mage.cards.Sets; -import org.mage.plugins.card.images.CardDownloadData; /** - * * @author spjspj */ public enum CopyPasteImageSource implements CardImageSource { @@ -74,7 +74,7 @@ public enum CopyPasteImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { if (singleLinks == null) { setupLinks(); } @@ -198,7 +198,7 @@ public enum CopyPasteImageSource implements CardImageSource { @Override public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { try { - return generateURL(card); + return generateCardUrl(card); } catch (Exception ex) { } return null; @@ -239,7 +239,7 @@ public enum CopyPasteImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { + public boolean isCardImageProvided(String setCode, String cardName) { missingCards.add(setCode + "/" + cardName); if (singleLinks != null) { @@ -248,6 +248,11 @@ public enum CopyPasteImageSource implements CardImageSource { return false; } + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { + return false; + } + @Override public boolean isSetSupportedComplete(String setCode) { return false; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java index 8d3e12236c2..e38898760fc 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java @@ -1,6 +1,8 @@ - package org.mage.plugins.card.dl.sources; +import org.apache.log4j.Logger; +import org.mage.plugins.card.images.CardDownloadData; + import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -9,9 +11,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import org.apache.log4j.Logger; -import org.mage.plugins.card.images.CardDownloadData; - /** * @author spjspj */ @@ -48,7 +47,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { if (singleLinks == null) { setupLinks(); } @@ -450,7 +449,7 @@ public enum GrabbagImageSource implements CardImageSource { @Override public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { try { - return generateURL(card); + return generateCardUrl(card); } catch (Exception ex) { java.util.logging.Logger.getLogger(GrabbagImageSource.class.getName()).log(Level.SEVERE, null, ex); } @@ -501,7 +500,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { + public boolean isCardImageProvided(String setCode, String cardName) { if (singleLinks == null) { setupLinks(); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java index c2ddfcc9874..4bd2c49433e 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java @@ -1,16 +1,10 @@ - package org.mage.plugins.card.dl.sources; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - import org.mage.plugins.card.images.CardDownloadData; +import java.net.URI; +import java.util.*; + /** * @author Pete Rossi */ @@ -234,7 +228,7 @@ public enum MagidexImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String cardDownloadName = card.getDownloadName().toLowerCase(Locale.ENGLISH); String cardSet = card.getSet(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java index f5104a22269..7c8a3685790 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java @@ -1,10 +1,9 @@ - package org.mage.plugins.card.dl.sources; -import java.util.Locale; - import org.mage.plugins.card.images.CardDownloadData; +import java.util.Locale; + /** * Site was shutdown by wizards Feb. 2015 * @@ -30,7 +29,7 @@ public enum MtgImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java index 9d82cbb425c..f43baec92c6 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java @@ -1,12 +1,11 @@ - package org.mage.plugins.card.dl.sources; -import java.io.IOException; -import java.util.HashMap; - import org.apache.log4j.Logger; import org.mage.plugins.card.images.CardDownloadData; +import java.io.IOException; +import java.util.HashMap; + /** * @author spjspj */ @@ -59,7 +58,7 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { return null; } @@ -352,8 +351,12 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { - return true; + public boolean isCardImageProvided(String setCode, String cardName) { + return false; } + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { + return true; + } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index 86f80a6fea5..1c0ecaf8577 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -1,22 +1,5 @@ package org.mage.plugins.card.dl.sources; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.prefs.Preferences; import mage.client.MageFrame; import mage.remote.Connection; import mage.remote.Connection.ProxyType; @@ -26,6 +9,13 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.mage.plugins.card.images.CardDownloadData; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.*; +import java.util.*; +import java.util.prefs.Preferences; + /** * @author LevelX2 */ @@ -330,7 +320,7 @@ public enum MythicspoilerComSource implements CardImageSource { } private Map getSetLinksFromPage(String cardSet, Set aliasesStart, Preferences prefs, - ProxyType proxyType, String baseUrl, String pageUrl) throws IOException { + ProxyType proxyType, String baseUrl, String pageUrl) throws IOException { Map pageLinks = new HashMap<>(); String urlDocument; @@ -392,7 +382,7 @@ public enum MythicspoilerComSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java index f176324825b..6d1f873c1ba 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java @@ -3,20 +3,23 @@ package org.mage.plugins.card.dl.sources; import mage.client.util.CardLanguage; import org.mage.plugins.card.images.CardDownloadData; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; /** - * @author Quercitron, JayDi85 + * @author JayDi85 */ public enum ScryfallImageSource implements CardImageSource { instance; - private final Set supportedSets; private final Map languageAliases; private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language ScryfallImageSource() { + // LANGUAGES // https://scryfall.com/docs/api/languages languageAliases = new HashMap<>(); languageAliases.put(CardLanguage.ENGLISH, "en"); @@ -30,225 +33,9 @@ public enum ScryfallImageSource implements CardImageSource { languageAliases.put(CardLanguage.RUSSIAN, "ru"); languageAliases.put(CardLanguage.CHINES_SIMPLE, "zhs"); languageAliases.put(CardLanguage.CHINES_TRADITION, "zht"); - - supportedSets = new LinkedHashSet<>(); - // supportedSets.add("PTC"); // - supportedSets.add("LEA"); - supportedSets.add("LEB"); - supportedSets.add("2ED"); - supportedSets.add("ARN"); - supportedSets.add("ATQ"); - supportedSets.add("3ED"); - supportedSets.add("LEG"); - supportedSets.add("DRK"); - supportedSets.add("FEM"); - supportedSets.add("4ED"); - supportedSets.add("ICE"); - supportedSets.add("CHR"); - supportedSets.add("HML"); - supportedSets.add("ALL"); - supportedSets.add("MIR"); - supportedSets.add("VIS"); - supportedSets.add("5ED"); - supportedSets.add("POR"); - supportedSets.add("WTH"); - supportedSets.add("TMP"); - supportedSets.add("STH"); - supportedSets.add("EXO"); - supportedSets.add("P02"); - supportedSets.add("UGL"); - supportedSets.add("USG"); - supportedSets.add("DD3DVD"); - supportedSets.add("DD3EVG"); - supportedSets.add("DD3GVL"); - supportedSets.add("DD3JVC"); - - supportedSets.add("ULG"); - supportedSets.add("6ED"); - supportedSets.add("UDS"); - supportedSets.add("PTK"); - supportedSets.add("S99"); - supportedSets.add("MMQ"); - // supportedSets.add("BRB");Battle Royale Box Set - supportedSets.add("NEM"); - supportedSets.add("S00"); - supportedSets.add("PCY"); - supportedSets.add("INV"); - // supportedSets.add("BTD"); // Beatdown Boxset - supportedSets.add("PLS"); - supportedSets.add("7ED"); - supportedSets.add("APC"); - supportedSets.add("ODY"); - // supportedSets.add("DKM"); // Deckmasters 2001 - supportedSets.add("TOR"); - supportedSets.add("JUD"); - supportedSets.add("ONS"); - supportedSets.add("LGN"); - supportedSets.add("SCG"); - supportedSets.add("8ED"); - supportedSets.add("MRD"); - supportedSets.add("DST"); - supportedSets.add("5DN"); - supportedSets.add("CHK"); - supportedSets.add("UNH"); - supportedSets.add("BOK"); - supportedSets.add("SOK"); - supportedSets.add("9ED"); - supportedSets.add("RAV"); - supportedSets.add("GPT"); - supportedSets.add("DIS"); - supportedSets.add("CSP"); - supportedSets.add("TSP"); - supportedSets.add("TSB"); - supportedSets.add("PLC"); - supportedSets.add("FUT"); - supportedSets.add("10E"); - supportedSets.add("MED"); - supportedSets.add("LRW"); - supportedSets.add("EVG"); - supportedSets.add("MOR"); - supportedSets.add("SHM"); - supportedSets.add("EVE"); - supportedSets.add("DRB"); - supportedSets.add("ME2"); - supportedSets.add("ALA"); - supportedSets.add("DD2"); - supportedSets.add("CON"); - supportedSets.add("DDC"); - supportedSets.add("ARB"); - supportedSets.add("M10"); - // supportedSets.add("TD0"); // Magic Online Deck Series - supportedSets.add("V09"); - supportedSets.add("HOP"); - supportedSets.add("ME3"); - supportedSets.add("ZEN"); - supportedSets.add("DDD"); - supportedSets.add("H09"); - supportedSets.add("WWK"); - supportedSets.add("DDE"); - supportedSets.add("ROE"); - // duels of the planewalkers: - supportedSets.add("DPA"); - supportedSets.add("DPAP"); - // - supportedSets.add("ARC"); - supportedSets.add("M11"); - supportedSets.add("V10"); - supportedSets.add("DDF"); - supportedSets.add("SOM"); - // supportedSets.add("TD0"); // Commander Theme Decks - supportedSets.add("PD2"); - supportedSets.add("ME4"); - supportedSets.add("MBS"); - supportedSets.add("DDG"); - supportedSets.add("NPH"); - supportedSets.add("CMD"); - supportedSets.add("M12"); - supportedSets.add("V11"); - supportedSets.add("DDH"); - supportedSets.add("ISD"); - supportedSets.add("PD3"); - supportedSets.add("DKA"); - supportedSets.add("DDI"); - supportedSets.add("AVR"); - supportedSets.add("PC2"); - supportedSets.add("M13"); - supportedSets.add("V12"); - supportedSets.add("DDJ"); - supportedSets.add("RTR"); - supportedSets.add("CM1"); - // supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia - supportedSets.add("GTC"); - supportedSets.add("DDK"); - supportedSets.add("DGM"); - supportedSets.add("MMA"); - supportedSets.add("M14"); - supportedSets.add("V13"); - supportedSets.add("DDL"); - supportedSets.add("THS"); - supportedSets.add("C13"); - supportedSets.add("BNG"); - supportedSets.add("DDM"); - supportedSets.add("JOU"); - // supportedSets.add("MD1"); // Modern Event Deck - supportedSets.add("CNS"); - supportedSets.add("VMA"); - supportedSets.add("M15"); - supportedSets.add("V14"); - supportedSets.add("DDN"); - supportedSets.add("KTK"); - supportedSets.add("C14"); - // supportedSets.add("DD3"); // Duel Decks Anthology - supportedSets.add("FRF"); - supportedSets.add("DDO"); - supportedSets.add("DTK"); - supportedSets.add("TPR"); - supportedSets.add("MM2"); - supportedSets.add("ORI"); - supportedSets.add("V15"); - supportedSets.add("DDP"); - supportedSets.add("BFZ"); - supportedSets.add("EXP"); - supportedSets.add("C15"); - // supportedSets.add("PZ1"); // Legendary Cube - supportedSets.add("OGW"); - supportedSets.add("DDQ"); - supportedSets.add("W16"); - supportedSets.add("SOI"); - supportedSets.add("EMA"); - supportedSets.add("EMN"); - supportedSets.add("V16"); - supportedSets.add("CN2"); - supportedSets.add("DDR"); - supportedSets.add("KLD"); - supportedSets.add("MPS"); - // supportedSets.add("PZ2"); - supportedSets.add("C16"); - supportedSets.add("PCA"); - supportedSets.add("AER"); - supportedSets.add("MM3"); - supportedSets.add("DDS"); - supportedSets.add("W17"); - supportedSets.add("AKH"); - supportedSets.add("CMA"); - supportedSets.add("E01"); - supportedSets.add("HOU"); - supportedSets.add("C17"); - supportedSets.add("XLN"); - supportedSets.add("DDT"); - supportedSets.add("IMA"); - supportedSets.add("E02"); - supportedSets.add("V17"); - supportedSets.add("UST"); - supportedSets.add("DDU"); - supportedSets.add("RIX"); - supportedSets.add("WMCQ"); - supportedSets.add("PPRO"); - supportedSets.add("A25"); - supportedSets.add("DOM"); - supportedSets.add("BBD"); - supportedSets.add("C18"); - supportedSets.add("CM2"); - supportedSets.add("M19"); - supportedSets.add("GS1"); - supportedSets.add("GRN"); - supportedSets.add("GK1"); - supportedSets.add("GNT"); - supportedSets.add("UMA"); - supportedSets.add("PUMA"); - supportedSets.add("RNA"); - // - supportedSets.add("EURO"); - supportedSets.add("GPX"); - supportedSets.add("ATH"); - supportedSets.add("GRC"); - supportedSets.add("ANA"); } - @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { - - String preferredCode = this.getCurrentLanguage().getCode(); + private CardImageUrls innerGenerateURL(CardDownloadData card, boolean isToken) { String defaultCode = CardLanguage.ENGLISH.getCode(); String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode); // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image @@ -259,22 +46,20 @@ public enum ScryfallImageSource implements CardImageSource { String baseUrl = null; String alternativeUrl = null; + // TOKENS TRY + + // tokens support only direct links + if (baseUrl == null && isToken) { + baseUrl = ScryfallImageSupportTokens.findTokenLink(card.getSet(), card.getName(), card.getType()); + alternativeUrl = null; + } + + // CARDS TRY + // direct links to images (non localization) if (baseUrl == null) { - - // set/card/number - String linkCode1 = card.getSet() + "/" + card.getName() + "/" + card.getCollectorId(); - if (directDownloadLinks.containsKey(linkCode1)) { - baseUrl = directDownloadLinks.get(linkCode1); - alternativeUrl = null; - } - - // set/card - String linkCode2 = card.getSet() + "/" + card.getName(); - if (directDownloadLinks.containsKey(linkCode2)) { - baseUrl = directDownloadLinks.get(linkCode2); - alternativeUrl = null; - } + baseUrl = ScryfallImageSupportCards.findDirectDownloadLink(card.getSet(), card.getName(), card.getCollectorId()); + alternativeUrl = null; } // special card number like "103a" and "U123" already compatible @@ -285,9 +70,9 @@ public enum ScryfallImageSource implements CardImageSource { // fix for Ultimate Box Topper (PUMA) -- need to use API // ignored and go to API call at the end } else { - baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + ".jpg"; - alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + ".jpg"; } } @@ -295,27 +80,33 @@ public enum ScryfallImageSource implements CardImageSource { // double faced cards do not supports by API (need direct link for img) // example: https://img.scryfall.com/cards/large/en/xln/173b.jpg if (baseUrl == null && card.isTwoFacedCard()) { - baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; - alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; } // basic cards by api call (redirect to img link) // example: https://api.scryfall.com/cards/xln/121/en?format=image if (baseUrl == null) { - baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + "/" + localizedCode + "?format=image"; - alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + "/" + defaultCode + "?format=image"; } return new CardImageUrls(baseUrl, alternativeUrl); } + @Override + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { + return innerGenerateURL(card, false); + + } + @Override public CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception { - return null; + return innerGenerateURL(card, true); } @Override @@ -345,7 +136,7 @@ public enum ScryfallImageSource implements CardImageSource { @Override public boolean isTokenSource() { - return false; + return true; } @Override @@ -368,132 +159,41 @@ public enum ScryfallImageSource implements CardImageSource { } - private String formatSetName(String setName) { - if (setNameReplacement.containsKey(setName)) { - setName = setNameReplacement.get(setName); + private String formatSetName(String setName, boolean isToken) { + if (isToken) { + // token uses direct link download, not set + return setName.toLowerCase(Locale.ENGLISH); + } else { + return ScryfallImageSupportCards.findScryfallSetCode(setName); } - return setName.toLowerCase(Locale.ENGLISH); } - private static final Map setNameReplacement = new HashMap() { - { - put("DD3GVL", "gvl"); - put("DD3JVC", "jvc"); - put("DD3DVD", "dvd"); - put("DD3EVG", "evg"); - put("MPS-AKH", "mp2"); - put("MBP", "pmei"); - put("WMCQ", "pwcq"); - put("EURO", "pelp"); - put("GPX", "pgpx"); - put("MED", "me1"); - } - }; - - private static final Map directDownloadLinks = new HashMap() { - { - // direct links to download images for special cards - - // Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years - // 2009 - https://scryfall.com/sets/pdtp - put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg"); - // 2010 - https://scryfall.com/sets/pdp10 - put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg"); - put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg"); - // 2011 - https://scryfall.com/sets/pdp11 - put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg"); - put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg"); - put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg"); - // 2012 - https://scryfall.com/sets/pdp12 - put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg"); - put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg"); - put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg"); - // 2013 - https://scryfall.com/sets/pdp13 - put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg"); - put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg"); - put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg"); - // 2014 - https://scryfall.com/sets/pdp14 - put("DPAP/Soul of Ravnica", "https://img.scryfall.com/cards/large/en/pdp14/1.jpg"); - put("DPAP/Soul of Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg"); - - // Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years - // 2006 - https://scryfall.com/sets/pgtw - put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg"); - put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg"); - put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg"); - // 2007 - https://scryfall.com/sets/pg07 - put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg"); - put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg"); - put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg"); - put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg"); - put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg"); - put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg"); - put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg"); - put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg"); - put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg"); - // 2008a - https://scryfall.com/sets/pg08 - put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg"); - put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg"); - put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg"); - put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg"); - put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg"); - put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg"); - put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg"); - put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg"); - - // Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years - // 2008b - https://scryfall.com/sets/pwpn - put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg"); - put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg"); - // 2009 - https://scryfall.com/sets/pwp09 - put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg"); - put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg"); - put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg"); - put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg"); - put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg"); - put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg"); - put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg"); - put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg"); - // 2010 - https://scryfall.com/sets/pwp10 - put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg"); - put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg"); - put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg"); - put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg"); - put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg"); - put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // same card but different year - put("GRC/Sylvan Ranger/51", "https://img.scryfall.com/cards/large/en/pwp10/51.jpg"); // same card but different year - put("GRC/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg"); - put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg"); - put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg"); - // 2011 - https://scryfall.com/sets/pwp11 - put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg"); - put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg"); - put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg"); - put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg"); - put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg"); - put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year - put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg"); - put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg"); - put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg"); - put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg"); - put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg"); - put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year - put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg"); - put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg"); - // 2012 - https://scryfall.com/sets/pwp12 - put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg"); - put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg"); - put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg"); - - // TODO: remove Grand Prix fix after scryfall fix image's link (that's link must be work: https://img.scryfall.com/cards/large/en/pgpx/2016b.jpg ) - put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg"); - } - }; - @Override public ArrayList getSupportedSets() { ArrayList supportedSetsCopy = new ArrayList<>(); - supportedSetsCopy.addAll(supportedSets); + + // cards + supportedSetsCopy.addAll(ScryfallImageSupportCards.getSupportedSets()); + + // tokens + for (String code : ScryfallImageSupportTokens.getSupportedSets().keySet()) { + if (!supportedSetsCopy.contains(code)) { + supportedSetsCopy.add(code); + } + } + return supportedSetsCopy; } + + @Override + public boolean isCardImageProvided(String setCode, String cardName) { + // all cards from set + return ScryfallImageSupportCards.getSupportedSets().contains(setCode); + } + + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { + // only direct tokens from set + return ScryfallImageSupportTokens.findTokenLink(setCode, cardName, tokenNumber) != null; + } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java new file mode 100644 index 00000000000..f365a441436 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java @@ -0,0 +1,392 @@ +package org.mage.plugins.card.dl.sources; + +import org.tritonus.share.ArraySet; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * @author JayDi85 + */ +public class ScryfallImageSupportCards { + + private static final Map xmageSetsToScryfall = new HashMap() { + { + // xmage -> scryfall + put("DD3GVL", "gvl"); + put("DD3JVC", "jvc"); + put("DD3DVD", "dvd"); + put("DD3EVG", "evg"); + put("MPS-AKH", "mp2"); + put("MBP", "pmei"); + put("WMCQ", "pwcq"); + put("EURO", "pelp"); + put("GPX", "pgpx"); + put("MED", "me1"); + } + }; + + private static final Set supportedSets = new ArraySet() { + { + // xmage set codes + // add("PTC"); // + add("LEA"); + add("LEB"); + add("2ED"); + add("ARN"); + add("ATQ"); + add("3ED"); + add("LEG"); + add("DRK"); + add("FEM"); + add("4ED"); + add("ICE"); + add("CHR"); + add("HML"); + add("ALL"); + add("MIR"); + add("VIS"); + add("5ED"); + add("POR"); + add("WTH"); + add("TMP"); + add("STH"); + add("EXO"); + add("P02"); + add("UGL"); + add("USG"); + add("DD3DVD"); + add("DD3EVG"); + add("DD3GVL"); + add("DD3JVC"); + + add("ULG"); + add("6ED"); + add("UDS"); + add("PTK"); + add("S99"); + add("MMQ"); + // add("BRB");Battle Royale Box Set + add("NEM"); + add("S00"); + add("PCY"); + add("INV"); + // add("BTD"); // Beatdown Boxset + add("PLS"); + add("7ED"); + add("APC"); + add("ODY"); + // add("DKM"); // Deckmasters 2001 + add("TOR"); + add("JUD"); + add("ONS"); + add("LGN"); + add("SCG"); + add("8ED"); + add("MRD"); + add("DST"); + add("5DN"); + add("CHK"); + add("UNH"); + add("BOK"); + add("SOK"); + add("9ED"); + add("RAV"); + add("GPT"); + add("DIS"); + add("CSP"); + add("TSP"); + add("TSB"); + add("PLC"); + add("FUT"); + add("10E"); + add("MED"); + add("LRW"); + add("EVG"); + add("MOR"); + add("SHM"); + add("EVE"); + add("DRB"); + add("ME2"); + add("ALA"); + add("DD2"); + add("CON"); + add("DDC"); + add("ARB"); + add("M10"); + // add("TD0"); // Magic Online Deck Series + add("V09"); + add("HOP"); + add("ME3"); + add("ZEN"); + add("DDD"); + add("H09"); + add("WWK"); + add("DDE"); + add("ROE"); + // duels of the planewalkers: + add("DPA"); + add("DPAP"); + // + add("ARC"); + add("M11"); + add("V10"); + add("DDF"); + add("SOM"); + // add("TD0"); // Commander Theme Decks + add("PD2"); + add("ME4"); + add("MBS"); + add("DDG"); + add("NPH"); + add("CMD"); + add("M12"); + add("V11"); + add("DDH"); + add("ISD"); + add("PD3"); + add("DKA"); + add("DDI"); + add("AVR"); + add("PC2"); + add("M13"); + add("V12"); + add("DDJ"); + add("RTR"); + add("CM1"); + // add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia + add("GTC"); + add("DDK"); + add("DGM"); + add("MMA"); + add("M14"); + add("V13"); + add("DDL"); + add("THS"); + add("C13"); + add("BNG"); + add("DDM"); + add("JOU"); + // add("MD1"); // Modern Event Deck + add("CNS"); + add("VMA"); + add("M15"); + add("V14"); + add("DDN"); + add("KTK"); + add("C14"); + // add("DD3"); // Duel Decks Anthology + add("FRF"); + add("DDO"); + add("DTK"); + add("TPR"); + add("MM2"); + add("ORI"); + add("V15"); + add("DDP"); + add("BFZ"); + add("EXP"); + add("C15"); + // add("PZ1"); // Legendary Cube + add("OGW"); + add("DDQ"); + add("W16"); + add("SOI"); + add("EMA"); + add("EMN"); + add("V16"); + add("CN2"); + add("DDR"); + add("KLD"); + add("MPS"); + // add("PZ2"); + add("C16"); + add("PCA"); + add("AER"); + add("MM3"); + add("DDS"); + add("W17"); + add("AKH"); + add("CMA"); + add("E01"); + add("HOU"); + add("C17"); + add("XLN"); + add("DDT"); + add("IMA"); + add("E02"); + add("V17"); + add("UST"); + add("DDU"); + add("RIX"); + add("WMCQ"); + add("PPRO"); + add("A25"); + add("DOM"); + add("BBD"); + add("C18"); + add("CM2"); + add("M19"); + add("GS1"); + add("GRN"); + add("GK1"); + add("GNT"); + add("UMA"); + add("PUMA"); + add("RNA"); + // + add("EURO"); + add("GPX"); + add("ATH"); + add("GRC"); + add("ANA"); + } + }; + + private static final Map directDownloadLinks = new HashMap() { + { + // xmage card -> direct or api link: + // examples: + // direct example: https://img.scryfall.com/cards/large/en/trix/6.jpg + // api example: https://api.scryfall.com/cards/trix/6/en?format=image + // api example: https://api.scryfall.com/cards/trix/6?format=image + // api format is primary + // + // code form for one card: + // set/card_name + // + // code form for same name cards (alternative images): + // set/card_name/card_number + // set/card_name/card_number + + // Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years + // 2009 - https://scryfall.com/sets/pdtp + put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg"); + // 2010 - https://scryfall.com/sets/pdp10 + put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg"); + put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg"); + // 2011 - https://scryfall.com/sets/pdp11 + put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg"); + put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg"); + put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg"); + // 2012 - https://scryfall.com/sets/pdp12 + put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg"); + put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg"); + put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg"); + // 2013 - https://scryfall.com/sets/pdp13 + put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg"); + put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg"); + put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg"); + // 2014 - https://scryfall.com/sets/pdp14 + put("DPAP/Soul of Ravnica", "https://img.scryfall.com/cards/large/en/pdp14/1.jpg"); + put("DPAP/Soul of Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg"); + + // Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years + // 2006 - https://scryfall.com/sets/pgtw + put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg"); + put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg"); + put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg"); + // 2007 - https://scryfall.com/sets/pg07 + put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg"); + put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg"); + put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg"); + put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg"); + put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg"); + put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg"); + put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg"); + put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg"); + put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg"); + // 2008a - https://scryfall.com/sets/pg08 + put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg"); + put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg"); + put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg"); + put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg"); + put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg"); + put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg"); + put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg"); + put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg"); + + // Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years + // 2008b - https://scryfall.com/sets/pwpn + put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg"); + put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg"); + // 2009 - https://scryfall.com/sets/pwp09 + put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg"); + put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg"); + put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg"); + put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg"); + put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg"); + put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg"); + put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg"); + put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg"); + // 2010 - https://scryfall.com/sets/pwp10 + put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg"); + put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg"); + put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg"); + put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg"); + put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg"); + put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // same card but different year + put("GRC/Sylvan Ranger/51", "https://img.scryfall.com/cards/large/en/pwp10/51.jpg"); // same card but different year + put("GRC/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg"); + put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg"); + put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg"); + // 2011 - https://scryfall.com/sets/pwp11 + put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg"); + put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg"); + put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg"); + put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg"); + put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg"); + put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year + put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg"); + put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg"); + put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg"); + put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg"); + put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg"); + put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year + put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg"); + put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg"); + // 2012 - https://scryfall.com/sets/pwp12 + put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg"); + put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg"); + put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg"); + + // TODO: remove Grand Prix fix after scryfall fix image's link (that's link must be work: https://img.scryfall.com/cards/large/en/pgpx/2016b.jpg ) + put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg"); + + // TODO: remove after scryfall add lands to RNA (that's link must works: https://api.scryfall.com/cards/rna/262/en?format=image) + put("RNA/Plains", "https://api.scryfall.com/cards/grn/260/en?format=image"); + put("RNA/Island", "https://api.scryfall.com/cards/grn/261/en?format=image"); + put("RNA/Swamp", "https://api.scryfall.com/cards/grn/262/en?format=image"); + put("RNA/Mountain", "https://api.scryfall.com/cards/grn/263/en?format=image"); + put("RNA/Forest", "https://api.scryfall.com/cards/grn/264/en?format=image"); + } + }; + + public static String findScryfallSetCode(String xmageCode) { + return xmageSetsToScryfall.getOrDefault(xmageCode, xmageCode).toLowerCase(Locale.ENGLISH); + } + + public static Set getSupportedSets() { + return supportedSets; + } + + public static String findDirectDownloadLink(String setCode, String cardName, String cardNumber) { + + // set/card/number + String linkCode1 = setCode + "/" + cardName + "/" + cardNumber; + if (directDownloadLinks.containsKey(linkCode1)) { + return directDownloadLinks.get(linkCode1); + } + + // set/card + String linkCode2 = setCode + "/" + cardName; + if (directDownloadLinks.containsKey(linkCode2)) { + return directDownloadLinks.get(linkCode2); + } + + // default + return null; + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java new file mode 100644 index 00000000000..0031ee5a084 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java @@ -0,0 +1,72 @@ +package org.mage.plugins.card.dl.sources; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author JayDi85 + */ +public class ScryfallImageSupportTokens { + + private static final Map supportedSets = new HashMap<>(); + + private static final Map supportedCards = new HashMap() { + { + // xmage token -> direct or api link: + // examples: + // direct example: https://img.scryfall.com/cards/large/en/trix/6.jpg + // api example: https://api.scryfall.com/cards/trix/6/en?format=image + // api example: https://api.scryfall.com/cards/trix/6?format=image + // api format is primary + // + // code form for one token: + // set/token_name + // + // code form for same name tokens (alternative images): + // set/token_name/1 + // set/token_name/2 + + // RIX + put("RIX/City's Blessing", "https://api.scryfall.com/cards/trix/6/en?format=image"); // TODO: missing from tokens data + put("RIX/Elemental/1", "https://api.scryfall.com/cards/trix/1/en?format=image"); + put("RIX/Elemental/2", "https://api.scryfall.com/cards/trix/2/en?format=image"); + put("RIX/Golem", "https://api.scryfall.com/cards/trix/4/en?format=image"); + put("RIX/Emblem Huatli, Radiant Champion", "https://api.scryfall.com/cards/trix/5/en?format=image"); + put("RIX/Saproling", "https://api.scryfall.com/cards/trix/3/en?format=image"); + + // RNA + put("RNA/Beast", "https://api.scryfall.com/cards/trna/8/en?format=image"); + put("RNA/Centaur", "https://api.scryfall.com/cards/trna/5/en?format=image"); + put("RNA/Emblem Domri, Chaos Bringer", "https://api.scryfall.com/cards/trna/13/en?format=image"); + put("RNA/Frog Lizard", "https://api.scryfall.com/cards/trna/6/en?format=image"); + put("RNA/Goblin", "https://api.scryfall.com/cards/trna/4/en?format=image"); + put("RNA/Human", "https://api.scryfall.com/cards/trna/1/en?format=image"); + put("RNA/Illusion", "https://api.scryfall.com/cards/trna/2/en?format=image"); + put("RNA/Ooze", "https://api.scryfall.com/cards/trna/7/en?format=image"); + put("RNA/Sphinx", "https://api.scryfall.com/cards/trna/9/en?format=image"); + put("RNA/Spirit", "https://api.scryfall.com/cards/trna/10/en?format=image"); + put("RNA/Thopter", "https://api.scryfall.com/cards/trna/11/en?format=image"); + put("RNA/Treasure", "https://api.scryfall.com/cards/trna/12/en?format=image"); + put("RNA/Zombie", "https://api.scryfall.com/cards/trna/3/en?format=image"); + + + // generate supported sets + supportedSets.clear(); + for (String cardName : this.keySet()) { + String[] s = cardName.split("\\/"); + if (s.length > 1) { + supportedSets.putIfAbsent(s[0], s[0]); + } + } + } + }; + + public static Map getSupportedSets() { + return supportedSets; + } + + public static String findTokenLink(String setCode, String tokenName, Integer tokenNumber) { + String search = setCode + "/" + tokenName + (!tokenNumber.equals(0) ? "/" + tokenNumber : ""); + return supportedCards.getOrDefault(search, null); + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java index ae000f70da5..d501e30ffe7 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java @@ -1,6 +1,11 @@ - package org.mage.plugins.card.dl.sources; +import mage.constants.SubType; +import org.apache.log4j.Logger; +import org.mage.plugins.card.images.CardDownloadData; +import org.mage.plugins.card.images.DownloadPicturesService; +import org.mage.plugins.card.utils.CardImageUtils; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -8,21 +13,9 @@ import java.io.InputStreamReader; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.logging.Level; -import mage.constants.SubType; -import org.apache.log4j.Logger; -import org.mage.plugins.card.images.CardDownloadData; -import org.mage.plugins.card.images.DownloadPicturesService; -import org.mage.plugins.card.utils.CardImageUtils; - /** * @author Quercitron */ @@ -58,7 +51,7 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { return null; } @@ -160,7 +153,12 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { + public boolean isCardImageProvided(String setCode, String cardName) { + return false; + } + + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { String searchName = cardName; if (cardName.toLowerCase(Locale.ENGLISH).contains("emblem")) { searchName = getEmblemName(cardName); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java index d0555b82424..0f335d7e9e9 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java @@ -452,7 +452,7 @@ public enum WizardCardsImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java index 10a78aef31e..ddec9bd3b4d 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java @@ -18,7 +18,6 @@ import net.java.truevfs.access.TVFS; import net.java.truevfs.kernel.spec.FsSyncException; import org.apache.log4j.Logger; import org.mage.plugins.card.dl.sources.*; -import org.mage.plugins.card.properties.SettingsManager; import org.mage.plugins.card.utils.CardImageUtils; import javax.swing.*; @@ -45,10 +44,10 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements private static DownloadPicturesService instance; private static final Logger logger = Logger.getLogger(DownloadPicturesService.class); - public static final String ALL_IMAGES = "- ALL images from selected source (can be slow)"; - public static final String ALL_MODERN_IMAGES = "- MODERN images (can be slow)"; - public static final String ALL_STANDARD_IMAGES = "- STANDARD images"; - public static final String ALL_TOKENS = "- TOKEN images"; + private static final String ALL_IMAGES = "- ALL images from selected source (can be slow)"; + private static final String ALL_MODERN_IMAGES = "- MODERN images (can be slow)"; + private static final String ALL_STANDARD_IMAGES = "- STANDARD images"; + private static final String ALL_TOKENS = "- TOKEN images"; private DownloadImagesDialog uiDialog; private boolean needCancel; @@ -60,16 +59,16 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements private int missingCardsCount = 0; private int missingTokensCount = 0; - List selectedSets = new ArrayList<>(); + private List selectedSets = new ArrayList<>(); private static CardImageSource selectedSource; private final Object sync = new Object(); private Proxy p = Proxy.NO_PROXY; enum DownloadSources { - WIZARDS("1. wizards.com - low quality CARDS, multi-language, can be SLOW", WizardCardsImageSource.instance), + WIZARDS("1. wizards.com - low quality CARDS, multi-language, slow download", WizardCardsImageSource.instance), TOKENS("2. tokens.mtg.onl - high quality TOKENS", TokensMtgImageSource.instance), - SCRYFALL("3. scryfall.com - high quality CARDS, multi-language", ScryfallImageSource.instance), + SCRYFALL("3. scryfall.com - high quality CARDS and TOKENS, multi-language", ScryfallImageSource.instance), MAGIDEX("4. magidex.com - high quality CARDS", MagidexImageSource.instance), GRAB_BAG("5. GrabBag - STAR WARS cards and tokens", GrabbagImageSource.instance), MYTHICSPOILER("6. mythicspoiler.com", MythicspoilerComSource.instance), @@ -333,7 +332,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements int numberCardImagesAvailable = 0; for (CardDownloadData data : cardsMissing) { if (data.isToken()) { - if (selectedSource.isTokenSource() && selectedSource.isImageProvided(data.getSet(), data.getName())) { + if (selectedSource.isTokenSource() && selectedSource.isTokenImageProvided(data.getSet(), data.getName(), data.getType())) { numberTokenImagesAvailable++; cardsDownloadQueue.add(data); } else { @@ -341,7 +340,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements } } else { if (selectedSets != null && selectedSets.contains(data.getSet())) { - if (selectedSource.isSetSupportedComplete(data.getSet()) || selectedSource.isImageProvided(data.getSet(), data.getName())) { + if (selectedSource.isSetSupportedComplete(data.getSet()) || selectedSource.isCardImageProvided(data.getSet(), data.getName())) { numberCardImagesAvailable++; cardsDownloadQueue.add(data); } @@ -393,7 +392,6 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements } private static List prepareMissingCards(List allCards, boolean redownloadMode) { - HashSet ignoreUrls = SettingsManager.getIntance().getIgnoreUrls(); // get filter for Standard Type 2 cards Set type2SetsFilter = new HashSet<>(); @@ -408,8 +406,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements List allCardsUrls = Collections.synchronizedList(new ArrayList<>()); try { allCards.parallelStream().forEach(card -> { - if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty() - && !ignoreUrls.contains(card.getSetCode())) { + if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) { String cardName = card.getName(); boolean isType2 = type2SetsFilter.contains(card.getSetCode()); CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard()); @@ -498,7 +495,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements if (params.length >= 5) { int type = 0; if (params[4] != null && !params[4].isEmpty()) { - type = Integer.parseInt(params[4].trim()); + type = Integer.parseInt(params[4].trim()); // token number for same names } String fileName = ""; if (params.length > 5 && params[5] != null && !params[5].isEmpty()) { @@ -547,6 +544,16 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements logger.error(ex); throw new RuntimeException("DownloadPicturesService : readFile() error"); } + + // TODO: delete and move to copy-pate images download mode + /* + for (CardDownloadData card : list) { + if (card.isToken()) { + System.out.println(card.getSet() + "/" + card.getName() + (!card.getType().equals(0) ? "/" + card.getType() : "")); + } + } + */ + return list; } @@ -586,8 +593,6 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements } if (p != null) { - HashSet ignoreUrls = SettingsManager.getIntance().getIgnoreUrls(); - update(0, cardsDownloadQueue.size()); logger.info("Started download of " + cardsDownloadQueue.size() + " images" + " from source: " + selectedSource.getSourceName() @@ -602,13 +607,13 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')'); CardImageUrls urls; - if (ignoreUrls.contains(card.getSet()) || card.isToken()) { + if (card.isToken()) { if (!"0".equals(card.getCollectorId())) { continue; } urls = selectedSource.generateTokenUrl(card); } else { - urls = selectedSource.generateURL(card); + urls = selectedSource.generateCardUrl(card); } if (urls == null) { @@ -929,7 +934,7 @@ class LoadMissingCardDataNew implements Runnable { private static DownloadPicturesService downloadPicturesService; public LoadMissingCardDataNew(DownloadPicturesService downloadPicturesService) { - this.downloadPicturesService = downloadPicturesService; + LoadMissingCardDataNew.downloadPicturesService = downloadPicturesService; } @Override @@ -940,5 +945,4 @@ class LoadMissingCardDataNew implements Runnable { public static void main() { (new Thread(new LoadMissingCardDataNew(downloadPicturesService))).start(); } - } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/properties/SettingsManager.java b/Mage.Client/src/main/java/org/mage/plugins/card/properties/SettingsManager.java deleted file mode 100644 index c7a6b87d62c..00000000000 --- a/Mage.Client/src/main/java/org/mage/plugins/card/properties/SettingsManager.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.mage.plugins.card.properties; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Properties; -import mage.client.constants.Constants; - -public class SettingsManager { - - private static SettingsManager settingsManager = null; - - public static synchronized SettingsManager getIntance() { - if (settingsManager == null) { - settingsManager = new SettingsManager(); - } - return settingsManager; - } - - private SettingsManager() { - loadImageProperties(); - } - - public void reloadImageProperties() { - loadImageProperties(); - } - - private void loadImageProperties() { - imageUrlProperties = new Properties(); - try { - InputStream is = SettingsManager.class.getClassLoader().getResourceAsStream(Constants.IO.IMAGE_PROPERTIES_FILE); - if (is == null) { - throw new RuntimeException("Couldn't load " + Constants.IO.IMAGE_PROPERTIES_FILE); - } - imageUrlProperties.load(is); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - public String getSetNameReplacement(String setName) { - String result = setName; - if (imageUrlProperties != null) { - result = imageUrlProperties.getProperty(setName, setName); - } - return result; - } - - public HashSet getIgnoreUrls() { - HashSet ignoreUrls = new HashSet<>(); - if (imageUrlProperties != null) { - String result = imageUrlProperties.getProperty("ignore.urls"); - if (result != null) { - String[] ignore = result.split(","); - ignoreUrls.addAll(Arrays.asList(ignore)); - } - } - return ignoreUrls; - } - - public ArrayList getTokenLookupOrder() { - ArrayList order = new ArrayList<>(); - if (imageUrlProperties != null) { - String result = imageUrlProperties.getProperty("token.lookup.order"); - if (result != null) { - String[] sets = result.split(","); - order.addAll(Arrays.asList(sets)); - } - } - return order; - } - - private Properties imageUrlProperties; -} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java index fb7c42aa090..c7dae393558 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java @@ -1,5 +1,16 @@ package org.mage.plugins.card.utils; +import mage.client.MageFrame; +import mage.client.constants.Constants; +import mage.client.dialog.PreferencesDialog; +import mage.remote.Connection; +import mage.remote.Connection.ProxyType; +import net.java.truevfs.access.TFile; +import org.apache.log4j.Logger; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.mage.plugins.card.images.CardDownloadData; + import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -12,18 +23,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.prefs.Preferences; -import mage.client.MageFrame; -import mage.client.constants.Constants; -import mage.client.dialog.PreferencesDialog; -import mage.remote.Connection; -import mage.remote.Connection.ProxyType; -import net.java.truevfs.access.TFile; -import org.apache.log4j.Logger; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.mage.plugins.card.images.CardDownloadData; -import org.mage.plugins.card.properties.SettingsManager; - public final class CardImageUtils { private static final HashMap pathCache = new HashMap<>(); @@ -53,7 +52,7 @@ public final class CardImageUtils { return filePath; } - log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + filePath); + log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + getTokenImagePath(card)); } else { log.warn("Trying to get token path for non token card. Set: " + card.getSet() + " Set Code: " + card.getTokenSetCode() + " Name: " + card.getName()); } @@ -85,20 +84,6 @@ public final class CardImageUtils { } } return filename; - -// makes no longer sense -// file = new TFile(filename); -// if (!file.exists()) { -// CardDownloadData updated = new CardDownloadData(card); -// updated.setName(card.getName() + " 1"); -// filename = buildImagePathToCard(updated); -// file = new TFile(filename); -// if (!file.exists()) { -// updated = new CardDownloadData(card); -// updated.setName(card.getName() + " 2"); -// filename = buildImagePathToCard(updated); -// } -// } } private static String searchForCardImage(CardDownloadData card) { @@ -112,30 +97,9 @@ public final class CardImageUtils { pathCache.put(card, path); return path; } - -// for (String set : SettingsManager.getIntance().getTokenLookupOrder()) { -// c.setSet(set); -// path = getTokenImagePath(c); -// file = new TFile(path); -// if (file.exists()) { -// pathCache.put(card, path); -// return path; -// } -// } return generateTokenDescriptorImagePath(card); } - public static String updateSet(String cardSet, boolean forUrl) { - String set = cardSet.toLowerCase(Locale.ENGLISH); - if (set.equals("con")) { - set = "cfx"; - } - if (forUrl) { - set = SettingsManager.getIntance().getSetNameReplacement(set); - } - return set; - } - public static String prepareCardNameForFile(String cardName) { return cardName.replace(":", "").replace("\"", "").replace("//", "-"); } @@ -162,6 +126,15 @@ public final class CardImageUtils { return path; } + public static String fixSetNameForWindows(String set) { + // windows can't create con folders + if (set.equals("CON") || set.equals("con")) { + return "COX"; + } else { + return set; + } + } + public static String buildImagePathToTokens() { String imagesPath = getImagesDir() + File.separator; @@ -182,7 +155,7 @@ public final class CardImageUtils { throw new IllegalArgumentException("Card " + card.getName() + " have empty set."); } - String set = updateSet(card.getSet(), false).toUpperCase(Locale.ENGLISH); // TODO: research auto-replace... old code? + String set = card.getSet().toUpperCase(Locale.ENGLISH); if (card.isToken()) { return buildImagePathToSetAsToken(set); @@ -195,14 +168,14 @@ public final class CardImageUtils { String imagesPath = getImagesDir() + File.separator; if (PreferencesDialog.isSaveImagesToZip()) { - return imagesPath + set + ".zip" + File.separator + set + File.separator; + return imagesPath + fixSetNameForWindows(set) + ".zip" + File.separator + fixSetNameForWindows(set) + File.separator; } else { - return imagesPath + set + File.separator; + return imagesPath + fixSetNameForWindows(set) + File.separator; } } private static String buildImagePathToSetAsToken(String set) { - return buildImagePathToTokens() + set + File.separator; + return buildImagePathToTokens() + fixSetNameForWindows(set) + File.separator; } public static String buildImagePathToCard(CardDownloadData card) { @@ -211,7 +184,7 @@ public final class CardImageUtils { String prefixType = ""; if (card.getType() != 0) { - prefixType = " " + Integer.toString(card.getType()); + prefixType = " " + card.getType(); } String cardName = card.getFileName(); @@ -228,6 +201,7 @@ public final class CardImageUtils { finalFileName = cardName + prefixType + ".full.jpg"; } + /* 2019-01-12: no needs in name corrections, all files must be same and auto-downloaded // if image file exists, correct name (for case sensitive systems) // use TFile for zips TFile dirFile = new TFile(setPath); @@ -246,12 +220,13 @@ public final class CardImageUtils { } catch (Exception ex) { log.error("Can't read card name from file, may be it broken: " + setPath); } + */ return setPath + finalFileName; } public static String generateFaceImagePath(String cardname, String set) { - return getImagesDir() + File.separator + "FACE" + File.separator + set + File.separator + prepareCardNameForFile(cardname) + ".jpg"; + return getImagesDir() + File.separator + "FACE" + File.separator + fixSetNameForWindows(set) + File.separator + prepareCardNameForFile(cardname) + ".jpg"; } public static String generateTokenDescriptorImagePath(CardDownloadData card) { diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt index bdb9410a86a..fd3f65f7aa2 100644 --- a/Mage.Client/src/main/resources/card-pictures-tok.txt +++ b/Mage.Client/src/main/resources/card-pictures-tok.txt @@ -86,6 +86,7 @@ |Generate|EMBLEM:MMA|Elspeth, Knight Errant||Emblem Elspeth|ElspethKnightErrantEmblem| |Generate|EMBLEM:SWS|Obi-Wan Kenobi||Emblem Obi-Wan Kenobi|ObiWanKenobiEmblem| |Generate|EMBLEM:RIX|Huatli, Radiant Champion||Emblem Huatli|HuatliRadiantChampionEmblem| +|Generate|EMBLEM:RNA|Domri, Chaos Bringer||Emblem Domri|DomriChaosBringerEmblem| |Generate|PLANE:PCA|Plane - Academy At Tolaria West|||AcademyAtTolariaWestPlane| |Generate|PLANE:PCA|Plane - Agyrem|||AgyremPlane| |Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane| @@ -1185,3 +1186,15 @@ |Generate|TOK:ZEN|Vampire|| |Generate|TOK:ZEN|Wolf|||WolfToken| |Generate|TOK:ZEN|Zombie Giant|||QuestForTheGravelordZombieToken| +|Generate|TOK:RNA|Beast|||RedGreenBeastToken| +|Generate|TOK:RNA|Centaur|||CentaurToken| +|Generate|TOK:RNA|Frog Lizard|||FrogLizardToken| +|Generate|TOK:RNA|Goblin|||GoblinToken| +|Generate|TOK:RNA|Human|||HumanToken| +|Generate|TOK:RNA|Illusion|||MesmerizingBenthidToken| +|Generate|TOK:RNA|Ooze|||BiogenicOozeToken| +|Generate|TOK:RNA|Sphinx|||WardenSphinxToken| +|Generate|TOK:RNA|Spirit|||SpiritWhiteToken| +|Generate|TOK:RNA|Thopter|||ThopterToken| +|Generate|TOK:RNA|Treasure|||TreasureToken| +|Generate|TOK:RNA|Zombie|||ZombieToken| \ No newline at end of file diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties deleted file mode 100644 index d3ab400892f..00000000000 --- a/Mage.Client/src/main/resources/image.url.properties +++ /dev/null @@ -1,78 +0,0 @@ -tsp=ts -tor=tr -mor=mt -ody=od -lrw=lw -plc=pc -gpt=gp -inv=in -ons=on -scg=sc -jud=ju -mmq=mm -pls=ps -mrd=mi -mir=mr -tst=ts -usg=us -apc=ap -nem=ne -dis=di -vis=vi -9ed=9e -8ed=8e -7ed=7e -4ed=4e -tsb=tsts -ulg=ul -5ed=5e -6ed=6e -btd=bd -sth=sh -por=po -s99=st -lgn=le -ice=ia -csp=cs -tmp=tp -s00=st2k -dst=ds -pcy=pr -uds=ud -exo=ex -lea=al -hop=pch -chr=ch -arn=an -wth=wl -leb=be -2ed=un -3ed=rv -brb=br -atq=aq -fem=fe -leg=lg -hml=hl -all=ai -drk=dk -ptk=p3k -gur=guru -ddc=dvd -dd2=jvc -ddd=gvl -unh=uh -dde=pvc -v09=fve -v10=fvr -v11=fvl -drb=fvd -h09=pds -ugl=ug -dd3dvd=ddadvd -dd3evg=ddaevg -dd3gvl=ddagvl -dd3jvc=ddajvc -# Remove setname as soon as the images can be downloaded -ignore.urls=TOK,H17 -# sets ordered by release time (newest goes first) -token.lookup.order=C18,M19,A25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC \ No newline at end of file diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml index 5eb7a110dab..f1535ccfae1 100644 --- a/Mage.Common/pom.xml +++ b/Mage.Common/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-common diff --git a/Mage.Common/src/main/java/mage/remote/SessionImpl.java b/Mage.Common/src/main/java/mage/remote/SessionImpl.java index a17883857c8..45f0b0c5be5 100644 --- a/Mage.Common/src/main/java/mage/remote/SessionImpl.java +++ b/Mage.Common/src/main/java/mage/remote/SessionImpl.java @@ -80,7 +80,7 @@ public class SessionImpl implements Session { // handling. public interface RemotingTask { - public boolean run() throws Throwable; + boolean run() throws Throwable; } // handleRemotingTaskExceptions runs the given task and handles exceptions appropriately. This @@ -223,7 +223,7 @@ public class SessionImpl implements Session { @Override public Optional getServerHostname() { - return isConnected() ? Optional.of(connection.getHost()) : Optional.empty(); + return isConnected() ? Optional.of(connection.getHost()) : Optional.empty(); } @Override @@ -392,26 +392,22 @@ public class SessionImpl implements Session { } private void updateDatabase(boolean forceDBComparison, ServerState serverState) { - long cardDBVersion = CardRepository.instance.getContentVersionFromDB(); - if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) { - List classNames = CardRepository.instance.getClassNames(); - List cards = server.getMissingCardsData(classNames); - CardRepository.instance.addCards(cards); - CardRepository.instance.setContentVersion(serverState.getCardsContentVersion()); - logger.info("Updating client cards DB - existing cards: " + classNames.size() + " new cards: " + cards.size() - + " content versions - server: " + serverState.getCardsContentVersion() + " client: " + cardDBVersion); - } - + // sets long expansionDBVersion = ExpansionRepository.instance.getContentVersionFromDB(); if (forceDBComparison || serverState.getExpansionsContentVersion() > expansionDBVersion) { List setCodes = ExpansionRepository.instance.getSetCodes(); List expansions = server.getMissingExpansionData(setCodes); - for (ExpansionInfo expansion : expansions) { - ExpansionRepository.instance.add(expansion); - } - ExpansionRepository.instance.setContentVersion(serverState.getExpansionsContentVersion()); - logger.info("Updating client expansions DB - existing sets: " + setCodes.size() + " new sets: " + expansions.size() - + " content versions - server: " + serverState.getExpansionsContentVersion() + " client: " + expansionDBVersion); + logger.info("DB: updating sets... Founded new: " + expansions.size()); + ExpansionRepository.instance.saveSets(expansions, null, serverState.getExpansionsContentVersion()); + } + + // cards + long cardDBVersion = CardRepository.instance.getContentVersionFromDB(); + if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) { + List classNames = CardRepository.instance.getClassNames(); + List cards = server.getMissingCardsData(classNames); + logger.info("DB: updating cards... Founded new: " + cards.size()); + CardRepository.instance.saveCards(cards, serverState.getCardsContentVersion()); } } diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index e4550bddf11..284ea65ef18 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -14,7 +14,7 @@ public class MageVersion implements Serializable, Comparable { */ public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; - public final static int MAGE_VERSION_PATCH = 32; + public final static int MAGE_VERSION_PATCH = 33; public final static String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0 public final static String MAGE_VERSION_MINOR_PATCH = "V0"; diff --git a/Mage.Common/src/main/java/mage/view/GameView.java b/Mage.Common/src/main/java/mage/view/GameView.java index ffc10011df4..f0466f6950a 100644 --- a/Mage.Common/src/main/java/mage/view/GameView.java +++ b/Mage.Common/src/main/java/mage/view/GameView.java @@ -1,14 +1,7 @@ - package mage.view; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageObject; import mage.abilities.costs.Cost; import mage.cards.Card; @@ -32,8 +25,10 @@ import mage.players.Player; import mage.watchers.common.CastSpellLastTurnWatcher; import org.apache.log4j.Logger; +import java.io.Serializable; +import java.util.*; + /** - * * @author BetaSteward_at_googlemail.com */ public class GameView implements Serializable { @@ -90,7 +85,7 @@ public class GameView implements Serializable { if (object != null) { if (object instanceof Permanent) { boolean controlled = ((Permanent) object).getControllerId().equals(createdForPlayerId); - stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, ((Permanent) object).getName(), new CardView(((Permanent) object), game, controlled, false, false))); + stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, object.getName(), new CardView(((Permanent) object), game, controlled, false, false))); } else { stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, card.getName(), new CardView(card, game, false, false, false))); } @@ -109,14 +104,14 @@ public class GameView implements Serializable { } else if (object instanceof Emblem) { CardView cardView = new CardView(new EmblemView((Emblem) object)); // Card sourceCard = (Card) ((Emblem) object).getSourceObject(); - ((StackAbility) stackObject).setName(((Emblem) object).getName()); + stackObject.setName(object.getName()); // ((StackAbility) stackObject).setExpansionSetCode(sourceCard.getExpansionSetCode()); stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, object.getName(), cardView)); checkPaid(stackObject.getId(), ((StackAbility) stackObject)); } else if (object instanceof Plane) { CardView cardView = new CardView(new PlaneView((Plane) object)); - ((StackAbility) stackObject).setName(((Plane) object).getName()); + stackObject.setName(object.getName()); stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, object.getName(), cardView)); checkPaid(stackObject.getId(), ((StackAbility) stackObject)); @@ -131,7 +126,7 @@ public class GameView implements Serializable { } else if (object instanceof StackAbility) { StackAbility stackAbility = ((StackAbility) object); stackAbility.newId(); - stack.put(stackObject.getId(), new CardView(((StackAbility) stackObject))); + stack.put(stackObject.getId(), new CardView(stackObject)); checkPaid(stackObject.getId(), ((StackAbility) stackObject)); } else { LOGGER.fatal("Object can't be cast to StackAbility: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString()); @@ -182,7 +177,7 @@ public class GameView implements Serializable { this.special = false; } - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn(); } else { diff --git a/Mage.Plugins/Mage.Counter.Plugin/pom.xml b/Mage.Plugins/Mage.Counter.Plugin/pom.xml index 27f3f04daa8..37dccf66a3c 100644 --- a/Mage.Plugins/Mage.Counter.Plugin/pom.xml +++ b/Mage.Plugins/Mage.Counter.Plugin/pom.xml @@ -7,7 +7,7 @@ org.mage mage-plugins - 1.4.32 + 1.4.33 mage-counter-plugin diff --git a/Mage.Plugins/pom.xml b/Mage.Plugins/pom.xml index 8ae91a6e66c..844a031c2dc 100644 --- a/Mage.Plugins/pom.xml +++ b/Mage.Plugins/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-plugins diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml index c754825bb39..50c953f3acd 100644 --- a/Mage.Server.Console/pom.xml +++ b/Mage.Server.Console/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 org.mage diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml index ae308a042c8..c458b09fd11 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-deck-constructed diff --git a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml index 98e6f8d47fb..3970fd8aec4 100644 --- a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml +++ b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-deck-limited diff --git a/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml index c8e41100ec6..c4468a780eb 100644 --- a/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-brawlduel diff --git a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml index 6acd4acfc23..68b7153f7c9 100644 --- a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml @@ -6,7 +6,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-brawlfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml index 6a96d18e1ea..9957ade0c13 100644 --- a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-canadianhighlanderduel diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml index 6bdd993258d..1be9b9c39b7 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-commanderduel diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml index 159cbc07010..c15e9c37865 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml @@ -6,7 +6,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-commanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml index 9c8f09b34e8..12379002c19 100644 --- a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-freeforall diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml index 3c49cfae83e..f09b70e6775 100644 --- a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml @@ -6,7 +6,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-freeformcommanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml index 2c78b0d5ad6..cfdab7bfbd9 100644 --- a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-momirduel diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml index 79f3c5abdf1..dc080d0c864 100644 --- a/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-momirfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml index f110bd92500..8c46ad880c2 100644 --- a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml @@ -6,7 +6,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-pennydreadfulcommanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml index c0744d767fe..c89f501bf29 100644 --- a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-tinyleadersduel diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml index 9f0fcd6fc9d..817912749f7 100644 --- a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml +++ b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-game-twoplayerduel diff --git a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml index 6bf13c4d634..38289a5a1e4 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-player-ai-draftbot diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml index f5503335224..c228f0dcef9 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-player-ai-ma diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index f38270bec6f..024e08dcc56 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -1,28 +1,12 @@ - package mage.player.ai; -import java.io.File; -import java.util.*; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; import mage.abilities.SpellAbility; import mage.abilities.common.PassAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.SearchEffect; -import mage.abilities.keyword.DeathtouchAbility; -import mage.abilities.keyword.DoubleStrikeAbility; -import mage.abilities.keyword.ExaltedAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.IndestructibleAbility; -import mage.abilities.keyword.ReachAbility; +import mage.abilities.keyword.*; import mage.cards.Card; import mage.cards.Cards; import mage.choices.Choice; @@ -49,8 +33,11 @@ import mage.target.Targets; import mage.util.RandomUtil; import org.apache.log4j.Logger; +import java.io.File; +import java.util.*; +import java.util.concurrent.*; + /** - * * @author nantuko */ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { @@ -180,10 +167,9 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { if (!suggested.isEmpty() && !(ability instanceof PassAbility)) { Iterator it = suggested.iterator(); while (it.hasNext()) { - Card card = game.getCard(ability.getSourceId()); String action = it.next(); - logger.info("Suggested action=" + action + ";card=" + card); - if (action.equals(card.getName())) { + Card card = game.getCard(ability.getSourceId()); + if (card != null && action.equals(card.getName())) { logger.info("-> removed from suggested=" + action); it.remove(); } @@ -930,7 +916,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { String line = scanner.nextLine(); if (line.startsWith("cast:") || line.startsWith("play:")) { - suggested.add(line.substring(5, line.length())); + suggested.add(line.substring(5)); } } System.out.println("suggested::"); @@ -953,7 +939,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { if (action != null && (action.startsWith("cast:") || action.startsWith("play:"))) { - suggested.add(action.substring(5, action.length())); + suggested.add(action.substring(5)); } } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java index 018ef807a11..a546d9b698d 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java @@ -1,4 +1,3 @@ - package mage.player.ai; import mage.MageObject; @@ -25,7 +24,6 @@ import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; /** - * * @author BetaSteward_at_googlemail.com */ public class SimulatedPlayer2 extends ComputerPlayer { @@ -173,6 +171,7 @@ public class SimulatedPlayer2 extends ComputerPlayer { // allActions.add(new SimulatedAction(sim, actions)); // } // } + /** * if suggested abilities exist, return only those from playables * @@ -191,11 +190,13 @@ public class SimulatedPlayer2 extends ComputerPlayer { List filtered = new ArrayList<>(); for (Ability ability : playables) { Card card = game.getCard(ability.getSourceId()); - for (String s : suggested) { - if (s.equals(card.getName())) { - logger.debug("matched: " + s); - forced = true; - filtered.add(ability); + if (card != null) { + for (String s : suggested) { + if (s.equals(card.getName())) { + logger.debug("matched: " + s); + forced = true; + filtered.add(ability); + } } } } @@ -216,26 +217,28 @@ public class SimulatedPlayer2 extends ComputerPlayer { for (Ability option : options) { if (!option.getTargets().isEmpty() && option.getTargets().get(0).getMaxNumberOfTargets() == 1) { Card card = game.getCard(ability.getSourceId()); - for (String s : suggested) { - String[] groups = s.split(";"); - logger.trace("s=" + s + ";groups=" + groups.length); - if (groups.length == 2) { - if (groups[0].equals(card.getName()) && groups[1].startsWith("name=")) { - // extract target and compare to suggested - String targetName = groups[1].split("=")[1]; - Player player = game.getPlayer(option.getFirstTarget()); - if (player != null && targetName.equals(player.getName())) { - System.out.println("matched(option): " + s); - filtered.add(option); - return filtered; - } else { - Card target = game.getCard(option.getFirstTarget()); - if (target != null && target.getName().equals(targetName)) { + if (card != null) { + for (String s : suggested) { + String[] groups = s.split(";"); + logger.trace("s=" + s + ";groups=" + groups.length); + if (groups.length == 2) { + if (groups[0].equals(card.getName()) && groups[1].startsWith("name=")) { + // extract target and compare to suggested + String targetName = groups[1].split("=")[1]; + Player player = game.getPlayer(option.getFirstTarget()); + if (player != null && targetName.equals(player.getName())) { System.out.println("matched(option): " + s); filtered.add(option); return filtered; + } else { + Card target = game.getCard(option.getFirstTarget()); + if (target != null && target.getName().equals(targetName)) { + System.out.println("matched(option): " + s); + filtered.add(option); + return filtered; + } + System.out.println("not equal UUID for target, player=" + player); } - System.out.println("not equal UUID for target, player=" + player); } } } diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml index 3d07accfddf..ea0fe82fa9f 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-player-ai diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 3625c367692..0d3cf9c08dd 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -500,6 +500,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { } if (target.getOriginalTarget() instanceof TargetPermanent) { List targets; + TargetPermanent t = (TargetPermanent) target.getOriginalTarget(); boolean outcomeTargets = true; if (outcome.isGood()) { targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), ((TargetPermanent) target).getFilter(), game, target.getTargets()); @@ -512,6 +513,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { outcomeTargets = false; //targets = game.getBattlefield().getActivePermanents(((TargetPermanent)target).getFilter(), playerId, game); } + if (targets.isEmpty() && target.isRequired()) { + targets = game.getBattlefield().getActivePermanents(t.getFilter(), playerId, game); + } for (Permanent permanent : targets) { if (((TargetPermanent) target).canTarget(abilityControllerId, permanent.getId(), source, game)) { target.addTarget(permanent.getId(), source, game); diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml index c3c78bb4e93..99b1af89d28 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-player-ai-mcts diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml index 1a6103ef54d..b9fa2e06d15 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-player-aiminimax diff --git a/Mage.Server.Plugins/Mage.Player.Human/pom.xml b/Mage.Server.Plugins/Mage.Player.Human/pom.xml index 59ecd9969b5..70766f01b85 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.Human/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-player-human diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml index 8e791631f4f..ae783f103b4 100644 --- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-tournament-boosterdraft diff --git a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml index 91a6ef148f1..f6035abaa47 100644 --- a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml +++ b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-tournament-constructed diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml index d51fc65a620..c30f7193e58 100644 --- a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml +++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml @@ -7,7 +7,7 @@ org.mage mage-server-plugins - 1.4.32 + 1.4.33 mage-tournament-sealed diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index 6e660046e92..8ee5605668b 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-server-plugins diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 1ca377aaf5f..4b762aa1d1a 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-server diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 39cfef9c589..03fe704d7e1 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -4,6 +4,7 @@ import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.repository.CardScanner; import mage.cards.repository.PluginClassloaderRegistery; +import mage.cards.repository.RepositoryUtil; import mage.game.match.MatchType; import mage.game.tournament.TournamentType; import mage.interfaces.MageServer; @@ -88,6 +89,10 @@ public final class Main { logger.info("Done."); } + // db init and updates checks (e.g. cleanup cards db on new version) + RepositoryUtil.bootstrapLocalDb(); + logger.info("Done."); + logger.info("Loading extension packages..."); if (!extensionFolder.exists()) { if (!extensionFolder.mkdirs()) { diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 395becdf947..41e8b9e6918 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -1,30 +1,31 @@ package mage.server.util; +import mage.abilities.Ability; +import mage.cards.Card; +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.RandomUtil; + import java.io.File; import java.lang.reflect.Constructor; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; -import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import mage.abilities.Ability; -import mage.cards.Card; -import mage.cards.Cards; -import mage.cards.repository.CardCriteria; -import mage.cards.repository.CardInfo; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; -import mage.util.RandomUtil; - /** * @author JayDi85 */ @@ -111,6 +112,9 @@ public final class SystemUtil { for (UUID cardID : cardsList) { Card card = game.getCard(cardID); + if (card == null) { + continue; + } // basic info (card + set) String cardInfo = card.getName() + " - " + card.getExpansionSetCode(); @@ -225,7 +229,7 @@ public final class SystemUtil { *
* Implementation note:
* 1. Read init.txt line by line
- * 2. Parse line using for searching groups like: [group 1] + * 2. Parse line using for searching groups like: [group 1] * 3. Parse line using the following format: line ::= * :::
* 4. If zone equals to 'hand', add card to player's library
@@ -432,6 +436,13 @@ public final class SystemUtil { game.addPlane((mage.game.command.Plane) plane, null, player.getId()); continue; } + } else if ("loyalty".equalsIgnoreCase(command.zone)) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(player.getId())) { + if (perm.getName().equals(command.cardName) && perm.getCardType().contains(CardType.PLANESWALKER)) { + perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), null, game); + } + } + continue; } Zone gameZone; @@ -537,8 +548,8 @@ public final class SystemUtil { /** * Get a diff between two dates * - * @param date1 the oldest date - * @param date2 the newest date + * @param date1 the oldest date + * @param date2 the newest date * @param timeUnit the unit in which you want the diff * @return the diff value, in the provided unit */ diff --git a/Mage.Sets/pom.xml b/Mage.Sets/pom.xml index 6f88ade019a..6992395f0d4 100644 --- a/Mage.Sets/pom.xml +++ b/Mage.Sets/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 org.mage diff --git a/Mage.Sets/src/mage/cards/a/AbandonHope.java b/Mage.Sets/src/mage/cards/a/AbandonHope.java index a89f5407510..635917a8982 100644 --- a/Mage.Sets/src/mage/cards/a/AbandonHope.java +++ b/Mage.Sets/src/mage/cards/a/AbandonHope.java @@ -1,26 +1,26 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; -import mage.filter.FilterCard; +import mage.filter.StaticFilters; import mage.game.Game; import mage.target.TargetPlayer; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author fireshoes */ public final class AbandonHope extends CardImpl { @@ -29,52 +29,35 @@ public final class AbandonHope extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{1}{B}"); // As an additional cost to cast Abandon Hope, discard X cards. - Ability ability = new SimpleStaticAbility(Zone.ALL, new AbandonHopeRuleEffect()); + Ability ability = new SimpleStaticAbility(Zone.ALL, new InfoEffect("As an additional cost to cast this spell, discard X cards")); ability.setRuleAtTheTop(true); this.addAbility(ability); // Look at target opponent's hand and choose X cards from it. That player discards those cards. - ManacostVariableValue manaX = new ManacostVariableValue(); + ManacostVariableValue manaX = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new DiscardCardYouChooseTargetEffect(manaX, TargetController.ANY)); this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().setCostAdjuster(AbandonHopeAdjuster.instance); } public AbandonHope(final AbandonHope card) { super(card); } - @Override - public void adjustCosts(Ability ability, Game game) { - int xValue = ability.getManaCostsToPay().getX(); - if (xValue > 0) { - ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, new FilterCard("cards")))); - } - } - @Override public AbandonHope copy() { return new AbandonHope(this); } } -class AbandonHopeRuleEffect extends OneShotEffect { - - public AbandonHopeRuleEffect() { - super(Outcome.Benefit); - this.staticText = "As an additional cost to cast this spell, discard X cards"; - } - - public AbandonHopeRuleEffect(final AbandonHopeRuleEffect effect) { - super(effect); - } +enum AbandonHopeAdjuster implements CostAdjuster { + instance; @Override - public AbandonHopeRuleEffect copy() { - return new AbandonHopeRuleEffect(this); + public void adjustCosts(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + if (xValue > 0) { + ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, StaticFilters.FILTER_CARD_CARDS))); + } } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java b/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java index cd82afc4ba1..263dd0d8ab4 100644 --- a/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java +++ b/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java @@ -1,25 +1,12 @@ package mage.cards.a; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneAllEffect; import mage.abilities.keyword.CyclingAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.WatcherScope; -import mage.constants.Zone; +import mage.cards.*; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; @@ -31,8 +18,12 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.watchers.Watcher; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class AbandonedSarcophagus extends CardImpl { @@ -55,7 +46,7 @@ public final class AbandonedSarcophagus extends CardImpl { } - public AbandonedSarcophagus(final AbandonedSarcophagus card) { + private AbandonedSarcophagus(final AbandonedSarcophagus card) { super(card); } @@ -67,15 +58,12 @@ public final class AbandonedSarcophagus extends CardImpl { class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl { - boolean cardHasCycling; - boolean cardWasCycledThisTurn; - - public AbandonedSarcophagusReplacementEffect() { + AbandonedSarcophagusReplacementEffect() { super(Duration.WhileOnBattlefield, Outcome.Exile); staticText = "If a card with cycling would be put into your graveyard from anywhere and it wasn't cycled, exile it instead"; } - public AbandonedSarcophagusReplacementEffect(final AbandonedSarcophagusReplacementEffect effect) { + private AbandonedSarcophagusReplacementEffect(final AbandonedSarcophagusReplacementEffect effect) { super(effect); } @@ -112,34 +100,33 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - cardWasCycledThisTurn = false; - cardHasCycling = false; - if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD - && !game.isSimulation()) { - Player controller = game.getPlayer(source.getControllerId()); - AbandonedSarcophagusWatcher watcher = (AbandonedSarcophagusWatcher) game.getState().getWatchers().get(AbandonedSarcophagusWatcher.class.getSimpleName()); - Card card = game.getCard(event.getTargetId()); - if (card != null - && controller != null - && watcher != null - && card.isOwnedBy(controller.getId())) { - for (Ability ability : card.getAbilities()) { - if (ability instanceof CyclingAbility) { - cardHasCycling = true; - } - } - Cards cards = watcher.getCardsCycledThisTurn(controller.getId()); - for (Card c : cards.getCards(game)) { - if (c == card) { - cardWasCycledThisTurn = true; - watcher.getCardsCycledThisTurn(controller.getId()).remove(card); //remove reference to the card as it is no longer needed - } - } - return (!cardWasCycledThisTurn - && cardHasCycling); + boolean cardWasCycledThisTurn = false; + boolean cardHasCycling = false; + if (!(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) || game.isSimulation()) { + return false; + } + Player controller = game.getPlayer(source.getControllerId()); + AbandonedSarcophagusWatcher watcher = game.getState().getWatcher(AbandonedSarcophagusWatcher.class); + Card card = game.getCard(event.getTargetId()); + if (card == null + || controller == null + || watcher == null + || !card.isOwnedBy(controller.getId())) { + return false; + } + for (Ability ability : card.getAbilities()) { + if (ability instanceof CyclingAbility) { + cardHasCycling = true; } } - return false; + Cards cards = watcher.getCardsCycledThisTurn(controller.getId()); + for (Card c : cards.getCards(game)) { + if (c == card) { + cardWasCycledThisTurn = true; + watcher.getCardsCycledThisTurn(controller.getId()).remove(card); //remove reference to the card as it is no longer needed + } + } + return !cardWasCycledThisTurn && cardHasCycling; } } @@ -147,11 +134,11 @@ class AbandonedSarcophagusWatcher extends Watcher { private final Map cycledCardsThisTurn = new HashMap<>(); - public AbandonedSarcophagusWatcher() { + AbandonedSarcophagusWatcher() { super(AbandonedSarcophagusWatcher.class.getSimpleName(), WatcherScope.GAME); } - public AbandonedSarcophagusWatcher(final AbandonedSarcophagusWatcher watcher) { + private AbandonedSarcophagusWatcher(final AbandonedSarcophagusWatcher watcher) { super(watcher); for (Entry entry : watcher.cycledCardsThisTurn.entrySet()) { cycledCardsThisTurn.put(entry.getKey(), entry.getValue().copy()); diff --git a/Mage.Sets/src/mage/cards/a/Abeyance.java b/Mage.Sets/src/mage/cards/a/Abeyance.java index dd9714b9d38..2d44f2abf17 100644 --- a/Mage.Sets/src/mage/cards/a/Abeyance.java +++ b/Mage.Sets/src/mage/cards/a/Abeyance.java @@ -1,8 +1,5 @@ - package mage.cards.a; -import java.util.Optional; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; @@ -17,8 +14,10 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.target.TargetPlayer; +import java.util.Optional; +import java.util.UUID; + /** - * * @author fireshoes */ public final class Abeyance extends CardImpl { @@ -46,12 +45,13 @@ public final class Abeyance extends CardImpl { class AbeyanceEffect extends ContinuousRuleModifyingEffectImpl { - public AbeyanceEffect() { + AbeyanceEffect() { super(Duration.EndOfTurn, Outcome.Detriment); - staticText = "Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities"; + staticText = "Until end of turn, target player can't cast instant or sorcery spells, " + + "and that player can't activate abilities that aren't mana abilities"; } - public AbeyanceEffect(final AbeyanceEffect effect) { + private AbeyanceEffect(final AbeyanceEffect effect) { super(effect); } @@ -69,29 +69,29 @@ class AbeyanceEffect extends ContinuousRuleModifyingEffectImpl { public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); if (mageObject != null) { - return "You can't cast instant or sorcery spells or activate abilities that aren't mana abilities this turn (" + mageObject.getIdName() + ")."; + return "You can't cast instant or sorcery spells or activate abilities " + + "that aren't mana abilities this turn (" + mageObject.getIdName() + ")."; } return null; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getFirstTarget() != null && source.getFirstTarget().equals(event.getPlayerId())) { - MageObject object = game.getObject(event.getSourceId()); - if(object == null){ - return false; - } - if (event.getType() == GameEvent.EventType.CAST_SPELL) { - if (object.isInstant() || object.isSorcery()) { - return true; - } - } - if (event.getType() == GameEvent.EventType.ACTIVATE_ABILITY) { - Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); - if (ability.isPresent() && !(ability.get() instanceof ActivatedManaAbilityImpl)) { - return true; - } - } + if (source.getFirstTarget() != null + && source.getFirstTarget().equals(event.getPlayerId())) { + return false; + } + MageObject object = game.getObject(event.getSourceId()); + if (object == null) { + return false; + } + if (event.getType() == GameEvent.EventType.CAST_SPELL + && (object.isInstant() || object.isSorcery())) { + return true; + } + if (event.getType() == GameEvent.EventType.ACTIVATE_ABILITY) { + Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); + return ability.isPresent() && !(ability.get() instanceof ActivatedManaAbilityImpl); } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java b/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java index c64aeee0fbe..0d84ef3c1e2 100644 --- a/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java +++ b/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java @@ -28,7 +28,7 @@ public final class AbzanAscendancy extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public AbzanAscendancy(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AbzanBattlePriest.java b/Mage.Sets/src/mage/cards/a/AbzanBattlePriest.java index c902e0f16b3..878fb3b4d68 100644 --- a/Mage.Sets/src/mage/cards/a/AbzanBattlePriest.java +++ b/Mage.Sets/src/mage/cards/a/AbzanBattlePriest.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -17,23 +16,23 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.CounterPredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AbzanBattlePriest extends CardImpl { private static final FilterPermanent filter = new FilterPermanent(); + static { filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new CounterPredicate(CounterType.P1P1)); } - static final String rule = "Each creature you control with a +1/+1 counter on it has lifelink"; - public AbzanBattlePriest(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); @@ -42,9 +41,15 @@ public final class AbzanBattlePriest extends CardImpl { // Outlast {W} this.addAbility(new OutlastAbility(new ManaCostsImpl<>("{W}"))); - + // Each creature you control with a +1/+1 counter on it has lifelink. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, filter, rule))); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityAllEffect( + LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, + filter, "Each creature you control with a +1/+1 counter on it has lifelink" + ) + )); } public AbzanBattlePriest(final AbzanBattlePriest card) { diff --git a/Mage.Sets/src/mage/cards/a/AccursedWitch.java b/Mage.Sets/src/mage/cards/a/AccursedWitch.java index 1cefa7ff16e..b6f4bc05f0e 100644 --- a/Mage.Sets/src/mage/cards/a/AccursedWitch.java +++ b/Mage.Sets/src/mage/cards/a/AccursedWitch.java @@ -1,8 +1,6 @@ package mage.cards.a; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.Mode; @@ -22,6 +20,8 @@ import mage.players.Player; import mage.target.Target; import mage.util.CardUtil; +import java.util.UUID; + /** * @author halljared */ @@ -44,7 +44,7 @@ public final class AccursedWitch extends CardImpl { this.addAbility(new DiesTriggeredAbility(new AccursedWitchReturnTransformedEffect())); } - public AccursedWitch(final AccursedWitch card) { + private AccursedWitch(final AccursedWitch card) { super(card); } @@ -56,12 +56,12 @@ public final class AccursedWitch extends CardImpl { class AccursedWitchReturnTransformedEffect extends OneShotEffect { - public AccursedWitchReturnTransformedEffect() { + AccursedWitchReturnTransformedEffect() { super(Outcome.PutCardInPlay); this.staticText = "Put {this} from your graveyard onto the battlefield transformed"; } - public AccursedWitchReturnTransformedEffect(final AccursedWitchReturnTransformedEffect effect) { + private AccursedWitchReturnTransformedEffect(final AccursedWitchReturnTransformedEffect effect) { super(effect); } @@ -73,29 +73,27 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { - game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); - //note: should check for null after game.getCard - Card card = game.getCard(source.getSourceId()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - return true; + if (controller == null || !(game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD)) { + return false; } - return false; + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); + //note: should check for null after game.getCard + Card card = game.getCard(source.getSourceId()); + if (card != null) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + return true; } } class AccursedWitchSpellsCostReductionEffect extends CostModificationEffectImpl { - public AccursedWitchSpellsCostReductionEffect() { + AccursedWitchSpellsCostReductionEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment, CostModificationType.REDUCE_COST); this.staticText = "Spells your opponents cast that target {this} cost {1} less to cast."; } - protected AccursedWitchSpellsCostReductionEffect(AccursedWitchSpellsCostReductionEffect effect) { + private AccursedWitchSpellsCostReductionEffect(AccursedWitchSpellsCostReductionEffect effect) { super(effect); } @@ -107,17 +105,16 @@ class AccursedWitchSpellsCostReductionEffect extends CostModificationEffectImpl @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility) { - if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { - for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { - Mode mode = abilityToModify.getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetUUID : target.getTargets()) { - Permanent permanent = game.getPermanent(targetUUID); - if (permanent != null && permanent.getId().equals(source.getSourceId())) { - return true; - } - } + if (!(abilityToModify instanceof SpellAbility) || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { + return false; + } + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetUUID : target.getTargets()) { + Permanent permanent = game.getPermanent(targetUUID); + if (permanent != null && permanent.getId().equals(source.getSourceId())) { + return true; } } } diff --git a/Mage.Sets/src/mage/cards/a/AchHansRun.java b/Mage.Sets/src/mage/cards/a/AchHansRun.java index 14a0b6d2002..18853779ff8 100644 --- a/Mage.Sets/src/mage/cards/a/AchHansRun.java +++ b/Mage.Sets/src/mage/cards/a/AchHansRun.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -25,8 +24,9 @@ import mage.players.Player; import mage.target.common.TargetCardInLibrary; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author L_J */ public final class AchHansRun extends CardImpl { @@ -38,7 +38,7 @@ public final class AchHansRun extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AchHansRunEffect(), TargetController.YOU, true)); } - public AchHansRun(final AchHansRun card) { + private AchHansRun(final AchHansRun card) { super(card); } @@ -50,12 +50,12 @@ public final class AchHansRun extends CardImpl { class AchHansRunEffect extends OneShotEffect { - public AchHansRunEffect() { + AchHansRunEffect() { super(Outcome.PutCreatureInPlay); this.staticText = "you may say \"Ach! Hans, run! It’s the …\" and the name of a creature card. If you do, search your library for a card with that name, put it onto the battlefield, then shuffle your library. That creature gains haste. Exile it at the beginning of the next end step"; } - public AchHansRunEffect(final AchHansRunEffect effect) { + private AchHansRunEffect(final AchHansRunEffect effect) { super(effect); } @@ -67,41 +67,41 @@ class AchHansRunEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - ChoiceImpl cardChoice = new ChoiceImpl(true); - cardChoice.setChoices(CardRepository.instance.getCreatureNames()); - cardChoice.setMessage("Choose a creature card name"); - if (controller.choose(Outcome.Detriment, cardChoice, game)) { - String cardName = cardChoice.getChoice(); - if (!game.isSimulation()) { - game.informPlayers(controller.getLogName() + ": \"Ach! Hans, run! It's the " + cardName + "!\""); - } - FilterCard nameFilter = new FilterCard(); - nameFilter.add(new NamePredicate(cardName)); - TargetCardInLibrary target = new TargetCardInLibrary(1, 1, nameFilter); - if (controller.searchLibrary(target, game)) { - Card card = controller.getLibrary().remove(target.getFirstTarget(), game); - if (card != null) { - if (card != null && controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { - Permanent creature = game.getPermanent(card.getId()); - if (creature != null) { - // gains haste - ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(creature, game)); - game.addEffect(effect, source); - // Exile at begin of next end step - ExileTargetEffect exileEffect = new ExileTargetEffect(null, null, Zone.BATTLEFIELD); - exileEffect.setTargetPointer(new FixedTarget(creature, game)); - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect); - game.addDelayedTriggeredAbility(delayedAbility, source); - } - } - } - controller.shuffleLibrary(source, game); - } - return true; - } + if (controller == null) { + return false; } - return false; + ChoiceImpl cardChoice = new ChoiceImpl(true); + cardChoice.setChoices(CardRepository.instance.getCreatureNames()); + cardChoice.setMessage("Choose a creature card name"); + if (!controller.choose(Outcome.Detriment, cardChoice, game)) { + return false; + } + String cardName = cardChoice.getChoice(); + game.informPlayers(controller.getLogName() + ": \"Ach! Hans, run! It's the " + cardName + "!\""); + FilterCard nameFilter = new FilterCard(); + nameFilter.add(new NamePredicate(cardName)); + TargetCardInLibrary target = new TargetCardInLibrary(1, 1, nameFilter); + if (!controller.searchLibrary(target, game)) { + return false; + } + Card card = controller.getLibrary().remove(target.getFirstTarget(), game); + if (card == null || !controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { + return false; + } + Permanent creature = game.getPermanent(card.getId()); + if (creature == null) { + return false; + } + // gains haste + ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(creature, game)); + game.addEffect(effect, source); + // Exile at begin of next end step + ExileTargetEffect exileEffect = new ExileTargetEffect(null, null, Zone.BATTLEFIELD); + exileEffect.setTargetPointer(new FixedTarget(creature, game)); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect); + game.addDelayedTriggeredAbility(delayedAbility, source); + controller.shuffleLibrary(source, game); + return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AcidSpewerDragon.java b/Mage.Sets/src/mage/cards/a/AcidSpewerDragon.java index 108c8d3ea8f..d6ee3adf34b 100644 --- a/Mage.Sets/src/mage/cards/a/AcidSpewerDragon.java +++ b/Mage.Sets/src/mage/cards/a/AcidSpewerDragon.java @@ -27,7 +27,7 @@ public final class AcidSpewerDragon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other Dragon creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/a/AdamaroFirstToDesire.java b/Mage.Sets/src/mage/cards/a/AdamaroFirstToDesire.java index a4b80c6083e..134eaaabf50 100644 --- a/Mage.Sets/src/mage/cards/a/AdamaroFirstToDesire.java +++ b/Mage.Sets/src/mage/cards/a/AdamaroFirstToDesire.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -14,14 +13,15 @@ import mage.constants.*; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AdamaroFirstToDesire extends CardImpl { public AdamaroFirstToDesire(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.SPIRIT); @@ -46,7 +46,7 @@ class MostCardsInOpponentsHandCount implements DynamicValue { @Override public int calculate(Game game, Ability source, Effect effect) { int maxCards = 0; - for (UUID opponentId: game.getOpponents(source.getControllerId())) { + for (UUID opponentId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(opponentId); if (opponent != null) { int cards = opponent.getHand().size(); @@ -60,7 +60,7 @@ class MostCardsInOpponentsHandCount implements DynamicValue { @Override public DynamicValue copy() { - return new mage.abilities.dynamicvalue.common.CardsInControllerHandCount(); + return new MostCardsInOpponentsHandCount(); } @Override diff --git a/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java b/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java index 58241914141..4c8c7bc6cc9 100644 --- a/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java +++ b/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java @@ -34,7 +34,7 @@ public final class AdarkarValkyrie extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AdarkarValkyrie(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java b/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java index fa866596582..c6eeeea5d52 100644 --- a/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java +++ b/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java @@ -1,26 +1,23 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.constants.*; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; +import java.util.UUID; + /** - * * @author JRHerlehy */ public final class AdelizTheCinderWind extends CardImpl { @@ -34,7 +31,7 @@ public final class AdelizTheCinderWind extends CardImpl { public AdelizTheCinderWind(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); - + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN, SubType.WIZARD); this.power = new MageInt(2); @@ -48,7 +45,7 @@ public final class AdelizTheCinderWind extends CardImpl { // Whenever you cast an instant or sorcery spell, Wizards you control get +1/+1 until end of turn. Effect effect = new BoostControlledEffect(1, 1, Duration.EndOfTurn, filter); - Ability ability = new SpellCastControllerTriggeredAbility(effect, StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); + Ability ability = new SpellCastControllerTriggeredAbility(effect, StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java b/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java index f03302bd766..18448c3cd88 100644 --- a/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java +++ b/Mage.Sets/src/mage/cards/a/AdmiralBeckettBrass.java @@ -124,7 +124,7 @@ class ControllerDealtDamageByPiratesPredicate implements Predicate { @Override public boolean apply(Permanent input, Game game) { - DamagedByPiratesWatcher watcher = (DamagedByPiratesWatcher) game.getState().getWatchers().get(DamagedByPiratesWatcher.class.getSimpleName()); + DamagedByPiratesWatcher watcher = game.getState().getWatcher(DamagedByPiratesWatcher.class); if (watcher != null) { return watcher.damagedByEnoughPirates(input.getControllerId(), game); } diff --git a/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java b/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java index a969bbc9895..2490d280e41 100644 --- a/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java +++ b/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java @@ -30,7 +30,7 @@ public final class AdmonitionAngel extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("nonland permanent other than Admonition Angel"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); } diff --git a/Mage.Sets/src/mage/cards/a/AegisAngel.java b/Mage.Sets/src/mage/cards/a/AegisAngel.java index 4750a5d59cb..7222995d67c 100644 --- a/Mage.Sets/src/mage/cards/a/AegisAngel.java +++ b/Mage.Sets/src/mage/cards/a/AegisAngel.java @@ -27,7 +27,7 @@ public final class AegisAngel extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AegisAngel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AegisAutomaton.java b/Mage.Sets/src/mage/cards/a/AegisAutomaton.java index ae6e30725aa..aca72950ae5 100644 --- a/Mage.Sets/src/mage/cards/a/AegisAutomaton.java +++ b/Mage.Sets/src/mage/cards/a/AegisAutomaton.java @@ -25,7 +25,7 @@ public final class AegisAutomaton extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AegisAutomaton(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AeonChronicler.java b/Mage.Sets/src/mage/cards/a/AeonChronicler.java index 4a6d8d4b4a3..8b3f42378d0 100644 --- a/Mage.Sets/src/mage/cards/a/AeonChronicler.java +++ b/Mage.Sets/src/mage/cards/a/AeonChronicler.java @@ -36,7 +36,7 @@ public final class AeonChronicler extends CardImpl { this.toughness = new MageInt(0); // Aeon Chronicler's power and toughness are each equal to the number of cards in your hand. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInControllerHandCount(), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(CardsInControllerHandCount.instance, Duration.EndOfGame))); // Suspend X-{X}{3}{U}. X can't be 0. this.addAbility(new SuspendAbility(Integer.MAX_VALUE, new ManaCostsImpl("{3}{U}"), this, true)); diff --git a/Mage.Sets/src/mage/cards/a/AerialGuide.java b/Mage.Sets/src/mage/cards/a/AerialGuide.java index c39dd4fa699..55ddd1a1a36 100644 --- a/Mage.Sets/src/mage/cards/a/AerialGuide.java +++ b/Mage.Sets/src/mage/cards/a/AerialGuide.java @@ -25,7 +25,7 @@ public final class AerialGuide extends CardImpl { static final FilterAttackingCreature filter = new FilterAttackingCreature("another target attacking creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AerialGuide(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/Aeromunculus.java b/Mage.Sets/src/mage/cards/a/Aeromunculus.java index 0dca6864e6e..4f2d962f01d 100644 --- a/Mage.Sets/src/mage/cards/a/Aeromunculus.java +++ b/Mage.Sets/src/mage/cards/a/Aeromunculus.java @@ -1,9 +1,7 @@ package mage.cards.a; import mage.MageInt; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.keyword.AdaptEffect; +import mage.abilities.keyword.AdaptAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,9 +27,7 @@ public final class Aeromunculus extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {2}{G}{U}: Adapt 1. - this.addAbility(new SimpleActivatedAbility( - new AdaptEffect(1), new ManaCostsImpl("{2}{G}{U}") - )); + this.addAbility(new AdaptAbility(1, "{2}{G}{U}")); } public Aeromunculus(final Aeromunculus card) { diff --git a/Mage.Sets/src/mage/cards/a/AetherBurst.java b/Mage.Sets/src/mage/cards/a/AetherBurst.java index 54355a980a9..fdda9a87270 100644 --- a/Mage.Sets/src/mage/cards/a/AetherBurst.java +++ b/Mage.Sets/src/mage/cards/a/AetherBurst.java @@ -13,29 +13,42 @@ import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; import java.util.UUID; import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; /** - * * @author magenoxx_at_gmail.com */ public final class AetherBurst extends CardImpl { - - private static final FilterCard filter = new FilterCard("cards named Aether Burst"); - - static { - filter.add(new NamePredicate("Aether Burst")); - } - public AetherBurst(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Return up to X target creatures to their owners' hands, where X is one plus the number of cards named Aether Burst in all graveyards as you cast Aether Burst. this.getSpellAbility().addEffect(new DynamicReturnToHandTargetEffect()); this.getSpellAbility().addTarget(new DynamicTargetCreaturePermanent()); + this.getSpellAbility().setTargetAdjuster(AetherBurstAdjuster.instance); + } + + + public AetherBurst(final AetherBurst card) { + super(card); + } + + @Override + public AetherBurst copy() { + return new AetherBurst(this); + } +} + +enum AetherBurstAdjuster implements TargetAdjuster { + instance; + private static final FilterCard filter = new FilterCard("cards named Aether Burst"); + + static { + filter.add(new NamePredicate("Aether Burst")); } @Override @@ -55,15 +68,6 @@ public final class AetherBurst extends CardImpl { target.setMaxNumberOfTargets(amount + 1); } } - - public AetherBurst(final AetherBurst card) { - super(card); - } - - @Override - public AetherBurst copy() { - return new AetherBurst(this); - } } class DynamicTargetCreaturePermanent extends TargetPermanent { diff --git a/Mage.Sets/src/mage/cards/a/AetherMutation.java b/Mage.Sets/src/mage/cards/a/AetherMutation.java index 4f0fad54ba3..c5b9b39587f 100644 --- a/Mage.Sets/src/mage/cards/a/AetherMutation.java +++ b/Mage.Sets/src/mage/cards/a/AetherMutation.java @@ -25,7 +25,7 @@ public final class AetherMutation extends CardImpl { this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // create X 1/1 green Saproling creature tokens, where X is that creature's converted mana cost. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance)); } public AetherMutation(final AetherMutation card) { diff --git a/Mage.Sets/src/mage/cards/a/AetherTide.java b/Mage.Sets/src/mage/cards/a/AetherTide.java index fc3c6c4915b..f368a6ff020 100644 --- a/Mage.Sets/src/mage/cards/a/AetherTide.java +++ b/Mage.Sets/src/mage/cards/a/AetherTide.java @@ -2,23 +2,22 @@ package mage.cards.a; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.costs.Cost; -import mage.abilities.costs.VariableCostImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.DiscardTargetCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.CardsImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.game.stack.StackObject; -import mage.players.Player; -import mage.target.TargetPermanent; import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -30,10 +29,16 @@ public final class AetherTide extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}"); // As an additional cost to cast Aether Tide, discard X creature cards. - this.getSpellAbility().addCost(new AetherTideCost()); + Ability ability = new SimpleStaticAbility(Zone.ALL, new InfoEffect("As an additional cost to cast {this}, discard X creature cards")); + ability.setRuleAtTheTop(true); + this.addAbility(ability); // Return X target creatures to their owners' hands. - this.getSpellAbility().addEffect(new ReturnToHandTargetPermanentEffect()); + Effect effect = new ReturnToHandTargetEffect(true); + effect.setText("Return X target creatures to their owners' hands"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().setTargetAdjuster(AetherTideTargetAdjuster.instance); + this.getSpellAbility().setCostAdjuster(AetherTideCostAdjuster.instance); } @@ -47,98 +52,25 @@ public final class AetherTide extends CardImpl { } } -class AetherTideCost extends VariableCostImpl { - - public AetherTideCost() { - super("discard X creature cards"); - text = "As an additional cost to cast {this}, discard X creature cards"; - } - - public AetherTideCost(AetherTideCost cost) { - super(cost); - } +enum AetherTideTargetAdjuster implements TargetAdjuster { + instance; @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - return (game.getPlayer(controllerId).getHand().count(new FilterCreatureCard(), game) > 0); + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetCreaturePermanent(xValue, xValue, new FilterCreaturePermanent(), false)); } - - @Override - public int getMaxValue(Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.getHand().count(new FilterCreatureCard(), game); - } - return 0; - } - - @Override - public int getMinValue(Ability source, Game game) { - return 0; - } - - @Override - public Cost getFixedCostsFromAnnouncedValue(int xValue) { - TargetCardInHand target = new TargetCardInHand(xValue, new FilterCreatureCard()); - return new DiscardTargetCost(target); - } - - @Override - public int announceXValue(Ability source, Game game) { - int xValue = 0; - Player controller = game.getPlayer(source.getControllerId()); - StackObject stackObject = game.getStack().getStackObject(source.getId()); - if (controller != null - && stackObject != null) { - xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game), - "Announce the number of creature cards to discard", game, source, this); - } - return xValue; - } - - @Override - public AetherTideCost copy() { - return new AetherTideCost(this); - } - } -class ReturnToHandTargetPermanentEffect extends OneShotEffect { - - public ReturnToHandTargetPermanentEffect() { - super(Outcome.ReturnToHand); - setText("Return X target creatures to their owners' hands"); - } - - public ReturnToHandTargetPermanentEffect(final ReturnToHandTargetPermanentEffect effect) { - super(effect); - } +enum AetherTideCostAdjuster implements CostAdjuster { + instance; @Override - public ReturnToHandTargetPermanentEffect copy() { - return new ReturnToHandTargetPermanentEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - int xPaid = source.getCosts().getVariableCosts().get(0).getAmount(); - if (controller != null - && xPaid > 0) { - int available = game.getBattlefield().count(new FilterCreaturePermanent(), - source.getSourceId(), - source.getControllerId(), game); - if (available > 0) { - TargetPermanent target = new TargetPermanent(Math.min(xPaid, available), - xPaid, - new FilterCreaturePermanent("creatures to return to their owner's hands"), - true); - if (controller.chooseTarget(outcome.Detriment, target, source, game)) { - controller.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game); - } - return true; - } + public void adjustCosts(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + if (xValue > 0) { + ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, new FilterCreatureCard("creature cards")))); } - return false; } } diff --git a/Mage.Sets/src/mage/cards/a/AetherbornMarauder.java b/Mage.Sets/src/mage/cards/a/AetherbornMarauder.java index 2e25504f2fb..927aa2b43a2 100644 --- a/Mage.Sets/src/mage/cards/a/AetherbornMarauder.java +++ b/Mage.Sets/src/mage/cards/a/AetherbornMarauder.java @@ -76,7 +76,7 @@ class AetherbornMarauderEffect extends OneShotEffect { Permanent sourceObject = game.getPermanent(source.getSourceId()); if (controller != null && sourceObject != null) { FilterControlledPermanent filter = new FilterControlledPermanent("permanent you control to remove +1/+1 counters from"); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new CounterPredicate(CounterType.P1P1)); boolean firstRun = true; while (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { diff --git a/Mage.Sets/src/mage/cards/a/AetherfluxReservoir.java b/Mage.Sets/src/mage/cards/a/AetherfluxReservoir.java index 5b25220b997..871b4d90ac6 100644 --- a/Mage.Sets/src/mage/cards/a/AetherfluxReservoir.java +++ b/Mage.Sets/src/mage/cards/a/AetherfluxReservoir.java @@ -50,8 +50,11 @@ class AetherfluxReservoirDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); - return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(sourceAbility.getControllerId()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); + if(watcher != null) { + return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(sourceAbility.getControllerId()); + } + return 0; } @Override diff --git a/Mage.Sets/src/mage/cards/a/AethersquallAncient.java b/Mage.Sets/src/mage/cards/a/AethersquallAncient.java index 7f2ef613107..fa621583395 100644 --- a/Mage.Sets/src/mage/cards/a/AethersquallAncient.java +++ b/Mage.Sets/src/mage/cards/a/AethersquallAncient.java @@ -27,7 +27,7 @@ public final class AethersquallAncient extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AethersquallAncient(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AetherstormRoc.java b/Mage.Sets/src/mage/cards/a/AetherstormRoc.java index 3424b95a3ac..aff1bf10b00 100644 --- a/Mage.Sets/src/mage/cards/a/AetherstormRoc.java +++ b/Mage.Sets/src/mage/cards/a/AetherstormRoc.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -21,17 +20,17 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class AetherstormRoc extends CardImpl { - private final UUID originalId; - public AetherstormRoc(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); this.subtype.add(SubType.BIRD); this.power = new MageInt(3); this.toughness = new MageInt(3); @@ -47,30 +46,32 @@ public final class AetherstormRoc extends CardImpl { Ability ability = new AttacksTriggeredAbility(doIfCostPaidEffect, false, "Whenever {this} attacks you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls."); ability.addTarget(new TargetCreaturePermanent(0, 1, new FilterCreaturePermanent("creature defending player controls"), false)); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(AetherstormRocAdjuster.instance); this.addAbility(ability); } public AetherstormRoc(final AetherstormRoc card) { super(card); - this.originalId = card.originalId; } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } - } @Override public AetherstormRoc copy() { return new AetherstormRoc(this); } } + +enum AetherstormRocAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); + filter.add(new ControllerIdPredicate(defenderId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); + ability.addTarget(target); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/Aggravate.java b/Mage.Sets/src/mage/cards/a/Aggravate.java index 6110f09d523..21d95858548 100644 --- a/Mage.Sets/src/mage/cards/a/Aggravate.java +++ b/Mage.Sets/src/mage/cards/a/Aggravate.java @@ -61,7 +61,7 @@ class AggravateRequirementEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), source.getSourceId()); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.wasDamaged(permanent, game); } diff --git a/Mage.Sets/src/mage/cards/a/AgonizingDemise.java b/Mage.Sets/src/mage/cards/a/AgonizingDemise.java index a183e73f73e..dcaab970431 100644 --- a/Mage.Sets/src/mage/cards/a/AgonizingDemise.java +++ b/Mage.Sets/src/mage/cards/a/AgonizingDemise.java @@ -40,7 +40,7 @@ public final class AgonizingDemise extends CardImpl { //If Agonizing Demise was kicked, it deals damage equal to that creature's power to the creature's controller. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageTargetControllerEffect(new TargetPermanentPowerCount()), + new DamageTargetControllerEffect(TargetPermanentPowerCount.instance), KickedCondition.instance, "if this spell was kicked, it deals damage equal to that creature's power to the creature's controller.")); diff --git a/Mage.Sets/src/mage/cards/a/AirdropCondor.java b/Mage.Sets/src/mage/cards/a/AirdropCondor.java index 447fbfae6c7..824ef1f5721 100644 --- a/Mage.Sets/src/mage/cards/a/AirdropCondor.java +++ b/Mage.Sets/src/mage/cards/a/AirdropCondor.java @@ -42,7 +42,7 @@ public final class AirdropCondor extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {1}{R}, Sacrifice a Goblin creature: Airdrop Condor deals damage equal to the sacrificed creature's power to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new SacrificeCostCreaturesPower()), new ManaCostsImpl("{1}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(SacrificeCostCreaturesPower.instance), new ManaCostsImpl("{1}{R}")); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AjaniCallerOfThePride.java b/Mage.Sets/src/mage/cards/a/AjaniCallerOfThePride.java index 0dfdd6a8bf5..a3b0b04fc46 100644 --- a/Mage.Sets/src/mage/cards/a/AjaniCallerOfThePride.java +++ b/Mage.Sets/src/mage/cards/a/AjaniCallerOfThePride.java @@ -49,7 +49,7 @@ public final class AjaniCallerOfThePride extends CardImpl { ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); // -8: create X 2/2 white Cat creature tokens, where X is your life total. - this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new CatToken(), new ControllerLifeCount()), -8)); + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new CatToken(), ControllerLifeCount.instance), -8)); } public AjaniCallerOfThePride(final AjaniCallerOfThePride card) { diff --git a/Mage.Sets/src/mage/cards/a/AjaniSteadfast.java b/Mage.Sets/src/mage/cards/a/AjaniSteadfast.java index 7d95193116a..1d4a95c8911 100644 --- a/Mage.Sets/src/mage/cards/a/AjaniSteadfast.java +++ b/Mage.Sets/src/mage/cards/a/AjaniSteadfast.java @@ -36,7 +36,7 @@ public final class AjaniSteadfast extends CardImpl { private static final FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("other planeswalker you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/a/AjaniUnyielding.java b/Mage.Sets/src/mage/cards/a/AjaniUnyielding.java index f7ba38516c5..ab5289a0286 100644 --- a/Mage.Sets/src/mage/cards/a/AjaniUnyielding.java +++ b/Mage.Sets/src/mage/cards/a/AjaniUnyielding.java @@ -35,7 +35,7 @@ public final class AjaniUnyielding extends CardImpl { static { nonlandPermanentFilter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); planeswalkerFilter.add(new ControllerPredicate(TargetController.YOU)); - planeswalkerFilter.add(new AnotherPredicate()); + planeswalkerFilter.add(AnotherPredicate.instance); } public AjaniUnyielding(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AjaniValiantProtector.java b/Mage.Sets/src/mage/cards/a/AjaniValiantProtector.java index 00f6ca6c98f..7bec5ea3f33 100644 --- a/Mage.Sets/src/mage/cards/a/AjaniValiantProtector.java +++ b/Mage.Sets/src/mage/cards/a/AjaniValiantProtector.java @@ -44,7 +44,7 @@ public final class AjaniValiantProtector extends CardImpl { this.addAbility(new LoyaltyAbility(new RevealCardsFromLibraryUntilEffect(new FilterCreatureCard(), Zone.HAND, Zone.LIBRARY), 1)); // -11: Put X +1/+1 counters on target creature, where X is your life total. That creature gains trample until end of turn. - Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), new ControllerLifeCount()); + Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), ControllerLifeCount.instance); effect.setText("Put X +1/+1 counters on target creature, where X is your life total."); ability = new LoyaltyAbility(effect, -11); effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); diff --git a/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java b/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java index 8a28d2545e2..02198d974d4 100644 --- a/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java +++ b/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java @@ -44,7 +44,7 @@ public final class AjaniWiseCounselor extends CardImpl { // −9: Put X +1/+1 counters on target creature, where X is your life total. Ability ability = new LoyaltyAbility(new AddCountersTargetEffect( CounterType.P1P1.createInstance(), - new ControllerLifeCount() + ControllerLifeCount.instance ).setText("put X +1/+1 counters on target creature, where X is your life total"), -9); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AkoumFlameseeker.java b/Mage.Sets/src/mage/cards/a/AkoumFlameseeker.java index d076743f8cb..5c1c67eea29 100644 --- a/Mage.Sets/src/mage/cards/a/AkoumFlameseeker.java +++ b/Mage.Sets/src/mage/cards/a/AkoumFlameseeker.java @@ -30,7 +30,7 @@ public final class AkoumFlameseeker extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public AkoumFlameseeker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java b/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java index 0e443e10e26..67907265a02 100644 --- a/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java +++ b/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java @@ -28,7 +28,7 @@ public final class AkroanConscriptor extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AkroanConscriptor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AkroanHoplite.java b/Mage.Sets/src/mage/cards/a/AkroanHoplite.java index 599a0dfa130..d19cdaf3b65 100644 --- a/Mage.Sets/src/mage/cards/a/AkroanHoplite.java +++ b/Mage.Sets/src/mage/cards/a/AkroanHoplite.java @@ -27,7 +27,7 @@ public final class AkroanHoplite extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public AkroanHoplite(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AlabasterPotion.java b/Mage.Sets/src/mage/cards/a/AlabasterPotion.java index 2e918e1fe18..9a69608a6f5 100644 --- a/Mage.Sets/src/mage/cards/a/AlabasterPotion.java +++ b/Mage.Sets/src/mage/cards/a/AlabasterPotion.java @@ -23,10 +23,10 @@ public final class AlabasterPotion extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{W}{W}"); // Choose one - Target player gains X life; or prevent the next X damage that would be dealt to any target this turn. - this.getSpellAbility().addEffect(new GainLifeTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new GainLifeTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); Mode mode = new Mode(); - mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue())); + mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, ManacostVariableValue.instance)); mode.addTarget(new TargetAnyTarget()); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/a/Alarum.java b/Mage.Sets/src/mage/cards/a/Alarum.java index 553c075fa38..ac526c698fc 100644 --- a/Mage.Sets/src/mage/cards/a/Alarum.java +++ b/Mage.Sets/src/mage/cards/a/Alarum.java @@ -23,7 +23,7 @@ public final class Alarum extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonattacking creature"); static { - filter.add(Predicates.not(new AttackingPredicate())); + filter.add(Predicates.not(AttackingPredicate.instance)); } public Alarum(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/Aleatory.java b/Mage.Sets/src/mage/cards/a/Aleatory.java index 71080e6298b..eb33925b2bc 100644 --- a/Mage.Sets/src/mage/cards/a/Aleatory.java +++ b/Mage.Sets/src/mage/cards/a/Aleatory.java @@ -67,7 +67,7 @@ class AleatoryEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { game.addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn), source); return true; } diff --git a/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java b/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java index 02b087e0ab3..7934c8b8585 100644 --- a/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java +++ b/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java @@ -113,7 +113,7 @@ class AlhammarretsArchiveReplacementEffect extends ReplacementEffectImpl { if (event.getPlayerId().equals(source.getControllerId())) { if (game.isActivePlayer(event.getPlayerId()) && game.getPhase().getStep().getType() == PhaseStep.DRAW) { - CardsDrawnDuringDrawStepWatcher watcher = (CardsDrawnDuringDrawStepWatcher) game.getState().getWatchers().get(CardsDrawnDuringDrawStepWatcher.class.getSimpleName()); + CardsDrawnDuringDrawStepWatcher watcher = game.getState().getWatcher(CardsDrawnDuringDrawStepWatcher.class); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) { return true; } diff --git a/Mage.Sets/src/mage/cards/a/AltarGolem.java b/Mage.Sets/src/mage/cards/a/AltarGolem.java index 52501d4637e..5b0dc5a367c 100644 --- a/Mage.Sets/src/mage/cards/a/AltarGolem.java +++ b/Mage.Sets/src/mage/cards/a/AltarGolem.java @@ -34,7 +34,7 @@ public final class AltarGolem extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public AltarGolem(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AltarOfTheBrood.java b/Mage.Sets/src/mage/cards/a/AltarOfTheBrood.java index 0fbb0b78f94..95122867986 100644 --- a/Mage.Sets/src/mage/cards/a/AltarOfTheBrood.java +++ b/Mage.Sets/src/mage/cards/a/AltarOfTheBrood.java @@ -21,7 +21,7 @@ public final class AltarOfTheBrood extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AltarOfTheBrood(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AlwaysWatching.java b/Mage.Sets/src/mage/cards/a/AlwaysWatching.java index ecb7a7d3506..a844009f12b 100644 --- a/Mage.Sets/src/mage/cards/a/AlwaysWatching.java +++ b/Mage.Sets/src/mage/cards/a/AlwaysWatching.java @@ -26,7 +26,7 @@ public final class AlwaysWatching extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creatures"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public AlwaysWatching(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AmbushKrotiq.java b/Mage.Sets/src/mage/cards/a/AmbushKrotiq.java index 821128e1d72..18e0f9a1506 100644 --- a/Mage.Sets/src/mage/cards/a/AmbushKrotiq.java +++ b/Mage.Sets/src/mage/cards/a/AmbushKrotiq.java @@ -22,7 +22,7 @@ public final class AmbushKrotiq extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AmbushKrotiq(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java b/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java index 23a6897b4b9..bdd8b1e1ed1 100644 --- a/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java +++ b/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java @@ -40,7 +40,7 @@ public class AminatouTheFateShifter extends CardImpl { static { filter.add(new OwnerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AminatouTheFateShifter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/Amplifire.java b/Mage.Sets/src/mage/cards/a/Amplifire.java new file mode 100644 index 00000000000..a93e1f986f9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/Amplifire.java @@ -0,0 +1,90 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; +import mage.cards.*; +import mage.constants.*; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Amplifire extends CardImpl { + + public Amplifire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // At the beginning of your upkeep, reveal cards from the top of your library until you reveal a creature card. Until your next turn, Amplifire's base power becomes twice that card's power and its base toughness becomes twice that card's toughness. Put the revealed cards on the bottom of your library in a random order. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new AmplifireEffect(), TargetController.YOU, false + )); + } + + private Amplifire(final Amplifire card) { + super(card); + } + + @Override + public Amplifire copy() { + return new Amplifire(this); + } +} + +class AmplifireEffect extends OneShotEffect { + + AmplifireEffect() { + super(Outcome.Benefit); + staticText = "reveal cards from the top of your library until you reveal a creature card. " + + "Until your next turn, {this}'s base power becomes twice that card's power " + + "and its base toughness becomes twice that card's toughness. " + + "Put the revealed cards on the bottom of your library in a random order."; + } + + private AmplifireEffect(final AmplifireEffect effect) { + super(effect); + } + + @Override + public AmplifireEffect copy() { + return new AmplifireEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Cards cards = new CardsImpl(); + Card lastCard = null; + for (Card card : player.getLibrary().getCards(game)) { + if (card != null) { + cards.add(card); + if (card.isCreature()) { + lastCard = card; + break; + } + } + } + player.revealCards(source, cards, game); + if (lastCard != null) { + game.addEffect(new SetPowerToughnessSourceEffect( + 2 * lastCard.getPower().getValue(), + 2 * lastCard.getToughness().getValue(), + Duration.UntilYourNextTurn, SubLayer.SetPT_7b + ), source); + } + player.putCardsOnBottomOfLibrary(cards, game, source, false); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java index f77efb80a82..dbf3e6a8417 100644 --- a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java +++ b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java @@ -34,7 +34,7 @@ public final class AnaBattlemage extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public AnaBattlemage(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AnabaAncestor.java b/Mage.Sets/src/mage/cards/a/AnabaAncestor.java index 261ab7c1e76..65a6936cc41 100644 --- a/Mage.Sets/src/mage/cards/a/AnabaAncestor.java +++ b/Mage.Sets/src/mage/cards/a/AnabaAncestor.java @@ -28,7 +28,7 @@ public final class AnabaAncestor extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MINOTAUR)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AnabaAncestor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AnafenzaKinTreeSpirit.java b/Mage.Sets/src/mage/cards/a/AnafenzaKinTreeSpirit.java index 3e6aa231965..3c8407616c2 100644 --- a/Mage.Sets/src/mage/cards/a/AnafenzaKinTreeSpirit.java +++ b/Mage.Sets/src/mage/cards/a/AnafenzaKinTreeSpirit.java @@ -25,8 +25,8 @@ public final class AnafenzaKinTreeSpirit extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); - filter.add(new AnotherPredicate()); + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); } public AnafenzaKinTreeSpirit(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java b/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java index 16fb5ec22a7..96e8487a47e 100644 --- a/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java +++ b/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java @@ -32,8 +32,8 @@ public final class AnafenzaTheForemost extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target tapped creature you control"); static { - filter.add(new AnotherPredicate()); - filter.add(new TappedPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(TappedPredicate.instance); } public AnafenzaTheForemost(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AncestorsProphet.java b/Mage.Sets/src/mage/cards/a/AncestorsProphet.java index 356f2cf0967..a83a788e70a 100644 --- a/Mage.Sets/src/mage/cards/a/AncestorsProphet.java +++ b/Mage.Sets/src/mage/cards/a/AncestorsProphet.java @@ -27,7 +27,7 @@ public final class AncestorsProphet extends CardImpl { static { filter.add(new SubtypePredicate(SubType.CLERIC)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public AncestorsProphet(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AncestralMask.java b/Mage.Sets/src/mage/cards/a/AncestralMask.java index 60e6948212c..bbfa90a8747 100644 --- a/Mage.Sets/src/mage/cards/a/AncestralMask.java +++ b/Mage.Sets/src/mage/cards/a/AncestralMask.java @@ -24,7 +24,7 @@ public final class AncestralMask extends CardImpl { private static final FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent("each other enchantment on the battlefield"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AncestralMask(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AncientExcavation.java b/Mage.Sets/src/mage/cards/a/AncientExcavation.java index 4965f68132a..c339ac270d0 100644 --- a/Mage.Sets/src/mage/cards/a/AncientExcavation.java +++ b/Mage.Sets/src/mage/cards/a/AncientExcavation.java @@ -61,7 +61,7 @@ class AncientExcavationEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - DynamicValue numCards = new CardsInControllerHandCount(); + DynamicValue numCards = CardsInControllerHandCount.instance; int amount = numCards.calculate(game, source, this); player.drawCards(amount, game); player.discard(amount, false, source, game); diff --git a/Mage.Sets/src/mage/cards/a/AncientHellkite.java b/Mage.Sets/src/mage/cards/a/AncientHellkite.java index a07bb7320ee..527f9bec33e 100644 --- a/Mage.Sets/src/mage/cards/a/AncientHellkite.java +++ b/Mage.Sets/src/mage/cards/a/AncientHellkite.java @@ -29,7 +29,7 @@ public final class AncientHellkite extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public AncientHellkite(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AncientHolocron.java b/Mage.Sets/src/mage/cards/a/AncientHolocron.java index 565a7f334bd..37c27e48365 100644 --- a/Mage.Sets/src/mage/cards/a/AncientHolocron.java +++ b/Mage.Sets/src/mage/cards/a/AncientHolocron.java @@ -23,7 +23,7 @@ public final class AncientHolocron extends CardImpl { private static final FilterSpell filter = new FilterSpell("multicolored spells"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public AncientHolocron(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AncientStirrings.java b/Mage.Sets/src/mage/cards/a/AncientStirrings.java index e9408b81cd0..490c2641f54 100644 --- a/Mage.Sets/src/mage/cards/a/AncientStirrings.java +++ b/Mage.Sets/src/mage/cards/a/AncientStirrings.java @@ -20,7 +20,7 @@ public final class AncientStirrings extends CardImpl { private static final FilterCard filter = new FilterCard("a colorless card"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } diff --git a/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java b/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java index c9935eb2c3c..bc7ddf8dacc 100644 --- a/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java +++ b/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java @@ -65,7 +65,7 @@ class AncientStoneIdolCostReductionEffect extends CostModificationEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public AncientStoneIdolCostReductionEffect() { diff --git a/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java b/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java index 19a9acf8388..b407c9e41f8 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java @@ -39,7 +39,7 @@ public final class AngelOfCondemnation extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AngelOfCondemnation(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AngelOfGrace.java b/Mage.Sets/src/mage/cards/a/AngelOfGrace.java new file mode 100644 index 00000000000..be50c0fc04b --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngelOfGrace.java @@ -0,0 +1,100 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileSourceFromGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.SetPlayerLifeSourceEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AngelOfGrace extends CardImpl { + + public AngelOfGrace(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Angel of Grace enters the battlefield, until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead. + this.addAbility(new EntersBattlefieldTriggeredAbility(new AngelOfGraceReplacementEffect())); + + // {4}{W}{W}, Exile Angel of Grace from your graveyard: Your life total becomes 10. + Ability ability = new SimpleActivatedAbility( + Zone.GRAVEYARD, new SetPlayerLifeSourceEffect(10), new ManaCostsImpl("{4}{W}{W}") + ); + ability.addCost(new ExileSourceFromGraveCost()); + this.addAbility(ability); + } + + private AngelOfGrace(final AngelOfGrace card) { + super(card); + } + + @Override + public AngelOfGrace copy() { + return new AngelOfGrace(this); + } +} + +class AngelOfGraceReplacementEffect extends ReplacementEffectImpl { + + AngelOfGraceReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead"; + } + + private AngelOfGraceReplacementEffect(final AngelOfGraceReplacementEffect effect) { + super(effect); + } + + @Override + public AngelOfGraceReplacementEffect copy() { + return new AngelOfGraceReplacementEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS; + } + + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getPlayerId().equals(source.getControllerId())) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && (controller.getLife() - event.getAmount()) < 1) { + event.setAmount(controller.getLife() - 1); + } + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return false; + } + +} diff --git a/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java b/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java index cb7bd647131..85a34e8ae67 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfJubilation.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -80,7 +79,8 @@ class AngelOfJubilationEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - for (Player player : game.getPlayers().values()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); player.setCanPayLifeCost(false); player.setCanPaySacrificeCostFilter(new FilterCreaturePermanent()); } @@ -113,8 +113,10 @@ class AngelOfJubilationSacrificeFilterEffect extends CostModificationEffectImpl @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify.getAbilityType() == AbilityType.ACTIVATED - || abilityToModify instanceof SpellAbility; + + return (abilityToModify.getAbilityType() == AbilityType.ACTIVATED + || abilityToModify instanceof SpellAbility) + && game.getState().getPlayersInRange(source.getControllerId(), game).contains(abilityToModify.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/a/AngelicArbiter.java b/Mage.Sets/src/mage/cards/a/AngelicArbiter.java index 75693f80c0f..4acf0a2b1b9 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicArbiter.java +++ b/Mage.Sets/src/mage/cards/a/AngelicArbiter.java @@ -66,7 +66,7 @@ class AngelicArbiterCantAttackTargetEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (game.isActivePlayer(permanent.getControllerId()) && game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(permanent.getControllerId()) > 0) { return true; } @@ -114,7 +114,7 @@ class AngelicArbiterEffect2 extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (game.isActivePlayer(event.getPlayerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { - PlayerAttackedWatcher watcher = (PlayerAttackedWatcher) game.getState().getWatchers().get(PlayerAttackedWatcher.class.getSimpleName()); + PlayerAttackedWatcher watcher = game.getState().getWatcher(PlayerAttackedWatcher.class); if (watcher != null && watcher.getNumberOfAttackersCurrentTurn(event.getPlayerId()) > 0) { return true; } diff --git a/Mage.Sets/src/mage/cards/a/AngelicCaptain.java b/Mage.Sets/src/mage/cards/a/AngelicCaptain.java index 4f04176e98d..3b16d8ebfb6 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicCaptain.java +++ b/Mage.Sets/src/mage/cards/a/AngelicCaptain.java @@ -26,7 +26,7 @@ public final class AngelicCaptain extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AngelicCaptain(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AngelicExaltation.java b/Mage.Sets/src/mage/cards/a/AngelicExaltation.java new file mode 100644 index 00000000000..a85f1acfe43 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngelicExaltation.java @@ -0,0 +1,84 @@ +package mage.cards.a; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AngelicExaltation extends CardImpl { + + public AngelicExaltation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + + // Whenever a creature you control attacks alone, it gets +X/+X until end of turn, where X is the number of creatures you control. + this.addAbility(new AngelicExaltationAbility()); + } + + private AngelicExaltation(final AngelicExaltation card) { + super(card); + } + + @Override + public AngelicExaltation copy() { + return new AngelicExaltation(this); + } +} + +class AngelicExaltationAbility extends TriggeredAbilityImpl { + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_CREATURE); + + public AngelicExaltationAbility() { + super(Zone.BATTLEFIELD, new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn, true), false); + } + + public AngelicExaltationAbility(final AngelicExaltationAbility ability) { + super(ability); + } + + @Override + public AngelicExaltationAbility copy() { + return new AngelicExaltationAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.isActivePlayer(this.controllerId)) { + if (game.getCombat().attacksAlone()) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a creature you control attacks alone, " + + "it gets +X/+X until end of turn, " + + "where X is the number of creatures you control."; + } + +} diff --git a/Mage.Sets/src/mage/cards/a/AngelicFavor.java b/Mage.Sets/src/mage/cards/a/AngelicFavor.java index 9ab91cae5dd..0fb54f81536 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicFavor.java +++ b/Mage.Sets/src/mage/cards/a/AngelicFavor.java @@ -38,7 +38,7 @@ public final class AngelicFavor extends CardImpl { private static final FilterControlledCreaturePermanent untappedCreatureYouControl = new FilterControlledCreaturePermanent("untapped creature you control"); static { - untappedCreatureYouControl.add(Predicates.not(new TappedPredicate())); + untappedCreatureYouControl.add(Predicates.not(TappedPredicate.instance)); } public AngelicFavor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java b/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java index 2a05d869ffc..5de5f29b030 100644 --- a/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java +++ b/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java @@ -72,7 +72,7 @@ class AngelsTrumpetTapEffect extends OneShotEffect { continue; } // Creatures that attacked are safe. - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null && watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(creature, game))) { continue; } diff --git a/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java b/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java index 665411c9814..cd6f1f23663 100644 --- a/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java +++ b/Mage.Sets/src/mage/cards/a/AngrathsMarauders.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -15,6 +14,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.util.CardUtil; /** @@ -63,15 +63,9 @@ class AngrathsMaraudersEffect extends ReplacementEffectImpl { @Override public boolean checksEventType(GameEvent event, Game game) { - switch (event.getType()) { - case DAMAGE_PLAYER: - return true; - case DAMAGE_CREATURE: - return true; - case DAMAGE_PLANESWALKER: - return true; - } - return false; + return event.getType().equals(EventType.DAMAGE_PLAYER) + || event.getType().equals(EventType.DAMAGE_CREATURE) + || event.getType().equals(EventType.DAMAGE_PLANESWALKER); } @Override diff --git a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java index f7291fa1123..94e44b7c8e9 100644 --- a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java +++ b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java @@ -69,7 +69,7 @@ class AnimarCostReductionEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - Ability spellAbility = (SpellAbility) abilityToModify; + Ability spellAbility = abilityToModify; Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (sourcePermanent != null && spellAbility != null) { int amount = sourcePermanent.getCounters(game).getCount(CounterType.P1P1); diff --git a/Mage.Sets/src/mage/cards/a/AnointerPriest.java b/Mage.Sets/src/mage/cards/a/AnointerPriest.java index 31784994a28..bc4f0e4e883 100644 --- a/Mage.Sets/src/mage/cards/a/AnointerPriest.java +++ b/Mage.Sets/src/mage/cards/a/AnointerPriest.java @@ -24,7 +24,7 @@ public final class AnointerPriest extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("a creature token"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public AnointerPriest(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/Antagonism.java b/Mage.Sets/src/mage/cards/a/Antagonism.java index 2bde3ac7b29..818a31125e5 100644 --- a/Mage.Sets/src/mage/cards/a/Antagonism.java +++ b/Mage.Sets/src/mage/cards/a/Antagonism.java @@ -49,7 +49,7 @@ class OpponentWasNotDealtDamageCondition implements Condition { public boolean apply(Game game, Ability source) { UUID activePlayer = game.getState().getActivePlayerId(); if (activePlayer != null) { - BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get(BloodthirstWatcher.class.getSimpleName(), activePlayer); + BloodthirstWatcher watcher = game.getState().getWatcher(BloodthirstWatcher.class, activePlayer); if (watcher != null) { return !watcher.conditionMet(); } diff --git a/Mage.Sets/src/mage/cards/a/ApexHawks.java b/Mage.Sets/src/mage/cards/a/ApexHawks.java index 796decca43d..12d41455eb8 100644 --- a/Mage.Sets/src/mage/cards/a/ApexHawks.java +++ b/Mage.Sets/src/mage/cards/a/ApexHawks.java @@ -35,7 +35,7 @@ public final class ApexHawks extends CardImpl { // Apex Hawks enters the battlefield with a +1/+1 counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true) + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true) ,"with a +1/+1 counter on it for each time it was kicked")); } diff --git a/Mage.Sets/src/mage/cards/a/AphettoDredging.java b/Mage.Sets/src/mage/cards/a/AphettoDredging.java index 5dcd18c3df8..9309b1bd80f 100644 --- a/Mage.Sets/src/mage/cards/a/AphettoDredging.java +++ b/Mage.Sets/src/mage/cards/a/AphettoDredging.java @@ -1,9 +1,7 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; @@ -18,9 +16,11 @@ import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author Quercitron */ public final class AphettoDredging extends CardImpl { @@ -32,20 +32,7 @@ public final class AphettoDredging extends CardImpl { Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return up to three target creature cards of the creature type of your choice from your graveyard to your hand"); this.getSpellAbility().addEffect(effect); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - Player controller = game.getPlayer(ability.getControllerId()); - Choice typeChoice = new ChoiceCreatureType(game.getObject(ability.getSourceId())); - if (controller != null && controller.choose(Outcome.PutCreatureInPlay, typeChoice, game)) { - String chosenType = typeChoice.getChoice(); - FilterCreatureCard filter = new FilterCreatureCard(chosenType + " cards"); - filter.add(new SubtypePredicate(SubType.byDescription(chosenType))); - ability.addTarget(new TargetCardInYourGraveyard(0, 3, filter)); - } - } + this.getSpellAbility().setTargetAdjuster(AphettoDredgingAdjuster.instance); } public AphettoDredging(final AphettoDredging card) { @@ -57,3 +44,19 @@ public final class AphettoDredging extends CardImpl { return new AphettoDredging(this); } } + +enum AphettoDredgingAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + Choice typeChoice = new ChoiceCreatureType(game.getObject(ability.getSourceId())); + if (controller != null && controller.choose(Outcome.PutCreatureInPlay, typeChoice, game)) { + String chosenType = typeChoice.getChoice(); + FilterCreatureCard filter = new FilterCreatureCard(chosenType + " cards"); + filter.add(new SubtypePredicate(SubType.byDescription(chosenType))); + ability.addTarget(new TargetCardInYourGraveyard(0, 3, filter)); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AphettoGrifter.java b/Mage.Sets/src/mage/cards/a/AphettoGrifter.java index a00ec7bb62e..c1e7324741f 100644 --- a/Mage.Sets/src/mage/cards/a/AphettoGrifter.java +++ b/Mage.Sets/src/mage/cards/a/AphettoGrifter.java @@ -28,7 +28,7 @@ public final class AphettoGrifter extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Wizards you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.WIZARD)); } diff --git a/Mage.Sets/src/mage/cards/a/ApocalypseChime.java b/Mage.Sets/src/mage/cards/a/ApocalypseChime.java index 18f862f153b..178b6930de2 100644 --- a/Mage.Sets/src/mage/cards/a/ApocalypseChime.java +++ b/Mage.Sets/src/mage/cards/a/ApocalypseChime.java @@ -27,7 +27,7 @@ public final class ApocalypseChime extends CardImpl { static { filter.add(Predicates.and( - Predicates.not(new TokenPredicate()), + Predicates.not(TokenPredicate.instance), new ExpansionSetPredicate("HML") )); } diff --git a/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java b/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java index db37a8a4433..9a1882a6e70 100644 --- a/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java +++ b/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java @@ -25,7 +25,7 @@ public final class ApocalypseDemon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ApocalypseDemon(UUID ownerId, CardSetInfo cardSetInfo) { diff --git a/Mage.Sets/src/mage/cards/a/ApocalypseHydra.java b/Mage.Sets/src/mage/cards/a/ApocalypseHydra.java index aa93fa740d2..d0d536f0879 100644 --- a/Mage.Sets/src/mage/cards/a/ApocalypseHydra.java +++ b/Mage.Sets/src/mage/cards/a/ApocalypseHydra.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -23,14 +22,15 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author Loki */ public final class ApocalypseHydra extends CardImpl { public ApocalypseHydra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{X}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{R}{G}"); this.subtype.add(SubType.HYDRA); this.power = new MageInt(0); @@ -46,7 +46,7 @@ public final class ApocalypseHydra extends CardImpl { this.addAbility(ability); } - public ApocalypseHydra(final ApocalypseHydra card) { + private ApocalypseHydra(final ApocalypseHydra card) { super(card); } @@ -63,28 +63,29 @@ class ApocalypseHydraEffect extends OneShotEffect { staticText = "with X +1/+1 counters on it. If X is 5 or more, it enters the battlefield with an additional X +1/+1 counters on it"; } - ApocalypseHydraEffect(final ApocalypseHydraEffect effect) { + private ApocalypseHydraEffect(final ApocalypseHydraEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanentEntering(source.getSourceId()); - if (permanent != null) { - SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (spellAbility != null - && spellAbility.getSourceId().equals(source.getSourceId()) - && permanent.getZoneChangeCounter(game) == spellAbility.getSourceObjectZoneChangeCounter()) { - int amount = spellAbility.getManaCostsToPay().getX(); - if (amount > 0) { - if (amount < 5) { - permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); - } else { - permanent.addCounters(CounterType.P1P1.createInstance(amount * 2), source, game); - } - } + if (permanent == null) { + return false; + } + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility == null + || !spellAbility.getSourceId().equals(source.getSourceId()) + || permanent.getZoneChangeCounter(game) != spellAbility.getSourceObjectZoneChangeCounter()) { + return false; + } + int amount = spellAbility.getManaCostsToPay().getX(); + if (amount > 0) { + if (amount < 5) { + permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); + } else { + permanent.addCounters(CounterType.P1P1.createInstance(amount * 2), source, game); } - return true; } return true; } diff --git a/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java b/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java index 97bf7f87a6b..a4cbd66ee7a 100644 --- a/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java +++ b/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java @@ -27,7 +27,7 @@ public final class ApothecaryGeist extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Elf"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.SPIRIT)); } diff --git a/Mage.Sets/src/mage/cards/a/AppealAuthority.java b/Mage.Sets/src/mage/cards/a/AppealAuthority.java index 0405aca0f8b..2a66436ed4f 100644 --- a/Mage.Sets/src/mage/cards/a/AppealAuthority.java +++ b/Mage.Sets/src/mage/cards/a/AppealAuthority.java @@ -43,7 +43,7 @@ public final class AppealAuthority extends SplitCard { // Authority // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Tap up to two target creatures your opponents control. Creatures you control gain vigilance until end of turn. getRightHalfCard().getSpellAbility().addEffect(new TapTargetEffect()); FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponents control"); diff --git a/Mage.Sets/src/mage/cards/a/AppliedBiomancy.java b/Mage.Sets/src/mage/cards/a/AppliedBiomancy.java new file mode 100644 index 00000000000..3cd408f094c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AppliedBiomancy.java @@ -0,0 +1,43 @@ +package mage.cards.a; + +import mage.abilities.Mode; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AppliedBiomancy extends CardImpl { + + public AppliedBiomancy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}{U}"); + + // Choose one or both — + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(2); + + // • Target creature gets +1/+1 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 1)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // • Return target creature to its owner's hand. + Mode mode = new Mode(new ReturnToHandTargetEffect()); + mode.addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addMode(mode); + } + + private AppliedBiomancy(final AppliedBiomancy card) { + super(card); + } + + @Override + public AppliedBiomancy copy() { + return new AppliedBiomancy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java index 574c2ce7b7c..235118e8b3c 100644 --- a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java +++ b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java @@ -65,7 +65,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect { Spell spell = game.getStack().getSpell(source.getSourceId()); if (controller != null && spell != null) { ApproachOfTheSecondSunWatcher watcher - = (ApproachOfTheSecondSunWatcher) game.getState().getWatchers().get(ApproachOfTheSecondSunWatcher.class.getSimpleName()); + = game.getState().getWatcher(ApproachOfTheSecondSunWatcher.class); if (watcher != null && !spell.isCopy() && watcher.getApproachesCast(controller.getId()) > 1 diff --git a/Mage.Sets/src/mage/cards/a/AquamorphEntity.java b/Mage.Sets/src/mage/cards/a/AquamorphEntity.java index 1ab44d76a07..637577aca2e 100644 --- a/Mage.Sets/src/mage/cards/a/AquamorphEntity.java +++ b/Mage.Sets/src/mage/cards/a/AquamorphEntity.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -21,8 +20,9 @@ import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AquamorphEntity extends CardImpl { @@ -42,7 +42,7 @@ public final class AquamorphEntity extends CardImpl { this.addAbility(new MorphAbility(this, new ManaCostsImpl("{2}{U}"))); } - public AquamorphEntity(final AquamorphEntity card) { + private AquamorphEntity(final AquamorphEntity card) { super(card); } @@ -57,12 +57,12 @@ class AquamorphEntityReplacementEffect extends ReplacementEffectImpl { private static final String choice51 = "a 5/1 creature"; private static final String choice15 = "a 1/5 creature"; - public AquamorphEntityReplacementEffect() { + AquamorphEntityReplacementEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); staticText = "as {this} enters the battlefield or is turned face up, it becomes your choice of 5/1 or 1/5"; } - public AquamorphEntityReplacementEffect(AquamorphEntityReplacementEffect effect) { + private AquamorphEntityReplacementEffect(AquamorphEntityReplacementEffect effect) { super(effect); } @@ -103,34 +103,32 @@ class AquamorphEntityReplacementEffect extends ReplacementEffectImpl { } else { permanent = game.getPermanent(event.getTargetId()); } - if (permanent != null) { - Choice choice = new ChoiceImpl(true); - choice.setMessage("Choose what the creature becomes to"); - choice.getChoices().add(choice51); - choice.getChoices().add(choice15); - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (!controller.choose(Outcome.Neutral, choice, game)) { - discard(); - return false; - } - } - int power = 0; - int toughness = 0; - switch (choice.getChoice()) { - case choice51: - power = 5; - toughness = 1; - break; - case choice15: - power = 1; - toughness = 5; - break; - } - game.addEffect(new SetPowerToughnessSourceEffect(power, toughness, Duration.Custom, SubLayer.SetPT_7b), source); + if (permanent == null) { + return false; } - return false; - + Choice choice = new ChoiceImpl(true); + choice.setMessage("Choose what the creature becomes to"); + choice.getChoices().add(choice51); + choice.getChoices().add(choice15); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && !controller.choose(Outcome.Neutral, choice, game)) { + discard(); + return false; + } + int power = 0; + int toughness = 0; + switch (choice.getChoice()) { + case choice51: + power = 5; + toughness = 1; + break; + case choice15: + power = 1; + toughness = 5; + break; + } + game.addEffect(new SetPowerToughnessSourceEffect(power, toughness, Duration.Custom, SubLayer.SetPT_7b), source); + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java b/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java index 3d5fca4ea89..7a1ef89b36b 100644 --- a/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java +++ b/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java @@ -39,7 +39,7 @@ public final class ArachnusSpinner extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SPIDER)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ArachnusSpinner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java b/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java index 9eb4e17736c..c0b90860417 100644 --- a/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java +++ b/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java @@ -41,10 +41,10 @@ public final class ArahboRoarOfTheWorld extends CardImpl { static { filter.add(new SubtypePredicate(SubType.CAT)); filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter2.add(new SubtypePredicate(SubType.CAT)); filter2.add(new ControllerPredicate(TargetController.YOU)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public ArahboRoarOfTheWorld(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/ArashiTheSkyAsunder.java b/Mage.Sets/src/mage/cards/a/ArashiTheSkyAsunder.java index 7a91c68a674..e474a02af84 100644 --- a/Mage.Sets/src/mage/cards/a/ArashiTheSkyAsunder.java +++ b/Mage.Sets/src/mage/cards/a/ArashiTheSkyAsunder.java @@ -43,13 +43,13 @@ public final class ArashiTheSkyAsunder extends CardImpl { this.toughness = new MageInt(5); // {X}{G}, {tap}: Arashi, the Sky Asunder deals X damage to target creature with flying. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{G}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{G}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Channel - {X}{G}{G}, Discard Arashi: Arashi deals X damage to each creature with flying. - this.addAbility(new ChannelAbility("{X}{G}{G}", new DamageAllEffect(new ManacostVariableValue(), filter))); + this.addAbility(new ChannelAbility("{X}{G}{G}", new DamageAllEffect(ManacostVariableValue.instance, filter))); } public ArashiTheSkyAsunder(final ArashiTheSkyAsunder card) { diff --git a/Mage.Sets/src/mage/cards/a/ArashinForemost.java b/Mage.Sets/src/mage/cards/a/ArashinForemost.java index fdee5a88fc4..2fbb32c68af 100644 --- a/Mage.Sets/src/mage/cards/a/ArashinForemost.java +++ b/Mage.Sets/src/mage/cards/a/ArashinForemost.java @@ -27,7 +27,7 @@ public final class ArashinForemost extends CardImpl { static { filter.add(new SubtypePredicate(SubType.WARRIOR)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ArashinForemost(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/ArashinWarBeast.java b/Mage.Sets/src/mage/cards/a/ArashinWarBeast.java index a59ec01c4d6..d6f18e479c8 100644 --- a/Mage.Sets/src/mage/cards/a/ArashinWarBeast.java +++ b/Mage.Sets/src/mage/cards/a/ArashinWarBeast.java @@ -51,7 +51,7 @@ class ArashinWarBeastTriggeredAbility extends TriggeredAbilityImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("one or more blockers"); static { - filter.add(new BlockingPredicate()); + filter.add(BlockingPredicate.instance); } boolean usedForCombatDamageStep; diff --git a/Mage.Sets/src/mage/cards/a/Arboria.java b/Mage.Sets/src/mage/cards/a/Arboria.java index 0cb05c3628a..6fa2572c54a 100644 --- a/Mage.Sets/src/mage/cards/a/Arboria.java +++ b/Mage.Sets/src/mage/cards/a/Arboria.java @@ -60,13 +60,13 @@ class ArboriaEffect extends RestrictionEffect { @Override public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game) { - CastSpellYourLastTurnWatcher watcher = (CastSpellYourLastTurnWatcher) game.getState().getWatchers().get(CastSpellYourLastTurnWatcher.class.getSimpleName()); + CastSpellYourLastTurnWatcher watcher = game.getState().getWatcher(CastSpellYourLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsCastOnPlayersTurn(defenderId) > 0) { return true; } PermanentsEnteredBattlefieldYourLastTurnWatcher watcher2 - = (PermanentsEnteredBattlefieldYourLastTurnWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldYourLastTurnWatcher.class.getSimpleName()); + = game.getState().getWatcher(PermanentsEnteredBattlefieldYourLastTurnWatcher.class); if (watcher2 != null && watcher2.getPermanentsEnteringOnPlayersLastTurn(game, defenderId) != null) { for (Permanent permanent : watcher2.getPermanentsEnteringOnPlayersLastTurn(game, defenderId)) { diff --git a/Mage.Sets/src/mage/cards/a/ArcadesSabboth.java b/Mage.Sets/src/mage/cards/a/ArcadesSabboth.java index 2cc2901e877..2737870ceed 100644 --- a/Mage.Sets/src/mage/cards/a/ArcadesSabboth.java +++ b/Mage.Sets/src/mage/cards/a/ArcadesSabboth.java @@ -29,8 +29,8 @@ public final class ArcadesSabboth extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); - filter.add(Predicates.not(new AttackingPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); + filter.add(Predicates.not(AttackingPredicate.instance)); } public ArcadesSabboth(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java b/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java index 028bc5bfcab..0dbc363239b 100644 --- a/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java +++ b/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java @@ -1,43 +1,36 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderAllEffect; +import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessEffect; import mage.abilities.keyword.DefenderAbility; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ArcadesTheStrategist extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature with defender"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(); static { filter.add(new AbilityPredicate(DefenderAbility.class)); + filter2.add(new AbilityPredicate(DefenderAbility.class)); } public ArcadesTheStrategist(UUID ownerId, CardSetInfo setInfo) { @@ -61,14 +54,14 @@ public final class ArcadesTheStrategist extends CardImpl { )); // Each creature you control with defender assigns combat damage equal to its toughness rather than its power and can attack as though it didn't have defender. - Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ArcadesTheStrategistCombatDamageRuleEffect()); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new CombatDamageByToughnessEffect(filter2, true).setText("Each creature you control with defender assigns combat damage equal to its toughness rather than its power")); ability.addEffect(new CanAttackAsThoughItDidntHaveDefenderAllEffect( Duration.WhileOnBattlefield, filter ).setText("and can attack as though it didn't have defender")); this.addAbility(ability); } - public ArcadesTheStrategist(final ArcadesTheStrategist card) { + private ArcadesTheStrategist(final ArcadesTheStrategist card) { super(card); } @@ -77,41 +70,3 @@ public final class ArcadesTheStrategist extends CardImpl { return new ArcadesTheStrategist(this); } } - -class ArcadesTheStrategistCombatDamageRuleEffect extends ContinuousEffectImpl { - - public ArcadesTheStrategistCombatDamageRuleEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Each creature you control with defender assigns combat damage equal to its toughness rather than its power"; - } - - public ArcadesTheStrategistCombatDamageRuleEffect(final ArcadesTheStrategistCombatDamageRuleEffect effect) { - super(effect); - } - - @Override - public ArcadesTheStrategistCombatDamageRuleEffect copy() { - return new ArcadesTheStrategistCombatDamageRuleEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - // Change the rule - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(source.getControllerId())); - filter.add(new AbilityPredicate(DefenderAbility.class)); - game.getCombat().setUseToughnessForDamage(true); - game.getCombat().addUseToughnessForDamageFilter(filter); - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} diff --git a/Mage.Sets/src/mage/cards/a/ArcboundCrusher.java b/Mage.Sets/src/mage/cards/a/ArcboundCrusher.java index 5e62cf8f8cf..f4d125a5540 100644 --- a/Mage.Sets/src/mage/cards/a/ArcboundCrusher.java +++ b/Mage.Sets/src/mage/cards/a/ArcboundCrusher.java @@ -25,7 +25,7 @@ public final class ArcboundCrusher extends CardImpl { private static final FilterPermanent filter = new FilterArtifactPermanent("another artifact"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ArcboundCrusher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java b/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java index 4d5bc436e43..e7f41f723fb 100644 --- a/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java +++ b/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java @@ -79,12 +79,12 @@ class ArchfiendOfDespairEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (controller != null && watcher != null) { for (UUID playerId : game.getOpponents(controller.getId())) { Player opponent = game.getPlayer(playerId); if (opponent != null) { - int lifeLost = watcher.getLiveLost(playerId); + int lifeLost = watcher.getLifeLost(playerId); if (lifeLost > 0) { opponent.loseLife(lifeLost, game, false); } diff --git a/Mage.Sets/src/mage/cards/a/ArchiveTrap.java b/Mage.Sets/src/mage/cards/a/ArchiveTrap.java index d0c3c88c159..4320b92011f 100644 --- a/Mage.Sets/src/mage/cards/a/ArchiveTrap.java +++ b/Mage.Sets/src/mage/cards/a/ArchiveTrap.java @@ -92,7 +92,7 @@ enum OpponentSearchesLibCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - ArchiveTrapWatcher watcher = (ArchiveTrapWatcher) game.getState().getWatchers().get(ArchiveTrapWatcher.class.getSimpleName()); + ArchiveTrapWatcher watcher = game.getState().getWatcher(ArchiveTrapWatcher.class); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && watcher != null) { for (UUID playerId : watcher.getPlayersSearchedLibrary()) { diff --git a/Mage.Sets/src/mage/cards/a/ArchmageAscension.java b/Mage.Sets/src/mage/cards/a/ArchmageAscension.java index 71f9e08a5db..efbcafce293 100644 --- a/Mage.Sets/src/mage/cards/a/ArchmageAscension.java +++ b/Mage.Sets/src/mage/cards/a/ArchmageAscension.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; @@ -22,8 +21,9 @@ import mage.players.Player; import mage.target.common.TargetCardInLibrary; import mage.watchers.common.CardsAmountDrawnThisTurnWatcher; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class ArchmageAscension extends CardImpl { @@ -74,7 +74,7 @@ class ArchmageAscensionTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent archmage = game.getPermanent(super.getSourceId()); CardsAmountDrawnThisTurnWatcher watcher - = (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.class.getSimpleName()); + = game.getState().getWatcher(CardsAmountDrawnThisTurnWatcher.class); return archmage != null && watcher != null && watcher.getAmountCardsDrawn(this.getControllerId()) >= 2; } diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java b/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java index ffc743472c6..fd4d1baa2af 100644 --- a/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java +++ b/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -9,26 +8,23 @@ import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.OneShotEffect; -import mage.constants.SubType; import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.VigilanceAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class ArchonOfValorsReach extends CardImpl { @@ -56,7 +52,7 @@ public final class ArchonOfValorsReach extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArchonOfValorsReachReplacementEffect())); } - public ArchonOfValorsReach(final ArchonOfValorsReach card) { + private ArchonOfValorsReach(final ArchonOfValorsReach card) { super(card); } @@ -68,14 +64,12 @@ public final class ArchonOfValorsReach extends CardImpl { class ArchonOfValorsReachChooseEffect extends OneShotEffect { - public static String VALUE_KEY = "_cardtype"; - - public ArchonOfValorsReachChooseEffect() { + ArchonOfValorsReachChooseEffect() { super(Outcome.Benefit); this.staticText = "choose artifact, enchantment, instant, sorcery, or planeswalker"; } - public ArchonOfValorsReachChooseEffect(final ArchonOfValorsReachChooseEffect effect) { + private ArchonOfValorsReachChooseEffect(final ArchonOfValorsReachChooseEffect effect) { super(effect); } @@ -96,7 +90,7 @@ class ArchonOfValorsReachChooseEffect extends OneShotEffect { if (controller.choose(Outcome.Neutral, choices, game)) { game.informPlayers(mageObject.getName() + ": Chosen card type is " + choices.getChoice()); System.out.println(mageObject.getId()); - game.getState().setValue(mageObject.getId().toString() + VALUE_KEY, choices.getChoice()); + game.getState().setValue(mageObject.getId().toString() + "_cardtype", choices.getChoice()); if (mageObject instanceof Permanent) { ((Permanent) mageObject).addInfo("chosen color", CardUtil.addToolTipMarkTags("Chosen card type: " + choices.getChoice()), game); } @@ -109,7 +103,7 @@ class ArchonOfValorsReachChooseEffect extends OneShotEffect { class ArchonOfValorsReachChoice extends ChoiceImpl { - public ArchonOfValorsReachChoice() { + ArchonOfValorsReachChoice() { super(true); this.choices.add("Artifact"); this.choices.add("Enchantment"); @@ -119,7 +113,7 @@ class ArchonOfValorsReachChoice extends ChoiceImpl { this.message = "Choose artifact, enchantment, instant, sorcery, or planeswalker"; } - public ArchonOfValorsReachChoice(final ArchonOfValorsReachChoice choice) { + private ArchonOfValorsReachChoice(final ArchonOfValorsReachChoice choice) { super(choice); } @@ -154,7 +148,7 @@ class ArchonOfValorsReachReplacementEffect extends ContinuousRuleModifyingEffect staticText = "Players can't cast spells of the chosen type"; } - ArchonOfValorsReachReplacementEffect(final ArchonOfValorsReachReplacementEffect effect) { + private ArchonOfValorsReachReplacementEffect(final ArchonOfValorsReachReplacementEffect effect) { super(effect); } diff --git a/Mage.Sets/src/mage/cards/a/ArchwayAngel.java b/Mage.Sets/src/mage/cards/a/ArchwayAngel.java new file mode 100644 index 00000000000..20da6285c53 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArchwayAngel.java @@ -0,0 +1,53 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class ArchwayAngel extends CardImpl { + + + private static final FilterPermanent filter = new FilterControlledPermanent("Gate you control"); + + static { + filter.add(new SubtypePredicate(SubType.GATE)); + } + + public ArchwayAngel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}"); + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Archway Angel enters the battlefield, you gain 2 life for each Gate you control. + Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(new PermanentsOnBattlefieldCount(filter, 2))); + this.addAbility(ability); + } + + public ArchwayAngel(final ArchwayAngel card) { + super(card); + } + + @Override + public ArchwayAngel copy() { + return new ArchwayAngel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArclightPhoenix.java b/Mage.Sets/src/mage/cards/a/ArclightPhoenix.java index 89fe19f8ee8..8301cc88c2b 100644 --- a/Mage.Sets/src/mage/cards/a/ArclightPhoenix.java +++ b/Mage.Sets/src/mage/cards/a/ArclightPhoenix.java @@ -72,8 +72,8 @@ enum ArclightPhoenixCondition implements Condition { @Override public boolean apply(Game game, Ability source) { ArclightPhoenixWatcher watcher - = (ArclightPhoenixWatcher) game.getState().getWatchers().get( - ArclightPhoenixWatcher.class.getSimpleName() + = game.getState().getWatcher( + ArclightPhoenixWatcher.class ); return watcher != null && watcher.getInstantSorceryCount(source.getControllerId()) > 2; } @@ -81,7 +81,7 @@ enum ArclightPhoenixCondition implements Condition { class ArclightPhoenixWatcher extends Watcher { - private final Map instantSorceryCount = new HashMap(); + private final Map instantSorceryCount = new HashMap<>(); public ArclightPhoenixWatcher() { super(ArclightPhoenixWatcher.class.getSimpleName(), WatcherScope.GAME); diff --git a/Mage.Sets/src/mage/cards/a/ArgothianEnchantress.java b/Mage.Sets/src/mage/cards/a/ArgothianEnchantress.java index 27cd7898b10..f6e8dd769a1 100644 --- a/Mage.Sets/src/mage/cards/a/ArgothianEnchantress.java +++ b/Mage.Sets/src/mage/cards/a/ArgothianEnchantress.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -13,8 +11,9 @@ import mage.constants.SubType; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.CardTypePredicate; +import java.util.UUID; + /** - * * @author Backfir3 */ public final class ArgothianEnchantress extends CardImpl { @@ -26,16 +25,18 @@ public final class ArgothianEnchantress extends CardImpl { } public ArgothianEnchantress(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.DRUID); this.power = new MageInt(0); this.toughness = new MageInt(1); + // Shroud this.addAbility(ShroudAbility.getInstance()); + // Whenever you cast an Enchantment spell, you draw a card. - this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1, "you"), filter, false)); } public ArgothianEnchantress(final ArgothianEnchantress card) { diff --git a/Mage.Sets/src/mage/cards/a/ArrestersAdmonition.java b/Mage.Sets/src/mage/cards/a/ArrestersAdmonition.java new file mode 100644 index 00000000000..27656402f5c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArrestersAdmonition.java @@ -0,0 +1,41 @@ +package mage.cards.a; + +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ArrestersAdmonition extends CardImpl { + + public ArrestersAdmonition(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); + + // Return target creature to its owner's hand. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Addendum — If you cast this spell during your main phase, draw a card. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), AddendumCondition.instance, + "
Addendum — If you cast this spell during your main phase, draw a card." + )); + } + + private ArrestersAdmonition(final ArrestersAdmonition card) { + super(card); + } + + @Override + public ArrestersAdmonition copy() { + return new ArrestersAdmonition(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArrestersZeal.java b/Mage.Sets/src/mage/cards/a/ArrestersZeal.java new file mode 100644 index 00000000000..9d488e442a4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArrestersZeal.java @@ -0,0 +1,70 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class ArrestersZeal extends CardImpl { + + public ArrestersZeal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + + // Target creature gets +2/+2 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Addendum — If you cast this spell during your main phase, that creature gains flying until end of turn. + this.getSpellAbility().addEffect(new ArrestersZealEffect()); + } + + public ArrestersZeal(final ArrestersZeal card) { + super(card); + } + + @Override + public ArrestersZeal copy() { + return new ArrestersZeal(this); + } +} + +class ArrestersZealEffect extends OneShotEffect { + + ArrestersZealEffect() { + super(Outcome.Benefit); + staticText = "
Addendum — If you cast this spell during your main phase, that creature gains flying until end of turn."; + } + + private ArrestersZealEffect(final ArrestersZealEffect effect) { + super(effect); + } + + @Override + public ArrestersZealEffect copy() { + return new ArrestersZealEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!AddendumCondition.instance.apply(game, source)) { + return false; + } + game.addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArtifactMutation.java b/Mage.Sets/src/mage/cards/a/ArtifactMutation.java index 2aaa2ef0272..43c0240f8e0 100644 --- a/Mage.Sets/src/mage/cards/a/ArtifactMutation.java +++ b/Mage.Sets/src/mage/cards/a/ArtifactMutation.java @@ -25,7 +25,7 @@ public final class ArtifactMutation extends CardImpl { this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); this.getSpellAbility().addTarget(new TargetArtifactPermanent()); // create X 1/1 green Saproling creature tokens, where X is that artifact's converted mana cost. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance)); } public ArtifactMutation(final ArtifactMutation card) { diff --git a/Mage.Sets/src/mage/cards/a/ArtificersAssistant.java b/Mage.Sets/src/mage/cards/a/ArtificersAssistant.java index d8c5d76f4fa..2a610e18b0e 100644 --- a/Mage.Sets/src/mage/cards/a/ArtificersAssistant.java +++ b/Mage.Sets/src/mage/cards/a/ArtificersAssistant.java @@ -22,7 +22,7 @@ public final class ArtificersAssistant extends CardImpl { private static final FilterSpell filter = new FilterSpell("a historic spell"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public ArtificersAssistant(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java b/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java index 86ad83f7f44..b260e580119 100644 --- a/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java +++ b/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java @@ -80,7 +80,7 @@ class AryelTapXTargetCost extends VariableCostImpl { static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Knights you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.KNIGHT)); } diff --git a/Mage.Sets/src/mage/cards/a/AsForetold.java b/Mage.Sets/src/mage/cards/a/AsForetold.java index f27e6900ebe..01dc7cb5670 100644 --- a/Mage.Sets/src/mage/cards/a/AsForetold.java +++ b/Mage.Sets/src/mage/cards/a/AsForetold.java @@ -91,17 +91,17 @@ class SpellWithManaCostLessThanOrEqualToCondition implements Condition { class AsForetoldAlternativeCost extends AlternativeCostSourceAbility { private UUID sourceAsForetold; - boolean activated; + private boolean wasActivated; AsForetoldAlternativeCost(UUID sourceAsForetold, int timeCounters) { super(new ManaCostsImpl("{0}"), new SpellWithManaCostLessThanOrEqualToCondition(timeCounters)); this.sourceAsForetold = sourceAsForetold; } - AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) { + private AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) { super(ability); this.sourceAsForetold = ability.sourceAsForetold; - this.activated = ability.activated; + this.wasActivated = ability.wasActivated; } @Override @@ -116,19 +116,18 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility { if (controller != null && asForetold != null) { if (controller.chooseUse(Outcome.Neutral, "Do you wish to use " + asForetold.getLogName() + " to pay the alternative cost ?", ability, game)) { - activated = super.askToActivateAlternativeCosts(ability, game); - if (activated) { + wasActivated = super.askToActivateAlternativeCosts(ability, game); + if (wasActivated) { // Get the watcher AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher - = (AsForetoldAltCostUsedWatcher) game.getState().getWatchers() - .get("asForetoldAltCostUsedWatcher", sourceAsForetold); + = game.getState().getWatcher(AsForetoldAltCostUsedWatcher.class, sourceAsForetold); // Mark as used asForetoldAltCostUsedWatcher.markUsedThisTurn(); } } } - return activated; + return wasActivated; } } @@ -161,8 +160,8 @@ class AsForetoldAddAltCostEffect extends ContinuousEffectImpl { if (sourcePermanent != null) { // Get the watcher AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher - = (AsForetoldAltCostUsedWatcher) game.getState().getWatchers() - .get("asForetoldAltCostUsedWatcher", sourcePermanent.getId()); + = game.getState().getWatcher( + AsForetoldAltCostUsedWatcher.class, sourcePermanent.getId()); // If we haven't used it yet this turn, give the option of using the zero alternative cost if (!asForetoldAltCostUsedWatcher.hasBeenUsedThisTurn()) { diff --git a/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java b/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java index 55f6c44791d..050b2493a30 100644 --- a/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java +++ b/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java @@ -27,7 +27,7 @@ public final class AshenSkinZubera extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(new ZuberasDiedDynamicValue())); + Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(ZuberasDiedDynamicValue.instance)); ability.addTarget(new TargetOpponent()); this.addAbility(ability, new ZuberasDiedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/a/AshenmoorCohort.java b/Mage.Sets/src/mage/cards/a/AshenmoorCohort.java index 8609bb3fa8d..c791c256806 100644 --- a/Mage.Sets/src/mage/cards/a/AshenmoorCohort.java +++ b/Mage.Sets/src/mage/cards/a/AshenmoorCohort.java @@ -29,7 +29,7 @@ public final class AshenmoorCohort extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.BLACK)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private static final String rule = "Ashenmoor Cohort gets +1/+1 as long as you control another black creature"; diff --git a/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java b/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java index 60cb57bd4f0..7fa11e14739 100644 --- a/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java +++ b/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java @@ -95,7 +95,7 @@ class AsmiraHolyAvengerDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - AsmiraHolyAvengerWatcher watcher = (AsmiraHolyAvengerWatcher) game.getState().getWatchers().get(AsmiraHolyAvengerWatcher.class.getSimpleName(), sourceAbility.getControllerId()); + AsmiraHolyAvengerWatcher watcher = game.getState().getWatcher(AsmiraHolyAvengerWatcher.class, sourceAbility.getControllerId()); if (watcher != null) { return watcher.getCreaturesCount(); } diff --git a/Mage.Sets/src/mage/cards/a/Asphyxiate.java b/Mage.Sets/src/mage/cards/a/Asphyxiate.java index 030206e5790..d5275dc2966 100644 --- a/Mage.Sets/src/mage/cards/a/Asphyxiate.java +++ b/Mage.Sets/src/mage/cards/a/Asphyxiate.java @@ -20,7 +20,7 @@ public final class Asphyxiate extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Asphyxiate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/Assassinate.java b/Mage.Sets/src/mage/cards/a/Assassinate.java index 891a186397e..47355573df1 100644 --- a/Mage.Sets/src/mage/cards/a/Assassinate.java +++ b/Mage.Sets/src/mage/cards/a/Assassinate.java @@ -20,7 +20,7 @@ public final class Assassinate extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public Assassinate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AssassinsBlade.java b/Mage.Sets/src/mage/cards/a/AssassinsBlade.java index fe2b98e641a..6f530833e28 100644 --- a/Mage.Sets/src/mage/cards/a/AssassinsBlade.java +++ b/Mage.Sets/src/mage/cards/a/AssassinsBlade.java @@ -29,7 +29,7 @@ public final class AssassinsBlade extends CardImpl { static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public AssassinsBlade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AssaultFormation.java b/Mage.Sets/src/mage/cards/a/AssaultFormation.java index 8895519cf38..645fec98a5e 100644 --- a/Mage.Sets/src/mage/cards/a/AssaultFormation.java +++ b/Mage.Sets/src/mage/cards/a/AssaultFormation.java @@ -1,26 +1,27 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderTargetEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AssaultFormation extends CardImpl { @@ -32,10 +33,10 @@ public final class AssaultFormation extends CardImpl { } public AssaultFormation(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); // Each creature you control assigns combat damage equal to its toughness rather than its power. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AssaultFormationCombatDamageRuleEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CombatDamageByToughnessEffect(StaticFilters.FILTER_PERMANENT_CREATURE, true))); // {G}: Target creature with defender can attack this turn as though it didn't have defender. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CanAttackAsThoughItDidntHaveDefenderTargetEffect(Duration.EndOfTurn), new ManaCostsImpl("{G}")); @@ -43,11 +44,11 @@ public final class AssaultFormation extends CardImpl { this.addAbility(ability); // {2}{G}: Creatures you control get +0/+1 until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0,1,Duration.EndOfTurn), new ManaCostsImpl("{2}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0, 1, Duration.EndOfTurn), new ManaCostsImpl("{2}{G}"))); } - public AssaultFormation(final AssaultFormation card) { + private AssaultFormation(final AssaultFormation card) { super(card); } @@ -56,40 +57,3 @@ public final class AssaultFormation extends CardImpl { return new AssaultFormation(this); } } - -class AssaultFormationCombatDamageRuleEffect extends ContinuousEffectImpl { - - public AssaultFormationCombatDamageRuleEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Each creature you control assigns combat damage equal to its toughness rather than its power"; - } - - public AssaultFormationCombatDamageRuleEffect(final AssaultFormationCombatDamageRuleEffect effect) { - super(effect); - } - - @Override - public AssaultFormationCombatDamageRuleEffect copy() { - return new AssaultFormationCombatDamageRuleEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - // Change the rule - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(source.getControllerId())); - game.getCombat().setUseToughnessForDamage(true); - game.getCombat().addUseToughnessForDamageFilter(filter); - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AsylumVisitor.java b/Mage.Sets/src/mage/cards/a/AsylumVisitor.java index bf7ea122ece..d31eb4c5705 100644 --- a/Mage.Sets/src/mage/cards/a/AsylumVisitor.java +++ b/Mage.Sets/src/mage/cards/a/AsylumVisitor.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -19,8 +17,9 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class AsylumVisitor extends CardImpl { @@ -33,11 +32,11 @@ public final class AsylumVisitor extends CardImpl { this.toughness = new MageInt(1); // At the beginning of each player's upkeep, if that player has no cards in hand, you draw a card and you lose 1 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.ANY, false), + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1, "you"), TargetController.ANY, false), new CardsInHandCondition(ComparisonType.EQUAL_TO, 0, null, TargetController.ACTIVE), "At the beginning of each player's upkeep, if that player has no cards in hand, you draw a card and you lose 1 life."); Effect effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AtalyaSamiteMaster.java b/Mage.Sets/src/mage/cards/a/AtalyaSamiteMaster.java index 386cb7f67d7..38c00a82ce0 100644 --- a/Mage.Sets/src/mage/cards/a/AtalyaSamiteMaster.java +++ b/Mage.Sets/src/mage/cards/a/AtalyaSamiteMaster.java @@ -41,7 +41,7 @@ public final class AtalyaSamiteMaster extends CardImpl { this.toughness = new MageInt(3); // {X}, {tap}: Choose one - Prevent the next X damage that would be dealt to target creature this turn; or you gain X life. Spend only white mana on X. - PreventDamageToTargetEffect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue()); + PreventDamageToTargetEffect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, ManacostVariableValue.instance); effect.setText("Prevent the next X damage that would be dealt to target creature this turn. Spend only white mana on X."); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); @@ -55,7 +55,7 @@ public final class AtalyaSamiteMaster extends CardImpl { // or you gain X life Mode mode = new Mode(); - mode.addEffect(new GainLifeEffect(new ManacostVariableValue()).setText("You gain X life. Spend only white mana on X.")); + mode.addEffect(new GainLifeEffect(ManacostVariableValue.instance).setText("You gain X life. Spend only white mana on X.")); ability.addMode(mode); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AthreosGodOfPassage.java b/Mage.Sets/src/mage/cards/a/AthreosGodOfPassage.java index fbd70641c0a..c2d40f3fb84 100644 --- a/Mage.Sets/src/mage/cards/a/AthreosGodOfPassage.java +++ b/Mage.Sets/src/mage/cards/a/AthreosGodOfPassage.java @@ -36,7 +36,7 @@ public final class AthreosGodOfPassage extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you own"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new OwnerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/a/Atogatog.java b/Mage.Sets/src/mage/cards/a/Atogatog.java index 107f7ccbbe1..0f17b1a8a08 100644 --- a/Mage.Sets/src/mage/cards/a/Atogatog.java +++ b/Mage.Sets/src/mage/cards/a/Atogatog.java @@ -37,7 +37,7 @@ public final class Atogatog extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(5); - DynamicValue xValue = new SacrificeCostCreaturesPower(); + DynamicValue xValue = SacrificeCostCreaturesPower.instance; // Sacrifice an Atog creature: Atogatog gets +X/+X until end of turn, where X is the sacrificed creature's power. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(xValue, xValue,Duration.EndOfTurn), diff --git a/Mage.Sets/src/mage/cards/a/AtzocanArcher.java b/Mage.Sets/src/mage/cards/a/AtzocanArcher.java index dfb3b1bbfd6..c07989dd627 100644 --- a/Mage.Sets/src/mage/cards/a/AtzocanArcher.java +++ b/Mage.Sets/src/mage/cards/a/AtzocanArcher.java @@ -25,7 +25,7 @@ public final class AtzocanArcher extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AtzocanArcher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AuraGraft.java b/Mage.Sets/src/mage/cards/a/AuraGraft.java index 414c76e5b1b..7e0293246cc 100644 --- a/Mage.Sets/src/mage/cards/a/AuraGraft.java +++ b/Mage.Sets/src/mage/cards/a/AuraGraft.java @@ -120,7 +120,7 @@ class MoveTargetAuraEffect extends OneShotEffect { } FilterPermanent filter = new FilterPermanent("another permanent " + enchantment.getLogName() + " can enchant"); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new PermanentCanBeAttachedToPredicate(enchantment)); Target target = new TargetPermanent(filter); target.setNotTarget(true); diff --git a/Mage.Sets/src/mage/cards/a/AuraMutation.java b/Mage.Sets/src/mage/cards/a/AuraMutation.java index 6586f22e633..7eaad0d970c 100644 --- a/Mage.Sets/src/mage/cards/a/AuraMutation.java +++ b/Mage.Sets/src/mage/cards/a/AuraMutation.java @@ -25,7 +25,7 @@ public final class AuraMutation extends CardImpl { this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetEnchantmentPermanent()); // create X 1/1 green Saproling creature tokens, where X is that enchantment's converted mana cost. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance)); } public AuraMutation(final AuraMutation card) { diff --git a/Mage.Sets/src/mage/cards/a/AuraOfDominion.java b/Mage.Sets/src/mage/cards/a/AuraOfDominion.java index e0956632a61..2f7be843a01 100644 --- a/Mage.Sets/src/mage/cards/a/AuraOfDominion.java +++ b/Mage.Sets/src/mage/cards/a/AuraOfDominion.java @@ -31,7 +31,7 @@ public final class AuraOfDominion extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } diff --git a/Mage.Sets/src/mage/cards/a/AureliasFury.java b/Mage.Sets/src/mage/cards/a/AureliasFury.java index 30fd2f477bd..01d4800511d 100644 --- a/Mage.Sets/src/mage/cards/a/AureliasFury.java +++ b/Mage.Sets/src/mage/cards/a/AureliasFury.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.*; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; @@ -27,6 +26,10 @@ import mage.target.common.TargetAnyTargetAmount; import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * GATECRASH FAQ 11.01.2013 *

@@ -59,7 +62,7 @@ public final class AureliasFury extends CardImpl { // Aurelia's Fury deals X damage divided as you choose among any number of target creatures and/or players. // Tap each creature dealt damage this way. Players dealt damage this way can't cast noncreature spells this turn. - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new DamageMultiEffect(xValue)); this.getSpellAbility().addEffect(new AureliasFuryEffect()); this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue)); @@ -67,7 +70,7 @@ public final class AureliasFury extends CardImpl { } - public AureliasFury(final AureliasFury card) { + private AureliasFury(final AureliasFury card) { super(card); } @@ -79,12 +82,12 @@ public final class AureliasFury extends CardImpl { class AureliasFuryEffect extends OneShotEffect { - public AureliasFuryEffect() { + AureliasFuryEffect() { super(Outcome.Benefit); this.staticText = "Tap each creature dealt damage this way. Players dealt damage this way can't cast noncreature spells this turn"; } - public AureliasFuryEffect(final AureliasFuryEffect effect) { + private AureliasFuryEffect(final AureliasFuryEffect effect) { super(effect); } @@ -95,15 +98,15 @@ class AureliasFuryEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - AureliasFuryDamagedByWatcher watcher = (AureliasFuryDamagedByWatcher) game.getState().getWatchers().get(AureliasFuryDamagedByWatcher.class.getSimpleName(), source.getSourceId()); + AureliasFuryDamagedByWatcher watcher = game.getState().getWatcher(AureliasFuryDamagedByWatcher.class, source.getSourceId()); if (watcher != null) { - for (UUID creatureId : watcher.damagedCreatures) { + for (UUID creatureId : watcher.getDamagedCreatures()) { Permanent permanent = game.getPermanent(creatureId); if (permanent != null) { permanent.tap(game); } } - for (UUID playerId : watcher.damagedPlayers) { + for (UUID playerId : watcher.getDamagedPlayers()) { ContinuousEffect effect = new AureliasFuryCantCastEffect(); effect.setTargetPointer(new FixedTarget(playerId)); game.addEffect(effect, source); @@ -117,12 +120,12 @@ class AureliasFuryEffect extends OneShotEffect { class AureliasFuryCantCastEffect extends ContinuousRuleModifyingEffectImpl { - public AureliasFuryCantCastEffect() { + AureliasFuryCantCastEffect() { super(Duration.EndOfTurn, Outcome.Benefit); staticText = "Players dealt damage this way can't cast noncreature spells this turn"; } - public AureliasFuryCantCastEffect(final AureliasFuryCantCastEffect effect) { + private AureliasFuryCantCastEffect(final AureliasFuryCantCastEffect effect) { super(effect); } @@ -165,14 +168,14 @@ class AureliasFuryCantCastEffect extends ContinuousRuleModifyingEffectImpl { class AureliasFuryDamagedByWatcher extends Watcher { - public Set damagedCreatures = new HashSet<>(); - public Set damagedPlayers = new HashSet<>(); + private final Set damagedCreatures = new HashSet<>(); + private final Set damagedPlayers = new HashSet<>(); - public AureliasFuryDamagedByWatcher() { + AureliasFuryDamagedByWatcher() { super(AureliasFuryDamagedByWatcher.class.getSimpleName(), WatcherScope.CARD); } - public AureliasFuryDamagedByWatcher(final AureliasFuryDamagedByWatcher watcher) { + private AureliasFuryDamagedByWatcher(final AureliasFuryDamagedByWatcher watcher) { super(watcher); this.damagedCreatures.addAll(watcher.damagedCreatures); this.damagedPlayers.addAll(watcher.damagedPlayers); @@ -210,4 +213,11 @@ class AureliasFuryDamagedByWatcher extends Watcher { damagedPlayers.clear(); } + Set getDamagedCreatures() { + return damagedCreatures; + } + + Set getDamagedPlayers() { + return damagedPlayers; + } } diff --git a/Mage.Sets/src/mage/cards/a/AuriokChampion.java b/Mage.Sets/src/mage/cards/a/AuriokChampion.java index 4b0fa72273e..6bb9d6e8fea 100644 --- a/Mage.Sets/src/mage/cards/a/AuriokChampion.java +++ b/Mage.Sets/src/mage/cards/a/AuriokChampion.java @@ -24,7 +24,7 @@ public final class AuriokChampion extends CardImpl { private static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AuriokChampion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/Aurochs.java b/Mage.Sets/src/mage/cards/a/Aurochs.java index d1b68781a73..ddd1acbe40a 100644 --- a/Mage.Sets/src/mage/cards/a/Aurochs.java +++ b/Mage.Sets/src/mage/cards/a/Aurochs.java @@ -27,7 +27,7 @@ public final class Aurochs extends CardImpl { static { filter1.add(new SubtypePredicate(SubType.AUROCHS)); - filter1.add(new AnotherPredicate()); + filter1.add(AnotherPredicate.instance); } public Aurochs(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AurochsHerd.java b/Mage.Sets/src/mage/cards/a/AurochsHerd.java index ab0b6b6ef20..62223e8f2ef 100644 --- a/Mage.Sets/src/mage/cards/a/AurochsHerd.java +++ b/Mage.Sets/src/mage/cards/a/AurochsHerd.java @@ -33,7 +33,7 @@ public final class AurochsHerd extends CardImpl { static { filter1.add(new SubtypePredicate(SubType.AUROCHS)); filter2.add(new SubtypePredicate(SubType.AUROCHS)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public AurochsHerd(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AuroraChampion.java b/Mage.Sets/src/mage/cards/a/AuroraChampion.java index 365bb5f82ec..b4932d81b25 100644 --- a/Mage.Sets/src/mage/cards/a/AuroraChampion.java +++ b/Mage.Sets/src/mage/cards/a/AuroraChampion.java @@ -25,7 +25,7 @@ public final class AuroraChampion extends CardImpl { private static final FilterTeamPermanent filter = new FilterTeamPermanent(SubType.WARRIOR, "another Warrior"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AuroraChampion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java b/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java index b09ac13a395..3ec0575da4f 100644 --- a/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java +++ b/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java @@ -1,8 +1,5 @@ - package mage.cards.a; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; @@ -27,8 +24,10 @@ import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; +import java.util.List; +import java.util.UUID; + /** - * * @author Styxo */ public final class AurraSingBaneOfJedi extends CardImpl { @@ -39,17 +38,17 @@ public final class AurraSingBaneOfJedi extends CardImpl { this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); - // +1:You may have {this} deal 2 damage to target creature. If you don't, {this} deals 1 damage to you. + // +1: You may have {this} deal 2 damage to target creature. If you don't, {this} deals 1 damage to you. Ability ability = new LoyaltyAbility(new AurraSingBaneOfJediEffect(), +1); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); - // -4:Target player gets an emblem wiht "Whenever a nontoken creature you control leave the battlefied, discard a card.". + // -4: Target player gets an emblem wiht "Whenever a nontoken creature you control leave the battlefied, discard a card.". ability = new LoyaltyAbility(new GetEmblemTargetPlayerEffect(new AurraSingBaneOfJediEmblem()), -4); ability.addTarget(new TargetPlayer()); this.addAbility(ability); - // -6:Each player discards their hand and sacrificies all creatures he or she controls. Each player's life total becomes 1." + // -6: Each player discards their hand and sacrificies all creatures he or she controls. Each player's life total becomes 1." ability = new LoyaltyAbility(new DiscardHandAllEffect(), -6); ability.addEffect(new SacrificeAllEffect()); Effect effect = new SetPlayerLifeAllEffect(1, TargetController.ANY); diff --git a/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java b/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java index ec6d5355c2e..acc437a5726 100644 --- a/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java +++ b/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java @@ -33,7 +33,7 @@ public final class AvacynGuardianAngel extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AvacynGuardianAngel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AvacynThePurifier.java b/Mage.Sets/src/mage/cards/a/AvacynThePurifier.java index e3ff29da23e..47dfa768b66 100644 --- a/Mage.Sets/src/mage/cards/a/AvacynThePurifier.java +++ b/Mage.Sets/src/mage/cards/a/AvacynThePurifier.java @@ -107,7 +107,7 @@ class AvacynThePurifierEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature"); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); for (Permanent permanent : permanents) { permanent.damage(3, source.getSourceId(), game, false, true); diff --git a/Mage.Sets/src/mage/cards/a/Avalanche.java b/Mage.Sets/src/mage/cards/a/Avalanche.java index ed9bbbeb213..703bd8f95a3 100644 --- a/Mage.Sets/src/mage/cards/a/Avalanche.java +++ b/Mage.Sets/src/mage/cards/a/Avalanche.java @@ -1,40 +1,32 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; import mage.game.Game; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class Avalanche extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent("snow lands"); - public Avalanche(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{2}{R}{R}"); // Destroy X target snow lands. this.getSpellAbility().addEffect(new DestroyTargetEffect("Destroy X target snow lands")); - this.getSpellAbility().addTarget(new TargetPermanent(filter)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetPermanent(xValue, xValue, filter, false)); - } + this.getSpellAbility().setTargetAdjuster(AvalancheAdjuster.instance); } public Avalanche(final Avalanche card) { @@ -46,3 +38,19 @@ public final class Avalanche extends CardImpl { return new Avalanche(this); } } + +enum AvalancheAdjuster implements TargetAdjuster { + instance; + private static final FilterPermanent filter = new FilterLandPermanent("snow lands"); + + static { + filter.add(new SupertypePredicate(SuperType.SNOW)); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetPermanent(xValue, xValue, filter, false)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfTheResolute.java b/Mage.Sets/src/mage/cards/a/AvatarOfTheResolute.java index 1265256eb77..987d7a0122a 100644 --- a/Mage.Sets/src/mage/cards/a/AvatarOfTheResolute.java +++ b/Mage.Sets/src/mage/cards/a/AvatarOfTheResolute.java @@ -28,7 +28,7 @@ public final class AvatarOfTheResolute extends CardImpl { static { filter.add(new CounterPredicate(CounterType.P1P1)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AvatarOfTheResolute(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java b/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java index 52e9da2dc82..551df4191a8 100644 --- a/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java +++ b/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java @@ -33,7 +33,7 @@ public final class AvenSoulgazer extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public AvenSoulgazer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AvengingArrow.java b/Mage.Sets/src/mage/cards/a/AvengingArrow.java index eb277e62ce9..e04ff459b60 100644 --- a/Mage.Sets/src/mage/cards/a/AvengingArrow.java +++ b/Mage.Sets/src/mage/cards/a/AvengingArrow.java @@ -53,7 +53,7 @@ class AvengingArrowTarget extends TargetPermanent { @Override public boolean canTarget(UUID id, Ability source, Game game) { - SourceDidDamageWatcher watcher = (SourceDidDamageWatcher) game.getState().getWatchers().get(SourceDidDamageWatcher.class.getSimpleName()); + SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); if (watcher != null) { if (watcher.damageSources.contains(id)) { return super.canTarget(id, source, game); @@ -66,7 +66,7 @@ class AvengingArrowTarget extends TargetPermanent { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); Set possibleTargets = new HashSet<>(); - SourceDidDamageWatcher watcher = (SourceDidDamageWatcher) game.getState().getWatchers().get(SourceDidDamageWatcher.class.getSimpleName()); + SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); if (watcher != null) { for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage.Sets/src/mage/cards/a/AviaryMechanic.java b/Mage.Sets/src/mage/cards/a/AviaryMechanic.java index 37acc4e67e9..59a64bd2345 100644 --- a/Mage.Sets/src/mage/cards/a/AviaryMechanic.java +++ b/Mage.Sets/src/mage/cards/a/AviaryMechanic.java @@ -21,7 +21,7 @@ public final class AviaryMechanic extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another permanent you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public AviaryMechanic(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AwakenTheErstwhile.java b/Mage.Sets/src/mage/cards/a/AwakenTheErstwhile.java new file mode 100644 index 00000000000..75403136dc9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AwakenTheErstwhile.java @@ -0,0 +1,85 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.ZombieToken; +import mage.players.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class AwakenTheErstwhile extends CardImpl { + + public AwakenTheErstwhile(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}"); + + // Each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens. + this.getSpellAbility().addEffect(new AwakenTheErstwhileEffect()); + } + + public AwakenTheErstwhile(final AwakenTheErstwhile card) { + super(card); + } + + @Override + public AwakenTheErstwhile copy() { + return new AwakenTheErstwhile(this); + } +} + +class AwakenTheErstwhileEffect extends OneShotEffect { + + public AwakenTheErstwhileEffect() { + super(Outcome.Detriment); + this.staticText = "each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens"; + } + + public AwakenTheErstwhileEffect(final AwakenTheErstwhileEffect effect) { + super(effect); + } + + @Override + public AwakenTheErstwhileEffect copy() { + return new AwakenTheErstwhileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + // discard hands + Map cardsAmount = new HashMap<>(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int cardsInHand = player.getHand().size(); + if (cardsInHand > 0) { + player.discard(cardsInHand, false, source, game); + cardsAmount.put(playerId, cardsInHand); + } + } + } + + // create tokens + for (UUID playerId : cardsAmount.keySet()) { + Player player = game.getPlayer(playerId); + int tokensCount = cardsAmount.get(playerId); + if (player != null && tokensCount > 0) { + new ZombieToken().putOntoBattlefield(tokensCount, game, source.getSourceId(), player.getId()); + } + } + + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/a/AweForTheGuilds.java b/Mage.Sets/src/mage/cards/a/AweForTheGuilds.java index f1569e4915a..4a0ee0ad5ff 100644 --- a/Mage.Sets/src/mage/cards/a/AweForTheGuilds.java +++ b/Mage.Sets/src/mage/cards/a/AweForTheGuilds.java @@ -22,7 +22,7 @@ public final class AweForTheGuilds extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Monocolored creatures"); static { - filter.add(Predicates.not(new MulticoloredPredicate())); + filter.add(Predicates.not(MulticoloredPredicate.instance)); } public AweForTheGuilds(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/a/AxebaneBeast.java b/Mage.Sets/src/mage/cards/a/AxebaneBeast.java new file mode 100644 index 00000000000..f620a5ff30a --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AxebaneBeast.java @@ -0,0 +1,32 @@ +package mage.cards.a; + +import java.util.UUID; + +import mage.MageInt; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * @author TheElk801 + */ +public final class AxebaneBeast extends CardImpl { + + public AxebaneBeast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + } + + private AxebaneBeast(final AxebaneBeast card) { + super(card); + } + + @Override + public AxebaneBeast copy() { + return new AxebaneBeast(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java b/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java index d552596e349..4e6c3c32821 100644 --- a/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java +++ b/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java @@ -45,7 +45,7 @@ public final class AyliEternalPilgrim extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // {1}, Sacrifice another creature: You gain life equal to the sacrificed creature's toughness. - Effect effect = new GainLifeEffect(new SacrificeCostCreaturesToughness()); + Effect effect = new GainLifeEffect(SacrificeCostCreaturesToughness.instance); effect.setText("You gain life equal to the sacrificed creature's toughness"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(1)); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE))); diff --git a/Mage.Sets/src/mage/cards/a/AzamiLadyOfScrolls.java b/Mage.Sets/src/mage/cards/a/AzamiLadyOfScrolls.java index 456b3bd39b4..0c3d861582f 100644 --- a/Mage.Sets/src/mage/cards/a/AzamiLadyOfScrolls.java +++ b/Mage.Sets/src/mage/cards/a/AzamiLadyOfScrolls.java @@ -27,7 +27,7 @@ public final class AzamiLadyOfScrolls extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Wizard you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.WIZARD)); } diff --git a/Mage.Sets/src/mage/cards/a/AzoriusKnightArbiter.java b/Mage.Sets/src/mage/cards/a/AzoriusKnightArbiter.java new file mode 100644 index 00000000000..11f763bf98d --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AzoriusKnightArbiter.java @@ -0,0 +1,41 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.keyword.CantBeBlockedSourceAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AzoriusKnightArbiter extends CardImpl { + + public AzoriusKnightArbiter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Azorius Knight-Arbiter can't be blocked. + this.addAbility(new CantBeBlockedSourceAbility()); + } + + private AzoriusKnightArbiter(final AzoriusKnightArbiter card) { + super(card); + } + + @Override + public AzoriusKnightArbiter copy() { + return new AzoriusKnightArbiter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AzoriusLocket.java b/Mage.Sets/src/mage/cards/a/AzoriusLocket.java new file mode 100644 index 00000000000..8f78a48347d --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AzoriusLocket.java @@ -0,0 +1,45 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class AzoriusLocket extends CardImpl { + + public AzoriusLocket(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {T}: Add {W} or {U}. + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlueManaAbility()); + + // {W/U}{W/U}{W/U}{W/U}, {T}, Sacrifice Azorius Locket: Draw two cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), new ManaCostsImpl<>("{W/U}{W/U}{W/U}{W/U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public AzoriusLocket(final AzoriusLocket card) { + super(card); + } + + @Override + public AzoriusLocket copy() { + return new AzoriusLocket(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AzoriusSkyguard.java b/Mage.Sets/src/mage/cards/a/AzoriusSkyguard.java new file mode 100644 index 00000000000..58cb054d70c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AzoriusSkyguard.java @@ -0,0 +1,47 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostOpponentsEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AzoriusSkyguard extends CardImpl { + + public AzoriusSkyguard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Creatures your opponents control get -1/-0. + this.addAbility(new SimpleStaticAbility(new BoostOpponentsEffect(-1, 0, Duration.WhileOnBattlefield))); + } + + private AzoriusSkyguard(final AzoriusSkyguard card) { + super(card); + } + + @Override + public AzoriusSkyguard copy() { + return new AzoriusSkyguard(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/Backlash.java b/Mage.Sets/src/mage/cards/b/Backlash.java index 274ab604164..b054f340c30 100644 --- a/Mage.Sets/src/mage/cards/b/Backlash.java +++ b/Mage.Sets/src/mage/cards/b/Backlash.java @@ -24,7 +24,7 @@ public final class Backlash extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Backlash(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BalduvianRage.java b/Mage.Sets/src/mage/cards/b/BalduvianRage.java index 832c748b7c4..9f3e910722f 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianRage.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianRage.java @@ -25,7 +25,7 @@ public final class BalduvianRage extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}"); // Target attacking creature gets +X/+0 until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterAttackingCreature())); // Draw a card at the beginning of the next turn's upkeep. diff --git a/Mage.Sets/src/mage/cards/b/BalduvianTradingPost.java b/Mage.Sets/src/mage/cards/b/BalduvianTradingPost.java index 9c4c948a5a5..d133e2483a8 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianTradingPost.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianTradingPost.java @@ -34,7 +34,7 @@ public final class BalduvianTradingPost extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MOUNTAIN)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public BalduvianTradingPost(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java index 1adf661c5c1..4a18b913d88 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java @@ -89,7 +89,7 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect { effect.apply(game, source); // Make blocked creatures unblocked - BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName()); + BlockedByOnlyOneCreatureThisCombatWatcher watcher = game.getState().getWatcher(BlockedByOnlyOneCreatureThisCombatWatcher.class); if (watcher != null) { Set combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId()); if (combatGroups != null) { diff --git a/Mage.Sets/src/mage/cards/b/BalefulForce.java b/Mage.Sets/src/mage/cards/b/BalefulForce.java index 09b09a0e70c..4107df58401 100644 --- a/Mage.Sets/src/mage/cards/b/BalefulForce.java +++ b/Mage.Sets/src/mage/cards/b/BalefulForce.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -14,24 +12,24 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BalefulForce extends CardImpl { public BalefulForce(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{B}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}{B}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(7); this.toughness = new MageInt(7); // At the beginning of each upkeep, you draw a card and you lose 1 life. - Ability ability = new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.ANY, false); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1, "you"), TargetController.ANY, false); Effect effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - ability.addEffect(effect); + ability.addEffect(effect.concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BallistaSquad.java b/Mage.Sets/src/mage/cards/b/BallistaSquad.java index 232a7b75f18..b52ad56e1d1 100644 --- a/Mage.Sets/src/mage/cards/b/BallistaSquad.java +++ b/Mage.Sets/src/mage/cards/b/BallistaSquad.java @@ -30,7 +30,7 @@ public final class BallistaSquad extends CardImpl { this.toughness = new MageInt(2); // {X}{W}, {T}: Ballista Squad deals X damage to target attacking or blocking creature. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{W}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{W}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetAttackingOrBlockingCreature()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BallynockCohort.java b/Mage.Sets/src/mage/cards/b/BallynockCohort.java index 564920405b7..e241fcec13a 100644 --- a/Mage.Sets/src/mage/cards/b/BallynockCohort.java +++ b/Mage.Sets/src/mage/cards/b/BallynockCohort.java @@ -32,7 +32,7 @@ public final class BallynockCohort extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private String rule = "{this} gets +1/+1 as long as you control another white creature"; diff --git a/Mage.Sets/src/mage/cards/b/BalothCageTrap.java b/Mage.Sets/src/mage/cards/b/BalothCageTrap.java index 9d419b79214..4c86becb5b9 100644 --- a/Mage.Sets/src/mage/cards/b/BalothCageTrap.java +++ b/Mage.Sets/src/mage/cards/b/BalothCageTrap.java @@ -50,7 +50,7 @@ enum BalothCageTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getSimpleName()); + PermanentsEnteredBattlefieldWatcher watcher = game.getState().getWatcher(PermanentsEnteredBattlefieldWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { List permanents = watcher.getThisTurnEnteringPermanents(opponentId); diff --git a/Mage.Sets/src/mage/cards/b/BalthorTheStout.java b/Mage.Sets/src/mage/cards/b/BalthorTheStout.java index ef768145d4d..1e280dd027f 100644 --- a/Mage.Sets/src/mage/cards/b/BalthorTheStout.java +++ b/Mage.Sets/src/mage/cards/b/BalthorTheStout.java @@ -28,7 +28,7 @@ public final class BalthorTheStout extends CardImpl { static { filter1.add(new SubtypePredicate(SubType.BARBARIAN)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); filter2.add(new SubtypePredicate(SubType.BARBARIAN)); } diff --git a/Mage.Sets/src/mage/cards/b/BaneOfTheLiving.java b/Mage.Sets/src/mage/cards/b/BaneOfTheLiving.java index e37a695bc91..a68033931f4 100644 --- a/Mage.Sets/src/mage/cards/b/BaneOfTheLiving.java +++ b/Mage.Sets/src/mage/cards/b/BaneOfTheLiving.java @@ -32,7 +32,7 @@ public final class BaneOfTheLiving extends CardImpl { // Morph {X}{B}{B} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{X}{B}{B}"))); // When Bane of the Living is turned face up, all creatures get -X/-X until end of turn. - DynamicValue morphX = new SignInversionDynamicValue(new MorphManacostVariableValue()); + DynamicValue morphX = new SignInversionDynamicValue(MorphManacostVariableValue.instance); this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new BoostAllEffect(morphX, morphX, Duration.EndOfTurn, new FilterCreaturePermanent("all creatures"), false, "", true))); } diff --git a/Mage.Sets/src/mage/cards/b/Banefire.java b/Mage.Sets/src/mage/cards/b/Banefire.java index 29d3a6a2fcc..b74cddb4a94 100644 --- a/Mage.Sets/src/mage/cards/b/Banefire.java +++ b/Mage.Sets/src/mage/cards/b/Banefire.java @@ -106,7 +106,7 @@ class BaneFireEffect extends OneShotEffect { class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl { - Condition condition = new testCondition(new ManacostVariableValue(), 5); + Condition condition = new testCondition(ManacostVariableValue.instance, 5); public BanefireCantCounterEffect() { super(Duration.WhileOnStack, Outcome.Benefit); diff --git a/Mage.Sets/src/mage/cards/b/BanefulOmen.java b/Mage.Sets/src/mage/cards/b/BanefulOmen.java index 9643aacd05d..31d22c9a48a 100644 --- a/Mage.Sets/src/mage/cards/b/BanefulOmen.java +++ b/Mage.Sets/src/mage/cards/b/BanefulOmen.java @@ -1,8 +1,6 @@ package mage.cards.b; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; @@ -15,15 +13,16 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import java.util.Set; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class BanefulOmen extends CardImpl { public BanefulOmen(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{B}{B}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}{B}{B}"); // At the beginning of your end step, you may reveal the top card of your library. If you do, each opponent loses life equal to that card's converted mana cost. this.addAbility(new BanefulOmenTriggeredAbility()); @@ -40,11 +39,11 @@ public final class BanefulOmen extends CardImpl { class BanefulOmenTriggeredAbility extends TriggeredAbilityImpl { - public BanefulOmenTriggeredAbility() { + BanefulOmenTriggeredAbility() { super(Zone.BATTLEFIELD, new BanefulOmenEffect(), true); } - public BanefulOmenTriggeredAbility(BanefulOmenTriggeredAbility ability) { + private BanefulOmenTriggeredAbility(BanefulOmenTriggeredAbility ability) { super(ability); } @@ -71,11 +70,11 @@ public final class BanefulOmen extends CardImpl { static class BanefulOmenEffect extends OneShotEffect { - public BanefulOmenEffect() { + BanefulOmenEffect() { super(Outcome.Benefit); } - public BanefulOmenEffect(final BanefulOmenEffect effect) { + private BanefulOmenEffect(final BanefulOmenEffect effect) { super(effect); } @@ -85,24 +84,26 @@ public final class BanefulOmen extends CardImpl { if (player == null) { return false; } - if (player.getLibrary().hasCards()) { - Card card = player.getLibrary().getFromTop(game); - Cards cards = new CardsImpl(); - cards.add(card); - player.revealCards("Baneful Omen", cards, game); + if (!player.getLibrary().hasCards()) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + Cards cards = new CardsImpl(); + cards.add(card); + player.revealCards("Baneful Omen", cards, game); - if (card != null) { - int loseLife = card.getConvertedManaCost(); - Set opponents = game.getOpponents(source.getControllerId()); - for (UUID opponentUuid : opponents) { - Player opponent = game.getPlayer(opponentUuid); - if (opponent != null) { - opponent.loseLife(loseLife, game, false); - } - } + if (card == null) { + return false; + } + int loseLife = card.getConvertedManaCost(); + Set opponents = game.getOpponents(source.getControllerId()); + for (UUID opponentUuid : opponents) { + Player opponent = game.getPlayer(opponentUuid); + if (opponent != null) { + opponent.loseLife(loseLife, game, false); } } - return false; + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/b/BankruptInBlood.java b/Mage.Sets/src/mage/cards/b/BankruptInBlood.java new file mode 100644 index 00000000000..f858051b679 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BankruptInBlood.java @@ -0,0 +1,35 @@ +package mage.cards.b; + +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BankruptInBlood extends CardImpl { + + public BankruptInBlood(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); + + // As an additional cost to cast this spell, sacrifice two creatures. + this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(2))); + + // Draw three cards. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(3)); + } + + private BankruptInBlood(final BankruptInBlood card) { + super(card); + } + + @Override + public BankruptInBlood copy() { + return new BankruptInBlood(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/Banshee.java b/Mage.Sets/src/mage/cards/b/Banshee.java index b2392191ad1..3d0b460a5d5 100644 --- a/Mage.Sets/src/mage/cards/b/Banshee.java +++ b/Mage.Sets/src/mage/cards/b/Banshee.java @@ -32,9 +32,9 @@ public final class Banshee extends CardImpl { this.toughness = new MageInt(1); // {X}, {T}: Banshee deals half X damage, rounded down, to any target, and half X damage, rounded up, to you. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new HalfValue(new ManacostVariableValue(), false)).setText("Banshee deals half X damage, rounded down, to any target,"), new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new HalfValue(ManacostVariableValue.instance, false)).setText("Banshee deals half X damage, rounded down, to any target,"), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); - ability.addEffect(new DamageControllerEffect(new HalfValue(new ManacostVariableValue(), true)).setText(" and half X damage, rounded up, to you")); + ability.addEffect(new DamageControllerEffect(new HalfValue(ManacostVariableValue.instance, true)).setText(" and half X damage, rounded up, to you")); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BantSureblade.java b/Mage.Sets/src/mage/cards/b/BantSureblade.java index 15c2410d1a1..e39241c04ed 100644 --- a/Mage.Sets/src/mage/cards/b/BantSureblade.java +++ b/Mage.Sets/src/mage/cards/b/BantSureblade.java @@ -29,8 +29,8 @@ public final class BantSureblade extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another multicolor permanent"); static { - filter.add(new MulticoloredPredicate()); - filter.add(new AnotherPredicate()); + filter.add(MulticoloredPredicate.instance); + filter.add(AnotherPredicate.instance); } public BantSureblade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BaronSengir.java b/Mage.Sets/src/mage/cards/b/BaronSengir.java index f69bada8d5e..41375fb1ce3 100644 --- a/Mage.Sets/src/mage/cards/b/BaronSengir.java +++ b/Mage.Sets/src/mage/cards/b/BaronSengir.java @@ -32,7 +32,7 @@ public final class BaronSengir extends CardImpl { static { filter.add(new SubtypePredicate(SubType.VAMPIRE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BaronSengir(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BarrageTyrant.java b/Mage.Sets/src/mage/cards/b/BarrageTyrant.java index 1c95a11f61e..8f4b20d1274 100644 --- a/Mage.Sets/src/mage/cards/b/BarrageTyrant.java +++ b/Mage.Sets/src/mage/cards/b/BarrageTyrant.java @@ -31,8 +31,8 @@ public final class BarrageTyrant extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another colorless creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public BarrageTyrant(UUID ownerId, CardSetInfo setInfo) { @@ -45,7 +45,7 @@ public final class BarrageTyrant extends CardImpl { this.addAbility(new DevoidAbility(this.color)); // {2}{R}, Sacrifice another colorless creature: Barrage Tyrant deals damage equal to the sacrificed creature's power to any target. - Effect effect = new DamageTargetEffect(new SacrificeCostCreaturesPower()); + Effect effect = new DamageTargetEffect(SacrificeCostCreaturesPower.instance); effect.setText("{this} deals damage equal to the sacrificed creature's power to any target"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}{R}")); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); diff --git a/Mage.Sets/src/mage/cards/b/BarrenGlory.java b/Mage.Sets/src/mage/cards/b/BarrenGlory.java index 78113c6343c..29ae7eb6666 100644 --- a/Mage.Sets/src/mage/cards/b/BarrenGlory.java +++ b/Mage.Sets/src/mage/cards/b/BarrenGlory.java @@ -24,7 +24,7 @@ public final class BarrenGlory extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BarrenGlory(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BartelRuneaxe.java b/Mage.Sets/src/mage/cards/b/BartelRuneaxe.java index a5ca949ea84..8c020d57cc4 100644 --- a/Mage.Sets/src/mage/cards/b/BartelRuneaxe.java +++ b/Mage.Sets/src/mage/cards/b/BartelRuneaxe.java @@ -81,7 +81,7 @@ class BartelRuneaxeEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); if (stackObject != null && event.getTargetId().equals(source.getSourceId())) { if (stackObject.hasSubtype(SubType.AURA, game)) { return true; diff --git a/Mage.Sets/src/mage/cards/b/BasilicaBellHaunt.java b/Mage.Sets/src/mage/cards/b/BasilicaBellHaunt.java new file mode 100644 index 00000000000..1fd93559398 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BasilicaBellHaunt.java @@ -0,0 +1,42 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BasilicaBellHaunt extends CardImpl { + + public BasilicaBellHaunt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}{B}{B}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When Basilica Bell-Haunt enters the battlefield, each opponent discards a card and you gain 3 life. + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT)); + ability.addEffect(new GainLifeEffect(3).setText("and you gain 3 life")); + this.addAbility(ability); + } + + private BasilicaBellHaunt(final BasilicaBellHaunt card) { + super(card); + } + + @Override + public BasilicaBellHaunt copy() { + return new BasilicaBellHaunt(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BastionProtector.java b/Mage.Sets/src/mage/cards/b/BastionProtector.java index 14844a9c4db..ba1fdaac309 100644 --- a/Mage.Sets/src/mage/cards/b/BastionProtector.java +++ b/Mage.Sets/src/mage/cards/b/BastionProtector.java @@ -27,7 +27,7 @@ public final class BastionProtector extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("Commander creatures"); static { - filter.add(new CommanderPredicate()); + filter.add(CommanderPredicate.instance); } public BastionProtector(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BattleAtTheBridge.java b/Mage.Sets/src/mage/cards/b/BattleAtTheBridge.java index b7d906149ef..6aced560b88 100644 --- a/Mage.Sets/src/mage/cards/b/BattleAtTheBridge.java +++ b/Mage.Sets/src/mage/cards/b/BattleAtTheBridge.java @@ -27,10 +27,10 @@ public final class BattleAtTheBridge extends CardImpl { addAbility(new ImproviseAbility()); // Target creature gets -X/-X until end of turn. You gain X life. - DynamicValue x = new SignInversionDynamicValue(new ManacostVariableValue()); + DynamicValue x = new SignInversionDynamicValue(ManacostVariableValue.instance); this.getSpellAbility().addEffect(new BoostTargetEffect(x, x, Duration.EndOfTurn, true)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new GainLifeEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new GainLifeEffect(ManacostVariableValue.instance)); } public BattleAtTheBridge(final BattleAtTheBridge card) { diff --git a/Mage.Sets/src/mage/cards/b/BattleScreech.java b/Mage.Sets/src/mage/cards/b/BattleScreech.java index 2fc92e6c6bf..2a9f3d72cdc 100644 --- a/Mage.Sets/src/mage/cards/b/BattleScreech.java +++ b/Mage.Sets/src/mage/cards/b/BattleScreech.java @@ -27,7 +27,7 @@ public final class BattleScreech extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public BattleScreech(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java b/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java index 1c94669e7c7..345086c7dfd 100644 --- a/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java +++ b/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java @@ -94,8 +94,4 @@ class BattletideAlchemistEffect extends PreventionEffectImpl { return event.getType() == EventType.DAMAGE_PLAYER; } - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return super.applies(event, source, game); - } } diff --git a/Mage.Sets/src/mage/cards/b/BazaarKrovod.java b/Mage.Sets/src/mage/cards/b/BazaarKrovod.java index 672dcfb1ec6..858ae9db6a1 100644 --- a/Mage.Sets/src/mage/cards/b/BazaarKrovod.java +++ b/Mage.Sets/src/mage/cards/b/BazaarKrovod.java @@ -28,7 +28,7 @@ public final class BazaarKrovod extends CardImpl { static final FilterAttackingCreature filter = new FilterAttackingCreature("another target attacking creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BazaarKrovod(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java b/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java index f63d0ebc8ad..542403fb70b 100644 --- a/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java +++ b/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java @@ -76,7 +76,7 @@ class BazaarOfWondersEffect extends OneShotEffect { String spellName = spell.getName(); FilterPermanent filter1 = new FilterPermanent(); filter1.add(new NamePredicate(spellName)); - filter1.add(Predicates.not(new TokenPredicate())); + filter1.add(Predicates.not(TokenPredicate.instance)); if (!game.getBattlefield().getActivePermanents(filter1, source.getControllerId(), game).isEmpty()) { spell.counter(source.getControllerId(), game); return true; diff --git a/Mage.Sets/src/mage/cards/b/BeastmastersMagemark.java b/Mage.Sets/src/mage/cards/b/BeastmastersMagemark.java index 98fd1d3bef4..418c6e671a2 100644 --- a/Mage.Sets/src/mage/cards/b/BeastmastersMagemark.java +++ b/Mage.Sets/src/mage/cards/b/BeastmastersMagemark.java @@ -29,7 +29,7 @@ public final class BeastmastersMagemark extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/b/BeastsOfBogardan.java b/Mage.Sets/src/mage/cards/b/BeastsOfBogardan.java index b9035891f6d..0564015c88c 100644 --- a/Mage.Sets/src/mage/cards/b/BeastsOfBogardan.java +++ b/Mage.Sets/src/mage/cards/b/BeastsOfBogardan.java @@ -30,7 +30,7 @@ public final class BeastsOfBogardan extends CardImpl { static { controlFilter.add(new ColorPredicate(ObjectColor.WHITE)); - controlFilter.add(Predicates.not(new TokenPredicate())); + controlFilter.add(Predicates.not(TokenPredicate.instance)); } public BeastsOfBogardan(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java b/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java new file mode 100644 index 00000000000..83c3d03a178 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java @@ -0,0 +1,83 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetLandPermanent; +import mage.target.common.TargetOpponentOrPlaneswalker; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BedeckBedazzle extends SplitCard { + + public BedeckBedazzle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B/R}{B/R}", "{4}{B}{R}", SpellAbilityType.SPLIT); + + // Bedeck + // Target creature gets +3/-3 until end of turn. + this.getLeftHalfCard().getSpellAbility().addEffect( + new BoostTargetEffect(3, -3, Duration.EndOfTurn) + ); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Bedazzle + // Destroy target nonbasic land. Bedazzle deals 2 damage to target opponent or planeswalker. + this.getRightHalfCard().getSpellAbility().addEffect(new BedazzleEffect()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetLandPermanent()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetOpponentOrPlaneswalker()); + } + + private BedeckBedazzle(final BedeckBedazzle card) { + super(card); + } + + @Override + public BedeckBedazzle copy() { + return new BedeckBedazzle(this); + } +} + +class BedazzleEffect extends OneShotEffect { + + BedazzleEffect() { + super(Outcome.Benefit); + staticText = "Destroy target nonbasic land. {this} deals 2 damage to target opponent or planeswalker."; + } + + private BedazzleEffect(final BedazzleEffect effect) { + super(effect); + } + + @Override + public BedazzleEffect copy() { + return new BedazzleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + permanent.destroy(source.getSourceId(), game, false); + } + Effect effect = new DamageTargetEffect(new StaticValue(2), true, "", true); + effect.setTargetPointer(new FixedTarget(source.getTargets().get(0).getFirstTarget(), game)); + effect.apply(game, source); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BelbesArmor.java b/Mage.Sets/src/mage/cards/b/BelbesArmor.java index e1e54a3e326..d9cc57f6a26 100644 --- a/Mage.Sets/src/mage/cards/b/BelbesArmor.java +++ b/Mage.Sets/src/mage/cards/b/BelbesArmor.java @@ -29,8 +29,8 @@ public final class BelbesArmor extends CardImpl { Ability ability = new SimpleActivatedAbility( Zone.BATTLEFIELD, new BoostTargetEffect( - new MultipliedValue(new ManacostVariableValue(), -1), - new ManacostVariableValue(), + new MultipliedValue(ManacostVariableValue.instance, -1), + ManacostVariableValue.instance, Duration.EndOfTurn ), new ManaCostsImpl("{X}")); diff --git a/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java b/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java index a5de154190f..e6243b73c8c 100644 --- a/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java +++ b/Mage.Sets/src/mage/cards/b/BelligerentBrontodon.java @@ -1,21 +1,19 @@ package mage.cards.b; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class BelligerentBrontodon extends CardImpl { @@ -28,10 +26,10 @@ public final class BelligerentBrontodon extends CardImpl { this.toughness = new MageInt(6); // Each creature you control assigns combat damage equal to its toughness rather than its power. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BelligerentBrontodonCombatDamageRuleEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CombatDamageByToughnessEffect(StaticFilters.FILTER_PERMANENT_CREATURE, true))); } - public BelligerentBrontodon(final BelligerentBrontodon card) { + private BelligerentBrontodon(final BelligerentBrontodon card) { super(card); } @@ -40,40 +38,3 @@ public final class BelligerentBrontodon extends CardImpl { return new BelligerentBrontodon(this); } } - -class BelligerentBrontodonCombatDamageRuleEffect extends ContinuousEffectImpl { - - public BelligerentBrontodonCombatDamageRuleEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Each creature you control assigns combat damage equal to its toughness rather than its power"; - } - - public BelligerentBrontodonCombatDamageRuleEffect(final BelligerentBrontodonCombatDamageRuleEffect effect) { - super(effect); - } - - @Override - public BelligerentBrontodonCombatDamageRuleEffect copy() { - return new BelligerentBrontodonCombatDamageRuleEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - // Change the rule - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(source.getControllerId())); - game.getCombat().setUseToughnessForDamage(true); - game.getCombat().addUseToughnessForDamageFilter(filter); - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} diff --git a/Mage.Sets/src/mage/cards/b/BellowingAegisaur.java b/Mage.Sets/src/mage/cards/b/BellowingAegisaur.java index e5942e94a59..e12a62d4bb7 100644 --- a/Mage.Sets/src/mage/cards/b/BellowingAegisaur.java +++ b/Mage.Sets/src/mage/cards/b/BellowingAegisaur.java @@ -27,7 +27,7 @@ public final class BellowingAegisaur extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BellowingAegisaur(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BelltollDragon.java b/Mage.Sets/src/mage/cards/b/BelltollDragon.java index f2f6f73f80d..1a0407c5ce6 100644 --- a/Mage.Sets/src/mage/cards/b/BelltollDragon.java +++ b/Mage.Sets/src/mage/cards/b/BelltollDragon.java @@ -27,7 +27,7 @@ public final class BelltollDragon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other Dragon creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java b/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java index 5835f6115cd..832d83f0d6f 100644 --- a/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java +++ b/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.dynamicvalue.common.StaticValue; @@ -18,19 +16,23 @@ import mage.game.events.GameEvent.EventType; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** * @author nantuko */ public final class BelltowerSphinx extends CardImpl { public BelltowerSphinx(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.subtype.add(SubType.SPHINX); this.power = new MageInt(2); this.toughness = new MageInt(5); + // Flying this.addAbility(FlyingAbility.getInstance()); + // Whenever a source deals damage to Belltower Sphinx, that source's controller puts that many cards from the top of their library into their graveyard. this.addAbility(new BelltowerSphinxEffect()); } diff --git a/Mage.Sets/src/mage/cards/b/BenBenAkkiHermit.java b/Mage.Sets/src/mage/cards/b/BenBenAkkiHermit.java index c8b93e3272e..a32d8b03f08 100644 --- a/Mage.Sets/src/mage/cards/b/BenBenAkkiHermit.java +++ b/Mage.Sets/src/mage/cards/b/BenBenAkkiHermit.java @@ -30,7 +30,7 @@ public final class BenBenAkkiHermit extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent("untapped Mountain you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.MOUNTAIN)); } diff --git a/Mage.Sets/src/mage/cards/b/BenalishMissionary.java b/Mage.Sets/src/mage/cards/b/BenalishMissionary.java index d0d4b011fe0..952a930598f 100644 --- a/Mage.Sets/src/mage/cards/b/BenalishMissionary.java +++ b/Mage.Sets/src/mage/cards/b/BenalishMissionary.java @@ -27,7 +27,7 @@ public final class BenalishMissionary extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocked creature"); static { - filter.add(new BlockedPredicate()); + filter.add(BlockedPredicate.instance); } public BenalishMissionary(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BenthicBiomancer.java b/Mage.Sets/src/mage/cards/b/BenthicBiomancer.java new file mode 100644 index 00000000000..54e0b622c0b --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BenthicBiomancer.java @@ -0,0 +1,47 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.OneOrMoreCountersAddedTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BenthicBiomancer extends CardImpl { + + public BenthicBiomancer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.WIZARD); + this.subtype.add(SubType.MUTANT); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{U}: Adapt 1. + this.addAbility(new AdaptAbility(1, "{1}{U}")); + + // Whenever one or more +1/+1 counters are put on Benthic Biomancer, draw a card, then discard a card. + Ability ability = new OneOrMoreCountersAddedTriggeredAbility(new DrawCardSourceControllerEffect(1)); + ability.addEffect(new DiscardControllerEffect(1).setText(", then discard a card")); + this.addAbility(ability); + } + + private BenthicBiomancer(final BenthicBiomancer card) { + super(card); + } + + @Override + public BenthicBiomancer copy() { + return new BenthicBiomancer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/Benthicore.java b/Mage.Sets/src/mage/cards/b/Benthicore.java index 9ca093b8612..48424e9d860 100644 --- a/Mage.Sets/src/mage/cards/b/Benthicore.java +++ b/Mage.Sets/src/mage/cards/b/Benthicore.java @@ -33,7 +33,7 @@ public final class Benthicore extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Merfolk you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.MERFOLK)); } diff --git a/Mage.Sets/src/mage/cards/b/Berserk.java b/Mage.Sets/src/mage/cards/b/Berserk.java index 3d38da94d83..d1f990e57e3 100644 --- a/Mage.Sets/src/mage/cards/b/Berserk.java +++ b/Mage.Sets/src/mage/cards/b/Berserk.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -26,8 +25,9 @@ import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; import mage.watchers.common.AttackedThisTurnWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Berserk extends CardImpl { @@ -43,7 +43,7 @@ public final class Berserk extends CardImpl { Effect effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); effect.setText("Target creature gains trample"); this.getSpellAbility().addEffect(effect); - effect = new BoostTargetEffect(new TargetPermanentPowerCount(), new StaticValue(0), Duration.EndOfTurn, true); + effect = new BoostTargetEffect(TargetPermanentPowerCount.instance, new StaticValue(0), Duration.EndOfTurn, true); effect.setText("and gets +X/+0 until end of turn, where X is its power"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(new BerserkDestroyEffect()); @@ -76,7 +76,7 @@ class BerserkReplacementEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.CAST_SPELL && event.getSourceId().equals(source.getSourceId())) { - CombatDamageStepStartedWatcher watcher = (CombatDamageStepStartedWatcher) game.getState().getWatchers().get(CombatDamageStepStartedWatcher.class.getSimpleName()); + CombatDamageStepStartedWatcher watcher = game.getState().getWatcher(CombatDamageStepStartedWatcher.class); return watcher == null || watcher.conditionMet(); } return false; @@ -96,7 +96,7 @@ class BerserkReplacementEffect extends ContinuousRuleModifyingEffectImpl { class CombatDamageStepStartedWatcher extends Watcher { public CombatDamageStepStartedWatcher() { - super(CombatDamageStepStartedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(CombatDamageStepStartedWatcher.class, WatcherScope.GAME); } public CombatDamageStepStartedWatcher(final CombatDamageStepStartedWatcher watcher) { @@ -170,11 +170,9 @@ class BerserkDelayedDestroyEffect extends OneShotEffect { if (controller != null) { Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (permanent != null) { - Watcher watcher = game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); - if (watcher instanceof AttackedThisTurnWatcher) { - if (((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))) { - return permanent.destroy(source.getSourceId(), game, false); - } + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); + if (watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))) { + return permanent.destroy(source.getSourceId(), game, false); } } } diff --git a/Mage.Sets/src/mage/cards/b/Betrayal.java b/Mage.Sets/src/mage/cards/b/Betrayal.java index 46d61656e4a..89f60dd1d12 100644 --- a/Mage.Sets/src/mage/cards/b/Betrayal.java +++ b/Mage.Sets/src/mage/cards/b/Betrayal.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; import mage.abilities.effects.common.AttachEffect; @@ -18,8 +16,9 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LoneFox */ public final class Betrayal extends CardImpl { @@ -31,7 +30,7 @@ public final class Betrayal extends CardImpl { } public Betrayal(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); this.subtype.add(SubType.AURA); // Enchant creature an opponent controls @@ -40,8 +39,9 @@ public final class Betrayal extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Whenever enchanted creature becomes tapped, you draw a card. - this.addAbility(new BecomesTappedAttachedTriggeredAbility(new DrawCardSourceControllerEffect(1), "enchanted creature")); + this.addAbility(new BecomesTappedAttachedTriggeredAbility(new DrawCardSourceControllerEffect(1, "you"), "enchanted creature")); } public Betrayal(final Betrayal card) { diff --git a/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java b/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java index 95fbfb8440f..bb4ac7ecfb6 100644 --- a/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java +++ b/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java @@ -32,7 +32,7 @@ public final class BetrothedOfFire extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("an untapped creature"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public BetrothedOfFire(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/Bifurcate.java b/Mage.Sets/src/mage/cards/b/Bifurcate.java index 4faba2a2605..397ab59792e 100644 --- a/Mage.Sets/src/mage/cards/b/Bifurcate.java +++ b/Mage.Sets/src/mage/cards/b/Bifurcate.java @@ -29,7 +29,7 @@ public final class Bifurcate extends CardImpl { private static FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creatures"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public Bifurcate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BindingMummy.java b/Mage.Sets/src/mage/cards/b/BindingMummy.java index 7ebaf193383..69217bf9a99 100644 --- a/Mage.Sets/src/mage/cards/b/BindingMummy.java +++ b/Mage.Sets/src/mage/cards/b/BindingMummy.java @@ -26,7 +26,7 @@ public final class BindingMummy extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Zombie"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.ZOMBIE)); } diff --git a/Mage.Sets/src/mage/cards/b/BiogenicOoze.java b/Mage.Sets/src/mage/cards/b/BiogenicOoze.java new file mode 100644 index 00000000000..7f6d1b87f4b --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BiogenicOoze.java @@ -0,0 +1,67 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.permanent.token.BiogenicOozeToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BiogenicOoze extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("Ooze you control"); + + static { + filter.add(new SubtypePredicate(SubType.OOZE)); + } + + public BiogenicOoze(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + + this.subtype.add(SubType.OOZE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Biogenic Ooze enters the battlefield, create a 2/2 green Ooze creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new BiogenicOozeToken()) + )); + + // At the beginning if your end step, put a +1/+1 counter on each Ooze you control. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter), + TargetController.YOU, false + )); + + // {1}{G}{G}{G}: Create a 2/2 green Ooze creature token. + this.addAbility(new SimpleActivatedAbility( + new CreateTokenEffect(new BiogenicOozeToken()), + new ManaCostsImpl("{1}{G}{G}{G}") + )); + } + + private BiogenicOoze(final BiogenicOoze card) { + super(card); + } + + @Override + public BiogenicOoze copy() { + return new BiogenicOoze(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BiogenicUpgrade.java b/Mage.Sets/src/mage/cards/b/BiogenicUpgrade.java new file mode 100644 index 00000000000..8d0622f6e4d --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BiogenicUpgrade.java @@ -0,0 +1,78 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.common.counter.DistributeCountersEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanentAmount; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BiogenicUpgrade extends CardImpl { + + public BiogenicUpgrade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}"); + + // Distribute three +1/+1 counters among one, two, or three target creatures, then double the number of +1/+1 counters on each of those creatures. + this.getSpellAbility().addEffect(new DistributeCountersEffect( + CounterType.P1P1, 3, false, + "one, two, or three target creatures" + )); + this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3)); + this.getSpellAbility().addEffect(new BiogenicUpgradeEffect()); + } + + private BiogenicUpgrade(final BiogenicUpgrade card) { + super(card); + } + + @Override + public BiogenicUpgrade copy() { + return new BiogenicUpgrade(this); + } +} + +class BiogenicUpgradeEffect extends OneShotEffect { + + BiogenicUpgradeEffect() { + super(Outcome.Benefit); + staticText = ", then double the number of +1/+1 counters on each of those creatures."; + } + + private BiogenicUpgradeEffect(final BiogenicUpgradeEffect effect) { + super(effect); + } + + @Override + public BiogenicUpgradeEffect copy() { + return new BiogenicUpgradeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID permanentId : source.getTargets().get(0).getTargets()) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent == null) { + continue; + } + Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance( + permanent.getCounters(game).getCount(CounterType.P1P1) + )); + effect.setTargetPointer(new FixedTarget(permanent, game)); + effect.apply(game, source); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java b/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java new file mode 100644 index 00000000000..4adf05b96ef --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java @@ -0,0 +1,159 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.ActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceImpl; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BiomancersFamiliar extends CardImpl { + + public BiomancersFamiliar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}"); + + this.subtype.add(SubType.MUTANT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Activated abilities of creatures you control cost {2} less to activate. This effect can't reduce the amount of mana an ability costs to activate to less than one mana. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BiomancersFamiliarCostReductionEffect())); + + // {T}: The next time target creature adapts this turn, it adapts as though it had no +1/+1 counters on it. + Ability ability = new SimpleActivatedAbility( + new BiomancersFamiliarReplacementEffect(), new TapSourceCost() + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private BiomancersFamiliar(final BiomancersFamiliar card) { + super(card); + } + + @Override + public BiomancersFamiliar copy() { + return new BiomancersFamiliar(this); + } +} + +class BiomancersFamiliarCostReductionEffect extends CostModificationEffectImpl { + + private static final String effectText = "Activated abilities of creatures you control cost {2} less to activate. " + + "This effect can't reduce the amount of mana an ability costs to activate to less than one mana"; + + BiomancersFamiliarCostReductionEffect() { + super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = effectText; + } + + private BiomancersFamiliarCostReductionEffect(final BiomancersFamiliarCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + Player controller = game.getPlayer(abilityToModify.getControllerId()); + if (controller != null) { + Mana mana = abilityToModify.getManaCostsToPay().getMana(); + int reduceMax = mana.getGeneric(); + if (reduceMax > 0 && mana.count() == mana.getGeneric()) { + reduceMax--; + } + if (reduceMax > 2) { + reduceMax = 2; + } + if (reduceMax > 0) { + ChoiceImpl choice = new ChoiceImpl(true); + Set set = new LinkedHashSet<>(); + + for (int i = 0; i <= reduceMax; i++) { + set.add(String.valueOf(i)); + } + choice.setChoices(set); + choice.setMessage("Reduce ability cost"); + if (!controller.choose(Outcome.Benefit, choice, game)) { + return false; + } + int reduce = Integer.parseInt(choice.getChoice()); + CardUtil.reduceCost(abilityToModify, reduce); + } + return true; + } + + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + if (abilityToModify.getAbilityType() == AbilityType.ACTIVATED + || (abilityToModify.getAbilityType() == AbilityType.MANA && abilityToModify instanceof ActivatedAbility)) { + //Activated abilities of creatures you control + Permanent permanent = game.getPermanent(abilityToModify.getSourceId()); + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { + return true; + } + } + return false; + } + + @Override + public BiomancersFamiliarCostReductionEffect copy() { + return new BiomancersFamiliarCostReductionEffect(this); + } +} + +class BiomancersFamiliarReplacementEffect extends ReplacementEffectImpl { + + BiomancersFamiliarReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "The next time target creature adapts this turn, " + + "it adapts as though it had no +1/+1 counters on it."; + } + + private BiomancersFamiliarReplacementEffect(final BiomancersFamiliarReplacementEffect effect) { + super(effect); + } + + @Override + public BiomancersFamiliarReplacementEffect copy() { + return new BiomancersFamiliarReplacementEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ADAPT; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getTargetId().equals(targetPointer.getFirst(game, source)); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + event.setFlag(true); + discard(); + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BiomassMutation.java b/Mage.Sets/src/mage/cards/b/BiomassMutation.java index eaf52684665..cbd6af34074 100644 --- a/Mage.Sets/src/mage/cards/b/BiomassMutation.java +++ b/Mage.Sets/src/mage/cards/b/BiomassMutation.java @@ -22,7 +22,7 @@ public final class BiomassMutation extends CardImpl { // Creatures you control have base power and toughness X/X until end of turn. - DynamicValue variableMana = new ManacostVariableValue(); + DynamicValue variableMana = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new SetPowerToughnessAllEffect(variableMana, variableMana, Duration.EndOfTurn, new FilterControlledCreaturePermanent("Creatures you control"), true)); } diff --git a/Mage.Sets/src/mage/cards/b/BirchloreRangers.java b/Mage.Sets/src/mage/cards/b/BirchloreRangers.java index c6ff1dbc105..749f216e295 100644 --- a/Mage.Sets/src/mage/cards/b/BirchloreRangers.java +++ b/Mage.Sets/src/mage/cards/b/BirchloreRangers.java @@ -26,7 +26,7 @@ public final class BirchloreRangers extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Elves you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.ELF)); } diff --git a/Mage.Sets/src/mage/cards/b/BirthingPod.java b/Mage.Sets/src/mage/cards/b/BirthingPod.java index 2242e3886d6..179040611b0 100644 --- a/Mage.Sets/src/mage/cards/b/BirthingPod.java +++ b/Mage.Sets/src/mage/cards/b/BirthingPod.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.Cost; @@ -17,7 +16,7 @@ import mage.constants.ComparisonType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; -import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; +import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; @@ -26,6 +25,8 @@ import mage.players.Player; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** * @author Loki */ @@ -36,9 +37,13 @@ public final class BirthingPod extends CardImpl { // {1}{G/P}, {tap}, Sacrifice a creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost, // put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery. - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new BirthingPodEffect(), new ManaCostsImpl("{1}{G/P}")); + Ability ability = new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, new BirthingPodEffect(), new ManaCostsImpl("{1}{G/P}") + ); ability.addCost(new TapSourceCost()); - ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent( + StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT + ))); this.addAbility(ability); } @@ -56,11 +61,12 @@ class BirthingPodEffect extends OneShotEffect { BirthingPodEffect() { super(Outcome.Benefit); - staticText = "Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost, put that card " - + "onto the battlefield, then shuffle your library"; + staticText = "Search your library for a creature card with converted mana cost equal to 1 " + + "plus the sacrificed creature's converted mana cost, put that card " + + "onto the battlefield, then shuffle your library"; } - BirthingPodEffect(final BirthingPodEffect effect) { + private BirthingPodEffect(final BirthingPodEffect effect) { super(effect); } @@ -77,20 +83,20 @@ class BirthingPodEffect extends OneShotEffect { } } Player controller = game.getPlayer(source.getControllerId()); - if (sacrificedPermanent != null && controller != null) { - int newConvertedCost = sacrificedPermanent.getConvertedManaCost() + 1; - FilterCard filter = new FilterCard("creature card with converted mana cost " + newConvertedCost); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, newConvertedCost)); - filter.add(new CardTypePredicate(CardType.CREATURE)); - TargetCardInLibrary target = new TargetCardInLibrary(filter); - if (controller.searchLibrary(target, game)) { - Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - controller.shuffleLibrary(source, game); - return true; + if (sacrificedPermanent == null || controller == null) { + return false; } - return false; + int newConvertedCost = sacrificedPermanent.getConvertedManaCost() + 1; + FilterCard filter = new FilterCard("creature card with converted mana cost " + newConvertedCost); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, newConvertedCost)); + filter.add(new CardTypePredicate(CardType.CREATURE)); + TargetCardInLibrary target = new TargetCardInLibrary(filter); + if (controller.searchLibrary(target, game)) { + Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + controller.shuffleLibrary(source, game); + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/b/BlackManaBattery.java b/Mage.Sets/src/mage/cards/b/BlackManaBattery.java index 2423fc449b4..0aa099282e4 100644 --- a/Mage.Sets/src/mage/cards/b/BlackManaBattery.java +++ b/Mage.Sets/src/mage/cards/b/BlackManaBattery.java @@ -36,7 +36,7 @@ public final class BlackManaBattery extends CardImpl { // {tap}, Remove any number of charge counters from Black Mana Battery: Add {B}, then add an additional {B} for each charge counter removed this way. ability = new DynamicManaAbility( Mana.BlackMana(1), - new IntPlusDynamicValue(1, new RemovedCountersForCostValue()), + new IntPlusDynamicValue(1, RemovedCountersForCostValue.instance), new TapSourceCost(), "Add {B}, then add {B} for each charge counter removed this way", true, new CountersSourceCount(CounterType.CHARGE)); diff --git a/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java b/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java index c27c99be182..22ef04c4630 100644 --- a/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java +++ b/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java @@ -30,8 +30,8 @@ public final class BlackOakOfOdunos extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another untapped creature you control"); static { - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TappedPredicate.instance)); } public BlackOakOfOdunos(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BladeJuggler.java b/Mage.Sets/src/mage/cards/b/BladeJuggler.java new file mode 100644 index 00000000000..a9c5e82aee6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BladeJuggler.java @@ -0,0 +1,49 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.SpectacleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BladeJuggler extends CardImpl { + + public BladeJuggler(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Spectacle {2}{B} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{2}{B}"))); + + // When Blade Juggler enters the battlefield, it deals 1 damage to you and you draw a card. + Ability ability = new EntersBattlefieldTriggeredAbility( + new DamageControllerEffect(1, "it") + ); + ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and you draw a card")); + this.addAbility(ability); + } + + private BladeJuggler(final BladeJuggler card) { + super(card); + } + + @Override + public BladeJuggler copy() { + return new BladeJuggler(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/Bladebrand.java b/Mage.Sets/src/mage/cards/b/Bladebrand.java new file mode 100644 index 00000000000..472d4cc8092 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Bladebrand.java @@ -0,0 +1,40 @@ +package mage.cards.b; + +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Bladebrand extends CardImpl { + + public Bladebrand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); + + // Target creature gains deathtouch until end of turn. + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + DeathtouchAbility.getInstance(), Duration.EndOfTurn + )); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + private Bladebrand(final Bladebrand card) { + super(card); + } + + @Override + public Bladebrand copy() { + return new Bladebrand(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BlaringCaptain.java b/Mage.Sets/src/mage/cards/b/BlaringCaptain.java index ab763490784..3a4c55c65cb 100644 --- a/Mage.Sets/src/mage/cards/b/BlaringCaptain.java +++ b/Mage.Sets/src/mage/cards/b/BlaringCaptain.java @@ -23,7 +23,7 @@ public final class BlaringCaptain extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WARRIOR, "attacking Warriors"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public BlaringCaptain(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BlatantThievery.java b/Mage.Sets/src/mage/cards/b/BlatantThievery.java index 39bfb83a74c..3a65bbec7d5 100644 --- a/Mage.Sets/src/mage/cards/b/BlatantThievery.java +++ b/Mage.Sets/src/mage/cards/b/BlatantThievery.java @@ -1,9 +1,7 @@ - package mage.cards.b; import java.util.*; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -18,6 +16,7 @@ import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; /** @@ -31,34 +30,37 @@ public final class BlatantThievery extends CardImpl { // For each opponent, gain control of target permanent that player controls. this.getSpellAbility().addEffect(new BlatantThieveryEffect()); + this.getSpellAbility().setTargetAdjuster(BlatantThieveryAdjuster.instance); } public BlatantThievery(final BlatantThievery card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterPermanent filter = new FilterPermanent("Permanent of player " + opponent.getName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetPermanent targetPermanent = new TargetPermanent(filter); - ability.addTarget(targetPermanent); - } - } - } - } - @Override public BlatantThievery copy() { return new BlatantThievery(this); } } +enum BlatantThieveryAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterPermanent filter = new FilterPermanent("Permanent of player " + opponent.getName()); + filter.add(new ControllerIdPredicate(opponentId)); + TargetPermanent targetPermanent = new TargetPermanent(filter); + ability.addTarget(targetPermanent); + } + } + } +} + class BlatantThieveryEffect extends OneShotEffect { BlatantThieveryEffect() { diff --git a/Mage.Sets/src/mage/cards/b/Blaze.java b/Mage.Sets/src/mage/cards/b/Blaze.java index bbeead84810..d2b4c019217 100644 --- a/Mage.Sets/src/mage/cards/b/Blaze.java +++ b/Mage.Sets/src/mage/cards/b/Blaze.java @@ -20,7 +20,7 @@ public final class Blaze extends CardImpl { // Blaze deals X damage to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/b/BlazingShoal.java b/Mage.Sets/src/mage/cards/b/BlazingShoal.java index 79e19d154d5..9f6238b97e4 100644 --- a/Mage.Sets/src/mage/cards/b/BlazingShoal.java +++ b/Mage.Sets/src/mage/cards/b/BlazingShoal.java @@ -38,7 +38,7 @@ public final class BlazingShoal extends CardImpl { this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter),true))); // Target creature gets +X/+0 until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(new ExileFromHandCostCardConvertedMana(), new StaticValue(0), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(ExileFromHandCostCardConvertedMana.instance, new StaticValue(0), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/b/BlindSpotGiant.java b/Mage.Sets/src/mage/cards/b/BlindSpotGiant.java index 52688ab0cfb..bb9a88fe7f6 100644 --- a/Mage.Sets/src/mage/cards/b/BlindSpotGiant.java +++ b/Mage.Sets/src/mage/cards/b/BlindSpotGiant.java @@ -25,7 +25,7 @@ public final class BlindSpotGiant extends CardImpl { static { filter.add(new SubtypePredicate(SubType.GIANT)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BlindSpotGiant(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java b/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java index e454c0342dd..8321019952a 100644 --- a/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java +++ b/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -14,22 +12,23 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; +import java.util.UUID; + /** * @author LevelX2 */ public final class BlistercoilWeird extends CardImpl { - - public BlistercoilWeird(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{U/R}"); - this.subtype.add(SubType.WEIRD); + public BlistercoilWeird(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U/R}"); + this.subtype.add(SubType.WEIRD); this.power = new MageInt(1); this.toughness = new MageInt(1); // Whenever you cast an instant or sorcery spell, Blistercoil Weird gets +1/+1 until end of turn. Untap it. - Ability ability = new SpellCastControllerTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); + Ability ability = new SpellCastControllerTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false); ability.addEffect(new UntapSourceEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/Blockbuster.java b/Mage.Sets/src/mage/cards/b/Blockbuster.java index 3dbb960768c..174ebca05f5 100644 --- a/Mage.Sets/src/mage/cards/b/Blockbuster.java +++ b/Mage.Sets/src/mage/cards/b/Blockbuster.java @@ -23,7 +23,7 @@ public final class Blockbuster extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public Blockbuster(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BloodChinFanatic.java b/Mage.Sets/src/mage/cards/b/BloodChinFanatic.java index 5ad22400d94..a05a7f28575 100644 --- a/Mage.Sets/src/mage/cards/b/BloodChinFanatic.java +++ b/Mage.Sets/src/mage/cards/b/BloodChinFanatic.java @@ -31,7 +31,7 @@ public final class BloodChinFanatic extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Warrior creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.WARRIOR)); } @@ -42,9 +42,9 @@ public final class BloodChinFanatic extends CardImpl { this.toughness = new MageInt(3); // {1}{B}, Sacrifice another Warrior creature: Target player loses X life and you gain X life, where X is the sacrificed creature's power. - Effect effect = new LoseLifeTargetEffect(new SacrificeCostCreaturesPower()); + Effect effect = new LoseLifeTargetEffect(SacrificeCostCreaturesPower.instance); effect.setText("Target player loses X life"); - Effect effect2 = new GainLifeEffect(new SacrificeCostCreaturesPower()); + Effect effect2 = new GainLifeEffect(SacrificeCostCreaturesPower.instance); effect2.setText("and you gain X life, where X is the sacrificed creature's power"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{B}")); ability.addEffect(effect2); diff --git a/Mage.Sets/src/mage/cards/b/BloodMoon.java b/Mage.Sets/src/mage/cards/b/BloodMoon.java index ca52c9989c7..1eef0357ac4 100644 --- a/Mage.Sets/src/mage/cards/b/BloodMoon.java +++ b/Mage.Sets/src/mage/cards/b/BloodMoon.java @@ -1,11 +1,14 @@ - package mage.cards.b; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.RedManaAbility; +import mage.abilities.mana.WhiteManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -22,7 +25,7 @@ import mage.game.permanent.Permanent; public final class BloodMoon extends CardImpl { public BloodMoon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // Nonbasic lands are Mountains. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BloodMoonEffect())); @@ -72,12 +75,28 @@ class BloodMoonEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 - land.removeAllAbilities(source.getSourceId(), game); - land.getSubtype(game).removeAll(SubType.getLandTypes(false)); + //land.getSubtype(game).removeAll(SubType.getLandTypes(false)); + land.getSubtype(game).clear(); land.getSubtype(game).add(SubType.MOUNTAIN); + land.removeAllAbilities(source.getSourceId(), game); break; case AbilityAddingRemovingEffects_6: - land.addAbility(new RedManaAbility(), source.getSourceId(), game); + land.removeAllAbilities(source.getSourceId(), game); + if (land.getSubtype(game).contains(SubType.FOREST)) { + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.PLAINS)) { + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.ISLAND)) { + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.SWAMP)) { + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + } break; } } @@ -86,6 +105,7 @@ class BloodMoonEffect extends ContinuousEffectImpl { @Override public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + return layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.TypeChangingEffects_4; } } diff --git a/Mage.Sets/src/mage/cards/b/BloodTribute.java b/Mage.Sets/src/mage/cards/b/BloodTribute.java index cd9587f4095..694c16ac064 100644 --- a/Mage.Sets/src/mage/cards/b/BloodTribute.java +++ b/Mage.Sets/src/mage/cards/b/BloodTribute.java @@ -37,7 +37,7 @@ public final class BloodTribute extends CardImpl { TextPartSubType textPartVampire = (TextPartSubType) addTextPart(new TextPartSubType(SubType.VAMPIRE)); FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped Vampire you control"); filter.add(new TextPartSubtypePredicate(textPartVampire)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); this.addAbility(new KickerAbility(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)))); // Target opponent loses half their life, rounded up. diff --git a/Mage.Sets/src/mage/cards/b/Bloodbriar.java b/Mage.Sets/src/mage/cards/b/Bloodbriar.java index f7920debb3e..644927bfcbf 100644 --- a/Mage.Sets/src/mage/cards/b/Bloodbriar.java +++ b/Mage.Sets/src/mage/cards/b/Bloodbriar.java @@ -25,7 +25,7 @@ public final class Bloodbriar extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Bloodbriar(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BloodcrazedGoblin.java b/Mage.Sets/src/mage/cards/b/BloodcrazedGoblin.java index a67946442bf..ab1708edb19 100644 --- a/Mage.Sets/src/mage/cards/b/BloodcrazedGoblin.java +++ b/Mage.Sets/src/mage/cards/b/BloodcrazedGoblin.java @@ -2,7 +2,6 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -17,15 +16,16 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.watchers.common.BloodthirstWatcher; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com * @author North */ public final class BloodcrazedGoblin extends CardImpl { public BloodcrazedGoblin(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.GOBLIN, SubType.BERSERKER); this.power = new MageInt(2); @@ -69,8 +69,8 @@ class BloodcrazedGoblinEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(source.getSourceId())) { - BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get(BloodthirstWatcher.class.getSimpleName(), source.getControllerId()); // BloodthirstWatcher - return !watcher.conditionMet(); + BloodthirstWatcher watcher = game.getState().getWatcher(BloodthirstWatcher.class, source.getControllerId()); // BloodthirstWatcher + return watcher != null && !watcher.conditionMet(); } return false; } diff --git a/Mage.Sets/src/mage/cards/b/BloodcrazedPaladin.java b/Mage.Sets/src/mage/cards/b/BloodcrazedPaladin.java index 979494a69d5..85cfe792f6c 100644 --- a/Mage.Sets/src/mage/cards/b/BloodcrazedPaladin.java +++ b/Mage.Sets/src/mage/cards/b/BloodcrazedPaladin.java @@ -34,7 +34,7 @@ public final class BloodcrazedPaladin extends CardImpl { // Bloodcrazed Paladin enters the battlefield with a +1/+1 counter on it for each creature that died this turn. Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), - new CreaturesDiedThisTurnCount(), true); + CreaturesDiedThisTurnCount.instance, true); effect.setText("with a +1/+1 counter on it for each creature that died this turn."); this.addAbility(new EntersBattlefieldAbility(effect), new CreaturesDiedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/b/BloodcurdlingScream.java b/Mage.Sets/src/mage/cards/b/BloodcurdlingScream.java index 405349caa76..50d803fc36c 100644 --- a/Mage.Sets/src/mage/cards/b/BloodcurdlingScream.java +++ b/Mage.Sets/src/mage/cards/b/BloodcurdlingScream.java @@ -21,7 +21,7 @@ public final class BloodcurdlingScream extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}"); // Target creature gets +X/+0 until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(new ExileFromHandCostCardConvertedMana(), new StaticValue(0), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(ExileFromHandCostCardConvertedMana.instance, new StaticValue(0), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/b/BloodhuskRitualist.java b/Mage.Sets/src/mage/cards/b/BloodhuskRitualist.java index 4fb929dd9f9..d3cc620816a 100644 --- a/Mage.Sets/src/mage/cards/b/BloodhuskRitualist.java +++ b/Mage.Sets/src/mage/cards/b/BloodhuskRitualist.java @@ -32,7 +32,7 @@ public final class BloodhuskRitualist extends CardImpl { this.addAbility(new MultikickerAbility("{B}")); // When Bloodhusk Ritualist enters the battlefield, target opponent discards a card for each time it was kicked. - Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(new MultikickerCount())); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(MultikickerCount.instance)); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java b/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java index adad0809f7d..5e951498c36 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java +++ b/Mage.Sets/src/mage/cards/b/BloodlordOfVaasgoth.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -18,6 +17,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import java.util.UUID; + /** * @author nantuko */ @@ -31,7 +32,7 @@ public final class BloodlordOfVaasgoth extends CardImpl { } public BloodlordOfVaasgoth(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.VAMPIRE, SubType.WARRIOR); this.power = new MageInt(3); @@ -47,7 +48,7 @@ public final class BloodlordOfVaasgoth extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new BloodlordOfVaasgothEffect(), filter, false, true)); } - public BloodlordOfVaasgoth(final BloodlordOfVaasgoth card) { + private BloodlordOfVaasgoth(final BloodlordOfVaasgoth card) { super(card); } @@ -63,12 +64,12 @@ class BloodlordOfVaasgothEffect extends ContinuousEffectImpl { private int zoneChangeCounter; private UUID permanentId; - public BloodlordOfVaasgothEffect() { + BloodlordOfVaasgothEffect() { super(Duration.OneUse, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); staticText = "it gains bloodthirst 3"; } - public BloodlordOfVaasgothEffect(final BloodlordOfVaasgothEffect effect) { + private BloodlordOfVaasgothEffect(final BloodlordOfVaasgothEffect effect) { super(effect); this.ability = effect.ability.copy(); this.zoneChangeCounter = effect.zoneChangeCounter; @@ -95,7 +96,6 @@ class BloodlordOfVaasgothEffect extends ContinuousEffectImpl { Permanent permanent = game.getPermanent(permanentId); if (permanent != null && permanent.getZoneChangeCounter(game) <= zoneChangeCounter) { permanent.addAbility(ability, source.getSourceId(), game); - return true; } else { if (game.getState().getZoneChangeCounter(permanentId) >= zoneChangeCounter) { discard(); diff --git a/Mage.Sets/src/mage/cards/b/BloodmistInfiltrator.java b/Mage.Sets/src/mage/cards/b/BloodmistInfiltrator.java new file mode 100644 index 00000000000..1a523bb7395 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BloodmistInfiltrator.java @@ -0,0 +1,54 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BloodmistInfiltrator extends CardImpl { + + private static final FilterControlledPermanent filter + = new FilterControlledCreaturePermanent("another creature"); + + static { + filter.add(AnotherPredicate.instance); + } + + public BloodmistInfiltrator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Whenever Bloodmist Infiltrator attacks, you may sacrifice another creature. If you do, Bloodmist Infiltrator can't be blocked this turn. + this.addAbility(new AttacksTriggeredAbility(new DoIfCostPaid( + new CantBeBlockedSourceEffect(Duration.EndOfTurn), + new SacrificeTargetCost(new TargetControlledPermanent(filter)) + ), false)); + } + + private BloodmistInfiltrator(final BloodmistInfiltrator card) { + super(card); + } + + @Override + public BloodmistInfiltrator copy() { + return new BloodmistInfiltrator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BloodshotCyclops.java b/Mage.Sets/src/mage/cards/b/BloodshotCyclops.java index 80aa19dbbb8..7cbe947de4d 100644 --- a/Mage.Sets/src/mage/cards/b/BloodshotCyclops.java +++ b/Mage.Sets/src/mage/cards/b/BloodshotCyclops.java @@ -33,7 +33,7 @@ public final class BloodshotCyclops extends CardImpl { // {T}, Sacrifice a creature: Bloodshot Cyclops deals damage equal to the sacrificed // creature's power to any target. SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(new SacrificeCostCreaturesPower()), + new DamageTargetEffect(SacrificeCostCreaturesPower.instance), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/b/BloodswornSteward.java b/Mage.Sets/src/mage/cards/b/BloodswornSteward.java index e9070d6d069..21ed7ccdc95 100644 --- a/Mage.Sets/src/mage/cards/b/BloodswornSteward.java +++ b/Mage.Sets/src/mage/cards/b/BloodswornSteward.java @@ -27,7 +27,7 @@ public final class BloodswornSteward extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("Commander creatures"); static { - filter.add(new CommanderPredicate()); + filter.add(CommanderPredicate.instance); } public BloodswornSteward(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BlueManaBattery.java b/Mage.Sets/src/mage/cards/b/BlueManaBattery.java index 9283e18893c..05ad3bfc873 100644 --- a/Mage.Sets/src/mage/cards/b/BlueManaBattery.java +++ b/Mage.Sets/src/mage/cards/b/BlueManaBattery.java @@ -36,7 +36,7 @@ public final class BlueManaBattery extends CardImpl { // {tap}, Remove any number of charge counters from Blue Mana Battery: Add {U}, then add an additional {U} for each charge counter removed this way. ability = new DynamicManaAbility( Mana.BlueMana(1), - new IntPlusDynamicValue(1, new RemovedCountersForCostValue()), + new IntPlusDynamicValue(1, RemovedCountersForCostValue.instance), new TapSourceCost(), "Add {U}, then add {U} for each charge counter removed this way", true, new CountersSourceCount(CounterType.CHARGE)); diff --git a/Mage.Sets/src/mage/cards/b/BlueSunsZenith.java b/Mage.Sets/src/mage/cards/b/BlueSunsZenith.java index 72d74af31fb..2e94941db50 100644 --- a/Mage.Sets/src/mage/cards/b/BlueSunsZenith.java +++ b/Mage.Sets/src/mage/cards/b/BlueSunsZenith.java @@ -21,7 +21,7 @@ public final class BlueSunsZenith extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}{U}{U}"); // Target player draws X cards. Shuffle Blue Sun's Zenith into its owner's library. - this.getSpellAbility().addEffect(new DrawCardTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addEffect(ShuffleSpellEffect.getInstance()); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java b/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java index 7b232219997..cebfdf8ec6f 100644 --- a/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java +++ b/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java @@ -19,7 +19,7 @@ public final class BoardTheWeatherlight extends CardImpl { private static final FilterCard filter = new FilterCard("a historic card"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public BoardTheWeatherlight(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BolracClanCrusher.java b/Mage.Sets/src/mage/cards/b/BolracClanCrusher.java new file mode 100644 index 00000000000..5b41bafcf18 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BolracClanCrusher.java @@ -0,0 +1,47 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveCounterCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BolracClanCrusher extends CardImpl { + + public BolracClanCrusher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // {T}, Remove a +1/+1 counter from a creature you control: Bolrac-Clan Crusher deals 2 damage to any target. + Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); + ability.addCost(new RemoveCounterCost(new TargetControlledCreaturePermanent(), CounterType.P1P1)); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + private BolracClanCrusher(final BolracClanCrusher card) { + super(card); + } + + @Override + public BolracClanCrusher copy() { + return new BolracClanCrusher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BoltwingMarauder.java b/Mage.Sets/src/mage/cards/b/BoltwingMarauder.java index 58c3574144b..230401b197f 100644 --- a/Mage.Sets/src/mage/cards/b/BoltwingMarauder.java +++ b/Mage.Sets/src/mage/cards/b/BoltwingMarauder.java @@ -26,7 +26,7 @@ public final class BoltwingMarauder extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature under your control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BoltwingMarauder(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BondOfAgony.java b/Mage.Sets/src/mage/cards/b/BondOfAgony.java index 761c1ad9886..a6da60f30ec 100644 --- a/Mage.Sets/src/mage/cards/b/BondOfAgony.java +++ b/Mage.Sets/src/mage/cards/b/BondOfAgony.java @@ -18,7 +18,7 @@ public final class BondOfAgony extends CardImpl { public BondOfAgony(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}"); - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; // As an additional cost to cast Bond of Agony, pay X life. // magenoxx: here we don't use PayVariableLifeCost as {X} shouldn't actually be announced diff --git a/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java b/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java index 57662b4c40a..7ea8bac0b4f 100644 --- a/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java +++ b/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java @@ -98,7 +98,7 @@ class BontuTheGlorifiedRestrictionEffect extends RestrictionEffect { public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(source.getSourceId())) { Player controller = game.getPlayer(source.getControllerId()); - CreaturesDiedWatcher watcher = (CreaturesDiedWatcher) game.getState().getWatchers().get(CreaturesDiedWatcher.class.getSimpleName()); + CreaturesDiedWatcher watcher = game.getState().getWatcher(CreaturesDiedWatcher.class); if (controller != null && watcher != null) { return (watcher.getAmountOfCreaturesDiedThisTurnByController(controller.getId()) == 0); diff --git a/Mage.Sets/src/mage/cards/b/Borrowing100000Arrows.java b/Mage.Sets/src/mage/cards/b/Borrowing100000Arrows.java index 2d6bd827eec..47ba5f1cd41 100644 --- a/Mage.Sets/src/mage/cards/b/Borrowing100000Arrows.java +++ b/Mage.Sets/src/mage/cards/b/Borrowing100000Arrows.java @@ -62,7 +62,7 @@ class Borrowing100000ArrowsEffect extends OneShotEffect { Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (opponent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerIdPredicate(opponent.getId())); return new DrawCardSourceControllerEffect(game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game)).apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/b/BorrowingTheEastWind.java b/Mage.Sets/src/mage/cards/b/BorrowingTheEastWind.java index 9d5ab407c52..53f13e39bef 100644 --- a/Mage.Sets/src/mage/cards/b/BorrowingTheEastWind.java +++ b/Mage.Sets/src/mage/cards/b/BorrowingTheEastWind.java @@ -27,7 +27,7 @@ public final class BorrowingTheEastWind extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{G}{G}"); // Borrowing the East Wind deals X damage to each creature with horsemanship and each player. - this.getSpellAbility().addEffect(new DamageEverythingEffect(new ManacostVariableValue(), filter)); } + this.getSpellAbility().addEffect(new DamageEverythingEffect(ManacostVariableValue.instance, filter)); } public BorrowingTheEastWind(final BorrowingTheEastWind card) { super(card); diff --git a/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java b/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java index 9e19d3430a9..15c1b4f486f 100644 --- a/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java +++ b/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java @@ -62,7 +62,7 @@ class BoseijuWhoSheltersAllWatcher extends Watcher { private final String originalId; public BoseijuWhoSheltersAllWatcher(UUID originalId) { - super(BoseijuWhoSheltersAllWatcher.class.getSimpleName(), WatcherScope.CARD); + super(BoseijuWhoSheltersAllWatcher.class, WatcherScope.CARD); this.originalId = originalId.toString(); } @@ -137,7 +137,7 @@ class BoseijuWhoSheltersAllCantCounterEffect extends ContinuousRuleModifyingEffe @Override public boolean applies(GameEvent event, Ability source, Game game) { - BoseijuWhoSheltersAllWatcher watcher = (BoseijuWhoSheltersAllWatcher) game.getState().getWatchers().get(BoseijuWhoSheltersAllWatcher.class.getSimpleName(), source.getSourceId()); + BoseijuWhoSheltersAllWatcher watcher = game.getState().getWatcher(BoseijuWhoSheltersAllWatcher.class, source.getSourceId()); Spell spell = game.getStack().getSpell(event.getTargetId()); return spell != null && watcher != null && watcher.spellCantBeCountered(spell.getId()); } diff --git a/Mage.Sets/src/mage/cards/b/BottleOfSuleiman.java b/Mage.Sets/src/mage/cards/b/BottleOfSuleiman.java index efc5271eff4..9d82fd071f8 100644 --- a/Mage.Sets/src/mage/cards/b/BottleOfSuleiman.java +++ b/Mage.Sets/src/mage/cards/b/BottleOfSuleiman.java @@ -61,7 +61,7 @@ class BottleOfSuleimanEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); if (you != null) { - if (you.flipCoin(game)) { + if (you.flipCoin(source, game, true)) { DjinnToken token = new DjinnToken(); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); return true; diff --git a/Mage.Sets/src/mage/cards/b/BottomlessVault.java b/Mage.Sets/src/mage/cards/b/BottomlessVault.java index 8bd5f7fa137..caad3bf15cd 100644 --- a/Mage.Sets/src/mage/cards/b/BottomlessVault.java +++ b/Mage.Sets/src/mage/cards/b/BottomlessVault.java @@ -44,7 +44,7 @@ public final class BottomlessVault extends CardImpl { // {tap}, Remove any number of storage counters from Bottomless Vault: Add {B} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.BlackMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {B} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/b/BoundByMoonsilver.java b/Mage.Sets/src/mage/cards/b/BoundByMoonsilver.java index 58c5928fdba..e3350aa8774 100644 --- a/Mage.Sets/src/mage/cards/b/BoundByMoonsilver.java +++ b/Mage.Sets/src/mage/cards/b/BoundByMoonsilver.java @@ -29,7 +29,7 @@ public final class BoundByMoonsilver extends CardImpl { private final static FilterControlledPermanent filter = new FilterControlledPermanent("another permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BoundByMoonsilver(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BraceForImpact.java b/Mage.Sets/src/mage/cards/b/BraceForImpact.java index 28f17918e2c..6b5a458592c 100644 --- a/Mage.Sets/src/mage/cards/b/BraceForImpact.java +++ b/Mage.Sets/src/mage/cards/b/BraceForImpact.java @@ -25,7 +25,7 @@ public final class BraceForImpact extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("multicolored creature"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public BraceForImpact(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BrainInAJar.java b/Mage.Sets/src/mage/cards/b/BrainInAJar.java index 161a5c9fcc3..78969941889 100644 --- a/Mage.Sets/src/mage/cards/b/BrainInAJar.java +++ b/Mage.Sets/src/mage/cards/b/BrainInAJar.java @@ -118,7 +118,7 @@ class BrainInAJarScryEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - int x = new RemovedCountersForCostValue().calculate(game, source, this); + int x = RemovedCountersForCostValue.instance.calculate(game, source, this); if (x > 0) { return controller.scry(x, source, game); } diff --git a/Mage.Sets/src/mage/cards/b/Braingeyser.java b/Mage.Sets/src/mage/cards/b/Braingeyser.java index f3bd4083b03..75dad9a4f61 100644 --- a/Mage.Sets/src/mage/cards/b/Braingeyser.java +++ b/Mage.Sets/src/mage/cards/b/Braingeyser.java @@ -21,7 +21,7 @@ public final class Braingeyser extends CardImpl { // Target player draws X cards. - this.getSpellAbility().addEffect(new DrawCardTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/b/Brainspoil.java b/Mage.Sets/src/mage/cards/b/Brainspoil.java index d7422bbba5a..f49bcc4a40e 100644 --- a/Mage.Sets/src/mage/cards/b/Brainspoil.java +++ b/Mage.Sets/src/mage/cards/b/Brainspoil.java @@ -21,7 +21,7 @@ public final class Brainspoil extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that isn't enchanted"); static { - filter.add(Predicates.not(new EnchantedPredicate())); + filter.add(Predicates.not(EnchantedPredicate.instance)); } public Brainspoil(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BrambleSovereign.java b/Mage.Sets/src/mage/cards/b/BrambleSovereign.java index ab9ad76b56e..caa98f8bf6e 100644 --- a/Mage.Sets/src/mage/cards/b/BrambleSovereign.java +++ b/Mage.Sets/src/mage/cards/b/BrambleSovereign.java @@ -32,8 +32,8 @@ public final class BrambleSovereign extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); - filter.add(new AnotherPredicate()); + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); } public BrambleSovereign(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BrandedBrawlers.java b/Mage.Sets/src/mage/cards/b/BrandedBrawlers.java index b7bff9ce2eb..469bfcc8850 100644 --- a/Mage.Sets/src/mage/cards/b/BrandedBrawlers.java +++ b/Mage.Sets/src/mage/cards/b/BrandedBrawlers.java @@ -28,7 +28,7 @@ public final class BrandedBrawlers extends CardImpl { static final private FilterLandPermanent filter = new FilterLandPermanent("an untapped land"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } final static private String rule = "{this} can't block if you control an untapped land"; diff --git a/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java b/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java index 4012646d0c0..6d80495ed51 100644 --- a/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java +++ b/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java @@ -1,4 +1,3 @@ - package mage.cards.b; import mage.MageInt; @@ -22,7 +21,6 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author TheElk801 */ public final class BrassTalonChimera extends CardImpl { @@ -43,9 +41,9 @@ public final class BrassTalonChimera extends CardImpl { // First strike this.addAbility(FirstStrikeAbility.getInstance()); - // Sacrifice Brass-Talon Chimera: Put a +2/+2 counter on target Chimera creature. It gains first strike. + // Sacrifice Brass-Talon Chimera: Put a +2/+2 counter on target Chimera creature. It gains first strike. (This effect lasts indefinitely.) Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P2P2.createInstance()), new SacrificeSourceCost()); - ability.addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield)); + ability.addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield).setText("It gains first strike. (This effect lasts indefinitely.)")); ability.addTarget(new TargetCreaturePermanent(filter)); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java b/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java index dd74b144c30..3d192902243 100644 --- a/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java +++ b/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java @@ -23,7 +23,7 @@ public final class BreachingHippocamp extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BreachingHippocamp(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BreakOpen.java b/Mage.Sets/src/mage/cards/b/BreakOpen.java index fcfc4f81e14..275c9fc7fb2 100644 --- a/Mage.Sets/src/mage/cards/b/BreakOpen.java +++ b/Mage.Sets/src/mage/cards/b/BreakOpen.java @@ -21,7 +21,7 @@ public final class BreakOpen extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Face-down creature an opponent controls"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); filter.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/b/BreathstealersCrypt.java b/Mage.Sets/src/mage/cards/b/BreathstealersCrypt.java index 503f832836f..aaeb5b471e2 100644 --- a/Mage.Sets/src/mage/cards/b/BreathstealersCrypt.java +++ b/Mage.Sets/src/mage/cards/b/BreathstealersCrypt.java @@ -46,7 +46,7 @@ class BreathstealersCryptEffect extends ReplacementEffectImpl { public BreathstealersCryptEffect() { super(Duration.WhileOnBattlefield, Outcome.LoseLife); - staticText = "If a player would draw a card, instead he or she draws a card and reveals it. If it's a creature card, that player discards it unless he or she pays 3 life"; + staticText = "If a player would draw a card, instead they draw a card and reveal it. If it's a creature card, that player discards it unless they pay 3 life"; } public BreathstealersCryptEffect(final BreathstealersCryptEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BriarberryCohort.java b/Mage.Sets/src/mage/cards/b/BriarberryCohort.java index ea7b0b76495..888f21eede9 100644 --- a/Mage.Sets/src/mage/cards/b/BriarberryCohort.java +++ b/Mage.Sets/src/mage/cards/b/BriarberryCohort.java @@ -32,7 +32,7 @@ public final class BriarberryCohort extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.BLUE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private String rule = "{this} gets +1/+1 as long as you control another blue creature"; diff --git a/Mage.Sets/src/mage/cards/b/BriarbridgePatrol.java b/Mage.Sets/src/mage/cards/b/BriarbridgePatrol.java index 9995cf93e47..594613056ff 100644 --- a/Mage.Sets/src/mage/cards/b/BriarbridgePatrol.java +++ b/Mage.Sets/src/mage/cards/b/BriarbridgePatrol.java @@ -56,7 +56,7 @@ enum BriarbridgePatrolCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PermanentsSacrificedWatcher watcher = (PermanentsSacrificedWatcher) game.getState().getWatchers().get(PermanentsSacrificedWatcher.class.getSimpleName()); + PermanentsSacrificedWatcher watcher = game.getState().getWatcher(PermanentsSacrificedWatcher.class); if (watcher != null) { List sacrificedPermanents = watcher.getThisTurnSacrificedPermanents(source.getControllerId()); if (sacrificedPermanents != null && !sacrificedPermanents.isEmpty()) { diff --git a/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java b/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java index fb1f645ac02..41df9ae8fa4 100644 --- a/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java +++ b/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java @@ -34,7 +34,7 @@ public final class BridgeFromBelow extends CardImpl { static{ filter1.add(new ControllerPredicate(TargetController.YOU)); - filter1.add(Predicates.not(new TokenPredicate())); + filter1.add(Predicates.not(TokenPredicate.instance)); filter2.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/b/Brightflame.java b/Mage.Sets/src/mage/cards/b/Brightflame.java index 8e70b4a364b..54f8ab2edf0 100644 --- a/Mage.Sets/src/mage/cards/b/Brightflame.java +++ b/Mage.Sets/src/mage/cards/b/Brightflame.java @@ -29,7 +29,7 @@ public final class Brightflame extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}{R}{W}{W}"); // Radiance - Brightflame deals X damage to target creature and each other creature that shares a color with it. You gain life equal to the damage dealt this way. - this.getSpellAbility().addEffect(new BrightflameEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new BrightflameEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().setAbilityWord(AbilityWord.RADIANCE); } diff --git a/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java b/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java index dd37a947c6d..d0fca035254 100644 --- a/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java +++ b/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java @@ -53,8 +53,8 @@ class BrimstoneVolleyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int damage = 3; - Watcher watcher = game.getState().getWatchers().get(MorbidWatcher.class.getSimpleName()); - if (watcher.conditionMet()) { + MorbidWatcher watcher = game.getState().getWatcher(MorbidWatcher.class); + if (watcher != null && watcher.conditionMet()) { damage = 5; } Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); diff --git a/Mage.Sets/src/mage/cards/b/BringToTrial.java b/Mage.Sets/src/mage/cards/b/BringToTrial.java new file mode 100644 index 00000000000..bf7b058150e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BringToTrial.java @@ -0,0 +1,42 @@ +package mage.cards.b; + +import mage.abilities.effects.common.ExileTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class BringToTrial extends CardImpl { + + static private final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power 4 or greater"); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public BringToTrial(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); + + + // Exile target creature with power 4 or greater. + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public BringToTrial(final BringToTrial card) { + super(card); + } + + @Override + public BringToTrial copy() { + return new BringToTrial(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BrionStoutarm.java b/Mage.Sets/src/mage/cards/b/BrionStoutarm.java index f6939807c74..a39a9e10602 100644 --- a/Mage.Sets/src/mage/cards/b/BrionStoutarm.java +++ b/Mage.Sets/src/mage/cards/b/BrionStoutarm.java @@ -30,7 +30,7 @@ public final class BrionStoutarm extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature other than Brion Stoutarm"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BrionStoutarm(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java b/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java index 484e49a2109..b9d4be4d1a3 100644 --- a/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java +++ b/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java @@ -30,7 +30,7 @@ public final class BrokenAmbitions extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}"); // Counter target spell unless its controller pays {X}. Clash with an opponent. If you win, that spell's controller puts the top four cards of their library into their graveyard. - this.getSpellAbility().addEffect(new BrokenAmbitionsEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new BrokenAmbitionsEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/b/BrokenVisage.java b/Mage.Sets/src/mage/cards/b/BrokenVisage.java index e250769885f..495b05ec36f 100644 --- a/Mage.Sets/src/mage/cards/b/BrokenVisage.java +++ b/Mage.Sets/src/mage/cards/b/BrokenVisage.java @@ -31,7 +31,7 @@ public final class BrokenVisage extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact attacking creature"); static { filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT))); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public BrokenVisage(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BronzeHorse.java b/Mage.Sets/src/mage/cards/b/BronzeHorse.java index 28180cf2bb4..bcd1ed31664 100644 --- a/Mage.Sets/src/mage/cards/b/BronzeHorse.java +++ b/Mage.Sets/src/mage/cards/b/BronzeHorse.java @@ -33,7 +33,7 @@ public final class BronzeHorse extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BronzeHorse(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BronzebeakMoa.java b/Mage.Sets/src/mage/cards/b/BronzebeakMoa.java index b8d9f77917c..949498cd939 100644 --- a/Mage.Sets/src/mage/cards/b/BronzebeakMoa.java +++ b/Mage.Sets/src/mage/cards/b/BronzebeakMoa.java @@ -25,7 +25,7 @@ public final class BronzebeakMoa extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature under your control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BronzebeakMoa (UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{W}"); diff --git a/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java b/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java index cb7d25fffe5..cd838bcfd06 100644 --- a/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java +++ b/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java @@ -1,34 +1,33 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.game.Game; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + import static mage.constants.Outcome.Benefit; /** - * * @author mpouedras */ public final class BroodOfCockroaches extends CardImpl { public BroodOfCockroaches(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); - + this.subtype.add(SubType.INSECT); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -37,7 +36,7 @@ public final class BroodOfCockroaches extends CardImpl { // at the beginning of the next end step, // you lose 1 life // and return Brood of Cockroaches to your hand. - this.addAbility(new DiesTriggeredAbility(new BroodOfCockroachesEffect())); + this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new BroodOfCockroachesEffect(), false, true)); } public BroodOfCockroaches(final BroodOfCockroaches card) { @@ -51,7 +50,7 @@ public final class BroodOfCockroaches extends CardImpl { } class BroodOfCockroachesEffect extends OneShotEffect { - private static final String effectText = "at the beginning of the next end step, you lose 1 life and return Brood of Cockroaches to your hand."; + private static final String effectText = "at the beginning of the next end step, you lose 1 life and return {this} to your hand."; BroodOfCockroachesEffect() { super(Benefit); diff --git a/Mage.Sets/src/mage/cards/b/BroodingSaurian.java b/Mage.Sets/src/mage/cards/b/BroodingSaurian.java index 9b71bf2e91c..221feab710f 100644 --- a/Mage.Sets/src/mage/cards/b/BroodingSaurian.java +++ b/Mage.Sets/src/mage/cards/b/BroodingSaurian.java @@ -50,7 +50,7 @@ class BroodingSaurianControlEffect extends ContinuousEffectImpl { private static final FilterPermanent filter = new FilterPermanent(); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public BroodingSaurianControlEffect() { diff --git a/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java b/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java index 1cfb85d3243..bacf632163e 100644 --- a/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java +++ b/Mage.Sets/src/mage/cards/b/BrothersYamazaki.java @@ -31,7 +31,7 @@ public final class BrothersYamazaki extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new NamePredicate("Brothers Yamazaki")); } diff --git a/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java b/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java index 3ed5ff115ef..ef8d9f5b947 100644 --- a/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java +++ b/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java @@ -31,7 +31,7 @@ public final class BrudicladTelchorEngineer extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature tokens you control"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public BrudicladTelchorEngineer(UUID ownerId, CardSetInfo setInfo) { @@ -64,7 +64,7 @@ class BrudicladTelchorEngineerEffect extends OneShotEffect { private static final FilterControlledPermanent filter = new FilterControlledPermanent("token you control"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public BrudicladTelchorEngineerEffect() { diff --git a/Mage.Sets/src/mage/cards/b/BrutalHordechief.java b/Mage.Sets/src/mage/cards/b/BrutalHordechief.java index e3b37d68008..c6e43f6dc7e 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalHordechief.java +++ b/Mage.Sets/src/mage/cards/b/BrutalHordechief.java @@ -74,7 +74,7 @@ public final class BrutalHordechief extends CardImpl { @Override public boolean apply(Game game, Ability source) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); if (watcher != null) { watcher.increment(); return true; @@ -155,7 +155,10 @@ class BrutalHordechiefChooseBlockersEffect extends ContinuousRuleModifyingEffect @Override public boolean applies(GameEvent event, Ability source, Game game) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); + if(watcher == null){ + return false; + } watcher.decrement(); if (watcher.copyCountApply > 0) { game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); diff --git a/Mage.Sets/src/mage/cards/b/BrutalSuppression.java b/Mage.Sets/src/mage/cards/b/BrutalSuppression.java index e45580406ed..0d332368773 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalSuppression.java +++ b/Mage.Sets/src/mage/cards/b/BrutalSuppression.java @@ -58,7 +58,7 @@ class BrutalSuppressionAdditionalCostEffect extends CostModificationEffectImpl { private static final FilterPermanent filter2 = new FilterPermanent("nontoken Rebels"); static{ filter2.add(new SubtypePredicate(SubType.REBEL)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } BrutalSuppressionAdditionalCostEffect() { diff --git a/Mage.Sets/src/mage/cards/b/BuildersBane.java b/Mage.Sets/src/mage/cards/b/BuildersBane.java index 094a17f47e8..7ee8821d2e8 100644 --- a/Mage.Sets/src/mage/cards/b/BuildersBane.java +++ b/Mage.Sets/src/mage/cards/b/BuildersBane.java @@ -1,11 +1,7 @@ package mage.cards.b; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -16,9 +12,13 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetArtifactPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; /** - * * @author sinsedrix */ public final class BuildersBane extends CardImpl { @@ -29,15 +29,7 @@ public final class BuildersBane extends CardImpl { // Destroy X target artifacts. Builder's Bane deals damage to each player equal to the number of artifacts he or she controlled put into a graveyard this way. this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addEffect(new BuildersBaneEffect()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetArtifactPermanent(xValue, xValue)); - } + this.getSpellAbility().setTargetAdjuster(BuildersBaneAdjuster.instance); } public BuildersBane(final BuildersBane card) { @@ -50,11 +42,22 @@ public final class BuildersBane extends CardImpl { } } +enum BuildersBaneAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetArtifactPermanent(xValue, xValue)); + } +} + class BuildersBaneEffect extends OneShotEffect { public BuildersBaneEffect() { super(Outcome.DestroyPermanent); - this.staticText = "Destroy X target artifacts. {this} deals damage to each player equal to the number of artifacts he or she controlled put into a graveyard this way"; + this.staticText = "Destroy X target artifacts. {this} deals damage to each player equal to the number of artifacts they controlled that were put into a graveyard this way"; } public BuildersBaneEffect(final BuildersBaneEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BullAurochs.java b/Mage.Sets/src/mage/cards/b/BullAurochs.java index 7f4e83734d8..7da88699f1b 100644 --- a/Mage.Sets/src/mage/cards/b/BullAurochs.java +++ b/Mage.Sets/src/mage/cards/b/BullAurochs.java @@ -27,7 +27,7 @@ public final class BullAurochs extends CardImpl { static { filter.add(new SubtypePredicate(SubType.AUROCHS)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BullAurochs(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BullRushBruiser.java b/Mage.Sets/src/mage/cards/b/BullRushBruiser.java index ac0cfeaab98..b89ace249d7 100644 --- a/Mage.Sets/src/mage/cards/b/BullRushBruiser.java +++ b/Mage.Sets/src/mage/cards/b/BullRushBruiser.java @@ -24,7 +24,7 @@ public final class BullRushBruiser extends CardImpl { private static final FilterTeamPermanent filter = new FilterTeamPermanent(SubType.WARRIOR, "another Warrior"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public BullRushBruiser(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/b/BurdenOfGreed.java b/Mage.Sets/src/mage/cards/b/BurdenOfGreed.java index 124aac6ceb2..2f8ad795d0c 100644 --- a/Mage.Sets/src/mage/cards/b/BurdenOfGreed.java +++ b/Mage.Sets/src/mage/cards/b/BurdenOfGreed.java @@ -48,7 +48,7 @@ class BurdenOfGreedCount implements DynamicValue { return 0; } FilterArtifactPermanent filter = new FilterArtifactPermanent(); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerIdPredicate(sourceAbility.getFirstTarget())); return game.getBattlefield().count(filter, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game); } diff --git a/Mage.Sets/src/mage/cards/b/BurnAtTheStake.java b/Mage.Sets/src/mage/cards/b/BurnAtTheStake.java index b804747d354..7707490f2de 100644 --- a/Mage.Sets/src/mage/cards/b/BurnAtTheStake.java +++ b/Mage.Sets/src/mage/cards/b/BurnAtTheStake.java @@ -27,7 +27,7 @@ public final class BurnAtTheStake extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public BurnAtTheStake(UUID ownerId, CardSetInfo setInfo) { @@ -69,7 +69,7 @@ class BurnAtTheStakeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int amount = (new GetXValue()).calculate(game, source, this) * 3; + int amount = (GetXValue.instance).calculate(game, source, this) * 3; Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); if (permanent != null) { diff --git a/Mage.Sets/src/mage/cards/b/BurnBright.java b/Mage.Sets/src/mage/cards/b/BurnBright.java new file mode 100644 index 00000000000..bfc8e02a9d7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BurnBright.java @@ -0,0 +1,31 @@ +package mage.cards.b; + +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BurnBright extends CardImpl { + + public BurnBright(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); + + // Creatures you control get +2/+0 until end of turn. + this.getSpellAbility().addEffect(new BoostControlledEffect(2, 0, Duration.EndOfTurn)); + } + + private BurnBright(final BurnBright card) { + super(card); + } + + @Override + public BurnBright copy() { + return new BurnBright(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java b/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java index 1585222ed7b..ec620a455e0 100644 --- a/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java +++ b/Mage.Sets/src/mage/cards/b/BurningCinderFuryOfCrimsonChaosFire.java @@ -184,7 +184,7 @@ class BurningCinderFuryOfCrimsonChaosFireCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - BurningCinderFuryOfCrimsonChaosFireWatcher watcher = (BurningCinderFuryOfCrimsonChaosFireWatcher) game.getState().getWatchers().get(BurningCinderFuryOfCrimsonChaosFireWatcher.class.getSimpleName()); + BurningCinderFuryOfCrimsonChaosFireWatcher watcher = game.getState().getWatcher(BurningCinderFuryOfCrimsonChaosFireWatcher.class); if (watcher != null) { return !watcher.tappedNonlandThisTurn(game.getActivePlayerId()); } diff --git a/Mage.Sets/src/mage/cards/b/BurningOfXinye.java b/Mage.Sets/src/mage/cards/b/BurningOfXinye.java index 1d7ff56bc77..16a159d914d 100644 --- a/Mage.Sets/src/mage/cards/b/BurningOfXinye.java +++ b/Mage.Sets/src/mage/cards/b/BurningOfXinye.java @@ -89,7 +89,7 @@ class BurningOfXinyeEffect extends OneShotEffect{ } for ( int idx = 0; idx < target.getTargets().size(); idx++) { - Permanent permanent = game.getPermanent((UUID)target.getTargets().get(idx)); + Permanent permanent = game.getPermanent(target.getTargets().get(idx)); if ( permanent != null ) { abilityApplied |= permanent.destroy(source.getSourceId(), game, false); diff --git a/Mage.Sets/src/mage/cards/b/BurningSands.java b/Mage.Sets/src/mage/cards/b/BurningSands.java index a8c0af943b0..01f30e5a5d8 100644 --- a/Mage.Sets/src/mage/cards/b/BurningSands.java +++ b/Mage.Sets/src/mage/cards/b/BurningSands.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; @@ -12,39 +11,29 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BurningSands extends CardImpl { - private final UUID originalId; - public BurningSands(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}"); // Whenever a creature dies, that creature's controller sacrifices a land. - Ability ability = new DiesCreatureTriggeredAbility(new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "that creature's controller"), false, false, true); - originalId = ability.getOriginalId(); + Ability ability = new DiesCreatureTriggeredAbility(new SacrificeEffect( + StaticFilters.FILTER_LAND, 1, "that creature's controller" + ), false, false, true); + ability.setTargetAdjuster(BurningSandsAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - UUID creatureId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); - Permanent creature = (Permanent) game.getLastKnownInformation(creatureId, Zone.BATTLEFIELD); - if (creature != null) { - ability.getEffects().get(0).setTargetPointer(new FixedTarget(creature.getControllerId())); - } - } - } - public BurningSands(final BurningSands card) { super(card); - this.originalId = card.originalId; } @Override @@ -52,3 +41,16 @@ public final class BurningSands extends CardImpl { return new BurningSands(this); } } + +enum BurningSandsAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + UUID creatureId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + Permanent creature = game.getPermanentOrLKIBattlefield(creatureId); + if (creature != null) { + ability.getEffects().get(0).setTargetPointer(new FixedTarget(creature.getControllerId())); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java b/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java index 52fd5e5c25c..18b29ddd9b7 100644 --- a/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java +++ b/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.dynamicvalue.common.StaticValue; @@ -19,14 +17,15 @@ import mage.game.events.GameEvent.EventType; import mage.game.stack.StackAbility; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author Loki */ public final class BurningTreeShaman extends CardImpl { public BurningTreeShaman(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); this.subtype.add(SubType.CENTAUR, SubType.SHAMAN); this.power = new MageInt(3); @@ -49,7 +48,7 @@ public final class BurningTreeShaman extends CardImpl { class BurningTreeShamanTriggeredAbility extends TriggeredAbilityImpl { BurningTreeShamanTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(new StaticValue(1), false, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(new StaticValue(1), true, "that player", true)); } BurningTreeShamanTriggeredAbility(final BurningTreeShamanTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/b/BurningTreeVandal.java b/Mage.Sets/src/mage/cards/b/BurningTreeVandal.java new file mode 100644 index 00000000000..fe6ea62ee96 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BurningTreeVandal.java @@ -0,0 +1,46 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BurningTreeVandal extends CardImpl { + + public BurningTreeVandal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Riot + this.addAbility(new RiotAbility()); + + // Whenever Burning-Tree Vandal attacks, you may discard a card. If you do, draw a card. + this.addAbility(new AttacksTriggeredAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(1), new DiscardCardCost() + ), false)); + } + + private BurningTreeVandal(final BurningTreeVandal card) { + super(card); + } + + @Override + public BurningTreeVandal copy() { + return new BurningTreeVandal(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/ByForce.java b/Mage.Sets/src/mage/cards/b/ByForce.java index 2263b8fc364..5c42282251b 100644 --- a/Mage.Sets/src/mage/cards/b/ByForce.java +++ b/Mage.Sets/src/mage/cards/b/ByForce.java @@ -1,18 +1,18 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.game.Game; import mage.target.common.TargetArtifactPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author spjspj */ public final class ByForce extends CardImpl { @@ -23,15 +23,7 @@ public final class ByForce extends CardImpl { // Destroy X target artifacts. this.getSpellAbility().addEffect(new DestroyTargetEffect("Destroy X target artifacts")); this.getSpellAbility().addTarget(new TargetArtifactPermanent()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetArtifactPermanent(xValue, xValue)); - } + this.getSpellAbility().setTargetAdjuster(ByForceAdjuster.instance); } public ByForce(final ByForce card) { @@ -43,3 +35,14 @@ public final class ByForce extends CardImpl { return new ByForce(this); } } + +enum ByForceAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetArtifactPermanent(xValue, xValue)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CabalInterrogator.java b/Mage.Sets/src/mage/cards/c/CabalInterrogator.java index 7e8862fdb93..4fd7e496e3d 100644 --- a/Mage.Sets/src/mage/cards/c/CabalInterrogator.java +++ b/Mage.Sets/src/mage/cards/c/CabalInterrogator.java @@ -78,7 +78,7 @@ class CabalInterrogatorEffect extends OneShotEffect { return false; } - int amountToReveal = (new ManacostVariableValue()).calculate(game, source, this); + int amountToReveal = (ManacostVariableValue.instance).calculate(game, source, this); Cards revealedCards = new CardsImpl(); if (amountToReveal > 0 && targetPlayer.getHand().size() > amountToReveal) { diff --git a/Mage.Sets/src/mage/cards/c/CacklingWitch.java b/Mage.Sets/src/mage/cards/c/CacklingWitch.java index ec76eecd38d..37f93e1542a 100644 --- a/Mage.Sets/src/mage/cards/c/CacklingWitch.java +++ b/Mage.Sets/src/mage/cards/c/CacklingWitch.java @@ -33,7 +33,7 @@ public final class CacklingWitch extends CardImpl { this.toughness = new MageInt(1); // {X}{B}, {tap}, Discard a card: Target creature gets +X/+0 until end of turn. - ManacostVariableValue manaX = new ManacostVariableValue(); + ManacostVariableValue manaX = ManacostVariableValue.instance; Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(manaX, new StaticValue(0), Duration.EndOfTurn), new ManaCostsImpl("{X}{B}")); diff --git a/Mage.Sets/src/mage/cards/c/CalciformPools.java b/Mage.Sets/src/mage/cards/c/CalciformPools.java index 72702e77fde..9d123691915 100644 --- a/Mage.Sets/src/mage/cards/c/CalciformPools.java +++ b/Mage.Sets/src/mage/cards/c/CalciformPools.java @@ -36,7 +36,7 @@ public final class CalciformPools extends CardImpl { this.addAbility(ability); // {1}, Remove X storage counters from Calciform Pools: Add X mana in any combination of {W} and/or {U}. ability = new SimpleManaAbility(Zone.BATTLEFIELD, - new AddManaInAnyCombinationEffect(new RemovedCountersForCostValue(), ColoredManaSymbol.W, ColoredManaSymbol.U), + new AddManaInAnyCombinationEffect(RemovedCountersForCostValue.instance, ColoredManaSymbol.W, ColoredManaSymbol.U), new GenericManaCost(1)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance())); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java b/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java index e5607074fe6..1a36673626a 100644 --- a/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java +++ b/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java @@ -114,7 +114,7 @@ class CallerOfTheClawDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - CallerOfTheClawWatcher watcher = (CallerOfTheClawWatcher) game.getState().getWatchers().get(CallerOfTheClawWatcher.class.getSimpleName(), sourceAbility.getControllerId()); + CallerOfTheClawWatcher watcher = game.getState().getWatcher(CallerOfTheClawWatcher.class, sourceAbility.getControllerId()); if (watcher != null) { return watcher.getCreaturesCount(); } diff --git a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java index f05249eeac4..37eb08abbed 100644 --- a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java +++ b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java @@ -1,14 +1,15 @@ package mage.cards.c; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.SetPowerSourceEffect; import mage.abilities.effects.common.continuous.SetToughnessSourceEffect; import mage.cards.CardImpl; @@ -21,8 +22,9 @@ import mage.filter.predicate.mageobject.ChosenSubtypePredicate; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class CallerOfTheHunt extends CardImpl { @@ -34,14 +36,24 @@ public final class CallerOfTheHunt extends CardImpl { // As an additional cost to cast Caller of the Hunt, choose a creature type. // Caller of the Hunt's power and toughness are each equal to the number of creatures of the chosen type on the battlefield. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new CallerOfTheHuntAdditionalCostEffect())); - + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("as an additional cost to cast this spell, choose a creature type. \r" + + "{this}'s power and toughness are each equal to the number of creatures of the chosen type on the battlefield"))); + this.getSpellAbility().setCostAdjuster(CallerOfTheHuntAdjuster.instance); } public CallerOfTheHunt(final CallerOfTheHunt card) { super(card); } + @Override + public CallerOfTheHunt copy() { + return new CallerOfTheHunt(this); + } +} + +enum CallerOfTheHuntAdjuster implements CostAdjuster { + instance; + @Override public void adjustCosts(Ability ability, Game game) { MageObject mageObject = game.getObject(ability.getSourceId()); @@ -56,34 +68,6 @@ public final class CallerOfTheHunt extends CardImpl { game.addEffect(effectToughness, ability); } } - - @Override - public CallerOfTheHunt copy() { - return new CallerOfTheHunt(this); - } -} - -class CallerOfTheHuntAdditionalCostEffect extends OneShotEffect { - - public CallerOfTheHuntAdditionalCostEffect() { - super(Outcome.Benefit); - this.staticText = "as an additional cost to cast this spell, choose a creature type. \r" - + "{this}'s power and toughness are each equal to the number of creatures of the chosen type on the battlefield"; - } - - public CallerOfTheHuntAdditionalCostEffect(final CallerOfTheHuntAdditionalCostEffect effect) { - super(effect); - } - - @Override - public CallerOfTheHuntAdditionalCostEffect copy() { - return new CallerOfTheHuntAdditionalCostEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } } class ChooseCreatureTypeEffect extends OneShotEffect { // code by LevelX2, but that other version is not compatible with this card @@ -116,5 +100,4 @@ class ChooseCreatureTypeEffect extends OneShotEffect { // code by LevelX2, but t public ChooseCreatureTypeEffect copy() { return new ChooseCreatureTypeEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/c/CalmingVerse.java b/Mage.Sets/src/mage/cards/c/CalmingVerse.java index 8d94a2f0d86..08a66a28efc 100644 --- a/Mage.Sets/src/mage/cards/c/CalmingVerse.java +++ b/Mage.Sets/src/mage/cards/c/CalmingVerse.java @@ -50,7 +50,7 @@ class CalmingVerseEffect extends OneShotEffect { static { untappedLandFilter.add(new CardTypePredicate(CardType.LAND)); - untappedLandFilter.add(Predicates.not(new TappedPredicate())); + untappedLandFilter.add(Predicates.not(TappedPredicate.instance)); } private static final FilterEnchantmentPermanent opponentEnchantmentsFilter = new FilterEnchantmentPermanent("enchantments you don't control"); diff --git a/Mage.Sets/src/mage/cards/c/CantonicaCasino.java b/Mage.Sets/src/mage/cards/c/CantonicaCasino.java index 4c528b303d5..f91d45b6987 100644 --- a/Mage.Sets/src/mage/cards/c/CantonicaCasino.java +++ b/Mage.Sets/src/mage/cards/c/CantonicaCasino.java @@ -1,13 +1,9 @@ package mage.cards.c; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.RollDiceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -15,21 +11,21 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author NinthWorld */ public final class CantonicaCasino extends CardImpl { public CantonicaCasino(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - // {T}: Roll two six-sided dice. If you roll doubles, gain 10 life. Otherwise, lose 1 life. this.addAbility(new SimpleActivatedAbility(new CantonicaCasinoEffect(), new TapSourceCost())); } - public CantonicaCasino(final CantonicaCasino card) { + private CantonicaCasino(final CantonicaCasino card) { super(card); } @@ -41,33 +37,31 @@ public final class CantonicaCasino extends CardImpl { class CantonicaCasinoEffect extends OneShotEffect { - public CantonicaCasinoEffect() { + CantonicaCasinoEffect() { super(Outcome.Neutral); - staticText = "Roll two six-sided dice. If you roll doubles, gain 10 life. Otherwise, lose 1 life"; + staticText = "Roll two six-sided dice. If you roll doubles, gain 10 life. Otherwise, you lose 1 life"; } - public CantonicaCasinoEffect(final CantonicaCasinoEffect effect) { + private CantonicaCasinoEffect(final CantonicaCasinoEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); - if(you != null) { + if (you != null) { // Roll two six-sided dice int dice1 = you.rollDice(game, 6); int dice2 = you.rollDice(game, 6); - if(dice1 == dice2) { + if (dice1 == dice2) { // If you roll doubles, gain 10 life you.gainLife(10, game, source); - return false; - } - else { + } else { // Otherwise, lose 1 life you.loseLife(1, game, false); - return false; } + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CaptainOfTheMists.java b/Mage.Sets/src/mage/cards/c/CaptainOfTheMists.java index 2a1470958ca..b936bb82bf2 100644 --- a/Mage.Sets/src/mage/cards/c/CaptainOfTheMists.java +++ b/Mage.Sets/src/mage/cards/c/CaptainOfTheMists.java @@ -31,7 +31,7 @@ public final class CaptainOfTheMists extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another Human"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.HUMAN)); } diff --git a/Mage.Sets/src/mage/cards/c/CaptainPhasma.java b/Mage.Sets/src/mage/cards/c/CaptainPhasma.java index 829342d2b6c..d37a042cd13 100644 --- a/Mage.Sets/src/mage/cards/c/CaptainPhasma.java +++ b/Mage.Sets/src/mage/cards/c/CaptainPhasma.java @@ -32,7 +32,7 @@ public final class CaptainPhasma extends CardImpl { static { filter.add(new SubtypePredicate(SubType.TROOPER)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filterCard.add(new SubtypePredicate(SubType.TROOPER)); } diff --git a/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java b/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java index 7262d6bc79f..7ae21466188 100644 --- a/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java +++ b/Mage.Sets/src/mage/cards/c/CaptivatingVampire.java @@ -34,7 +34,7 @@ public final class CaptivatingVampire extends CardImpl { static { filter1.add(new SubtypePredicate(SubType.VAMPIRE)); filter2.add(new SubtypePredicate(SubType.VAMPIRE)); - filter2.add(Predicates.not(new TappedPredicate())); + filter2.add(Predicates.not(TappedPredicate.instance)); } public CaptivatingVampire(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CaptiveAudience.java b/Mage.Sets/src/mage/cards/c/CaptiveAudience.java new file mode 100644 index 00000000000..1c1fc05480a --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CaptiveAudience.java @@ -0,0 +1,138 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenTargetEffect; +import mage.abilities.effects.common.SetPlayerLifeSourceEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.common.discard.DiscardHandControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; +import mage.game.permanent.token.ZombieToken; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetOpponent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +import static mage.constants.Outcome.Benefit; + +/** + * @author TheElk801 + */ +public final class CaptiveAudience extends CardImpl { + + public CaptiveAudience(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{B}{R}"); + + // Captive Audience enters the battlefield under the control of an opponent of your choice. + this.addAbility(new EntersBattlefieldAbility(new CaptiveAudienceETBEffect())); + + // At the beginning of your upkeep, choose one that hasn't been chosen — + // • Your life total becomes 4. + Ability ability = new BeginningOfUpkeepTriggeredAbility(new SetPlayerLifeSourceEffect(4), TargetController.YOU, false); + ability.getModes().setEachModeOnlyOnce(true); + + // • Discard your hand. + ability.addMode(new Mode(new DiscardHandControllerEffect())); + + // • Each opponent creates five 2/2 black Zombie creature tokens. + ability.addMode(new Mode(new CaptiveAudienceCreateTokensEffect())); + this.addAbility(ability); + } + + private CaptiveAudience(final CaptiveAudience card) { + super(card); + } + + @Override + public CaptiveAudience copy() { + return new CaptiveAudience(this); + } +} + +class CaptiveAudienceETBEffect extends OneShotEffect { + + CaptiveAudienceETBEffect() { + super(Benefit); + staticText = "under the control of an opponent of your choice"; + } + + private CaptiveAudienceETBEffect(final CaptiveAudienceETBEffect effect) { + super(effect); + } + + @Override + public CaptiveAudienceETBEffect copy() { + return new CaptiveAudienceETBEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Target target = new TargetOpponent(); + target.setNotTarget(true); + if (!controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) { + return false; + } + Player player = game.getPlayer(target.getFirstTarget()); + if (player == null) { + return false; + } + ContinuousEffect continuousEffect = new GainControlTargetEffect( + Duration.WhileOnBattlefield, true, player.getId() + ); + continuousEffect.setTargetPointer( + new FixedTarget(source.getSourceId(), source.getSourceObjectZoneChangeCounter()) + ); + game.addEffect(continuousEffect, source); + return true; + } +} + +class CaptiveAudienceCreateTokensEffect extends OneShotEffect { + + CaptiveAudienceCreateTokensEffect() { + super(Benefit); + staticText = "Each opponent creates five 2/2 black Zombie creature tokens."; + } + + private CaptiveAudienceCreateTokensEffect(final CaptiveAudienceCreateTokensEffect effect) { + super(effect); + } + + @Override + public CaptiveAudienceCreateTokensEffect copy() { + return new CaptiveAudienceCreateTokensEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + for (Player player : game.getPlayers().values()) { + if (player != null && controller.hasOpponent(player.getId(), game)) { + Effect effect = new CreateTokenTargetEffect(new ZombieToken(), 5); + effect.setTargetPointer(new FixedTarget(player.getId(), game)); + effect.apply(game, source); + } + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CarapaceForger.java b/Mage.Sets/src/mage/cards/c/CarapaceForger.java index 03ce8bd225e..01d92bba753 100644 --- a/Mage.Sets/src/mage/cards/c/CarapaceForger.java +++ b/Mage.Sets/src/mage/cards/c/CarapaceForger.java @@ -2,40 +2,44 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author Loki */ public final class CarapaceForger extends CardImpl { - private static final String text = "Metalcraft — Carapace Forger gets +2/+2 as long as you control three or more artifacts"; - public CarapaceForger (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + public CarapaceForger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.ARTIFICER); this.power = new MageInt(2); this.toughness = new MageInt(2); - ContinuousEffect boostSource = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield); - ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, text); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), + MetalcraftCondition.instance, "Metalcraft — {this} gets " + + "+2/+2 as long as you control three or more artifacts" + ) + )); } - public CarapaceForger (final CarapaceForger card) { + public CarapaceForger(final CarapaceForger card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/c/CarefulConsideration.java b/Mage.Sets/src/mage/cards/c/CarefulConsideration.java index 17f41df1874..f23ff03b5c6 100644 --- a/Mage.Sets/src/mage/cards/c/CarefulConsideration.java +++ b/Mage.Sets/src/mage/cards/c/CarefulConsideration.java @@ -2,7 +2,7 @@ package mage.cards.c; import java.util.UUID; -import mage.abilities.condition.common.MyMainPhaseCondition; +import mage.abilities.condition.common.AddendumCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawDiscardTargetEffect; import mage.cards.CardImpl; @@ -24,7 +24,7 @@ public final class CarefulConsideration extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new DrawDiscardTargetEffect(4,2), new DrawDiscardTargetEffect(4,3), - MyMainPhaseCondition.instance, + AddendumCondition.instance, "Target player draws four cards, then discards three cards. If you cast this spell during your main phase, instead that player draws four cards, then discards two cards")); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/c/CaribouRange.java b/Mage.Sets/src/mage/cards/c/CaribouRange.java index f2ae348ca77..4599b610cea 100644 --- a/Mage.Sets/src/mage/cards/c/CaribouRange.java +++ b/Mage.Sets/src/mage/cards/c/CaribouRange.java @@ -34,7 +34,7 @@ public final class CaribouRange extends CardImpl { static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a Caribou token"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); filter.add(new SubtypePredicate(SubType.CARIBOU)); } diff --git a/Mage.Sets/src/mage/cards/c/CarnifexDemon.java b/Mage.Sets/src/mage/cards/c/CarnifexDemon.java index 9d2bb438dd5..72a8bdb8689 100644 --- a/Mage.Sets/src/mage/cards/c/CarnifexDemon.java +++ b/Mage.Sets/src/mage/cards/c/CarnifexDemon.java @@ -28,7 +28,7 @@ public final class CarnifexDemon extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CarnifexDemon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java b/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java new file mode 100644 index 00000000000..e5cdc2a4437 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java @@ -0,0 +1,82 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CarnivalCarnage extends SplitCard { + + public CarnivalCarnage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{B/R}", "{2}{B}{R}", SpellAbilityType.SPLIT); + + // Carnival + // Carnival deals 1 damage to target creature or planeswalker and 1 damage to that permanent's controller. + this.getLeftHalfCard().getSpellAbility().addEffect(new CarnivalEffect()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker()); + + // Carnage + // Carnage deals 3 damage to target opponent. That player discards two cards. + this.getRightHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(3)); + this.getRightHalfCard().getSpellAbility().addEffect( + new DiscardTargetEffect(2).setText("That player discards two cards.") + ); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetOpponent()); + } + + private CarnivalCarnage(final CarnivalCarnage card) { + super(card); + } + + @Override + public CarnivalCarnage copy() { + return new CarnivalCarnage(this); + } +} + +class CarnivalEffect extends OneShotEffect { + + CarnivalEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 1 damage to target creature or planeswalker " + + "and 1 damage to that permanent's controller"; + } + + private CarnivalEffect(final CarnivalEffect effect) { + super(effect); + } + + @Override + public CarnivalEffect copy() { + return new CarnivalEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + permanent.damage(1, source.getSourceId(), game); + Player player = game.getPlayer(permanent.getControllerId()); + if (player != null) { + player.damage(1, source.getSourceId(), game); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/Carrion.java b/Mage.Sets/src/mage/cards/c/Carrion.java index 335d1c595a4..befed330ea5 100644 --- a/Mage.Sets/src/mage/cards/c/Carrion.java +++ b/Mage.Sets/src/mage/cards/c/Carrion.java @@ -25,7 +25,7 @@ public final class Carrion extends CardImpl { this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); // Put X 0/1 black Insect creature tokens onto the battlefield, where X is the sacrificed creature's power. - this.getSpellAbility().addEffect(new CreateTokenEffect(new CarrionBlackInsectToken(), new SacrificeCostCreaturesPower())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new CarrionBlackInsectToken(), SacrificeCostCreaturesPower.instance)); } public Carrion(final Carrion card) { diff --git a/Mage.Sets/src/mage/cards/c/CarrionImp.java b/Mage.Sets/src/mage/cards/c/CarrionImp.java new file mode 100644 index 00000000000..0804414d36b --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CarrionImp.java @@ -0,0 +1,51 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CarrionImp extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature card from a graveyard"); + + public CarrionImp(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.IMP); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Carrion Imp enters the battlefield, you may exile target creature card from a graveyard. If you do, you gain 2 life. + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect(), true); + ability.addEffect(new GainLifeEffect(2).concatBy("If you do,")); + ability.addTarget(new TargetCardInGraveyard(filter)); + this.addAbility(ability); + } + + private CarrionImp(final CarrionImp card) { + super(card); + } + + @Override + public CarrionImp copy() { + return new CarrionImp(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CatacombCrocodile.java b/Mage.Sets/src/mage/cards/c/CatacombCrocodile.java new file mode 100644 index 00000000000..d6beb926a3e --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CatacombCrocodile.java @@ -0,0 +1,32 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CatacombCrocodile extends CardImpl { + + public CatacombCrocodile(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.subtype.add(SubType.CROCODILE); + this.power = new MageInt(3); + this.toughness = new MageInt(7); + } + + private CatacombCrocodile(final CatacombCrocodile card) { + super(card); + } + + @Override + public CatacombCrocodile copy() { + return new CatacombCrocodile(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CatacombSifter.java b/Mage.Sets/src/mage/cards/c/CatacombSifter.java index 43f3e15b984..39d60404112 100644 --- a/Mage.Sets/src/mage/cards/c/CatacombSifter.java +++ b/Mage.Sets/src/mage/cards/c/CatacombSifter.java @@ -26,7 +26,7 @@ public final class CatacombSifter extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/c/CatapultMaster.java b/Mage.Sets/src/mage/cards/c/CatapultMaster.java index 0664a36eb64..ea9a17d070a 100644 --- a/Mage.Sets/src/mage/cards/c/CatapultMaster.java +++ b/Mage.Sets/src/mage/cards/c/CatapultMaster.java @@ -28,7 +28,7 @@ public final class CatapultMaster extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Soldiers you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.SOLDIER)); } public CatapultMaster(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CatapultSquad.java b/Mage.Sets/src/mage/cards/c/CatapultSquad.java index db703b595e1..b8b9bd3af75 100644 --- a/Mage.Sets/src/mage/cards/c/CatapultSquad.java +++ b/Mage.Sets/src/mage/cards/c/CatapultSquad.java @@ -29,7 +29,7 @@ public final class CatapultSquad extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Soldiers you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.SOLDIER)); } diff --git a/Mage.Sets/src/mage/cards/c/CathedralMembrane.java b/Mage.Sets/src/mage/cards/c/CathedralMembrane.java index 01c4248f3f3..c68b2490952 100644 --- a/Mage.Sets/src/mage/cards/c/CathedralMembrane.java +++ b/Mage.Sets/src/mage/cards/c/CathedralMembrane.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.*; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ZoneChangeTriggeredAbility; @@ -15,6 +14,10 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * @author BetaSteward */ @@ -35,7 +38,7 @@ public final class CathedralMembrane extends CardImpl { } - public CathedralMembrane(final CathedralMembrane card) { + private CathedralMembrane(final CathedralMembrane card) { super(card); } @@ -47,11 +50,11 @@ public final class CathedralMembrane extends CardImpl { class CathedralMembraneAbility extends ZoneChangeTriggeredAbility { - public CathedralMembraneAbility() { + CathedralMembraneAbility() { super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CathedralMembraneEffect(), "When {this} dies during combat, ", false); } - public CathedralMembraneAbility(CathedralMembraneAbility ability) { + private CathedralMembraneAbility(CathedralMembraneAbility ability) { super(ability); } @@ -74,12 +77,12 @@ class CathedralMembraneAbility extends ZoneChangeTriggeredAbility { class CathedralMembraneEffect extends OneShotEffect { - public CathedralMembraneEffect() { + CathedralMembraneEffect() { super(Outcome.Damage); staticText = "it deals 6 damage to each creature it blocked this combat"; } - public CathedralMembraneEffect(final CathedralMembraneEffect effect) { + private CathedralMembraneEffect(final CathedralMembraneEffect effect) { super(effect); } @@ -90,9 +93,9 @@ class CathedralMembraneEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - CathedralMembraneWatcher watcher = (CathedralMembraneWatcher) game.getState().getWatchers().get(CathedralMembraneWatcher.class.getSimpleName(), source.getSourceId()); + CathedralMembraneWatcher watcher = game.getState().getWatcher(CathedralMembraneWatcher.class, source.getSourceId()); if (watcher != null) { - for (UUID uuid : watcher.blockedCreatures) { + for (UUID uuid : watcher.getBlockedCreatures()) { Permanent permanent = game.getPermanent(uuid); if (permanent != null) { permanent.damage(6, source.getSourceId(), game, false, true); @@ -105,13 +108,13 @@ class CathedralMembraneEffect extends OneShotEffect { class CathedralMembraneWatcher extends Watcher { - public Set blockedCreatures = new HashSet<>(); + private final Set blockedCreatures = new HashSet<>(); - public CathedralMembraneWatcher() { + CathedralMembraneWatcher() { super(CathedralMembraneWatcher.class.getSimpleName(), WatcherScope.CARD); } - public CathedralMembraneWatcher(final CathedralMembraneWatcher watcher) { + private CathedralMembraneWatcher(final CathedralMembraneWatcher watcher) { super(watcher); this.blockedCreatures.addAll(watcher.blockedCreatures); } @@ -134,4 +137,7 @@ class CathedralMembraneWatcher extends Watcher { blockedCreatures.clear(); } + Set getBlockedCreatures() { + return blockedCreatures; + } } diff --git a/Mage.Sets/src/mage/cards/c/CauldronHaze.java b/Mage.Sets/src/mage/cards/c/CauldronHaze.java index db95a2d1e11..28f0e6d9c7e 100644 --- a/Mage.Sets/src/mage/cards/c/CauldronHaze.java +++ b/Mage.Sets/src/mage/cards/c/CauldronHaze.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.PersistAbility; import mage.cards.CardImpl; @@ -10,13 +9,14 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class CauldronHaze extends CardImpl { - private final String rule = "Choose any number of target creatures. Each of those creatures gains persist until end of turn"; + private static final String rule = "Choose any number of target creatures. Each of those creatures gains persist until end of turn"; public CauldronHaze(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W/B}"); @@ -24,7 +24,6 @@ public final class CauldronHaze extends CardImpl { // Choose any number of target creatures. Each of those creatures gains persist until end of turn. this.getSpellAbility().addEffect(new GainAbilityTargetEffect(new PersistAbility(), Duration.EndOfTurn, rule)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); - } public CauldronHaze(final CauldronHaze card) { diff --git a/Mage.Sets/src/mage/cards/c/CavalcadeOfCalamity.java b/Mage.Sets/src/mage/cards/c/CavalcadeOfCalamity.java new file mode 100644 index 00000000000..7c7f863bad6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CavalcadeOfCalamity.java @@ -0,0 +1,72 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CavalcadeOfCalamity extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creaure you control with power 1 or less"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 2)); + } + + public CavalcadeOfCalamity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + + // Whenever a creature you control with power 1 or less attacks, Cavalcade of Calamity deals 1 damage to the player or planeswalker that creature is attacking. + this.addAbility(new AttacksAllTriggeredAbility( + new CavalcadeOfCalamityEffect(), false, filter, + SetTargetPointer.PERMANENT, false, false + )); + } + + private CavalcadeOfCalamity(final CavalcadeOfCalamity card) { + super(card); + } + + @Override + public CavalcadeOfCalamity copy() { + return new CavalcadeOfCalamity(this); + } +} + +class CavalcadeOfCalamityEffect extends OneShotEffect { + + CavalcadeOfCalamityEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 1 damage to the player or planeswalker that creature is attacking."; + } + + private CavalcadeOfCalamityEffect(final CavalcadeOfCalamityEffect effect) { + super(effect); + } + + @Override + public CavalcadeOfCalamityEffect copy() { + return new CavalcadeOfCalamityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return game.damagePlayerOrPlaneswalker( + game.getCombat().getDefenderId(targetPointer.getFirst(game, source)), 1, + source.getSourceId(), game, false, true + ) > 0; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CavalryPegasus.java b/Mage.Sets/src/mage/cards/c/CavalryPegasus.java index 023e566e087..6d46fa8c7c9 100644 --- a/Mage.Sets/src/mage/cards/c/CavalryPegasus.java +++ b/Mage.Sets/src/mage/cards/c/CavalryPegasus.java @@ -25,7 +25,7 @@ public final class CavalryPegasus extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("each attacking Human"); static { filter.add(new SubtypePredicate(SubType.HUMAN)); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public CavalryPegasus(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CavernOfSouls.java b/Mage.Sets/src/mage/cards/c/CavernOfSouls.java index 87e9f839ebe..57d0c4482e4 100644 --- a/Mage.Sets/src/mage/cards/c/CavernOfSouls.java +++ b/Mage.Sets/src/mage/cards/c/CavernOfSouls.java @@ -197,7 +197,7 @@ class CavernOfSoulsCantCounterEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - CavernOfSoulsWatcher watcher = (CavernOfSoulsWatcher) game.getState().getWatchers().get(CavernOfSoulsWatcher.class.getSimpleName(), source.getSourceId()); + CavernOfSoulsWatcher watcher = game.getState().getWatcher(CavernOfSoulsWatcher.class, source.getSourceId()); Spell spell = game.getStack().getSpell(event.getTargetId()); return spell != null && watcher != null && watcher.spellCantBeCountered(spell.getId()); } diff --git a/Mage.Sets/src/mage/cards/c/CennsHeir.java b/Mage.Sets/src/mage/cards/c/CennsHeir.java index ed5c3645f2b..c5dc2acad2a 100644 --- a/Mage.Sets/src/mage/cards/c/CennsHeir.java +++ b/Mage.Sets/src/mage/cards/c/CennsHeir.java @@ -25,7 +25,7 @@ public final class CennsHeir extends CardImpl { static { filter.add(new SubtypePredicate(SubType.KITHKIN)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CennsHeir(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CephalidShrine.java b/Mage.Sets/src/mage/cards/c/CephalidShrine.java index 4bd752a8408..63121de89df 100644 --- a/Mage.Sets/src/mage/cards/c/CephalidShrine.java +++ b/Mage.Sets/src/mage/cards/c/CephalidShrine.java @@ -109,7 +109,7 @@ class CephalidShrineEffect extends OneShotEffect { } // even if the cost is 0, we still offer Cost cost = new GenericManaCost(count); - if (game.getStack().contains((StackObject) spell) + if (game.getStack().contains(spell) && cost.canPay(source, source.getSourceId(), controller.getId(), game) && controller.chooseUse(outcome, "Pay " + cost.getText() + " to prevent countering " + spell.getName() + "?", source, game) && cost.pay(source, game, source.getSourceId(), controller.getId(), false) diff --git a/Mage.Sets/src/mage/cards/c/CerebralVortex.java b/Mage.Sets/src/mage/cards/c/CerebralVortex.java index 84217202544..eca4f82e049 100644 --- a/Mage.Sets/src/mage/cards/c/CerebralVortex.java +++ b/Mage.Sets/src/mage/cards/c/CerebralVortex.java @@ -66,7 +66,7 @@ class CerebralVortexEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (targetPlayer != null) { - CerebralVortexWatcher watcher = (CerebralVortexWatcher) game.getState().getWatchers().get(CerebralVortexWatcher.class.getSimpleName()); + CerebralVortexWatcher watcher = game.getState().getWatcher(CerebralVortexWatcher.class); if (watcher != null) { targetPlayer.damage(watcher.getDraws(targetPlayer.getId()), source.getSourceId(), game, false, true); return true; diff --git a/Mage.Sets/src/mage/cards/c/CeremoniousRejection.java b/Mage.Sets/src/mage/cards/c/CeremoniousRejection.java index c3aed499b7e..e8ef317b006 100644 --- a/Mage.Sets/src/mage/cards/c/CeremoniousRejection.java +++ b/Mage.Sets/src/mage/cards/c/CeremoniousRejection.java @@ -19,7 +19,7 @@ public final class CeremoniousRejection extends CardImpl { private static final FilterSpell filter = new FilterSpell("colorless spell"); static{ - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public CeremoniousRejection(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/Cessation.java b/Mage.Sets/src/mage/cards/c/Cessation.java index 1407222dcf6..c06f089f7c7 100644 --- a/Mage.Sets/src/mage/cards/c/Cessation.java +++ b/Mage.Sets/src/mage/cards/c/Cessation.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -11,33 +9,31 @@ import mage.abilities.effects.common.combat.CantAttackAttachedEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Backfir3 */ public final class Cessation extends CardImpl { public Cessation(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); this.subtype.add(SubType.AURA); - //Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); - this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + //Enchanted creature can't attack. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA))); + //When Cessation is put into a graveyard from the battlefield, return Cessation to its owner's hand. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ReturnToHandSourceEffect())); } diff --git a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java index 04f12fe4cf8..4cba73bcdca 100644 --- a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java +++ b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java @@ -86,7 +86,7 @@ class ChainsOfMephistophelesReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (game.isActivePlayer(event.getPlayerId()) && game.getPhase().getStep().getType() == PhaseStep.DRAW) { - CardsDrawnDuringDrawStepWatcher watcher = (CardsDrawnDuringDrawStepWatcher) game.getState().getWatchers().get(CardsDrawnDuringDrawStepWatcher.class.getSimpleName()); + CardsDrawnDuringDrawStepWatcher watcher = game.getState().getWatcher(CardsDrawnDuringDrawStepWatcher.class); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) { return true; } diff --git a/Mage.Sets/src/mage/cards/c/ChamberSentry.java b/Mage.Sets/src/mage/cards/c/ChamberSentry.java index 60c11825020..7e8969db2a5 100644 --- a/Mage.Sets/src/mage/cards/c/ChamberSentry.java +++ b/Mage.Sets/src/mage/cards/c/ChamberSentry.java @@ -44,7 +44,7 @@ public final class ChamberSentry extends CardImpl { "with a +1/+1 counter on it for each color of mana spent to cast it")); // {X}, {T}, Remove X +1/+1 counters from Chamber Sentry: It deals X damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()) + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance) .setText("It deals X damage to any target"), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java b/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java index de10a0845e0..79b077a5d31 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java +++ b/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java @@ -30,7 +30,7 @@ public final class ChampionOfLambholt extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfStraySouls.java b/Mage.Sets/src/mage/cards/c/ChampionOfStraySouls.java index 24434b01b7f..f8e27453659 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionOfStraySouls.java +++ b/Mage.Sets/src/mage/cards/c/ChampionOfStraySouls.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -22,22 +21,23 @@ import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ChampionOfStraySouls extends CardImpl { - private final UUID originalId; private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ChampionOfStraySouls(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); this.subtype.add(SubType.SKELETON); this.subtype.add(SubType.WARRIOR); @@ -49,7 +49,6 @@ public final class ChampionOfStraySouls extends CardImpl { * ability, before you pay any costs. You can't target any of the * creatures you sacrifice. */ - //TODO: Make ability properly copiable // {3}{B}{B}, {T}, Sacrifice X other creatures: Return X target creatures from your graveyard to the battlefield. Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); effect.setText("Return X target creatures from your graveyard to the battlefield"); @@ -57,32 +56,17 @@ public final class ChampionOfStraySouls extends CardImpl { ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeXTargetCost(filter)); ability.addTarget(new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, new FilterCreatureCard("creature cards from your graveyard"))); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(ChampionOfStraySoulsAdjuster.instance); this.addAbility(ability); // {5}{B}{B}: Put Champion of Stray Souls on top of your library from your graveyard. this.addAbility(new SimpleActivatedAbility(Zone.GRAVEYARD, new PutOnLibrarySourceEffect(true, "Put {this} on top of your library from your graveyard"), new ManaCostsImpl("{5}{B}{B}"))); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - for (Effect effect : ability.getEffects()) { - if (effect instanceof ReturnFromGraveyardToBattlefieldTargetEffect) { - int xValue = new GetXValue().calculate(game, ability, null); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInYourGraveyard(xValue, xValue, new FilterCreatureCard("creature cards from your graveyard"))); - } - } - } } public ChampionOfStraySouls(final ChampionOfStraySouls card) { super(card); - this.originalId = card.originalId; } @Override @@ -90,3 +74,18 @@ public final class ChampionOfStraySouls extends CardImpl { return new ChampionOfStraySouls(this); } } + +enum ChampionOfStraySoulsAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + for (Effect effect : ability.getEffects()) { + if (effect instanceof ReturnFromGraveyardToBattlefieldTargetEffect) { + int xValue = GetXValue.instance.calculate(game, ability, null); + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard(xValue, xValue, new FilterCreatureCard("creature cards from your graveyard"))); + } + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfTheParish.java b/Mage.Sets/src/mage/cards/c/ChampionOfTheParish.java index 8e57197839b..617487fb233 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionOfTheParish.java +++ b/Mage.Sets/src/mage/cards/c/ChampionOfTheParish.java @@ -24,7 +24,7 @@ public final class ChampionOfTheParish extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another Human"); static { filter.add(new SubtypePredicate(SubType.HUMAN)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ChampionOfTheParish(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ChanceEncounter.java b/Mage.Sets/src/mage/cards/c/ChanceEncounter.java index 84d4fbbac84..20801608a89 100644 --- a/Mage.Sets/src/mage/cards/c/ChanceEncounter.java +++ b/Mage.Sets/src/mage/cards/c/ChanceEncounter.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -16,27 +15,29 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; +import mage.game.events.CoinFlippedEvent; import mage.game.events.GameEvent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ChanceEncounter extends CardImpl { public ChanceEncounter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); // Whenever you win a coin flip, put a luck counter on Chance Encounter. this.addAbility(new ChanceEncounterTriggeredAbility()); - + // At the beginning of your upkeep, if Chance Encounter has ten or more luck counters on it, you win the game. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new WinGameSourceControllerEffect(), TargetController.YOU, false); + TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new WinGameSourceControllerEffect(), TargetController.YOU, false); this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceHasCounterCondition(CounterType.LUCK, 10, Integer.MAX_VALUE), "At the beginning of your upkeep, if {this} has ten or more luck counters on it, you win the game")); } - public ChanceEncounter(final ChanceEncounter card) { + private ChanceEncounter(final ChanceEncounter card) { super(card); } @@ -47,30 +48,33 @@ public final class ChanceEncounter extends CardImpl { } class ChanceEncounterTriggeredAbility extends TriggeredAbilityImpl { - - public ChanceEncounterTriggeredAbility() { + + ChanceEncounterTriggeredAbility() { super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.LUCK.createInstance()), false); } - - public ChanceEncounterTriggeredAbility(final ChanceEncounterTriggeredAbility ability) { + + private ChanceEncounterTriggeredAbility(final ChanceEncounterTriggeredAbility ability) { super(ability); } - + @Override public ChanceEncounterTriggeredAbility copy() { return new ChanceEncounterTriggeredAbility(this); } - + @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.COIN_FLIPPED; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { - return this.isControlledBy(event.getPlayerId()) && event.getFlag(); + CoinFlippedEvent flipEvent = (CoinFlippedEvent) event; + return flipEvent.getPlayerId().equals(controllerId) + && flipEvent.isWinnable() + && (flipEvent.getChosen() == flipEvent.getResult()); } - + @Override public String getRule() { return "Whenever you win a coin flip, " + super.getRule(); diff --git a/Mage.Sets/src/mage/cards/c/ChaosMaw.java b/Mage.Sets/src/mage/cards/c/ChaosMaw.java index 7916f847db4..c53c0263ea3 100644 --- a/Mage.Sets/src/mage/cards/c/ChaosMaw.java +++ b/Mage.Sets/src/mage/cards/c/ChaosMaw.java @@ -14,7 +14,7 @@ import mage.filter.predicate.permanent.AnotherPredicate; public final class ChaosMaw extends CardImpl { private static FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ChaosMaw(UUID ownerId, CardSetInfo cardSetInfo){ super(ownerId, cardSetInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); diff --git a/Mage.Sets/src/mage/cards/c/ChaoticGoo.java b/Mage.Sets/src/mage/cards/c/ChaoticGoo.java index 9e80008f076..d66c6778fea 100644 --- a/Mage.Sets/src/mage/cards/c/ChaoticGoo.java +++ b/Mage.Sets/src/mage/cards/c/ChaoticGoo.java @@ -67,7 +67,7 @@ class ChaoticGooEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { game.informPlayers("Chaotic Goo: Won flip. Put a +1/+1 counter on Chaotic Goo."); new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)).apply(game, source); return true; diff --git a/Mage.Sets/src/mage/cards/c/ChaoticStrike.java b/Mage.Sets/src/mage/cards/c/ChaoticStrike.java index 49424f17232..2c97e2a4150 100644 --- a/Mage.Sets/src/mage/cards/c/ChaoticStrike.java +++ b/Mage.Sets/src/mage/cards/c/ChaoticStrike.java @@ -65,7 +65,7 @@ class ChaoticStrikeEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { game.addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn), source); return true; } diff --git a/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java b/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java index 52d71ff7668..28603c5d0f2 100644 --- a/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java +++ b/Mage.Sets/src/mage/cards/c/ChargingCinderhorn.java @@ -62,7 +62,7 @@ class ChargingCinderhornCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null) { return watcher.getAttackedThisTurnCreatures().isEmpty(); } diff --git a/Mage.Sets/src/mage/cards/c/ChargingWarBoar.java b/Mage.Sets/src/mage/cards/c/ChargingWarBoar.java new file mode 100644 index 00000000000..64cc6041eb9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChargingWarBoar.java @@ -0,0 +1,65 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ChargingWarBoar extends CardImpl { + + private static final Condition condition + = new PermanentsOnTheBattlefieldCondition(new FilterControlledPlaneswalkerPermanent(SubType.DOMRI)); + + public ChargingWarBoar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + + this.subtype.add(SubType.BOAR); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // As long as you control a Domri planeswalker, Charging War Boar gets +1/+1 and has trample. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), + condition, "As long as you control a Domri planeswalker, {this} gets +1/+1" + ) + ); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + TrampleAbility.getInstance(), Duration.WhileOnBattlefield + ), condition, "and has trample" + )); + this.addAbility(ability); + } + + private ChargingWarBoar(final ChargingWarBoar card) { + super(card); + } + + @Override + public ChargingWarBoar copy() { + return new ChargingWarBoar(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java index 46363fd9170..a4bfcdfa488 100644 --- a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java +++ b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -27,8 +25,9 @@ import mage.game.stack.Spell; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class CherishedHatchling extends CardImpl { @@ -67,7 +66,7 @@ class CherishedHatchlingTriggeredAbility extends DelayedTriggeredAbility { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CherishedHatchlingTriggeredAbility() { @@ -113,48 +112,3 @@ class CherishedHatchlingTriggeredAbility extends DelayedTriggeredAbility { return "and whenever you cast a Dinosaur spell this turn, " + super.getRule(); } } - -//class CherishedHatchlingGainAbilityEffect extends ContinuousEffectImpl { -// -// private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); -// -// static { -// filter.add(new AnotherPredicate()); -// } -// private Ability abilityToAdd = null; -// private Card relatedCard = null; -// -// public CherishedHatchlingGainAbilityEffect() { -// super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); -// staticText = "it gains \"When this creature enters the battlefield, you may have it fight another target creature.\""; -// } -// -// public CherishedHatchlingGainAbilityEffect(final CherishedHatchlingGainAbilityEffect effect) { -// super(effect); -// this.abilityToAdd = effect.abilityToAdd; -// this.relatedCard = effect.relatedCard; -// } -// -// @Override -// public CherishedHatchlingGainAbilityEffect copy() { -// return new CherishedHatchlingGainAbilityEffect(this); -// } -// -// @Override -// public boolean apply(Game game, Ability source) { -// if (relatedCard == null) { -// Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); -// if (spell != null) { -// relatedCard = game.getCard(spell.getSourceId()); -// Effect effect = new FightTargetSourceEffect(); -// effect.setText("you may have it fight another target creature"); -// abilityToAdd = new EntersBattlefieldTriggeredAbility(effect, true); -// abilityToAdd.addTarget(new TargetCreaturePermanent(filter)); -// } -// } -// if (relatedCard != null) { -// game.getState().addOtherAbility(relatedCard, abilityToAdd, false); -// } -// return true; -// } -//} diff --git a/Mage.Sets/src/mage/cards/c/Chewbacca.java b/Mage.Sets/src/mage/cards/c/Chewbacca.java index 66f13c8ea06..be15218f899 100644 --- a/Mage.Sets/src/mage/cards/c/Chewbacca.java +++ b/Mage.Sets/src/mage/cards/c/Chewbacca.java @@ -26,7 +26,7 @@ public final class Chewbacca extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Chewbacca(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java b/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java index d206feff7e5..f7ffe1d408b 100644 --- a/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java +++ b/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java @@ -27,8 +27,8 @@ public final class ChewbaccaTheBeast extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); - filter.add(new AttackingPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(AttackingPredicate.instance); } public ChewbaccaTheBeast(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ChickenALaKing.java b/Mage.Sets/src/mage/cards/c/ChickenALaKing.java index 54fc631a3b3..db786af300e 100644 --- a/Mage.Sets/src/mage/cards/c/ChickenALaKing.java +++ b/Mage.Sets/src/mage/cards/c/ChickenALaKing.java @@ -33,7 +33,7 @@ public final class ChickenALaKing extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Chicken you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.CHICKEN)); } diff --git a/Mage.Sets/src/mage/cards/c/ChiefChirpa.java b/Mage.Sets/src/mage/cards/c/ChiefChirpa.java index 4751f53f001..5cd547a4408 100644 --- a/Mage.Sets/src/mage/cards/c/ChiefChirpa.java +++ b/Mage.Sets/src/mage/cards/c/ChiefChirpa.java @@ -40,7 +40,7 @@ public final class ChiefChirpa extends CardImpl { diedFilter.add(new ControllerPredicate(TargetController.YOU)); ewokFilter.add(new SubtypePredicate(SubType.EWOK)); - ewokFilter.add(new AnotherPredicate()); + ewokFilter.add(AnotherPredicate.instance); } public ChiefChirpa(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ChildrenOfKorlis.java b/Mage.Sets/src/mage/cards/c/ChildrenOfKorlis.java index c38f2ec2f41..6275d1f0f3e 100644 --- a/Mage.Sets/src/mage/cards/c/ChildrenOfKorlis.java +++ b/Mage.Sets/src/mage/cards/c/ChildrenOfKorlis.java @@ -52,9 +52,9 @@ class SourceControllerLostLifeCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { - return watcher.getLiveLost(sourceAbility.getControllerId()); + return watcher.getLifeLost(sourceAbility.getControllerId()); } return 0; } diff --git a/Mage.Sets/src/mage/cards/c/ChillHaunting.java b/Mage.Sets/src/mage/cards/c/ChillHaunting.java index 2730c08155f..d13c2420f26 100644 --- a/Mage.Sets/src/mage/cards/c/ChillHaunting.java +++ b/Mage.Sets/src/mage/cards/c/ChillHaunting.java @@ -28,7 +28,7 @@ public final class ChillHaunting extends CardImpl { // Target creature gets -X/-X until end of turn. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - DynamicValue xval = new SignInversionDynamicValue(new GetXValue()); + DynamicValue xval = new SignInversionDynamicValue(GetXValue.instance); this.getSpellAbility().addEffect(new BoostTargetEffect(xval, xval, Duration.EndOfTurn)); } diff --git a/Mage.Sets/src/mage/cards/c/Chillbringer.java b/Mage.Sets/src/mage/cards/c/Chillbringer.java new file mode 100644 index 00000000000..bd03de10b71 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/Chillbringer.java @@ -0,0 +1,47 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Chillbringer extends CardImpl { + + public Chillbringer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); + + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Chillbringer enters the battlefield, tap target creature an opponent controls. It doesn't untap during its controller's next untap step. + Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); + ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("It")); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + private Chillbringer(final Chillbringer card) { + super(card); + } + + @Override + public Chillbringer copy() { + return new Chillbringer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChimeOfNight.java b/Mage.Sets/src/mage/cards/c/ChimeOfNight.java index 5f3a207f0b7..60ae0c61488 100644 --- a/Mage.Sets/src/mage/cards/c/ChimeOfNight.java +++ b/Mage.Sets/src/mage/cards/c/ChimeOfNight.java @@ -1,25 +1,25 @@ package mage.cards.c; -import java.util.UUID; import mage.ObjectColor; -import mage.target.common.TargetCreaturePermanent; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DestroyTargetEffect; -import mage.constants.Outcome; -import mage.target.TargetPermanent; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ChimeOfNight extends CardImpl { @@ -43,7 +43,7 @@ public final class ChimeOfNight extends CardImpl { this.addAbility(ability); // When Chime of Night is put into a graveyard from the battlefield, destroy target nonblack creature. - ability = new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DestroyTargetEffect(), false); + ability = new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DestroyTargetEffect()); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChiseiHeartOfOceans.java b/Mage.Sets/src/mage/cards/c/ChiseiHeartOfOceans.java index 207982df3b9..916b686a1cb 100644 --- a/Mage.Sets/src/mage/cards/c/ChiseiHeartOfOceans.java +++ b/Mage.Sets/src/mage/cards/c/ChiseiHeartOfOceans.java @@ -29,7 +29,7 @@ public final class ChiseiHeartOfOceans extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new CounterAnyPredicate()); + filter.add(CounterAnyPredicate.instance); } public ChiseiHeartOfOceans(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java b/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java index 5a31f0d5b8e..e4771fc0e7d 100644 --- a/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java +++ b/Mage.Sets/src/mage/cards/c/ChosenOfMarkov.java @@ -28,7 +28,7 @@ public final class ChosenOfMarkov extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Vampire you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/c/ChromeMox.java b/Mage.Sets/src/mage/cards/c/ChromeMox.java index b3b414ee191..75fd118e48c 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeMox.java +++ b/Mage.Sets/src/mage/cards/c/ChromeMox.java @@ -1,8 +1,5 @@ package mage.cards.c; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.Mana; import mage.ObjectColor; @@ -30,8 +27,11 @@ import mage.target.TargetCard; import mage.util.CardUtil; import mage.util.GameLog; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author Plopman */ public final class ChromeMox extends CardImpl { @@ -141,7 +141,7 @@ class ChromeMoxManaEffect extends ManaEffect { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); if (imprintedCard != null) { ObjectColor color = imprintedCard.getColor(game); @@ -172,7 +172,7 @@ class ChromeMoxManaEffect extends ManaEffect { Player player = game.getPlayer(source.getControllerId()); if (permanent != null && player != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); if (imprintedCard != null) { Choice choice = new ChoiceColor(true); diff --git a/Mage.Sets/src/mage/cards/c/ChromeSteed.java b/Mage.Sets/src/mage/cards/c/ChromeSteed.java index b0e34f7e10f..87b468f3c26 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeSteed.java +++ b/Mage.Sets/src/mage/cards/c/ChromeSteed.java @@ -2,38 +2,42 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author Loki */ public final class ChromeSteed extends CardImpl { - private static final String text = "Metalcraft — Chrome Steed gets +2/+2 as long as you control three or more artifacts"; - public ChromeSteed (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}"); + public ChromeSteed(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); this.subtype.add(SubType.HORSE); this.power = new MageInt(2); this.toughness = new MageInt(2); - ContinuousEffect boostSource = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield); - ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, text); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), + MetalcraftCondition.instance, "Metalcraft — {this} gets " + + "+2/+2 as long as you control three or more artifacts" + ) + )); } - public ChromeSteed (final ChromeSteed card) { + public ChromeSteed(final ChromeSteed card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/c/CinderCloud.java b/Mage.Sets/src/mage/cards/c/CinderCloud.java index 24d02c18e8a..9cdc4082931 100644 --- a/Mage.Sets/src/mage/cards/c/CinderCloud.java +++ b/Mage.Sets/src/mage/cards/c/CinderCloud.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -15,8 +14,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author ciaccona007 */ public final class CinderCloud extends CardImpl { @@ -43,7 +43,8 @@ class CinderCloudEffect extends OneShotEffect { public CinderCloudEffect() { super(Outcome.Benefit); - this.staticText = "Destroy target creature. If a white creature dies this way, {this} deals damage to that creature's controller equal to the creature's power"; + this.staticText = "Destroy target creature. If a white creature dies this way, " + + "{this} deals damage to that creature's controller equal to the creature's power"; } public CinderCloudEffect(final CinderCloudEffect effect) { @@ -71,6 +72,6 @@ class CinderCloudEffect extends OneShotEffect { permanentController.damage(damage, source.getSourceId(), game, false, true); } } - return true; + return false; } } diff --git a/Mage.Sets/src/mage/cards/c/CinderElemental.java b/Mage.Sets/src/mage/cards/c/CinderElemental.java index 8adeae708e2..16a0dfcae52 100644 --- a/Mage.Sets/src/mage/cards/c/CinderElemental.java +++ b/Mage.Sets/src/mage/cards/c/CinderElemental.java @@ -31,7 +31,7 @@ public final class CinderElemental extends CardImpl { this.toughness = new MageInt(2); // {X}{R}, {tap}, Sacrifice Cinder Elemental: Cinder Elemental deals X damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{R}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/c/CinderGiant.java b/Mage.Sets/src/mage/cards/c/CinderGiant.java index bce7205df58..24cfbac2280 100644 --- a/Mage.Sets/src/mage/cards/c/CinderGiant.java +++ b/Mage.Sets/src/mage/cards/c/CinderGiant.java @@ -21,7 +21,7 @@ public final class CinderGiant extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("each other creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CinderGiant(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/Cindervines.java b/Mage.Sets/src/mage/cards/c/Cindervines.java new file mode 100644 index 00000000000..80233fc9451 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/Cindervines.java @@ -0,0 +1,88 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Cindervines extends CardImpl { + + public Cindervines(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}{G}"); + + // Whenever an opponent casts a noncreature spell, Cindervines deals 1 damage to that player. + this.addAbility(new SpellCastOpponentTriggeredAbility( + Zone.BATTLEFIELD, new DamageTargetEffect(1, true, "that player"), + StaticFilters.FILTER_SPELL_NON_CREATURE, false, SetTargetPointer.PLAYER + )); + + // {1}, Sacrifice Cindervines: Destroy target artifact or enchantment. Cindervines deals 2 damage to that permanent's controller. + Ability ability = new SimpleActivatedAbility( + new CindervinesEffect(), new GenericManaCost(1) + ); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); + this.addAbility(ability); + } + + private Cindervines(final Cindervines card) { + super(card); + } + + @Override + public Cindervines copy() { + return new Cindervines(this); + } +} + +class CindervinesEffect extends OneShotEffect { + + CindervinesEffect() { + super(Outcome.Benefit); + staticText = "Destroy target artifact or enchantment. " + + "{this} deals 2 damage to that permanent's controller."; + } + + private CindervinesEffect(final CindervinesEffect effect) { + super(effect); + } + + @Override + public CindervinesEffect copy() { + return new CindervinesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + Player player = game.getPlayer(permanent.getControllerId()); + if (player == null) { + return false; + } + permanent.destroy(source.getSourceId(), game, false); + player.damage(2, source.getSourceId(), game); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CircleOfAffliction.java b/Mage.Sets/src/mage/cards/c/CircleOfAffliction.java index cc3962342fe..4091fb8bf09 100644 --- a/Mage.Sets/src/mage/cards/c/CircleOfAffliction.java +++ b/Mage.Sets/src/mage/cards/c/CircleOfAffliction.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -29,7 +28,7 @@ import mage.target.TargetPlayer; public final class CircleOfAffliction extends CardImpl { public CircleOfAffliction(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); // As Circle of Affliction enters the battlefield, choose a color. this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral))); @@ -69,12 +68,12 @@ class CircleOfAfflictionTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent circleOfAffliction = game.getPermanentOrLKIBattlefield(getSourceId()); - if (circleOfAffliction != null) { + if (circleOfAffliction != null && event.getTargetId().equals(getControllerId())) { ObjectColor chosenColor = (ObjectColor) game.getState().getValue(circleOfAffliction.getId() + "_color"); if (chosenColor != null) { MageObject damageSource = game.getObject(event.getSourceId()); if (damageSource != null) { - if ( damageSource.getColor(game).shares(chosenColor) ) { + if (damageSource.getColor(game).shares(chosenColor)) { return true; } } @@ -92,4 +91,4 @@ class CircleOfAfflictionTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever a source of the chosen color deals damage to you, you may pay {1}. If you do, target player loses 1 life and you gain 1 life."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CitadelOfPain.java b/Mage.Sets/src/mage/cards/c/CitadelOfPain.java index 40973164a4b..1cf2bbde90a 100644 --- a/Mage.Sets/src/mage/cards/c/CitadelOfPain.java +++ b/Mage.Sets/src/mage/cards/c/CitadelOfPain.java @@ -56,7 +56,7 @@ class CitadelOfPainEffect extends OneShotEffect { } static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public CitadelOfPainEffect() { diff --git a/Mage.Sets/src/mage/cards/c/CitadelSiege.java b/Mage.Sets/src/mage/cards/c/CitadelSiege.java index 86093720e51..99948a47061 100644 --- a/Mage.Sets/src/mage/cards/c/CitadelSiege.java +++ b/Mage.Sets/src/mage/cards/c/CitadelSiege.java @@ -15,28 +15,33 @@ import mage.constants.CardType; import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.Predicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author LevelX2 */ public final class CitadelSiege extends CardImpl { private final static String ruleTrigger1 = "&bull Khans — At the beginning of combat on your turn, put two +1/+1 counters on target creature you control."; private final static String ruleTrigger2 = "&bull Dragons — At the beginning of combat on each opponent's turn, tap target creature that player controls."; + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by the active player"); + + static { + filter.add(CitadelSiegePredicate.instance); + } public CitadelSiege(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // As Citadel Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?","Khans", "Dragons"),null, - "As {this} enters the battlefield, choose Khans or Dragons.","")); + this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, + "As {this} enters the battlefield, choose Khans or Dragons.", "")); // * Khans - At the beginning of combat on your turn, put two +1/+1 counters on target creature you control. Ability ability = new ConditionalTriggeredAbility( @@ -51,21 +56,10 @@ public final class CitadelSiege extends CardImpl { new BeginningOfCombatTriggeredAbility(new TapTargetEffect(), TargetController.OPPONENT, false), new ModeChoiceSourceCondition("Dragons"), ruleTrigger2); - ability.addTarget(new TargetCreaturePermanent()); + ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (this.getAbilities().contains(ability) && ability.getRule().startsWith("&bull Dragons")) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that player controls"); - filter.add(new ControllerIdPredicate(game.getCombat().getAttackingPlayerId())); - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(filter)); - } - } - - public CitadelSiege(final CitadelSiege card) { super(card); } @@ -75,3 +69,12 @@ public final class CitadelSiege extends CardImpl { return new CitadelSiege(this); } } + +enum CitadelSiegePredicate implements Predicate { + instance; + + @Override + public boolean apply(Permanent input, Game game) { + return input.getControllerId().equals(game.getActivePlayerId()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CityInABottle.java b/Mage.Sets/src/mage/cards/c/CityInABottle.java index 00a469b7562..547ba0933ec 100644 --- a/Mage.Sets/src/mage/cards/c/CityInABottle.java +++ b/Mage.Sets/src/mage/cards/c/CityInABottle.java @@ -139,7 +139,7 @@ class CityInABottleStateTriggeredAbility extends StateTriggeredAbility { private static final FilterPermanent filter = new FilterPermanent("a nontoken permanent originally printed in the Arabian Nights expansion other than City in a Bottle"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(Predicates.or(getArabianNightsNamePredicates())); } @@ -173,7 +173,7 @@ class CityInABottleSacrificeEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterPermanent("a nontoken permanent originally printed in the Arabian Nights expansion other than City in a Bottle"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(Predicates.or(getArabianNightsNamePredicates())); } diff --git a/Mage.Sets/src/mage/cards/c/CivicStalwart.java b/Mage.Sets/src/mage/cards/c/CivicStalwart.java new file mode 100644 index 00000000000..b9f6fecc0e6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CivicStalwart.java @@ -0,0 +1,40 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class CivicStalwart extends CardImpl { + + public CivicStalwart(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + this.subtype.add(SubType.ELEPHANT); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Civic Stalwart enters the battlefield, creatures you control get +1/+1 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new BoostControlledEffect(1, 1, Duration.EndOfTurn, new FilterCreaturePermanent("creatures")))); + } + + public CivicStalwart(final CivicStalwart card) { + super(card); + } + + @Override + public CivicStalwart copy() { + return new CivicStalwart(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java index 775632b928a..0f3f1eb7d26 100644 --- a/Mage.Sets/src/mage/cards/c/CivilizedScholar.java +++ b/Mage.Sets/src/mage/cards/c/CivilizedScholar.java @@ -12,6 +12,7 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.h.HomicidalBruteWatcher; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; @@ -54,31 +55,7 @@ public final class CivilizedScholar extends CardImpl { } } -class HomicidalBruteWatcher extends Watcher { - public HomicidalBruteWatcher() { - super(HomicidalBruteWatcher.class.getSimpleName(), WatcherScope.CARD); - } - - public HomicidalBruteWatcher(final HomicidalBruteWatcher watcher) { - super(watcher); - } - - @Override - public HomicidalBruteWatcher copy() { - return new HomicidalBruteWatcher(this); - } - - @Override - public void watch(GameEvent event, Game game) { - if (condition == true) { - return; - } - if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { - condition = true; - } - } -} class CivilizedScholarEffect extends OneShotEffect { @@ -87,7 +64,7 @@ class CivilizedScholarEffect extends OneShotEffect { staticText = "Draw a card, then discard a card. If a creature card is discarded this way, untap {this}, then transform it"; } - public CivilizedScholarEffect(final CivilizedScholarEffect effect) { + private CivilizedScholarEffect(final CivilizedScholarEffect effect) { super(effect); } diff --git a/Mage.Sets/src/mage/cards/c/ClaimFame.java b/Mage.Sets/src/mage/cards/c/ClaimFame.java index f0444ad01af..5ebf4cfa89a 100644 --- a/Mage.Sets/src/mage/cards/c/ClaimFame.java +++ b/Mage.Sets/src/mage/cards/c/ClaimFame.java @@ -42,7 +42,7 @@ public final class ClaimFame extends SplitCard { // Fame // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Target creature gets +2/+0 and gains haste until end of turn. getRightHalfCard().getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn)); getRightHalfCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn) diff --git a/Mage.Sets/src/mage/cards/c/ClamorShaman.java b/Mage.Sets/src/mage/cards/c/ClamorShaman.java new file mode 100644 index 00000000000..3d8e5b0fea4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ClamorShaman.java @@ -0,0 +1,49 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ClamorShaman extends CardImpl { + + public ClamorShaman(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Riot + this.addAbility(new RiotAbility()); + + // Whenever Clamor Shaman attacks, target creature an opponent controls can't block this turn. + Ability ability = new AttacksTriggeredAbility( + new CantBlockTargetEffect(Duration.EndOfTurn), false + ); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + private ClamorShaman(final ClamorShaman card) { + super(card); + } + + @Override + public ClamorShaman copy() { + return new ClamorShaman(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ClanDefiance.java b/Mage.Sets/src/mage/cards/c/ClanDefiance.java index 49d307e93ed..7400b1fb4f7 100644 --- a/Mage.Sets/src/mage/cards/c/ClanDefiance.java +++ b/Mage.Sets/src/mage/cards/c/ClanDefiance.java @@ -36,16 +36,16 @@ public final class ClanDefiance extends CardImpl { this.getSpellAbility().getModes().setMinModes(1); this.getSpellAbility().getModes().setMaxModes(3); // Clan Defiance deals X damage to target creature with flying; - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); // Clan Defiance deals X damage to target creature without flying; Mode mode1 = new Mode(); - mode1.addEffect(new DamageTargetEffect(new ManacostVariableValue())); + mode1.addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); mode1.addTarget(new TargetCreaturePermanent(filter2)); this.getSpellAbility().addMode(mode1); // and/or Clan Defiance deals X damage to target player. Mode mode2 = new Mode(); - mode2.addEffect(new DamageTargetEffect(new ManacostVariableValue())); + mode2.addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); mode2.addTarget(new TargetPlayerOrPlaneswalker()); this.getSpellAbility().addMode(mode2); diff --git a/Mage.Sets/src/mage/cards/c/ClanGuildmage.java b/Mage.Sets/src/mage/cards/c/ClanGuildmage.java new file mode 100644 index 00000000000..85ba5ee568d --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ClanGuildmage.java @@ -0,0 +1,85 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.permanent.token.TokenImpl; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ClanGuildmage extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledLandPermanent(); + + public ClanGuildmage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {1}{R}, {T}: Target creature can't block this turn. + Ability ability = new SimpleActivatedAbility( + new CantBlockTargetEffect(Duration.EndOfTurn), new ManaCostsImpl("{1}{R}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // {2}{G}, {T}: Target land you control becomes a 4/4 Elemental creature with haste until end of turn. It's still a land. + ability = new SimpleActivatedAbility(new BecomesCreatureTargetEffect( + new ClanGuildmageToken(), false, true, Duration.EndOfTurn + ), new ManaCostsImpl("{2}{G}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private ClanGuildmage(final ClanGuildmage card) { + super(card); + } + + @Override + public ClanGuildmage copy() { + return new ClanGuildmage(this); + } +} + +class ClanGuildmageToken extends TokenImpl { + + public ClanGuildmageToken() { + super("", "4/4 Elemental creature with haste"); + this.cardType.add(CardType.CREATURE); + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + this.addAbility(HasteAbility.getInstance()); + } + + public ClanGuildmageToken(final ClanGuildmageToken token) { + super(token); + } + + public ClanGuildmageToken copy() { + return new ClanGuildmageToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ClashOfWills.java b/Mage.Sets/src/mage/cards/c/ClashOfWills.java index 0108bc26916..a16fe93da3d 100644 --- a/Mage.Sets/src/mage/cards/c/ClashOfWills.java +++ b/Mage.Sets/src/mage/cards/c/ClashOfWills.java @@ -19,7 +19,7 @@ public final class ClashOfWills extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}"); // Counter target spell unless its controller pays {X}. - this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/c/ClearTheLand.java b/Mage.Sets/src/mage/cards/c/ClearTheLand.java index abb2b345579..5f1a55058a8 100644 --- a/Mage.Sets/src/mage/cards/c/ClearTheLand.java +++ b/Mage.Sets/src/mage/cards/c/ClearTheLand.java @@ -25,7 +25,7 @@ public final class ClearTheLand extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); - // Each player reveals the top five cards of his or her library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest. + // Each player reveals the top five cards of their library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest. getSpellAbility().addEffect(new ClearTheLandEffect()); } @@ -43,7 +43,7 @@ class ClearTheLandEffect extends OneShotEffect { public ClearTheLandEffect() { super(Outcome.Benefit); - this.staticText = "Each player reveals the top five cards of his or her library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest."; + this.staticText = "Each player reveals the top five cards of their library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest."; } public ClearTheLandEffect(final ClearTheLandEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/ClearTheMind.java b/Mage.Sets/src/mage/cards/c/ClearTheMind.java new file mode 100644 index 00000000000..b92b0ae932a --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ClearTheMind.java @@ -0,0 +1,72 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ClearTheMind extends CardImpl { + + public ClearTheMind(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}"); + + // Target player shuffles their graveyard into their library. + this.getSpellAbility().addEffect(new ClearTheMindEffect()); + this.getSpellAbility().addTarget(new TargetPlayer()); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + private ClearTheMind(final ClearTheMind card) { + super(card); + } + + @Override + public ClearTheMind copy() { + return new ClearTheMind(this); + } +} + +class ClearTheMindEffect extends OneShotEffect { + + ClearTheMindEffect() { + super(Outcome.Benefit); + staticText = "Target player shuffles their graveyard into their library."; + } + + private ClearTheMindEffect(final ClearTheMindEffect effect) { + super(effect); + } + + @Override + public ClearTheMindEffect copy() { + return new ClearTheMindEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player == null) { + return false; + } + player.putCardsOnBottomOfLibrary( + new CardsImpl(player.getGraveyard().getCards(game)), + game, source, false + ); + player.shuffleLibrary(source, game); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ClearTheStage.java b/Mage.Sets/src/mage/cards/c/ClearTheStage.java new file mode 100644 index 00000000000..fd5266eddff --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ClearTheStage.java @@ -0,0 +1,81 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.condition.common.FerociousCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ClearTheStage extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature card from your graveyard"); + + public ClearTheStage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}"); + + // Target creature gets -3/-3 until end of turn. If you control a creature with power 4 or greater, you may return up to one target creature card from your graveyard to your hand. + this.getSpellAbility().addEffect(new ClearTheStageEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 1, filter)); + } + + private ClearTheStage(final ClearTheStage card) { + super(card); + } + + @Override + public ClearTheStage copy() { + return new ClearTheStage(this); + } +} + +class ClearTheStageEffect extends OneShotEffect { + + ClearTheStageEffect() { + super(Outcome.Benefit); + staticText = "Target creature gets -3/-3 until end of turn. If you control a creature with power 4 or greater, " + + "you may return up to one target creature card from your graveyard to your hand."; + } + + private ClearTheStageEffect(final ClearTheStageEffect effect) { + super(effect); + } + + @Override + public ClearTheStageEffect copy() { + return new ClearTheStageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.addEffect(new BoostTargetEffect(-3, -3), source); + if (!FerociousCondition.instance.apply(game, source)) { + return true; + } + Player player = game.getPlayer(source.getControllerId()); + if (player == null || !player.chooseUse(Outcome.Benefit, "Return a creature card from your graveyard to your hand?", source, game)) { + return false; + } + Card card = game.getCard(source.getTargets().get(1).getFirstTarget()); + if (card == null) { + return false; + } + return player.moveCards(card, Zone.HAND, source, game); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ClockOfOmens.java b/Mage.Sets/src/mage/cards/c/ClockOfOmens.java index 3708f17477a..9b852701256 100644 --- a/Mage.Sets/src/mage/cards/c/ClockOfOmens.java +++ b/Mage.Sets/src/mage/cards/c/ClockOfOmens.java @@ -26,7 +26,7 @@ public final class ClockOfOmens extends CardImpl { static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ClockOfOmens(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/Clockspinning.java b/Mage.Sets/src/mage/cards/c/Clockspinning.java index 0c76c6572c1..2bb9c92c716 100644 --- a/Mage.Sets/src/mage/cards/c/Clockspinning.java +++ b/Mage.Sets/src/mage/cards/c/Clockspinning.java @@ -1,9 +1,5 @@ - package mage.cards.c; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -23,8 +19,11 @@ import mage.players.Player; import mage.target.common.TargetPermanentOrSuspendedCard; import mage.target.targetpointer.FixedTarget; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author spjspj */ public final class Clockspinning extends CardImpl { @@ -133,7 +132,6 @@ class ClockspinningAddOrRemoveCounterEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getFirstTarget()); - Card card = game.getCard(source.getFirstTarget()); if (player != null && permanent != null) { if (player.chooseUse(Outcome.Neutral, "Do you want to to remove a counter?", source, game)) { @@ -151,6 +149,8 @@ class ClockspinningAddOrRemoveCounterEffect extends OneShotEffect { } return true; } + + Card card = game.getCard(source.getFirstTarget()); if (player != null && card != null) { if (player.chooseUse(Outcome.Neutral, "Do you want to to remove a counter?", source, game)) { Counter counter = selectCounterType(game, source, card); diff --git a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java index 7eabddb97fa..696fca568a1 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java @@ -63,7 +63,7 @@ public final class ClockworkAvian extends CardImpl { Zone.BATTLEFIELD, new AvianAddCountersSourceEffect( CounterType.P1P0.createInstance(), - new ManacostVariableValue(), + ManacostVariableValue.instance, true, true ), new ManaCostsImpl("{X}"), diff --git a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java index e02f4434b43..9fa1356e13e 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java @@ -59,7 +59,7 @@ public final class ClockworkBeast extends CardImpl { Zone.BATTLEFIELD, new BeastAddCountersSourceEffect( CounterType.P1P0.createInstance(), - new ManacostVariableValue(), + ManacostVariableValue.instance, true, true ), new ManaCostsImpl("{X}"), diff --git a/Mage.Sets/src/mage/cards/c/ClockworkSteed.java b/Mage.Sets/src/mage/cards/c/ClockworkSteed.java index fe4557ef8dd..c2975f53d2c 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkSteed.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkSteed.java @@ -70,7 +70,7 @@ public final class ClockworkSteed extends CardImpl { Zone.BATTLEFIELD, new ClockworkSteedAddCountersSourceEffect( CounterType.P1P0.createInstance(), - new ManacostVariableValue(), + ManacostVariableValue.instance, true, true ), new ManaCostsImpl("{X}"), diff --git a/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java b/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java index 4480d844ced..0cd0288d2e2 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java @@ -73,7 +73,7 @@ public final class ClockworkSwarm extends CardImpl { Zone.BATTLEFIELD, new SwarmAddCountersSourceEffect( CounterType.P1P0.createInstance(), - new ManacostVariableValue(), + ManacostVariableValue.instance, true, true ), new ManaCostsImpl("{X}"), diff --git a/Mage.Sets/src/mage/cards/c/CloneShell.java b/Mage.Sets/src/mage/cards/c/CloneShell.java index 4007df8bcd5..84171a085bd 100644 --- a/Mage.Sets/src/mage/cards/c/CloneShell.java +++ b/Mage.Sets/src/mage/cards/c/CloneShell.java @@ -1,8 +1,5 @@ - package mage.cards.c; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; @@ -20,6 +17,9 @@ import mage.players.Player; import mage.target.TargetCard; import mage.util.CardUtil; +import java.util.List; +import java.util.UUID; + /** * @author nantuko */ @@ -115,11 +115,13 @@ class CloneShellDiesEffect extends OneShotEffect { Permanent permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); if (permanent != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); - imprintedCard.setFaceDown(false, game); - if (imprintedCard.isCreature()) { - controller.moveCards(imprintedCard, Zone.BATTLEFIELD, source, game); + if (imprintedCard != null) { + imprintedCard.setFaceDown(false, game); + if (imprintedCard.isCreature()) { + controller.moveCards(imprintedCard, Zone.BATTLEFIELD, source, game); + } } } } diff --git a/Mage.Sets/src/mage/cards/c/CloudgoatRanger.java b/Mage.Sets/src/mage/cards/c/CloudgoatRanger.java index 368b1c19149..11722998664 100644 --- a/Mage.Sets/src/mage/cards/c/CloudgoatRanger.java +++ b/Mage.Sets/src/mage/cards/c/CloudgoatRanger.java @@ -34,7 +34,7 @@ public final class CloudgoatRanger extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Kithkin you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.KITHKIN)); } diff --git a/Mage.Sets/src/mage/cards/c/ClovenCasting.java b/Mage.Sets/src/mage/cards/c/ClovenCasting.java index 91c8961b969..389fc161c12 100644 --- a/Mage.Sets/src/mage/cards/c/ClovenCasting.java +++ b/Mage.Sets/src/mage/cards/c/ClovenCasting.java @@ -27,7 +27,7 @@ public final class ClovenCasting extends CardImpl { filter.add(Predicates.or( new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public ClovenCasting(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CoastalPiracy.java b/Mage.Sets/src/mage/cards/c/CoastalPiracy.java index f3a94fc0a6b..6eef0cd9d1e 100644 --- a/Mage.Sets/src/mage/cards/c/CoastalPiracy.java +++ b/Mage.Sets/src/mage/cards/c/CoastalPiracy.java @@ -61,7 +61,7 @@ class CoastalPiracyTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage() - && game.getOpponents(this.controllerId).contains(((DamagedPlayerEvent) event).getPlayerId())) { + && game.getOpponents(this.controllerId).contains(event.getPlayerId())) { Permanent creature = game.getPermanent(event.getSourceId()); if (creature != null && creature.isControlledBy(controllerId)) { return true; diff --git a/Mage.Sets/src/mage/cards/c/CoastalWizard.java b/Mage.Sets/src/mage/cards/c/CoastalWizard.java index 54bb6b7b243..1ed09be1495 100644 --- a/Mage.Sets/src/mage/cards/c/CoastalWizard.java +++ b/Mage.Sets/src/mage/cards/c/CoastalWizard.java @@ -27,7 +27,7 @@ public final class CoastalWizard extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CoastalWizard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CobraTrap.java b/Mage.Sets/src/mage/cards/c/CobraTrap.java index a84de7815de..6845197a353 100644 --- a/Mage.Sets/src/mage/cards/c/CobraTrap.java +++ b/Mage.Sets/src/mage/cards/c/CobraTrap.java @@ -55,7 +55,7 @@ enum CobraTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - CobraTrapWatcher watcher = (CobraTrapWatcher) game.getState().getWatchers().get(CobraTrapWatcher.class.getSimpleName()); + CobraTrapWatcher watcher = game.getState().getWatcher(CobraTrapWatcher.class); return watcher != null && watcher.conditionMet(source.getControllerId()); } @@ -86,7 +86,7 @@ class CobraTrapWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.DESTROYED_PERMANENT) { - Permanent perm = (Permanent) game.getPermanentOrLKIBattlefield(event.getTargetId()); // can regenerate or be indestructible + Permanent perm = game.getPermanentOrLKIBattlefield(event.getTargetId()); // can regenerate or be indestructible if (perm != null && !perm.isCreature()) { if (!game.getStack().isEmpty()) { StackObject spell = game.getStack().getStackObject(event.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/c/Cocoon.java b/Mage.Sets/src/mage/cards/c/Cocoon.java new file mode 100644 index 00000000000..ce5d8be5c5f --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/Cocoon.java @@ -0,0 +1,115 @@ + +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; +import mage.abilities.effects.common.TapEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * @author L_J + */ +public final class Cocoon extends CardImpl { + + public Cocoon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}"); + this.subtype.add(SubType.AURA); + + // Enchant creature you control + TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + + // When Cocoon enters the battlefield, tap enchanted creature and put three pupa counters on Cocoon. + Ability ability = new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()); + ability.addEffect(new AddCountersSourceEffect(CounterType.PUPA.createInstance(3))); + this.addAbility(ability); + + // Enchanted creature doesn’t untap during your untap step if Cocoon has a pupa counter on it. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousRuleModifyingEffect(new DontUntapInControllersUntapStepEnchantedEffect(), + new SourceHasCounterCondition(CounterType.PUPA)).setText("Enchanted creature doesn't untap during its controller's untap step if Cocoon has a pupa counter on it"))); + + // At the beginning of your upkeep, remove a pupa counter from Cocoon. If you can’t, sacrifice it, put a +1/+1 counter on enchanted creature, and that creature gains flying. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CocoonEffect(), TargetController.YOU, false)); + + } + + public Cocoon(final Cocoon card) { + super(card); + } + + @Override + public Cocoon copy() { + return new Cocoon(this); + } +} + +class CocoonEffect extends OneShotEffect { + + CocoonEffect() { + super(Outcome.Sacrifice); + staticText = "remove a pupa counter from {this}. If you can’t, sacrifice it, put a +1/+1 counter on enchanted creature, and that creature gains flying"; + } + + CocoonEffect(final CocoonEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (permanent != null) { + int amount = permanent.getCounters(game).getCount(CounterType.PUPA); + if (amount > 0) { + permanent.removeCounters(CounterType.PUPA.createInstance(), game); + } else { + Permanent enchantedPermanent = game.getPermanent(permanent.getAttachedTo()); + permanent.sacrifice(source.getSourceId(), game); + if (enchantedPermanent != null) { + Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); + effect.setTargetPointer(new FixedTarget(enchantedPermanent, game)); + effect.apply(game, source); + ContinuousEffect effect2 = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.Custom); + effect2.setTargetPointer(new FixedTarget(enchantedPermanent, game)); + game.addEffect(effect2, source); + } + } + return true; + } + return false; + } + + @Override + public CocoonEffect copy() { + return new CocoonEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CodeOfConstraint.java b/Mage.Sets/src/mage/cards/c/CodeOfConstraint.java new file mode 100644 index 00000000000..f548ade2784 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CodeOfConstraint.java @@ -0,0 +1,73 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CodeOfConstraint extends CardImpl { + + public CodeOfConstraint(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); + + // Target creature gets -4/-0 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(-4, 0)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + + // Addendum — If you cast this spell during your main phase, tap that creature and it doesn't untap during its controller's next untap step. + this.getSpellAbility().addEffect(new CodeOfConstraintEffect()); + } + + private CodeOfConstraint(final CodeOfConstraint card) { + super(card); + } + + @Override + public CodeOfConstraint copy() { + return new CodeOfConstraint(this); + } +} + +class CodeOfConstraintEffect extends OneShotEffect { + + CodeOfConstraintEffect() { + super(Outcome.Benefit); + staticText = "
Addendum — If you cast this spell during your main phase, " + + "tap that creature and it doesn't untap during its controller's next untap step."; + } + + private CodeOfConstraintEffect(final CodeOfConstraintEffect effect) { + super(effect); + } + + @Override + public CodeOfConstraintEffect copy() { + return new CodeOfConstraintEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (AddendumCondition.instance.apply(game, source)) { + new TapTargetEffect().apply(game, source); + game.addEffect(new DontUntapInControllersNextUntapStepTargetEffect(), source); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CollectiveEffort.java b/Mage.Sets/src/mage/cards/c/CollectiveEffort.java index bdf26e0adb7..534bec0969d 100644 --- a/Mage.Sets/src/mage/cards/c/CollectiveEffort.java +++ b/Mage.Sets/src/mage/cards/c/CollectiveEffort.java @@ -44,7 +44,7 @@ public final class CollectiveEffort extends CardImpl { private static final FilterPlayer filterPlayer = new FilterPlayer("player whose creatures get +1/+1 counters"); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); filterDestroyCreature.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); } diff --git a/Mage.Sets/src/mage/cards/c/CollisionColossus.java b/Mage.Sets/src/mage/cards/c/CollisionColossus.java new file mode 100644 index 00000000000..74a9473184c --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CollisionColossus.java @@ -0,0 +1,60 @@ +package mage.cards.c; + +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SpellAbilityType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CollisionColossus extends SplitCard { + + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public CollisionColossus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R/G}", "{R}{G}", SpellAbilityType.SPLIT); + + // Collision + // Collision deals 6 damage to target creature with flying. + this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(6)); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter)); + + // Colossus + // Target creature gets +4/+2 and gains trample until end of turn. + this.getRightHalfCard().getSpellAbility().addEffect( + new BoostTargetEffect(4, 2, Duration.EndOfTurn) + .setText("target creature gets +4/+2") + ); + this.getRightHalfCard().getSpellAbility().addEffect(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains trample until end of turn")); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private CollisionColossus(final CollisionColossus card) { + super(card); + } + + @Override + public CollisionColossus copy() { + return new CollisionColossus(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CombineGuildmage.java b/Mage.Sets/src/mage/cards/c/CombineGuildmage.java new file mode 100644 index 00000000000..82d0b72cd7c --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CombineGuildmage.java @@ -0,0 +1,143 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CombineGuildmage extends CardImpl { + + private static final FilterPermanent filter1 + = new FilterControlledCreaturePermanent("creature you control (to remove a counter from)"); + private static final FilterPermanent filter2 + = new FilterControlledCreaturePermanent("creature you control (to move a counter to)"); + + public CombineGuildmage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {1}{G}, {T}: This turn, each creature you control enters the battlefield with an additional +1/+1 counter on it. + Ability ability = new SimpleActivatedAbility( + new CombineGuildmageReplacementEffect(), new ManaCostsImpl("{1}{G}") + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // {1}{U}, {T}: Move a +1/+1 counter from target creature you control onto another target creature you control. + ability = new SimpleActivatedAbility( + new CombineGuildmageCounterEffect(), new ManaCostsImpl("{1}{U}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter1)); + ability.addTarget(new TargetPermanent(filter2)); + this.addAbility(ability); + } + + private CombineGuildmage(final CombineGuildmage card) { + super(card); + } + + @Override + public CombineGuildmage copy() { + return new CombineGuildmage(this); + } +} + +class CombineGuildmageReplacementEffect extends ReplacementEffectImpl { + + CombineGuildmageReplacementEffect() { + super(Duration.EndOfTurn, Outcome.BoostCreature); + this.staticText = "This turn, each creature you control enters the battlefield with an additional +1/+1 counter on it"; + } + + private CombineGuildmageReplacementEffect(CombineGuildmageReplacementEffect effect) { + super(effect); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); + return permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.isCreature(); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent target = ((EntersTheBattlefieldEvent) event).getTarget(); + if (target != null) { + target.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects()); + } + return false; + } + + @Override + public CombineGuildmageReplacementEffect copy() { + return new CombineGuildmageReplacementEffect(this); + } +} + +class CombineGuildmageCounterEffect extends OneShotEffect { + + CombineGuildmageCounterEffect() { + super(Outcome.Benefit); + staticText = "Move a +1/+1 counter from target creature you control onto another target creature you control."; + } + + private CombineGuildmageCounterEffect(final CombineGuildmageCounterEffect effect) { + super(effect); + } + + @Override + public CombineGuildmageCounterEffect copy() { + return new CombineGuildmageCounterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent fromPermanent = game.getPermanent(source.getFirstTarget()); + Permanent toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + if (fromPermanent == null || toPermanent == null) { + return false; + } + if (fromPermanent.getCounters(game).getCount(CounterType.P1P1) > 0) { + fromPermanent.removeCounters(CounterType.P1P1.createInstance(), game); + toPermanent.addCounters(CounterType.P1P1.createInstance(), source, game); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CometStorm.java b/Mage.Sets/src/mage/cards/c/CometStorm.java index c88df06c348..41c3de1510c 100644 --- a/Mage.Sets/src/mage/cards/c/CometStorm.java +++ b/Mage.Sets/src/mage/cards/c/CometStorm.java @@ -1,9 +1,7 @@ - package mage.cards.c; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.MultikickerAbility; @@ -15,6 +13,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -31,27 +30,30 @@ public final class CometStorm extends CardImpl { // Choose any target, then choose another any target for each time Comet Storm was kicked. Comet Storm deals X damage to each of them. this.getSpellAbility().addEffect(new CometStormEffect()); this.getSpellAbility().addTarget(new TargetAnyTarget(1)); + this.getSpellAbility().setTargetAdjuster(CometStormAdjuster.instance); } public CometStorm(final CometStorm card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numbTargets = new MultikickerCount().calculate(game, ability, null) + 1; - ability.addTarget(new TargetAnyTarget(numbTargets)); - } - } - @Override public CometStorm copy() { return new CometStorm(this); } } +enum CometStormAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numbTargets = MultikickerCount.instance.calculate(game, ability, null) + 1; + ability.addTarget(new TargetAnyTarget(numbTargets)); + } +} + class CometStormEffect extends OneShotEffect { public CometStormEffect() { diff --git a/Mage.Sets/src/mage/cards/c/CommanderCody.java b/Mage.Sets/src/mage/cards/c/CommanderCody.java index 94867b369dc..2b20b390fa4 100644 --- a/Mage.Sets/src/mage/cards/c/CommanderCody.java +++ b/Mage.Sets/src/mage/cards/c/CommanderCody.java @@ -25,7 +25,7 @@ public final class CommanderCody extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-token Trooper creatures"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(new SubtypePredicate(SubType.TROOPER)); } diff --git a/Mage.Sets/src/mage/cards/c/CommitMemory.java b/Mage.Sets/src/mage/cards/c/CommitMemory.java index 4d6c2e77e37..a0fb02b1e59 100644 --- a/Mage.Sets/src/mage/cards/c/CommitMemory.java +++ b/Mage.Sets/src/mage/cards/c/CommitMemory.java @@ -45,7 +45,7 @@ public final class CommitMemory extends SplitCard { // Memory // Aftermath // Each player shuffles their hand and graveyard into their library, then draws seven cards. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addEffect(new ShuffleHandGraveyardAllEffect()); Effect effect = new DrawCardAllEffect(7); effect.setText(", then draws seven cards"); diff --git a/Mage.Sets/src/mage/cards/c/CommuneWithLava.java b/Mage.Sets/src/mage/cards/c/CommuneWithLava.java index 6f4f3bb193a..30392efead8 100644 --- a/Mage.Sets/src/mage/cards/c/CommuneWithLava.java +++ b/Mage.Sets/src/mage/cards/c/CommuneWithLava.java @@ -17,7 +17,6 @@ import java.util.Set; import java.util.UUID; /** - * * @author jeffwadsworth */ public final class CommuneWithLava extends CardImpl { @@ -60,7 +59,7 @@ class CommuneWithLavaEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Card sourceCard = game.getCard(source.getSourceId()); - if (controller != null) { + if (controller != null && sourceCard != null) { int amount = source.getManaCostsToPay().getX(); Set cards = controller.getLibrary().getTopCards(game, amount); controller.moveCardsToExile(cards, source, game, true, CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName()); @@ -105,9 +104,7 @@ class CommuneWithLavaMayPlayEffect extends AsThoughEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (castOnTurn != game.getTurnNum() && game.getPhase().getStep().getType() == PhaseStep.END_TURN) { - if (game.isActivePlayer(source.getControllerId())) { - return true; - } + return game.isActivePlayer(source.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/c/Condescend.java b/Mage.Sets/src/mage/cards/c/Condescend.java index 05ce5af84c0..26c8ceb6f9c 100644 --- a/Mage.Sets/src/mage/cards/c/Condescend.java +++ b/Mage.Sets/src/mage/cards/c/Condescend.java @@ -21,7 +21,7 @@ public final class Condescend extends CardImpl { // Counter target spell unless its controller pays {X}. - this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetSpell()); // Scry 2. this.getSpellAbility().addEffect(new ScryEffect(2)); diff --git a/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java b/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java index 3dc843647f1..c3bb6e17822 100644 --- a/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java +++ b/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java @@ -38,7 +38,7 @@ public final class ConduitOfRuin extends CardImpl { private static final FilterCreatureCard filterCost = new FilterCreatureCard("The first creature spell"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); filter.add(new ConvertedManaCostPredicate(ComparisonType.MORE_THAN, 6)); filterCost.add(new FirstCastCreatureSpellPredicate()); } @@ -117,7 +117,7 @@ class FirstCastCreatureSpellPredicate implements ObjectPlayerPredicate input, Game game) { if (input.getObject() instanceof Spell && ((Spell) input.getObject()).isCreature()) { - ConduitOfRuinWatcher watcher = (ConduitOfRuinWatcher) game.getState().getWatchers().get(ConduitOfRuinWatcher.class.getSimpleName()); + ConduitOfRuinWatcher watcher = game.getState().getWatcher(ConduitOfRuinWatcher.class); return watcher != null && watcher.creatureSpellsCastThisTurn(input.getPlayerId()) == 0; } return false; diff --git a/Mage.Sets/src/mage/cards/c/ConfusionInTheRanks.java b/Mage.Sets/src/mage/cards/c/ConfusionInTheRanks.java index 388e46d2bc9..fe65023e65f 100644 --- a/Mage.Sets/src/mage/cards/c/ConfusionInTheRanks.java +++ b/Mage.Sets/src/mage/cards/c/ConfusionInTheRanks.java @@ -1,10 +1,6 @@ package mage.cards.c; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.Effect; @@ -22,9 +18,14 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.UUID; /** - * * @author anonymous */ public final class ConfusionInTheRanks extends CardImpl { @@ -38,7 +39,6 @@ public final class ConfusionInTheRanks extends CardImpl { new CardTypePredicate(CardType.ENCHANTMENT) )); } - private final UUID originalId; public ConfusionInTheRanks(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}"); @@ -49,54 +49,18 @@ public final class ConfusionInTheRanks extends CardImpl { new ExchangeControlTargetEffect( Duration.EndOfGame, "its controller chooses target permanent " - + "another player controls that shares a card type with it. " - + "Exchange control of those permanents" + + "another player controls that shares a card type with it. " + + "Exchange control of those permanents" ), filter, false, SetTargetPointer.PERMANENT, null ); ability.addTarget(new TargetPermanent()); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(ConfusionInTheRanksAdjuster.instance); this.addAbility(ability); } public ConfusionInTheRanks(final ConfusionInTheRanks card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - UUID enteringPermanentId = null; - for (Effect effect : ability.getEffects()) { - enteringPermanentId = effect.getTargetPointer().getFirst(game, ability); - } - if (enteringPermanentId == null) { - return; - } - Permanent enteringPermanent = game.getPermanent(enteringPermanentId); - if (enteringPermanent == null) { - return; - } - ability.getTargets().clear(); - FilterPermanent filterTarget = new FilterPermanent(); - String message = ""; - filterTarget.add(Predicates.not(new ControllerIdPredicate(enteringPermanent.getControllerId()))); - Set cardTypesPredicates = new HashSet<>(1); - for (CardType cardTypeEntering : enteringPermanent.getCardType()) { - cardTypesPredicates.add(new CardTypePredicate(cardTypeEntering)); - if (!message.isEmpty()) { - message += "or "; - } - message += cardTypeEntering.toString().toLowerCase(Locale.ENGLISH) + ' '; - } - filterTarget.add(Predicates.or(cardTypesPredicates)); - message += "you don't control"; - filterTarget.setMessage(message); - TargetPermanent target = new TargetPermanent(filterTarget); - target.setTargetController(enteringPermanent.getControllerId()); - ability.getTargets().add(target); - } } @Override @@ -104,3 +68,40 @@ public final class ConfusionInTheRanks extends CardImpl { return new ConfusionInTheRanks(this); } } + +enum ConfusionInTheRanksAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + UUID enteringPermanentId = null; + for (Effect effect : ability.getEffects()) { + enteringPermanentId = effect.getTargetPointer().getFirst(game, ability); + } + if (enteringPermanentId == null) { + return; + } + Permanent enteringPermanent = game.getPermanent(enteringPermanentId); + if (enteringPermanent == null) { + return; + } + ability.getTargets().clear(); + FilterPermanent filterTarget = new FilterPermanent(); + String message = ""; + filterTarget.add(Predicates.not(new ControllerIdPredicate(enteringPermanent.getControllerId()))); + Set cardTypesPredicates = new HashSet<>(1); + for (CardType cardTypeEntering : enteringPermanent.getCardType()) { + cardTypesPredicates.add(new CardTypePredicate(cardTypeEntering)); + if (!message.isEmpty()) { + message += "or "; + } + message += cardTypeEntering.toString().toLowerCase(Locale.ENGLISH) + ' '; + } + filterTarget.add(Predicates.or(cardTypesPredicates)); + message += "you don't control"; + filterTarget.setMessage(message); + TargetPermanent target = new TargetPermanent(filterTarget); + target.setTargetController(enteringPermanent.getControllerId()); + ability.getTargets().add(target); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CongregationAtDawn.java b/Mage.Sets/src/mage/cards/c/CongregationAtDawn.java index 822d0addf2f..cdfd7c2e605 100644 --- a/Mage.Sets/src/mage/cards/c/CongregationAtDawn.java +++ b/Mage.Sets/src/mage/cards/c/CongregationAtDawn.java @@ -67,7 +67,7 @@ class CongregationAtDawnEffect extends OneShotEffect { if (controller.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { Cards revealed = new CardsImpl(); - for (UUID cardId : (List) target.getTargets()) { + for (UUID cardId : target.getTargets()) { Card card = controller.getLibrary().remove(cardId, game); revealed.add(card); } diff --git a/Mage.Sets/src/mage/cards/c/ConsecrateConsume.java b/Mage.Sets/src/mage/cards/c/ConsecrateConsume.java new file mode 100644 index 00000000000..72fc2b36a95 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConsecrateConsume.java @@ -0,0 +1,94 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.SacrificeEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ConsecrateConsume extends SplitCard { + + public ConsecrateConsume(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{1}{W/B}", "{2}{W}{B}", SpellAbilityType.SPLIT); + + // Consecrate + // Exile target card from a graveyard. + this.getLeftHalfCard().getSpellAbility().addEffect(new ExileTargetEffect()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCardInGraveyard()); + + // Draw a card. + this.getLeftHalfCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + + // Consume + // Target player sacrifices a creature with the greatest power among creatures they control. You gain life equal to its power. + this.getRightHalfCard().getSpellAbility().addEffect(new ConsumeEffect()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetPlayer()); + } + + private ConsecrateConsume(final ConsecrateConsume card) { + super(card); + } + + @Override + public ConsecrateConsume copy() { + return new ConsecrateConsume(this); + } +} + +class ConsumeEffect extends OneShotEffect { + + ConsumeEffect() { + super(Outcome.Benefit); + staticText = "Target player sacrifices a creature " + + "with the greatest power among creatures they control. " + + "You gain life equal to its power."; + } + + private ConsumeEffect(final ConsumeEffect effect) { + super(effect); + } + + @Override + public ConsumeEffect copy() { + return new ConsumeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(source.getFirstTarget()); + if (player == null || controller == null) { + return false; + } + int greatestPower = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(player.getId())) { + if (permanent != null && permanent.isCreature()) { + greatestPower = Math.max(permanent.getPower().getValue(), greatestPower); + } + } + FilterPermanent filter = new FilterCreaturePermanent("creature with power " + greatestPower); + filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, greatestPower)); + new SacrificeEffect(filter, 1, "").apply(game, source); + controller.gainLife(greatestPower, game, source); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ConsecratedByBlood.java b/Mage.Sets/src/mage/cards/c/ConsecratedByBlood.java index 6b03575c2a6..cc1b5456e10 100644 --- a/Mage.Sets/src/mage/cards/c/ConsecratedByBlood.java +++ b/Mage.Sets/src/mage/cards/c/ConsecratedByBlood.java @@ -32,7 +32,7 @@ public final class ConsecratedByBlood extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("two other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ConsecratedByBlood(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ConsignOblivion.java b/Mage.Sets/src/mage/cards/c/ConsignOblivion.java index 8a46e4a0d39..f54697f3d1a 100644 --- a/Mage.Sets/src/mage/cards/c/ConsignOblivion.java +++ b/Mage.Sets/src/mage/cards/c/ConsignOblivion.java @@ -29,7 +29,7 @@ public final class ConsignOblivion extends SplitCard { // Oblivion {4}{B} // Sorcery // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Target opponent discards two cards. getRightHalfCard().getSpellAbility().addEffect(new DiscardTargetEffect(2)); getRightHalfCard().getSpellAbility().addTarget(new TargetOpponent()); diff --git a/Mage.Sets/src/mage/cards/c/ConsignToThePit.java b/Mage.Sets/src/mage/cards/c/ConsignToThePit.java new file mode 100644 index 00000000000..18a9df9d95a --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConsignToThePit.java @@ -0,0 +1,69 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ConsignToThePit extends CardImpl { + + public ConsignToThePit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{B}"); + + // Destroy target creature. Consign to the Pit deals 2 damage to that creature's controller. + this.getSpellAbility().addEffect(new ConsignToThePitEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private ConsignToThePit(final ConsignToThePit card) { + super(card); + } + + @Override + public ConsignToThePit copy() { + return new ConsignToThePit(this); + } +} + +class ConsignToThePitEffect extends OneShotEffect { + + ConsignToThePitEffect() { + super(Outcome.Benefit); + staticText = "Destroy target creature. {this} deals 2 damage to that creature's controller."; + } + + private ConsignToThePitEffect(final ConsignToThePitEffect effect) { + super(effect); + } + + @Override + public ConsignToThePitEffect copy() { + return new ConsignToThePitEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + Player player = game.getPlayer(permanent.getControllerId()); + if (player == null) { + return false; + } + permanent.destroy(source.getSourceId(), game, false); + player.damage(2, source.getSourceId(), game); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/Conspiracy.java b/Mage.Sets/src/mage/cards/c/Conspiracy.java index dcac9387fbb..c9d92287aa4 100644 --- a/Mage.Sets/src/mage/cards/c/Conspiracy.java +++ b/Mage.Sets/src/mage/cards/c/Conspiracy.java @@ -1,9 +1,5 @@ - package mage.cards.c; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -22,8 +18,11 @@ import mage.game.stack.StackObject; import mage.players.Player; import mage.util.SubTypeList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + /** - * * @author anonymous */ public final class Conspiracy extends CardImpl { @@ -72,14 +71,14 @@ class ConspiracyEffect extends ContinuousEffectImpl { // in graveyard for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { setCreatureSubtype(card, subType, game); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { setCreatureSubtype(card, subType, game); } } @@ -99,13 +98,13 @@ class ConspiracyEffect extends ContinuousEffectImpl { for (UUID commanderId : controller.getCommandersIds()) { if (game.getState().getZone(commanderId) == Zone.COMMAND) { Card card = game.getCard(commanderId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { setCreatureSubtype(card, subType, game); } } } // creature spells you control - for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { + for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { StackObject stackObject = iterator.next(); if (stackObject instanceof Spell && stackObject.isControlledBy(source.getControllerId()) diff --git a/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java b/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java index a2a81ff2a78..16798cb14c1 100644 --- a/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java +++ b/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java @@ -29,7 +29,7 @@ public final class ConsulsShieldguard extends CardImpl { private final static FilterAttackingCreature filter = new FilterAttackingCreature(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ConsulsShieldguard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/ContainmentPriest.java b/Mage.Sets/src/mage/cards/c/ContainmentPriest.java index e3cffabc67c..701eb3aa4a0 100644 --- a/Mage.Sets/src/mage/cards/c/ContainmentPriest.java +++ b/Mage.Sets/src/mage/cards/c/ContainmentPriest.java @@ -1,6 +1,5 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -10,19 +9,16 @@ import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.players.Player; import mage.watchers.common.CreatureWasCastWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ContainmentPriest extends CardImpl { @@ -94,16 +90,14 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { - Card card = game.getCard(event.getTargetId()); Object entersTransformed = game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId()); - if (entersTransformed instanceof Boolean && (Boolean) entersTransformed && card.getSecondCardFace() != null) { + Card card = game.getCard(event.getTargetId()); + if (card != null && entersTransformed instanceof Boolean && (Boolean) entersTransformed && card.getSecondCardFace() != null) { card = card.getSecondCardFace(); } - if (card.isCreature()) { // TODO: Bestow Card cast as Enchantment probably not handled correctly - CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get(CreatureWasCastWatcher.class.getSimpleName()); - if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { - return true; - } + if (card != null && card.isCreature()) { // TODO: Bestow Card cast as Enchantment probably not handled correctly + CreatureWasCastWatcher watcher = game.getState().getWatcher(CreatureWasCastWatcher.class); + return watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId()); } } return false; diff --git a/Mage.Sets/src/mage/cards/c/Conversion.java b/Mage.Sets/src/mage/cards/c/Conversion.java index 24f0ef8d1f5..8731aaba764 100644 --- a/Mage.Sets/src/mage/cards/c/Conversion.java +++ b/Mage.Sets/src/mage/cards/c/Conversion.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.List; @@ -13,11 +12,14 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; import mage.abilities.mana.WhiteManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterLandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -27,13 +29,15 @@ import mage.game.permanent.Permanent; */ public final class Conversion extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent(SubType.MOUNTAIN, "Mountains"); - public Conversion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of your upkeep, sacrifice Conversion unless you pay {W}{W}. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{W}{W}")), TargetController.YOU, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new SacrificeSourceUnlessPaysEffect( + new ManaCostsImpl("{W}{W}")), + TargetController.YOU, + false)); // All Mountains are Plains. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConversionEffect())); @@ -72,15 +76,45 @@ public final class Conversion extends CardImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent land : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + for (Permanent land : game.getBattlefield().getAllActivePermanents(CardType.LAND)) { switch (layer) { - case AbilityAddingRemovingEffects_6: - land.removeAllAbilities(source.getSourceId(), game); - land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); - break; case TypeChangingEffects_4: - land.getSubtype(game).clear(); - land.getSubtype(game).add(SubType.PLAINS); + if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + land.getSubtype(game).clear(); + land.getSubtype(game).add(SubType.PLAINS); + game.getState().setValue("conversion" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game), + "true"); + } + break; + case AbilityAddingRemovingEffects_6: + if (game.getState().getValue("conversion" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game)) != null + && game.getState().getValue("conversion" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game)).equals("true")) { + land.removeAllAbilities(source.getSourceId(), game); + if (land.getSubtype(game).contains(SubType.FOREST)) { + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.PLAINS)) { + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.ISLAND)) { + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.SWAMP)) { + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + } + } break; } } @@ -89,20 +123,17 @@ public final class Conversion extends CardImpl { @Override public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + return layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.TypeChangingEffects_4; } @Override public Set isDependentTo(List allEffectsInLayer) { - // the dependent classes needs to be an enclosed class for dependent check of continuous effects return allEffectsInLayer .stream() - .filter(effect->effect.getDependencyTypes().contains(DependencyType.BecomeMountain)) + .filter(effect -> effect.getDependencyTypes().contains(DependencyType.BecomePlains)) .map(Effect::getId) .collect(Collectors.toSet()); - } - } - } diff --git a/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java b/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java index 8fe61fdfd93..a894eec2486 100644 --- a/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java +++ b/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java @@ -35,7 +35,7 @@ public final class CopperLeafAngel extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {tap}, Sacrifice X lands: Put X +1/+1 counters on Copper-Leaf Angel. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(),new GetXValue(), false), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(),GetXValue.instance, false), new TapSourceCost()); ability.addCost(new SacrificeXTargetCost(new FilterControlledLandPermanent("lands"), false)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CopperhoofVorrac.java b/Mage.Sets/src/mage/cards/c/CopperhoofVorrac.java index ea42ffd4a07..0a48307d1fe 100644 --- a/Mage.Sets/src/mage/cards/c/CopperhoofVorrac.java +++ b/Mage.Sets/src/mage/cards/c/CopperhoofVorrac.java @@ -28,7 +28,7 @@ public final class CopperhoofVorrac extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("untapped permanent your opponents control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/c/CoralAtoll.java b/Mage.Sets/src/mage/cards/c/CoralAtoll.java index 0fc9f416938..92a7ab94cf9 100644 --- a/Mage.Sets/src/mage/cards/c/CoralAtoll.java +++ b/Mage.Sets/src/mage/cards/c/CoralAtoll.java @@ -30,7 +30,7 @@ public final class CoralAtoll extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ISLAND)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public CoralAtoll(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CoralCommando.java b/Mage.Sets/src/mage/cards/c/CoralCommando.java new file mode 100644 index 00000000000..16b2ed94393 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CoralCommando.java @@ -0,0 +1,33 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CoralCommando extends CardImpl { + + public CoralCommando(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + } + + private CoralCommando(final CoralCommando card) { + super(card); + } + + @Override + public CoralCommando copy() { + return new CoralCommando(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CoralReef.java b/Mage.Sets/src/mage/cards/c/CoralReef.java index a15a7c6afc2..24093ec4c58 100644 --- a/Mage.Sets/src/mage/cards/c/CoralReef.java +++ b/Mage.Sets/src/mage/cards/c/CoralReef.java @@ -40,7 +40,7 @@ public final class CoralReef extends CardImpl { static { islandFilter.add(new SubtypePredicate(SubType.ISLAND)); - untappedBlueCreatureFilter.add(Predicates.not(new TappedPredicate())); + untappedBlueCreatureFilter.add(Predicates.not(TappedPredicate.instance)); untappedBlueCreatureFilter.add(new ColorPredicate(ObjectColor.BLUE)); } diff --git a/Mage.Sets/src/mage/cards/c/CorrosiveGale.java b/Mage.Sets/src/mage/cards/c/CorrosiveGale.java index 3a4ca7d2346..e5a5ccb8e41 100644 --- a/Mage.Sets/src/mage/cards/c/CorrosiveGale.java +++ b/Mage.Sets/src/mage/cards/c/CorrosiveGale.java @@ -27,7 +27,7 @@ public final class CorrosiveGale extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{G/P}"); - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, filter)); } public CorrosiveGale(final CorrosiveGale card) { diff --git a/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java b/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java index b135e5b7e78..d33404a5451 100644 --- a/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java +++ b/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java @@ -31,7 +31,7 @@ public final class CorrosiveOoze extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("equipped creature"); static { - filter.add(new EquippedPredicate()); + filter.add(EquippedPredicate.instance); } public CorrosiveOoze(UUID ownerId, CardSetInfo setInfo) { @@ -76,7 +76,7 @@ class CorrosiveOozeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - CorrosiveOozeCombatWatcher watcher = (CorrosiveOozeCombatWatcher) game.getState().getWatchers().get(CorrosiveOozeCombatWatcher.class.getSimpleName()); + CorrosiveOozeCombatWatcher watcher = game.getState().getWatcher(CorrosiveOozeCombatWatcher.class); if (controller != null && watcher != null) { MageObjectReference sourceMor = new MageObjectReference(source.getSourceObject(game), game); // get equipmentsToDestroy of creatres already left the battlefield @@ -118,8 +118,8 @@ class CorrosiveOozeEffect extends OneShotEffect { class CorrosiveOozeCombatWatcher extends Watcher { - public final HashMap> oozeBlocksOrBlocked = new HashMap<>(); - public final HashMap> oozeEquipmentsToDestroy = new HashMap<>(); + private final Map> oozeBlocksOrBlocked = new HashMap<>(); + private final Map> oozeEquipmentsToDestroy = new HashMap<>(); public CorrosiveOozeCombatWatcher() { super(CorrosiveOozeCombatWatcher.class.getSimpleName(), WatcherScope.GAME); @@ -127,11 +127,11 @@ class CorrosiveOozeCombatWatcher extends Watcher { public CorrosiveOozeCombatWatcher(final CorrosiveOozeCombatWatcher watcher) { super(watcher); - for (Map.Entry> entry : watcher.oozeBlocksOrBlocked.entrySet()) { - HashSet newSet = new HashSet<>(entry.getValue()); + for (Map.Entry> entry : watcher.oozeBlocksOrBlocked.entrySet()) { + Set newSet = new HashSet<>(entry.getValue()); oozeBlocksOrBlocked.put(entry.getKey(), newSet); } - for (Map.Entry> entry : watcher.oozeEquipmentsToDestroy.entrySet()) { + for (Map.Entry> entry : watcher.oozeEquipmentsToDestroy.entrySet()) { HashSet newSet = new HashSet<>(entry.getValue()); oozeEquipmentsToDestroy.put(entry.getKey(), newSet); } @@ -148,7 +148,7 @@ class CorrosiveOozeCombatWatcher extends Watcher { if (attacker != null && CardUtil.haveSameNames(attacker.getName(), "Corrosive Ooze")) { // To check for name is not working if Ooze is copied but name changed if (blocker != null && hasAttachedEquipment(game, blocker)) { MageObjectReference oozeMor = new MageObjectReference(attacker, game); - HashSet relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>()); + Set relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>()); relatedCreatures.add(new MageObjectReference(event.getSourceId(), game)); oozeBlocksOrBlocked.put(oozeMor, relatedCreatures); } @@ -156,7 +156,7 @@ class CorrosiveOozeCombatWatcher extends Watcher { if (blocker != null && CardUtil.haveSameNames(blocker.getName(), "Corrosive Ooze")) { if (attacker != null && hasAttachedEquipment(game, attacker)) { MageObjectReference oozeMor = new MageObjectReference(blocker, game); - HashSet relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>()); + Set relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>()); relatedCreatures.add(new MageObjectReference(event.getTargetId(), game)); oozeBlocksOrBlocked.put(oozeMor, relatedCreatures); } @@ -167,14 +167,14 @@ class CorrosiveOozeCombatWatcher extends Watcher { if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { if (game.getTurn() != null && TurnPhase.COMBAT == game.getTurn().getPhaseType()) { // Check if a previous blocked or blocked by creatures is leaving the battlefield - for (Map.Entry> entry : oozeBlocksOrBlocked.entrySet()) { + for (Map.Entry> entry : oozeBlocksOrBlocked.entrySet()) { for (MageObjectReference mor : entry.getValue()) { if (mor.refersTo(((ZoneChangeEvent) event).getTarget(), game)) { // check for equipments and remember for (UUID attachmentId : ((ZoneChangeEvent) event).getTarget().getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); if (attachment != null && attachment.hasSubtype(SubType.EQUIPMENT, game)) { - HashSet toDestroy = oozeEquipmentsToDestroy.getOrDefault(entry.getKey(), new HashSet<>()); + Set toDestroy = oozeEquipmentsToDestroy.getOrDefault(entry.getKey(), new HashSet<>()); toDestroy.add(new MageObjectReference(attachment, game)); oozeEquipmentsToDestroy.put(entry.getKey(), toDestroy); } diff --git a/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java b/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java index bf527160874..a6e289d8f46 100644 --- a/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java +++ b/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java @@ -93,9 +93,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { MageObject object = game.getObject(event.getSourceId()); String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); - if (object != null && CardUtil.haveSameNames(object.getName(), needName)) { - return true; - } + return object != null && CardUtil.haveSameNames(object.getName(), needName); } return false; } @@ -123,8 +121,10 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl if ((abilityToModify instanceof SpellAbility) && abilityToModify.isControlledBy(source.getControllerId())) { Card card = game.getCard(abilityToModify.getSourceId()); - String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); - return CardUtil.haveSameNames(card.getName(), needName); + if (card != null) { + String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + return CardUtil.haveSameNames(card.getName(), needName); + } } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java b/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java index 4706b03adb8..6c4fad4bf0e 100644 --- a/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java +++ b/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java @@ -29,7 +29,7 @@ public final class CourtStreetDenizen extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another white creature"); private static final FilterCreaturePermanent filterOpponentCreature = new FilterCreaturePermanent("creature an opponent controls"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ColorPredicate(ObjectColor.WHITE)); filter.add(new ControllerPredicate(TargetController.YOU)); filterOpponentCreature.add(new ControllerPredicate(TargetController.OPPONENT)); diff --git a/Mage.Sets/src/mage/cards/c/CovetedJewel.java b/Mage.Sets/src/mage/cards/c/CovetedJewel.java index 01cf2199b55..0e068ed2a5c 100644 --- a/Mage.Sets/src/mage/cards/c/CovetedJewel.java +++ b/Mage.Sets/src/mage/cards/c/CovetedJewel.java @@ -1,6 +1,5 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -13,20 +12,16 @@ import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class CovetedJewel extends CardImpl { @@ -130,7 +125,7 @@ class CovetedJewelControlEffect extends ContinuousEffectImpl { Player newControllingPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); if (permanent == null || newControllingPlayer == null || !newControllingPlayer.isInGame()) { this.discard(); - return true; + return false; } permanent.changeControllerId(getTargetPointer().getFirst(game, source), game); return true; diff --git a/Mage.Sets/src/mage/cards/c/CovetedPeacock.java b/Mage.Sets/src/mage/cards/c/CovetedPeacock.java index 9b748f40682..dbe7642a590 100644 --- a/Mage.Sets/src/mage/cards/c/CovetedPeacock.java +++ b/Mage.Sets/src/mage/cards/c/CovetedPeacock.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -11,18 +10,23 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class CovetedPeacock extends CardImpl { - private final UUID originalId; + public static final FilterPermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(DefendingPlayerControlsPredicate.instance); + } public CovetedPeacock(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); @@ -36,26 +40,12 @@ public final class CovetedPeacock extends CardImpl { // Whenever Coveted Peacock attacks, you may goad target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new GoadTargetEffect(), true, "Whenever {this} attacks, you may goad target creature defending player controls."); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } public CovetedPeacock(final CovetedPeacock card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - ability.addTarget(target); - } } @Override diff --git a/Mage.Sets/src/mage/cards/c/CrabappleCohort.java b/Mage.Sets/src/mage/cards/c/CrabappleCohort.java index 3cc760d1094..aa536b97243 100644 --- a/Mage.Sets/src/mage/cards/c/CrabappleCohort.java +++ b/Mage.Sets/src/mage/cards/c/CrabappleCohort.java @@ -33,7 +33,7 @@ public final class CrabappleCohort extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.GREEN)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CrabappleCohort(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/Crackleburr.java b/Mage.Sets/src/mage/cards/c/Crackleburr.java index b958d200618..d970807b973 100644 --- a/Mage.Sets/src/mage/cards/c/Crackleburr.java +++ b/Mage.Sets/src/mage/cards/c/Crackleburr.java @@ -38,10 +38,10 @@ public final class Crackleburr extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.RED)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter2.add(new ColorPredicate(ObjectColor.BLUE)); - filter2.add(new TappedPredicate()); + filter2.add(TappedPredicate.instance); } public Crackleburr(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CracklingPerimeter.java b/Mage.Sets/src/mage/cards/c/CracklingPerimeter.java index b2a49d8229e..0c1e9fc08f7 100644 --- a/Mage.Sets/src/mage/cards/c/CracklingPerimeter.java +++ b/Mage.Sets/src/mage/cards/c/CracklingPerimeter.java @@ -27,7 +27,7 @@ public final class CracklingPerimeter extends CardImpl { static { filter.add(new SubtypePredicate(SubType.GATE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public CracklingPerimeter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CrashingBoars.java b/Mage.Sets/src/mage/cards/c/CrashingBoars.java index 9e47943bd4b..26678b713cb 100644 --- a/Mage.Sets/src/mage/cards/c/CrashingBoars.java +++ b/Mage.Sets/src/mage/cards/c/CrashingBoars.java @@ -53,7 +53,7 @@ class CrashingBoarsEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } CrashingBoarsEffect() { diff --git a/Mage.Sets/src/mage/cards/c/CratersClaws.java b/Mage.Sets/src/mage/cards/c/CratersClaws.java index 7d212220f11..acdea1c74a7 100644 --- a/Mage.Sets/src/mage/cards/c/CratersClaws.java +++ b/Mage.Sets/src/mage/cards/c/CratersClaws.java @@ -24,8 +24,8 @@ public final class CratersClaws extends CardImpl { // Crater's Claws deals X damage to any target. // Ferocious — Crater's Claws deals X plus 2 damage to that creature or player instead if you control a creature with power 4 or greater. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageTargetEffect(new IntPlusDynamicValue(2, new ManacostVariableValue())), - new DamageTargetEffect(new ManacostVariableValue()), + new DamageTargetEffect(new IntPlusDynamicValue(2, ManacostVariableValue.instance)), + new DamageTargetEffect(ManacostVariableValue.instance), FerociousCondition.instance, "{this} deals X damage to any target." + "
Ferocious — {this} deals X plus 2 damage to that permanent or player instead if you control a creature with power 4 or greater")); diff --git a/Mage.Sets/src/mage/cards/c/CrazedFirecat.java b/Mage.Sets/src/mage/cards/c/CrazedFirecat.java index fdc96f3f9ae..dac9cfa97ac 100644 --- a/Mage.Sets/src/mage/cards/c/CrazedFirecat.java +++ b/Mage.Sets/src/mage/cards/c/CrazedFirecat.java @@ -66,7 +66,7 @@ class CrazedFirecatEffect extends OneShotEffect { Permanent sourceObject = game.getPermanent(source.getSourceId()); if (controller != null && sourceObject != null) { int flipsWon = 0; - while (controller.flipCoin(game)) { + while (controller.flipCoin(source, game, true)) { flipsWon++; } sourceObject.addCounters(CounterType.P1P1.createInstance(flipsWon), source, game); diff --git a/Mage.Sets/src/mage/cards/c/CreatureBond.java b/Mage.Sets/src/mage/cards/c/CreatureBond.java index a1a84630738..7a6fff4437a 100644 --- a/Mage.Sets/src/mage/cards/c/CreatureBond.java +++ b/Mage.Sets/src/mage/cards/c/CreatureBond.java @@ -35,7 +35,7 @@ public final class CreatureBond extends CardImpl { this.addAbility(ability); // When enchanted creature dies, Creature Bond deals damage equal to that creature's toughness to the creature's controller. - this.addAbility( new DiesAttachedTriggeredAbility(new DamageAttachedControllerEffect(new AttachedPermanentToughnessValue()), "enchanted creature")); + this.addAbility( new DiesAttachedTriggeredAbility(new DamageAttachedControllerEffect(AttachedPermanentToughnessValue.instance), "enchanted creature")); } public CreatureBond(final CreatureBond card) { diff --git a/Mage.Sets/src/mage/cards/c/CreepyDoll.java b/Mage.Sets/src/mage/cards/c/CreepyDoll.java index ad0b08e0992..71c3056523a 100644 --- a/Mage.Sets/src/mage/cards/c/CreepyDoll.java +++ b/Mage.Sets/src/mage/cards/c/CreepyDoll.java @@ -100,7 +100,7 @@ class CreepyDollEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (player.flipCoin(game)) { + if (player.flipCoin(source, game, true)) { UUID targetId = getTargetPointer().getFirst(game, source); Permanent permanent = game.getPermanent(targetId); if (permanent != null) { diff --git a/Mage.Sets/src/mage/cards/c/CrimsonHellkite.java b/Mage.Sets/src/mage/cards/c/CrimsonHellkite.java index a929af7dfd1..f9f867142d4 100644 --- a/Mage.Sets/src/mage/cards/c/CrimsonHellkite.java +++ b/Mage.Sets/src/mage/cards/c/CrimsonHellkite.java @@ -43,7 +43,7 @@ public final class CrimsonHellkite extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // {X}, {tap}: Crimson Hellkite deals X damage to target creature. Spend only red mana on X. - Effect effect = new DamageTargetEffect(new ManacostVariableValue()); + Effect effect = new DamageTargetEffect(ManacostVariableValue.instance); effect.setText("{this} deals X damage to target creature. Spend only red mana on X"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/c/CrimsonHonorGuard.java b/Mage.Sets/src/mage/cards/c/CrimsonHonorGuard.java index 341e4494f54..147aeb97ba3 100644 --- a/Mage.Sets/src/mage/cards/c/CrimsonHonorGuard.java +++ b/Mage.Sets/src/mage/cards/c/CrimsonHonorGuard.java @@ -56,7 +56,7 @@ class CrimsonHonorGuardEffect extends OneShotEffect { private final static FilterPermanent filter = new FilterPermanent("Commander"); static { - filter.add(new CommanderPredicate()); + filter.add(CommanderPredicate.instance); } public CrimsonHonorGuardEffect() { diff --git a/Mage.Sets/src/mage/cards/c/CrookOfCondemnation.java b/Mage.Sets/src/mage/cards/c/CrookOfCondemnation.java index 71016541e7a..8770fff76c4 100644 --- a/Mage.Sets/src/mage/cards/c/CrookOfCondemnation.java +++ b/Mage.Sets/src/mage/cards/c/CrookOfCondemnation.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileSourceCost; @@ -15,29 +14,28 @@ import mage.constants.CardType; import mage.constants.Zone; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class CrookOfCondemnation extends CardImpl { - - private UUID exileId = UUID.randomUUID(); public CrookOfCondemnation(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - + // {1}, {t}: Exile target card from a graveyard. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{1}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCardInGraveyard()); this.addAbility(ability); - + // {1}, Exile Crook of Condemnation: Exile all cards from all graveyards. Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileGraveyardAllPlayersEffect(), new ManaCostsImpl("{1}")); ability2.addCost(new ExileSourceCost()); this.addAbility(ability2); - + } public CrookOfCondemnation(final CrookOfCondemnation card) { diff --git a/Mage.Sets/src/mage/cards/c/CrookclawElder.java b/Mage.Sets/src/mage/cards/c/CrookclawElder.java index a570f6c7f96..54f59b87c56 100644 --- a/Mage.Sets/src/mage/cards/c/CrookclawElder.java +++ b/Mage.Sets/src/mage/cards/c/CrookclawElder.java @@ -33,9 +33,9 @@ public final class CrookclawElder extends CardImpl { static { filter.add(new SubtypePredicate(SubType.BIRD)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter2.add(new SubtypePredicate(SubType.WIZARD)); - filter2.add(Predicates.not(new TappedPredicate())); + filter2.add(Predicates.not(TappedPredicate.instance)); } public CrookclawElder(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CrookedScales.java b/Mage.Sets/src/mage/cards/c/CrookedScales.java index 6a0e880cf7e..0b19ce0bc44 100644 --- a/Mage.Sets/src/mage/cards/c/CrookedScales.java +++ b/Mage.Sets/src/mage/cards/c/CrookedScales.java @@ -72,7 +72,7 @@ class CrookedScalesEffect extends OneShotEffect { Cost cost; String message = "You lost the flip. Pay {3} to prevent your creature from being destroyed?"; do { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { if (theirGuy != null) { theirGuy.destroy(controller.getId(), game, false); } diff --git a/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java b/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java index 0aa256d1170..c23faefedb9 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfConvergence.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -20,11 +19,12 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** * @author jeffwadsworth */ @@ -46,7 +46,7 @@ public final class CrownOfConvergence extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CrownOfConvergenceEffect(), new ManaCostsImpl("{G}{W}"))); } - public CrownOfConvergence(final CrownOfConvergence card) { + private CrownOfConvergence(final CrownOfConvergence card) { super(card); } @@ -58,8 +58,6 @@ public final class CrownOfConvergence extends CardImpl { class CrownOfConvergenceColorBoostEffect extends BoostAllEffect { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creatures you control"); - private static final String effectText = "creatures you control that share a color with that card get +1/+1"; CrownOfConvergenceColorBoostEffect() { @@ -67,7 +65,7 @@ class CrownOfConvergenceColorBoostEffect extends BoostAllEffect { staticText = effectText; } - CrownOfConvergenceColorBoostEffect(CrownOfConvergenceColorBoostEffect effect) { + private CrownOfConvergenceColorBoostEffect(CrownOfConvergenceColorBoostEffect effect) { super(effect); } @@ -77,7 +75,7 @@ class CrownOfConvergenceColorBoostEffect extends BoostAllEffect { if (you != null) { Card topCard = you.getLibrary().getFromTop(game); if (topCard != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), source.getSourceId(), game)) { if (permanent.getColor(game).shares(topCard.getColor(game)) && !permanent.getColor(game).isColorless()) { permanent.addPower(power.calculate(game, source, this)); permanent.addToughness(toughness.calculate(game, source, this)); @@ -97,12 +95,12 @@ class CrownOfConvergenceColorBoostEffect extends BoostAllEffect { class CrownOfConvergenceEffect extends OneShotEffect { - public CrownOfConvergenceEffect() { + CrownOfConvergenceEffect() { super(Outcome.Neutral); staticText = "Put the top card of your library on the bottom of your library"; } - public CrownOfConvergenceEffect(final CrownOfConvergenceEffect effect) { + private CrownOfConvergenceEffect(final CrownOfConvergenceEffect effect) { super(effect); } diff --git a/Mage.Sets/src/mage/cards/c/CrucibleOfTheSpiritDragon.java b/Mage.Sets/src/mage/cards/c/CrucibleOfTheSpiritDragon.java index 1eb974792d8..0b8fe29b228 100644 --- a/Mage.Sets/src/mage/cards/c/CrucibleOfTheSpiritDragon.java +++ b/Mage.Sets/src/mage/cards/c/CrucibleOfTheSpiritDragon.java @@ -44,7 +44,7 @@ public final class CrucibleOfTheSpiritDragon extends CardImpl { // {T}, Remove X storage counters from Crucible of the Spirit Dragon: Add X mana in any combination of colors. Spend this mana only to cast Dragon spells or activate abilities of Dragons. ability = new ConditionalAnyColorManaAbility( new TapSourceCost(), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new CrucibleOfTheSpiritDragonManaBuilder(), false ); diff --git a/Mage.Sets/src/mage/cards/c/CruelRevival.java b/Mage.Sets/src/mage/cards/c/CruelRevival.java index cfc5ba90496..8b06c4f8365 100644 --- a/Mage.Sets/src/mage/cards/c/CruelRevival.java +++ b/Mage.Sets/src/mage/cards/c/CruelRevival.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -21,8 +19,9 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class CruelRevival extends CardImpl { @@ -37,7 +36,7 @@ public final class CruelRevival extends CardImpl { } public CruelRevival(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}"); // Destroy target non-Zombie creature. It can't be regenerated. Return up to one target Zombie card from your graveyard to your hand. @@ -70,10 +69,11 @@ class CruelRevivalEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent targetDestroy = game.getPermanent(source.getFirstTarget()); - Card targetRetrieve = game.getCard(source.getTargets().get(1).getFirstTarget()); if (targetDestroy != null) { targetDestroy.destroy(source.getSourceId(), game, true); } + + Card targetRetrieve = game.getCard(source.getTargets().get(1).getFirstTarget()); if (targetRetrieve != null) { targetRetrieve.moveToZone(Zone.HAND, source.getSourceId(), game, true); } diff --git a/Mage.Sets/src/mage/cards/c/CruelSadist.java b/Mage.Sets/src/mage/cards/c/CruelSadist.java index 3be03cd96ea..63e7c85fac2 100644 --- a/Mage.Sets/src/mage/cards/c/CruelSadist.java +++ b/Mage.Sets/src/mage/cards/c/CruelSadist.java @@ -44,7 +44,7 @@ public final class CruelSadist extends CardImpl { this.addAbility(ability); // {2}{B}, {T}, Remove X +1/+1 counters from Cruel Sadist: Cruel Sadist deals X damage to target creature. - Effect effect = new DamageTargetEffect(new RemovedCountersForCostValue()); + Effect effect = new DamageTargetEffect(RemovedCountersForCostValue.instance); effect.setText("{this} deals X damage to target creature"); ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}{B}")); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/c/CruelUltimatum.java b/Mage.Sets/src/mage/cards/c/CruelUltimatum.java index f4df0d42232..490c2d4d4f8 100644 --- a/Mage.Sets/src/mage/cards/c/CruelUltimatum.java +++ b/Mage.Sets/src/mage/cards/c/CruelUltimatum.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -21,8 +19,9 @@ import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author North */ public final class CruelUltimatum extends CardImpl { @@ -80,7 +79,8 @@ class CruelUltimatumEffect extends OneShotEffect { if (card == null) { return false; } - controller.moveCards(card, Zone.HAND, source, game); + + return controller.moveCards(card, Zone.HAND, source, game); } return true; } diff --git a/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java b/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java new file mode 100644 index 00000000000..23ac8658fcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java @@ -0,0 +1,126 @@ +package mage.cards.c; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CryOfTheCarnarium extends CardImpl { + + public CryOfTheCarnarium(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}"); + + // All creatures get -2/-2 until end of turn. Exile all creature cards in all graveyards that were put there from the battlefield this turn. If a creature would die this turn, exile it instead. + this.getSpellAbility().addEffect(new BoostAllEffect(-2, -2, Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new CryOfTheCarnariumExileEffect()); + this.getSpellAbility().addEffect(new CryOfTheCarnariumReplacementEffect()); + this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); + } + + private CryOfTheCarnarium(final CryOfTheCarnarium card) { + super(card); + } + + @Override + public CryOfTheCarnarium copy() { + return new CryOfTheCarnarium(this); + } +} + +class CryOfTheCarnariumExileEffect extends OneShotEffect { + + CryOfTheCarnariumExileEffect() { + super(Outcome.Benefit); + staticText = "Exile all creature cards in all graveyards that were put there from the battlefield this turn."; + } + + private CryOfTheCarnariumExileEffect(final CryOfTheCarnariumExileEffect effect) { + super(effect); + } + + @Override + public CryOfTheCarnariumExileEffect copy() { + return new CryOfTheCarnariumExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); + if (player == null || watcher == null) { + return false; + } + Cards cards = new CardsImpl(); + for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { + if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { + Card card = mor.getCard(game); + if (card != null && card.isCreature()) { + cards.add(card); + } + } + } + player.moveCards(cards, Zone.EXILED, source, game); + return true; + } +} + +class CryOfTheCarnariumReplacementEffect extends ReplacementEffectImpl { + + CryOfTheCarnariumReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Exile); + staticText = " If a creature would die this turn, exile it instead."; + } + + private CryOfTheCarnariumReplacementEffect(final CryOfTheCarnariumReplacementEffect effect) { + super(effect); + } + + @Override + public CryOfTheCarnariumReplacementEffect copy() { + return new CryOfTheCarnariumReplacementEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (permanent != null) { + Player player = game.getPlayer(permanent.getControllerId()); + if (player != null) { + return player.moveCards(permanent, Zone.EXILED, source, game); + } + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + return zEvent.getTarget() != null + && zEvent.getTarget().isCreature() + && zEvent.getFromZone() == Zone.BATTLEFIELD + && zEvent.getToZone() == Zone.GRAVEYARD; + } + +} diff --git a/Mage.Sets/src/mage/cards/c/CryptRats.java b/Mage.Sets/src/mage/cards/c/CryptRats.java index f19332295b1..d5dfc118933 100644 --- a/Mage.Sets/src/mage/cards/c/CryptRats.java +++ b/Mage.Sets/src/mage/cards/c/CryptRats.java @@ -38,7 +38,7 @@ public final class CryptRats extends CardImpl { this.toughness = new MageInt(1); // {X}: Crypt Rats deals X damage to each creature and each player. Spend only black mana on X. - Effect effect = new DamageEverythingEffect(new ManacostVariableValue()); + Effect effect = new DamageEverythingEffect(ManacostVariableValue.instance); effect.setText("{this} deals X damage to each creature and each player. Spend only black mana on X"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect,new ManaCostsImpl("{X}")); VariableCost variableCost = ability.getManaCostsToPay().getVariableCosts().get(0); diff --git a/Mage.Sets/src/mage/cards/c/Cryptbreaker.java b/Mage.Sets/src/mage/cards/c/Cryptbreaker.java index 446fe224f6f..71255d87091 100644 --- a/Mage.Sets/src/mage/cards/c/Cryptbreaker.java +++ b/Mage.Sets/src/mage/cards/c/Cryptbreaker.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -25,8 +23,9 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.permanent.token.ZombieToken; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class Cryptbreaker extends CardImpl { @@ -34,12 +33,12 @@ public final class Cryptbreaker extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Zombies you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.ZOMBIE)); } public Cryptbreaker(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); this.subtype.add(SubType.ZOMBIE); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -51,12 +50,10 @@ public final class Cryptbreaker extends CardImpl { this.addAbility(ability); // Tap three untapped Zombies you control: You draw a card and you lose 1 life. - Effect effect = new DrawCardSourceControllerEffect(1); - effect.setText("You draw a card"); + Effect effect = new DrawCardSourceControllerEffect(1, "you"); ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true))); effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - ability.addEffect(effect); + ability.addEffect(effect.concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CrypticGateway.java b/Mage.Sets/src/mage/cards/c/CrypticGateway.java index 704e9dc48bd..ea840305cfb 100644 --- a/Mage.Sets/src/mage/cards/c/CrypticGateway.java +++ b/Mage.Sets/src/mage/cards/c/CrypticGateway.java @@ -39,7 +39,7 @@ public final class CrypticGateway extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } TargetControlledPermanent target; @@ -70,7 +70,7 @@ class CrypticGatewayCost extends CostImpl { TargetControlledPermanent target; static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public CrypticGatewayCost(TargetControlledPermanent target) { @@ -87,7 +87,7 @@ class CrypticGatewayCost extends CostImpl { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { int numTargets = 0; while (numTargets < 2 && target.choose(Outcome.Tap, controllerId, sourceId, game)) { - for (UUID targetId : (List) target.getTargets()) { + for (UUID targetId : target.getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent == null) { return false; diff --git a/Mage.Sets/src/mage/cards/c/Cryptoplasm.java b/Mage.Sets/src/mage/cards/c/Cryptoplasm.java index ac76c4b3397..2fcf2c30d97 100644 --- a/Mage.Sets/src/mage/cards/c/Cryptoplasm.java +++ b/Mage.Sets/src/mage/cards/c/Cryptoplasm.java @@ -28,7 +28,7 @@ public final class Cryptoplasm extends CardImpl { final static FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Cryptoplasm(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CultGuildmage.java b/Mage.Sets/src/mage/cards/c/CultGuildmage.java new file mode 100644 index 00000000000..7fa8895aaeb --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CultGuildmage.java @@ -0,0 +1,54 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.target.TargetPlayer; +import mage.target.common.TargetOpponentOrPlaneswalker; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class CultGuildmage extends CardImpl { + + public CultGuildmage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{R}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {3}{B}, {T}: Target player discards a card. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new ManaCostsImpl("{3}{B}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + + // {R}, {T}: Cult Guildmage deals 1 damage to target opponent or planeswalker. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{R}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetOpponentOrPlaneswalker()); + this.addAbility(ability); + } + + public CultGuildmage(final CultGuildmage card) { + super(card); + } + + @Override + public CultGuildmage copy() { + return new CultGuildmage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CultivatorDrone.java b/Mage.Sets/src/mage/cards/c/CultivatorDrone.java index 6c86c444542..9dc80b53106 100644 --- a/Mage.Sets/src/mage/cards/c/CultivatorDrone.java +++ b/Mage.Sets/src/mage/cards/c/CultivatorDrone.java @@ -92,7 +92,7 @@ class CultivatorDroneManaCondition extends ManaCondition implements Condition { } } if (costToPay instanceof ManaCost) { - return ((ManaCost) costToPay).getText().contains("{C}"); + return costToPay.getText().contains("{C}"); } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CuombajjWitches.java b/Mage.Sets/src/mage/cards/c/CuombajjWitches.java index 2bb7d7a7772..5d58744bdbb 100644 --- a/Mage.Sets/src/mage/cards/c/CuombajjWitches.java +++ b/Mage.Sets/src/mage/cards/c/CuombajjWitches.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -11,68 +10,42 @@ import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetOpponent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LoneFox - */ public final class CuombajjWitches extends CardImpl { - private final UUID originalId; - public CuombajjWitches(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(3); - //TODO: Make ability properly copiable // {T}: Cuombajj Witches deals 1 damage to any target and 1 damage to any target of an opponent's choice. Effect effect = new DamageTargetEffect(1); effect.setText("{this} deals 1 damage to any target and 1 damage to any target of an opponent's choice"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); ability.addTarget(new TargetAnyTarget()); + ability.setTargetAdjuster(CuombajjWitchesAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability.getOriginalId().equals(originalId)) { - Player controller = game.getPlayer(ability.getControllerId()); - if(controller != null) { - UUID opponentId = null; - if(game.getOpponents(controller.getId()).size() > 1) { - Target target = new TargetOpponent(true); - if(controller.chooseTarget(Outcome.Neutral, target, ability, game)) { - opponentId = target.getFirstTarget(); - } - } - else { - opponentId = game.getOpponents(controller.getId()).iterator().next(); - } - - if(opponentId != null) { - ability.getTargets().get(1).setTargetController(opponentId); - } - } - } } public CuombajjWitches(final CuombajjWitches card) { super(card); - this.originalId = card.originalId; } @Override @@ -80,3 +53,26 @@ public final class CuombajjWitches extends CardImpl { return new CuombajjWitches(this); } } + +enum CuombajjWitchesAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller != null) { + UUID opponentId = null; + if (game.getOpponents(controller.getId()).size() > 1) { + Target target = new TargetOpponent(true); + if (controller.chooseTarget(Outcome.Neutral, target, ability, game)) { + opponentId = target.getFirstTarget(); + } + } else { + opponentId = game.getOpponents(controller.getId()).iterator().next(); + } + if (opponentId != null) { + ability.getTargets().get(1).setTargetController(opponentId); + } + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CurseOfExhaustion.java b/Mage.Sets/src/mage/cards/c/CurseOfExhaustion.java index d08a2bb66ff..ea636fef2a4 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfExhaustion.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfExhaustion.java @@ -77,7 +77,7 @@ class CurseOfExhaustionEffect extends ContinuousRuleModifyingEffectImpl { if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); if (player != null && event.getPlayerId().equals(player.getId())) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) > 0) { return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java b/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java index cc40d560843..0414cd2ef06 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java @@ -1,15 +1,10 @@ package mage.cards.c; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -18,9 +13,13 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.CurseOfTheSwineBoarToken; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; /** - * * @author LevelX2 */ public final class CurseOfTheSwine extends CardImpl { @@ -31,15 +30,7 @@ public final class CurseOfTheSwine extends CardImpl { // Exile X target creatures. For each creature exiled this way, its controller creates a 2/2 green Boar creature token. this.getSpellAbility().addEffect(new CurseOfTheSwineEffect()); // Correct number of targets will be set in adjustTargets - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility && ability.getAbilityType() == AbilityType.SPELL) { - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); - } + this.getSpellAbility().setTargetAdjuster(CurseOfTheSwineAdjuster.instance); } public CurseOfTheSwine(final CurseOfTheSwine card) { @@ -52,6 +43,16 @@ public final class CurseOfTheSwine extends CardImpl { } } +enum CurseOfTheSwineAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} + class CurseOfTheSwineEffect extends OneShotEffect { public CurseOfTheSwineEffect() { diff --git a/Mage.Sets/src/mage/cards/c/CurtainOfLight.java b/Mage.Sets/src/mage/cards/c/CurtainOfLight.java index c96889ff7a4..5f1e7056ef7 100644 --- a/Mage.Sets/src/mage/cards/c/CurtainOfLight.java +++ b/Mage.Sets/src/mage/cards/c/CurtainOfLight.java @@ -31,8 +31,8 @@ public final class CurtainOfLight extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked attacking creature"); static { - filter.add(new AttackingPredicate()); - filter.add(Predicates.not(new BlockedPredicate())); + filter.add(AttackingPredicate.instance); + filter.add(Predicates.not(BlockedPredicate.instance)); } public CurtainOfLight(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java b/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java index 2653f5d1f35..ab23d88f7d7 100644 --- a/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java +++ b/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java @@ -29,7 +29,7 @@ public final class CustodiSoulbinders extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public CustodiSoulbinders(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java b/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java index ae27d4bddab..1f19992beca 100644 --- a/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java +++ b/Mage.Sets/src/mage/cards/c/CustodiSoulcaller.java @@ -1,10 +1,6 @@ package mage.cards.c; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -12,7 +8,10 @@ import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffec import mage.abilities.keyword.MeleeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.WatcherScope; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.Predicates; @@ -23,16 +22,21 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import mage.watchers.Watcher; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author L_J */ public final class CustodiSoulcaller extends CardImpl { public CustodiSoulcaller(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); this.power = new MageInt(1); @@ -45,25 +49,10 @@ public final class CustodiSoulcaller extends CardImpl { Ability ability = new AttacksTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false); ability.addWatcher(new CustodiSoulcallerWatcher()); ability.addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card with converted mana cost X or less from your graveyard, where X is the number of players you attacked with a creature this combat"))); + ability.setTargetAdjuster(CustodiSoulcallerAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getClass().equals(AttacksTriggeredAbility.class)) { - ability.getTargets().clear(); - CustodiSoulcallerWatcher watcher = (CustodiSoulcallerWatcher) game.getState().getWatchers().get(CustodiSoulcallerWatcher.class.getSimpleName()); - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); - if (watcher != null && watcher.playersAttacked != null) { - int xValue = watcher.getNumberOfAttackedPlayers(sourcePermanent.getControllerId()); - FilterCard filter = new FilterCard("creature card with converted mana cost " + xValue + " or less"); - filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(Predicates.or(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue), new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue))); - ability.getTargets().add(new TargetCardInYourGraveyard(filter)); - } - } - } - public CustodiSoulcaller(final CustodiSoulcaller card) { super(card); } @@ -74,9 +63,27 @@ public final class CustodiSoulcaller extends CardImpl { } } +enum CustodiSoulcallerAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + CustodiSoulcallerWatcher watcher = (CustodiSoulcallerWatcher) game.getState().getWatchers().get(CustodiSoulcallerWatcher.class.getSimpleName()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); + if (watcher != null) { + int xValue = watcher.getNumberOfAttackedPlayers(sourcePermanent.getControllerId()); + FilterCard filter = new FilterCard("creature card with converted mana cost " + xValue + " or less"); + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(Predicates.or(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue), new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue))); + ability.getTargets().add(new TargetCardInYourGraveyard(filter)); + } + } +} + class CustodiSoulcallerWatcher extends Watcher { - protected final HashMap> playersAttacked = new HashMap<>(0); + private final HashMap> playersAttacked = new HashMap<>(0); CustodiSoulcallerWatcher() { super("CustodiSoulcallerWatcher", WatcherScope.GAME); @@ -91,8 +98,7 @@ class CustodiSoulcallerWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == EventType.BEGIN_COMBAT_STEP_PRE) { this.playersAttacked.clear(); - } - else if (event.getType() == EventType.ATTACKER_DECLARED) { + } else if (event.getType() == EventType.ATTACKER_DECLARED) { Set attackedPlayers = this.playersAttacked.getOrDefault(event.getPlayerId(), new HashSet<>(1)); attackedPlayers.add(event.getTargetId()); this.playersAttacked.put(event.getPlayerId(), attackedPlayers); diff --git a/Mage.Sets/src/mage/cards/c/CutRibbons.java b/Mage.Sets/src/mage/cards/c/CutRibbons.java index 4378f21ff68..b29a27ae096 100644 --- a/Mage.Sets/src/mage/cards/c/CutRibbons.java +++ b/Mage.Sets/src/mage/cards/c/CutRibbons.java @@ -28,8 +28,8 @@ public final class CutRibbons extends SplitCard { // to // Ribbons // Each opponent loses X life. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); - getRightHalfCard().getSpellAbility().addEffect(new LoseLifeOpponentsEffect(new ManacostVariableValue())); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().getSpellAbility().addEffect(new LoseLifeOpponentsEffect(ManacostVariableValue.instance)); } diff --git a/Mage.Sets/src/mage/cards/c/CutTheEarthlyBond.java b/Mage.Sets/src/mage/cards/c/CutTheEarthlyBond.java index 2eb73ac3d34..a3f122cd61c 100644 --- a/Mage.Sets/src/mage/cards/c/CutTheEarthlyBond.java +++ b/Mage.Sets/src/mage/cards/c/CutTheEarthlyBond.java @@ -21,7 +21,7 @@ public final class CutTheEarthlyBond extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("enchanted permanent"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); } public CutTheEarthlyBond(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java index b37803bd255..b548a8db00a 100644 --- a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java +++ b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java @@ -1,9 +1,5 @@ package mage.cards.c; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -34,8 +30,9 @@ import mage.target.common.TargetLandPermanent; import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; +import java.util.*; + /** - * * @author MTGfan */ public final class CyclopeanTomb extends CardImpl { @@ -55,11 +52,12 @@ public final class CyclopeanTomb extends CardImpl { ability.addTarget(new TargetLandPermanent(filter)); ability.addEffect(new BecomeSwampEffect(Duration.Custom, false, true, SubType.SWAMP)); this.addAbility(ability, new CyclopeanTombCounterWatcher()); + // When Cyclopean Tomb is put into a graveyard from the battlefield, at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with Cyclopean Tomb but that a mire counter has not been removed from with Cyclopean Tomb. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new CyclopeanTombCreateTriggeredEffect())); } - public CyclopeanTomb(final CyclopeanTomb card) { + private CyclopeanTomb(final CyclopeanTomb card) { super(card); } @@ -71,12 +69,12 @@ public final class CyclopeanTomb extends CardImpl { class BecomeSwampEffect extends BecomesBasicLandTargetEffect { - public BecomeSwampEffect(Duration duration, boolean chooseLandType, boolean loseOther, SubType... landNames) { + BecomeSwampEffect(Duration duration, boolean chooseLandType, boolean loseOther, SubType... landNames) { super(duration, chooseLandType, loseOther, landNames); staticText = "That land is a Swamp for as long as it has a mire counter on it"; } - public BecomeSwampEffect(final BecomeSwampEffect effect) { + private BecomeSwampEffect(final BecomeSwampEffect effect) { super(effect); } @@ -101,12 +99,12 @@ class BecomeSwampEffect extends BecomesBasicLandTargetEffect { class CyclopeanTombCreateTriggeredEffect extends OneShotEffect { - public CyclopeanTombCreateTriggeredEffect() { + CyclopeanTombCreateTriggeredEffect() { super(Outcome.Benefit); this.staticText = "at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with {this} but that a mire counter has not been removed from with {this}"; } - public CyclopeanTombCreateTriggeredEffect(final CyclopeanTombCreateTriggeredEffect effect) { + private CyclopeanTombCreateTriggeredEffect(final CyclopeanTombCreateTriggeredEffect effect) { super(effect); } @@ -132,12 +130,12 @@ class CyclopeanTombCreateTriggeredEffect extends OneShotEffect { class CyclopeanTombEffect extends OneShotEffect { - public CyclopeanTombEffect() { + CyclopeanTombEffect() { super(Outcome.Benefit); this.staticText = "At the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with {this} but that a mire counter has not been removed from with {this}"; } - public CyclopeanTombEffect(final CyclopeanTombEffect effect) { + private CyclopeanTombEffect(final CyclopeanTombEffect effect) { super(effect); } @@ -150,7 +148,7 @@ class CyclopeanTombEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObjectReference mor = new MageObjectReference(source.getSourceId(), source.getSourceObjectZoneChangeCounter(), game); - CyclopeanTombCounterWatcher watcher = (CyclopeanTombCounterWatcher) game.getState().getWatchers().get(CyclopeanTombCounterWatcher.class.getSimpleName()); + CyclopeanTombCounterWatcher watcher = game.getState().getWatcher(CyclopeanTombCounterWatcher.class); if (controller != null && watcher != null) { Set landRef = watcher.landMiredByCyclopeanTombInstance(mor, game); @@ -168,8 +166,8 @@ class CyclopeanTombEffect extends OneShotEffect { filter.add(Predicates.or(idPref)); TargetLandPermanent target = new TargetLandPermanent(1, 1, filter, true); /*Player must choose a land each upkeep. Using the message are above the player hand where frequent interactions - * take place is the most logical way to prompt for this scenario. A new constructor added to provide a not optional - * option for any cards like this where the player must choose a target in such the way this card requires. + * take place is the most logical way to prompt for this scenario. A new constructor added to provide a not optional + * option for any cards like this where the player must choose a target in such the way this card requires. */ if (controller.chooseTarget(Outcome.Neutral, target, source, game)) { Permanent chosenLand = game.getPermanent(target.getFirstTarget()); @@ -189,13 +187,13 @@ class CyclopeanTombEffect extends OneShotEffect { class CyclopeanTombCounterWatcher extends Watcher { - public HashMap> counterData = new HashMap<>(); + private final Map> counterData = new HashMap<>(); - public CyclopeanTombCounterWatcher() { + CyclopeanTombCounterWatcher() { super(CyclopeanTombCounterWatcher.class.getSimpleName(), WatcherScope.GAME); } - public CyclopeanTombCounterWatcher(final CyclopeanTombCounterWatcher watcher) { + private CyclopeanTombCounterWatcher(final CyclopeanTombCounterWatcher watcher) { super(watcher); for (MageObjectReference mageObjectReference : watcher.counterData.keySet()) { Set miredLands = new HashSet<>(); @@ -228,11 +226,6 @@ class CyclopeanTombCounterWatcher extends Watcher { } } - @Override - public void reset() { - super.reset(); - } - public Set landMiredByCyclopeanTombInstance(MageObjectReference mor, Game game) { if (counterData.containsKey(mor)) { return counterData.get(mor); diff --git a/Mage.Sets/src/mage/cards/c/CytoplastRootKin.java b/Mage.Sets/src/mage/cards/c/CytoplastRootKin.java index 427e58c7980..56b2902961e 100644 --- a/Mage.Sets/src/mage/cards/c/CytoplastRootKin.java +++ b/Mage.Sets/src/mage/cards/c/CytoplastRootKin.java @@ -32,7 +32,7 @@ public final class CytoplastRootKin extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creature you control that has a +1/+1 counter on it"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new CounterPredicate(CounterType.P1P1)); } diff --git a/Mage.Sets/src/mage/cards/d/DAvenantTrapper.java b/Mage.Sets/src/mage/cards/d/DAvenantTrapper.java index d763b44edb7..313cb115944 100644 --- a/Mage.Sets/src/mage/cards/d/DAvenantTrapper.java +++ b/Mage.Sets/src/mage/cards/d/DAvenantTrapper.java @@ -23,7 +23,7 @@ public final class DAvenantTrapper extends CardImpl { private static final FilterSpell filter = new FilterSpell("a historic spell"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public DAvenantTrapper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DaggerCaster.java b/Mage.Sets/src/mage/cards/d/DaggerCaster.java new file mode 100644 index 00000000000..b505371fee8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DaggerCaster.java @@ -0,0 +1,49 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DaggerCaster extends CardImpl { + + public DaggerCaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // When Dagger Caster enters the battlefield, it deals 1 damage to each opponent and 1 damage to each creature your opponents control. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect( + 1, TargetController.OPPONENT, "it" + )); + ability.addEffect( + new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) + .setText("and 1 damage to each creature your opponents control") + ); + this.addAbility(ability); + } + + private DaggerCaster(final DaggerCaster card) { + super(card); + } + + @Override + public DaggerCaster copy() { + return new DaggerCaster(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DamiaSageOfStone.java b/Mage.Sets/src/mage/cards/d/DamiaSageOfStone.java index 2ca4be33812..4b750825856 100644 --- a/Mage.Sets/src/mage/cards/d/DamiaSageOfStone.java +++ b/Mage.Sets/src/mage/cards/d/DamiaSageOfStone.java @@ -59,7 +59,7 @@ public final class DamiaSageOfStone extends CardImpl { class DamiaSageOfStoneTriggeredAbility extends BeginningOfUpkeepTriggeredAbility { DamiaSageOfStoneTriggeredAbility() { - super(new DrawCardSourceControllerEffect(new IntPlusDynamicValue(7, new MultipliedValue(new CardsInControllerHandCount(), -1))), TargetController.YOU, false); + super(new DrawCardSourceControllerEffect(new IntPlusDynamicValue(7, new MultipliedValue(CardsInControllerHandCount.instance, -1))), TargetController.YOU, false); } DamiaSageOfStoneTriggeredAbility(final DamiaSageOfStoneTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/d/DampingEngine.java b/Mage.Sets/src/mage/cards/d/DampingEngine.java index 2884c643d09..573f507d551 100644 --- a/Mage.Sets/src/mage/cards/d/DampingEngine.java +++ b/Mage.Sets/src/mage/cards/d/DampingEngine.java @@ -27,7 +27,6 @@ */ package mage.cards.d; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.SpecialAction; @@ -39,11 +38,7 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.events.GameEvent; @@ -51,8 +46,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetControlledPermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public class DampingEngine extends CardImpl { @@ -119,8 +115,7 @@ class DampingEngineEffect extends ContinuousRuleModifyingEffectImpl { Player player = game.getPlayer(event.getPlayerId()); Permanent dampingEngine = game.getPermanent(source.getSourceId()); final Card card = game.getCard(event.getSourceId()); - if (player != null - || card != null) { + if (player != null || card != null) { // check type of spell if (card.isCreature() || card.isArtifact() @@ -129,13 +124,10 @@ class DampingEngineEffect extends ContinuousRuleModifyingEffectImpl { // check to see if the player has more permanents if (new ControlsMorePermanentsThanEachOtherPlayer(player).apply(game, source)) { // check to see if the player choose to ignore the effect - if (game.getState().getValue("ignoreEffect") != null - && dampingEngine != null - && game.getState().getValue("ignoreEffect").equals - (dampingEngine.getId() + "ignoreEffect" + game.getState().getPriorityPlayerId() + game.getState().getTurnNum())) { - return false; - } - return true; + return game.getState().getValue("ignoreEffect") == null + || dampingEngine == null + || !game.getState().getValue("ignoreEffect").equals + (dampingEngine.getId() + "ignoreEffect" + game.getState().getPriorityPlayerId() + game.getState().getTurnNum()); } } } diff --git a/Mage.Sets/src/mage/cards/d/DampingSphere.java b/Mage.Sets/src/mage/cards/d/DampingSphere.java index 8447bc0aed4..b4780d80d7f 100644 --- a/Mage.Sets/src/mage/cards/d/DampingSphere.java +++ b/Mage.Sets/src/mage/cards/d/DampingSphere.java @@ -103,7 +103,7 @@ class DampingSphereIncreasementAllEffect extends SpellsCostIncreasementAllEffect @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { int additionalCost = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(abilityToModify.getControllerId()); CardUtil.increaseCost(abilityToModify, additionalCost); diff --git a/Mage.Sets/src/mage/cards/d/DanceOfMany.java b/Mage.Sets/src/mage/cards/d/DanceOfMany.java index e99a8ca72ed..6b58f60fe46 100644 --- a/Mage.Sets/src/mage/cards/d/DanceOfMany.java +++ b/Mage.Sets/src/mage/cards/d/DanceOfMany.java @@ -39,7 +39,7 @@ public final class DanceOfMany extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public DanceOfMany(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DaringArchaeologist.java b/Mage.Sets/src/mage/cards/d/DaringArchaeologist.java index 9ee2191281c..133b8784685 100644 --- a/Mage.Sets/src/mage/cards/d/DaringArchaeologist.java +++ b/Mage.Sets/src/mage/cards/d/DaringArchaeologist.java @@ -27,7 +27,7 @@ public final class DaringArchaeologist extends CardImpl { private static final FilterSpell filter = new FilterSpell("a historic spell"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public DaringArchaeologist(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DarkProphecy.java b/Mage.Sets/src/mage/cards/d/DarkProphecy.java index 91c3f34f599..4881da9516f 100644 --- a/Mage.Sets/src/mage/cards/d/DarkProphecy.java +++ b/Mage.Sets/src/mage/cards/d/DarkProphecy.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.effects.Effect; @@ -14,28 +12,27 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class DarkProphecy extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature you control"); + static { filter.add(new ControllerPredicate(TargetController.YOU)); } public DarkProphecy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{B}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}{B}"); // Whenever a creature you control dies, you draw a card and you lose 1 life. - Effect effect = new DrawCardSourceControllerEffect(1); - effect.setText("you draw a card"); + Effect effect = new DrawCardSourceControllerEffect(1, "you"); Ability ability = new DiesCreatureTriggeredAbility(effect, false, filter); effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - ability.addEffect(effect); + ability.addEffect(effect.concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DarkSalvation.java b/Mage.Sets/src/mage/cards/d/DarkSalvation.java index 30100994acd..9c0b24555c4 100644 --- a/Mage.Sets/src/mage/cards/d/DarkSalvation.java +++ b/Mage.Sets/src/mage/cards/d/DarkSalvation.java @@ -34,7 +34,7 @@ public final class DarkSalvation extends CardImpl { // Target player creates X 2/2 black Zombie creature tokens, then up to one target creature gets -1/-1 until end of turn for each Zombie that player controls. this.getSpellAbility().addTarget(new TargetPlayer()); - Effect effect = new CreateTokenTargetEffect(new ZombieToken(), new ManacostVariableValue()); + Effect effect = new CreateTokenTargetEffect(new ZombieToken(), ManacostVariableValue.instance); effect.setText("Target player creates X 2/2 black Zombie creature tokens"); this.getSpellAbility().addEffect(effect); DynamicValue value = new ZombiesControlledByTargetPlayerCount(); diff --git a/Mage.Sets/src/mage/cards/d/DarkbladeAgent.java b/Mage.Sets/src/mage/cards/d/DarkbladeAgent.java index 85a91830aa8..f87221674b7 100644 --- a/Mage.Sets/src/mage/cards/d/DarkbladeAgent.java +++ b/Mage.Sets/src/mage/cards/d/DarkbladeAgent.java @@ -1,8 +1,5 @@ package mage.cards.d; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; @@ -12,19 +9,18 @@ import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.DeathtouchAbility; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.WatcherScope; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class DarkbladeAgent extends CardImpl { @@ -46,7 +42,7 @@ public final class DarkbladeAgent extends CardImpl { Duration.WhileOnBattlefield ), DarkbladeAgentCondition.instance, "As long as you've surveilled this turn, " - + "{this} has deathtouch" + + "{this} has deathtouch" ) ); ability.addEffect(new ConditionalContinuousEffect( @@ -56,7 +52,7 @@ public final class DarkbladeAgent extends CardImpl { ), Duration.WhileOnBattlefield ), DarkbladeAgentCondition.instance, "and \"Whenever this creature deals " - + "combat damage to a player, draw a card.\"" + + "combat damage to a player, draw a card.\"" )); this.addAbility(ability, new DarkbladeAgentWatcher()); } @@ -77,9 +73,8 @@ enum DarkbladeAgentCondition implements Condition { @Override public boolean apply(Game game, Ability source) { DarkbladeAgentWatcher watcher - = (DarkbladeAgentWatcher) game.getState().getWatchers().get( - DarkbladeAgentWatcher.class.getSimpleName() - ); + = game.getState().getWatcher( + DarkbladeAgentWatcher.class); return watcher != null && watcher.getSurveiledThisTurn(source.getControllerId()); } @@ -87,10 +82,10 @@ enum DarkbladeAgentCondition implements Condition { class DarkbladeAgentWatcher extends Watcher { - private final Set surveiledThisTurn = new HashSet(); + private final Set surveiledThisTurn = new HashSet<>(); public DarkbladeAgentWatcher() { - super(DarkbladeAgentWatcher.class.getSimpleName(), WatcherScope.GAME); + super(DarkbladeAgentWatcher.class, WatcherScope.GAME); } public DarkbladeAgentWatcher(final DarkbladeAgentWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/d/DarkslickShores.java b/Mage.Sets/src/mage/cards/d/DarkslickShores.java index 1739e630876..0dffdd6e4b2 100644 --- a/Mage.Sets/src/mage/cards/d/DarkslickShores.java +++ b/Mage.Sets/src/mage/cards/d/DarkslickShores.java @@ -26,7 +26,7 @@ public final class DarkslickShores extends CardImpl { private final static FilterLandPermanent filter = new FilterLandPermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DarkslickShores(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java b/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java index 1e684d94f6d..dbf5f6a79d5 100644 --- a/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java +++ b/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -12,8 +11,6 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -50,12 +47,6 @@ public final class DaruSpiritualist extends CardImpl { class DaruSpiritualistTriggeredAbility extends TriggeredAbilityImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Cleric creature you control"); - - static { - filter.add(new SubtypePredicate(SubType.CLERIC)); - } - public DaruSpiritualistTriggeredAbility(Effect effect) { super(Zone.BATTLEFIELD, effect); } @@ -77,7 +68,7 @@ class DaruSpiritualistTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent creature = game.getPermanent(event.getTargetId()); - if (creature != null && filter.match(creature, getSourceId(), getControllerId(), game)) { + if (creature != null && creature.hasSubtype(SubType.CLERIC, game) && creature.getControllerId().equals(getControllerId()) && creature.isCreature()) { this.getEffects().setTargetPointer(new FixedTarget(creature, game)); return true; } diff --git a/Mage.Sets/src/mage/cards/d/DauntlessBodyguard.java b/Mage.Sets/src/mage/cards/d/DauntlessBodyguard.java index 1d7eedc6ade..6b28ec08fce 100644 --- a/Mage.Sets/src/mage/cards/d/DauntlessBodyguard.java +++ b/Mage.Sets/src/mage/cards/d/DauntlessBodyguard.java @@ -65,7 +65,7 @@ class DauntlessBodyguardChooseCreatureEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DauntlessBodyguardChooseCreatureEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DauntlessDourbark.java b/Mage.Sets/src/mage/cards/d/DauntlessDourbark.java index 15fb9b45822..be7b60f0b46 100644 --- a/Mage.Sets/src/mage/cards/d/DauntlessDourbark.java +++ b/Mage.Sets/src/mage/cards/d/DauntlessDourbark.java @@ -36,7 +36,7 @@ public final class DauntlessDourbark extends CardImpl { filter.add(Predicates.or(new SubtypePredicate(SubType.FOREST), new SubtypePredicate(SubType.TREEFOLK))); filter2.add(new SubtypePredicate(SubType.TREEFOLK)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } final static private String rule = "{this} has trample as long as you control another Treefolk"; diff --git a/Mage.Sets/src/mage/cards/d/DawnglowInfusion.java b/Mage.Sets/src/mage/cards/d/DawnglowInfusion.java index a6527a52fee..7faec30b05a 100644 --- a/Mage.Sets/src/mage/cards/d/DawnglowInfusion.java +++ b/Mage.Sets/src/mage/cards/d/DawnglowInfusion.java @@ -25,7 +25,7 @@ public final class DawnglowInfusion extends CardImpl { // You gain X life if {G} was spent to cast Dawnglow Infusion and X life if {W} was spent to cast it. - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new GainLifeEffect(xValue), new ManaWasSpentCondition(ColoredManaSymbol.G), "You gain X life if {G} was spent to cast {this}")); diff --git a/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java b/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java index 4e6416c9e54..88bb01666ea 100644 --- a/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java +++ b/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java @@ -32,8 +32,8 @@ public final class DazzlingBeauty extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked attacking creature"); static { - filter.add(new AttackingPredicate()); - filter.add(Predicates.not(new BlockedPredicate())); + filter.add(AttackingPredicate.instance); + filter.add(Predicates.not(BlockedPredicate.instance)); } public DazzlingBeauty(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeadRevels.java b/Mage.Sets/src/mage/cards/d/DeadRevels.java new file mode 100644 index 00000000000..b0c8368e773 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeadRevels.java @@ -0,0 +1,41 @@ +package mage.cards.d; + +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.keyword.SpectacleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DeadRevels extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature cards from your graveyard"); + + public DeadRevels(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); + + // Return up to two target creature cards from your graveyard to your hand. + this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 2, filter)); + + // Spectacle {1}{B} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{1}{B}"))); + } + + private DeadRevels(final DeadRevels card) { + super(card); + } + + @Override + public DeadRevels copy() { + return new DeadRevels(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java b/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java index eeb855dd357..a8c31839c7a 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java @@ -27,7 +27,7 @@ public final class DeadeyeHarpooner extends CardImpl { private final static FilterOpponentsCreaturePermanent filter = new FilterOpponentsCreaturePermanent("tapped creature an opponent controls"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public DeadeyeHarpooner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeathCloud.java b/Mage.Sets/src/mage/cards/d/DeathCloud.java index c239907ad62..1ce4f411208 100644 --- a/Mage.Sets/src/mage/cards/d/DeathCloud.java +++ b/Mage.Sets/src/mage/cards/d/DeathCloud.java @@ -25,7 +25,7 @@ public final class DeathCloud extends CardImpl { // Each player loses X life, discards X cards, sacrifices X creatures, then sacrifices X lands. - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new LoseLifeAllPlayersEffect(xValue)); Effect effect = new DiscardEachPlayerEffect(xValue, false); effect.setText(", discards X cards"); diff --git a/Mage.Sets/src/mage/cards/d/DeathDenied.java b/Mage.Sets/src/mage/cards/d/DeathDenied.java index e54bf6697ee..baf509a483b 100644 --- a/Mage.Sets/src/mage/cards/d/DeathDenied.java +++ b/Mage.Sets/src/mage/cards/d/DeathDenied.java @@ -2,7 +2,6 @@ package mage.cards.d; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; @@ -13,35 +12,24 @@ import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import java.util.UUID; /** - * * @author LevelX2 */ public final class DeathDenied extends CardImpl { public DeathDenied(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}{B}"); this.subtype.add(SubType.ARCANE); // Return X target creature cards from your graveyard to your hand. Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return X target creature cards from your graveyard to your hand"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(1, new FilterCreatureCard())); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard((xValue != 1 ? " creature cards" : "creature card") + " from your graveyard")); - ability.addTarget(target); - } + this.getSpellAbility().setTargetAdjuster(DeathDeniedAdjuster.instance); } public DeathDenied(final DeathDenied card) { @@ -53,3 +41,15 @@ public final class DeathDenied extends CardImpl { return new DeathDenied(this); } } + +enum DeathDeniedAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard(new StringBuilder(xValue).append(xValue != 1 ? " creature cards" : "creature card").append(" from your graveyard").toString())); + ability.addTarget(target); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeathGrasp.java b/Mage.Sets/src/mage/cards/d/DeathGrasp.java index e0e3426b6e5..114635e43cc 100644 --- a/Mage.Sets/src/mage/cards/d/DeathGrasp.java +++ b/Mage.Sets/src/mage/cards/d/DeathGrasp.java @@ -21,8 +21,8 @@ public final class DeathGrasp extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{W}{B}"); - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); - this.getSpellAbility().addEffect(new GainLifeEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); + this.getSpellAbility().addEffect(new GainLifeEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/d/DeathMatch.java b/Mage.Sets/src/mage/cards/d/DeathMatch.java index d5827dfbd02..389b27cd260 100644 --- a/Mage.Sets/src/mage/cards/d/DeathMatch.java +++ b/Mage.Sets/src/mage/cards/d/DeathMatch.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -13,17 +11,16 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FirstTargetPointer; +import java.util.UUID; + /** - * * @author LoneFox - * */ public final class DeathMatch extends CardImpl { - private final UUID originalId; - public DeathMatch(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); @@ -32,24 +29,12 @@ public final class DeathMatch extends CardImpl { Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new DeathMatchEffect(), StaticFilters.FILTER_PERMANENT_CREATURE, false, SetTargetPointer.PLAYER, ""); ability.addTarget(new TargetCreaturePermanent()); + ability.setTargetAdjuster(DeathMatchAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - UUID controllerId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); - if (controllerId != null) { - ability.getTargets().get(0).setTargetController(controllerId); - ability.getEffects().get(0).setTargetPointer(new FirstTargetPointer()); - } - } } public DeathMatch(final DeathMatch card) { super(card); - this.originalId = card.originalId; } @Override @@ -58,6 +43,19 @@ public final class DeathMatch extends CardImpl { } } +enum DeathMatchAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + UUID controllerId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + if (controllerId != null) { + ability.getTargets().get(0).setTargetController(controllerId); + ability.getEffects().get(0).setTargetPointer(new FirstTargetPointer()); + } + } +} + class DeathMatchEffect extends OneShotEffect { public DeathMatchEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DeathMutation.java b/Mage.Sets/src/mage/cards/d/DeathMutation.java index d24bec85c23..879b21f6d89 100644 --- a/Mage.Sets/src/mage/cards/d/DeathMutation.java +++ b/Mage.Sets/src/mage/cards/d/DeathMutation.java @@ -35,7 +35,7 @@ public final class DeathMutation extends CardImpl { this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); this.getSpellAbility().addTarget(new TargetPermanent(filter)); // create X 1/1 green Saproling creature tokens, where X is that creature's converted mana cost. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance)); } public DeathMutation(final DeathMutation card) { diff --git a/Mage.Sets/src/mage/cards/d/DeathStroke.java b/Mage.Sets/src/mage/cards/d/DeathStroke.java index c47e389c792..db727116c47 100644 --- a/Mage.Sets/src/mage/cards/d/DeathStroke.java +++ b/Mage.Sets/src/mage/cards/d/DeathStroke.java @@ -19,7 +19,7 @@ public final class DeathStroke extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public DeathStroke(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeathWind.java b/Mage.Sets/src/mage/cards/d/DeathWind.java index 69fbaadadfc..663ba2f6043 100644 --- a/Mage.Sets/src/mage/cards/d/DeathWind.java +++ b/Mage.Sets/src/mage/cards/d/DeathWind.java @@ -22,7 +22,7 @@ public final class DeathWind extends CardImpl { // Target creature gets -X/-X until end of turn. - DynamicValue x = new SignInversionDynamicValue(new ManacostVariableValue()); + DynamicValue x = new SignInversionDynamicValue(ManacostVariableValue.instance); this.getSpellAbility().addEffect(new BoostTargetEffect(x, x, Duration.EndOfTurn, true)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java b/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java index 4aa59062ae6..023015b9e0d 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java +++ b/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java @@ -29,7 +29,7 @@ public final class DeathbringerRegent extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DeathbringerRegent(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeathforgeShaman.java b/Mage.Sets/src/mage/cards/d/DeathforgeShaman.java index a9c707fd5a9..7ebbe2c241c 100644 --- a/Mage.Sets/src/mage/cards/d/DeathforgeShaman.java +++ b/Mage.Sets/src/mage/cards/d/DeathforgeShaman.java @@ -69,7 +69,7 @@ class DeathforgeShamanEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - DynamicValue value = new MultikickerCount(); + DynamicValue value = MultikickerCount.instance; int damage = value.calculate(game, source, this) * 2; return new DamageTargetEffect(damage).apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/d/DeathlessAncient.java b/Mage.Sets/src/mage/cards/d/DeathlessAncient.java index 5d7e6046821..6719a9fafa6 100644 --- a/Mage.Sets/src/mage/cards/d/DeathlessAncient.java +++ b/Mage.Sets/src/mage/cards/d/DeathlessAncient.java @@ -27,7 +27,7 @@ public final class DeathlessAncient extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Vampires you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/d/DeathsShadow.java b/Mage.Sets/src/mage/cards/d/DeathsShadow.java index 2591c2d11fa..5fa0ee15d9d 100644 --- a/Mage.Sets/src/mage/cards/d/DeathsShadow.java +++ b/Mage.Sets/src/mage/cards/d/DeathsShadow.java @@ -28,7 +28,7 @@ public final class DeathsShadow extends CardImpl { this.toughness = new MageInt(13); // Death's Shadow gets -X/-X, where X is your life total. - SignInversionDynamicValue x = new SignInversionDynamicValue(new ControllerLifeCount(), false); + SignInversionDynamicValue x = new SignInversionDynamicValue(ControllerLifeCount.instance, false); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(x, x, Duration.WhileOnBattlefield))); } diff --git a/Mage.Sets/src/mage/cards/d/DebtorsTransport.java b/Mage.Sets/src/mage/cards/d/DebtorsTransport.java new file mode 100644 index 00000000000..ef22d1d33f8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DebtorsTransport.java @@ -0,0 +1,36 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.keyword.AfterlifeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DebtorsTransport extends CardImpl { + + public DebtorsTransport(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}"); + + this.subtype.add(SubType.THRULL); + this.power = new MageInt(5); + this.toughness = new MageInt(3); + + // Afterlife 2 + this.addAbility(new AfterlifeAbility(2)); + } + + private DebtorsTransport(final DebtorsTransport card) { + super(card); + } + + @Override + public DebtorsTransport copy() { + return new DebtorsTransport(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DecayingSoil.java b/Mage.Sets/src/mage/cards/d/DecayingSoil.java index dec74944c59..8c709b42aa5 100644 --- a/Mage.Sets/src/mage/cards/d/DecayingSoil.java +++ b/Mage.Sets/src/mage/cards/d/DecayingSoil.java @@ -40,7 +40,7 @@ public final class DecayingSoil extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static{ filter.add(new OwnerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public DecayingSoil(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java b/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java index 1cce7d6d6f9..d11d20163ec 100644 --- a/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java +++ b/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java @@ -76,7 +76,7 @@ class DeceiverOfFormEffect extends OneShotEffect { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, controller.getId(), game)) { if (!permanent.getId().equals(sourceObject.getId())) { Permanent newBluePrint = null; - newBluePrint = new PermanentCard((Card) copyFromCard, source.getControllerId(), game); + newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); CopyEffect copyEffect = new CopyEffect(Duration.EndOfTurn, newBluePrint, permanent.getId()); copyEffect.newId(); diff --git a/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java b/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java index 2d0c35432a3..75e0cc4bb4e 100644 --- a/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java +++ b/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -13,24 +12,29 @@ import mage.abilities.effects.common.counter.RemoveCounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author spjspj */ public final class DecimatorBeetle extends CardImpl { - private final UUID originalId; + public static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(DefendingPlayerControlsPredicate.instance); + } public DecimatorBeetle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}"); @@ -46,29 +50,14 @@ public final class DecimatorBeetle extends CardImpl { this.addAbility(ability); // Whenever Decimator Beetle attacks, remove a -1/-1 counter from target creature you control and put a -1/-1 counter on up to one target creature defending player controls. - Ability ability2 = new AttacksTriggeredAbility(new DecimatorBeetleEffect(), false); - ability2.addTarget(new TargetControlledCreaturePermanent()); - ability2.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - this.addAbility(ability2); - this.originalId = ability2.getOriginalId(); + ability = new AttacksTriggeredAbility(new DecimatorBeetleEffect(), false); + ability.addTarget(new TargetControlledCreaturePermanent()); + ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + this.addAbility(ability); } public DecimatorBeetle(final DecimatorBeetle card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - ability.addTarget(new TargetControlledCreaturePermanent()); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } } @Override diff --git a/Mage.Sets/src/mage/cards/d/DecoratedChampion.java b/Mage.Sets/src/mage/cards/d/DecoratedChampion.java index aff6d8543bc..bdae9b0118c 100644 --- a/Mage.Sets/src/mage/cards/d/DecoratedChampion.java +++ b/Mage.Sets/src/mage/cards/d/DecoratedChampion.java @@ -22,7 +22,7 @@ public final class DecoratedChampion extends CardImpl { private static final FilterTeamPermanent filter = new FilterTeamPermanent(SubType.WARRIOR, "another Warrior"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DecoratedChampion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java b/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java index 27aa099dcd8..2da79ce805e 100644 --- a/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java +++ b/Mage.Sets/src/mage/cards/d/DecreeOfJustice.java @@ -32,7 +32,7 @@ public final class DecreeOfJustice extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{2}{W}{W}"); // Create X 4/4 white Angel creature tokens with flying. - this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), ManacostVariableValue.instance)); // Cycling {2}{W} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}{W}"))); diff --git a/Mage.Sets/src/mage/cards/d/DeeprootElite.java b/Mage.Sets/src/mage/cards/d/DeeprootElite.java index 8f2133da262..ca4130031cb 100644 --- a/Mage.Sets/src/mage/cards/d/DeeprootElite.java +++ b/Mage.Sets/src/mage/cards/d/DeeprootElite.java @@ -26,7 +26,7 @@ public final class DeeprootElite extends CardImpl { private static final FilterPermanent filterYourAnotherMerfolk = new FilterPermanent(SubType.MERFOLK, "another " + SubType.MERFOLK.toString()); static { - filterYourAnotherMerfolk.add(new AnotherPredicate()); + filterYourAnotherMerfolk.add(AnotherPredicate.instance); filterYourAnotherMerfolk.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/d/Deface.java b/Mage.Sets/src/mage/cards/d/Deface.java new file mode 100644 index 00000000000..fa2d602b2e2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Deface.java @@ -0,0 +1,50 @@ +package mage.cards.d; + +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetArtifactPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Deface extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with defender"); + + static { + filter.add(new AbilityPredicate(DefenderAbility.class)); + } + + public Deface(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}"); + + // Choose one — + // • Destroy target artifact. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetArtifactPermanent()); + + // • Destroy target creature with defender. + Mode mode = new Mode(new DestroyTargetEffect()); + mode.addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addMode(mode); + } + + private Deface(final Deface card) { + super(card); + } + + @Override + public Deface copy() { + return new Deface(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java b/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java index b71d27ff4f1..731df0f5c73 100644 --- a/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java +++ b/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java @@ -60,7 +60,7 @@ class DefiantGreatmawTriggeredAbility extends TriggeredAbilityImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/d/DefilerOfSouls.java b/Mage.Sets/src/mage/cards/d/DefilerOfSouls.java index 0e97a8be107..2e1f05f99d6 100644 --- a/Mage.Sets/src/mage/cards/d/DefilerOfSouls.java +++ b/Mage.Sets/src/mage/cards/d/DefilerOfSouls.java @@ -72,7 +72,7 @@ class DefilerOfSoulsEffect extends OneShotEffect { if (player == null) { return false; } - filter.add(new MonocoloredPredicate()); + filter.add(MonocoloredPredicate.instance); int amount; int realCount = game.getBattlefield().countAll(filter, player.getId(), game); @@ -90,7 +90,7 @@ class DefilerOfSoulsEffect extends OneShotEffect { } for ( int idx = 0; idx < target.getTargets().size(); idx++) { - Permanent permanent = game.getPermanent((UUID)target.getTargets().get(idx)); + Permanent permanent = game.getPermanent(target.getTargets().get(idx)); if ( permanent != null ) { abilityApplied |= permanent.sacrifice(source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/d/DelayTactic.java b/Mage.Sets/src/mage/cards/d/DelayTactic.java index a51d607b436..7607fe00f80 100644 --- a/Mage.Sets/src/mage/cards/d/DelayTactic.java +++ b/Mage.Sets/src/mage/cards/d/DelayTactic.java @@ -41,7 +41,7 @@ public final class DelayTactic extends CardImpl { this.getSpellAbility().addEffect(new GainAbilityAllEffect(HexproofAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent()) .setText("Creatures you control gain hexproof until end of turn")); - // Creatures target opponent controls don't untap during his or her next untap step. + // Creatures target opponent controls don't untap during their next untap step. Mode mode = new Mode(); mode.addEffect(new DelayTacticEffect()); mode.addTarget(new TargetOpponent()); @@ -63,7 +63,7 @@ class DelayTacticEffect extends OneShotEffect { DelayTacticEffect() { super(Outcome.Benefit); - this.staticText = "Creatures target opponent controls don't untap during his or her next untap step"; + this.staticText = "Creatures target opponent controls don't untap during their next untap step"; } DelayTacticEffect(final DelayTacticEffect effect) { diff --git a/Mage.Sets/src/mage/cards/d/Demonfire.java b/Mage.Sets/src/mage/cards/d/Demonfire.java index 71711b70c12..b8dfbc7148c 100644 --- a/Mage.Sets/src/mage/cards/d/Demonfire.java +++ b/Mage.Sets/src/mage/cards/d/Demonfire.java @@ -31,7 +31,7 @@ public final class Demonfire extends CardImpl { // Demonfire deals X damage to any target. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageTargetEffect(new ManacostVariableValue()), + new DamageTargetEffect(ManacostVariableValue.instance), new InvertCondition(HellbentCondition.instance), "{this} deals X damage to any target")); @@ -41,7 +41,7 @@ public final class Demonfire extends CardImpl { // Hellbent - If you have no cards in hand, Demonfire can't be countered and the damage can't be prevented. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageTargetEffect(new ManacostVariableValue(), false), + new DamageTargetEffect(ManacostVariableValue.instance, false), HellbentCondition.instance, "
Hellbent — If you have no cards in hand, this spell can't be countered and the damage can't be prevented.")); // can't be countered diff --git a/Mage.Sets/src/mage/cards/d/DemonicTaskmaster.java b/Mage.Sets/src/mage/cards/d/DemonicTaskmaster.java index 252b91460ca..13671d2f68c 100644 --- a/Mage.Sets/src/mage/cards/d/DemonicTaskmaster.java +++ b/Mage.Sets/src/mage/cards/d/DemonicTaskmaster.java @@ -24,7 +24,7 @@ public final class DemonicTaskmaster extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature other than Demonic Taskmaster"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DemonicTaskmaster(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DemonlordOfAshmouth.java b/Mage.Sets/src/mage/cards/d/DemonlordOfAshmouth.java index e409e89cb4b..23928b343ac 100644 --- a/Mage.Sets/src/mage/cards/d/DemonlordOfAshmouth.java +++ b/Mage.Sets/src/mage/cards/d/DemonlordOfAshmouth.java @@ -24,7 +24,7 @@ public final class DemonlordOfAshmouth extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(" another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DemonlordOfAshmouth(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/Denied.java b/Mage.Sets/src/mage/cards/d/Denied.java index a896f1e1630..b5825c8b1ea 100644 --- a/Mage.Sets/src/mage/cards/d/Denied.java +++ b/Mage.Sets/src/mage/cards/d/Denied.java @@ -58,7 +58,7 @@ class DeniedEffect extends OneShotEffect { return true; } Player player = game.getPlayer(targetSpell.getControllerId()); - Object object = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + Object object = game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (player != null && object instanceof String) { player.revealCards("Denied!", player.getHand(), game, true); String namedCard = (String) object; diff --git a/Mage.Sets/src/mage/cards/d/DenizenOfTheDeep.java b/Mage.Sets/src/mage/cards/d/DenizenOfTheDeep.java index 7797d8b3cec..806ce42168b 100644 --- a/Mage.Sets/src/mage/cards/d/DenizenOfTheDeep.java +++ b/Mage.Sets/src/mage/cards/d/DenizenOfTheDeep.java @@ -22,7 +22,7 @@ public final class DenizenOfTheDeep extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static{ - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DenizenOfTheDeep(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DeposeDeploy.java b/Mage.Sets/src/mage/cards/d/DeposeDeploy.java new file mode 100644 index 00000000000..b7a040e204f --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeposeDeploy.java @@ -0,0 +1,54 @@ +package mage.cards.d; + +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.SpellAbilityType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.ThopterColorlessToken; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DeposeDeploy extends SplitCard { + + public DeposeDeploy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W/U}", "{2}{W}{U}", SpellAbilityType.SPLIT); + + // Depose + // Tap target creature. + // Draw a card. + this.getLeftHalfCard().getSpellAbility().addEffect(new TapTargetEffect()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getLeftHalfCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + + // Deploy + // Creature two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control. + this.getRightHalfCard().getSpellAbility().addEffect( + new CreateTokenEffect(new ThopterColorlessToken(), 2) + ); + this.getRightHalfCard().getSpellAbility().addEffect( + new GainLifeEffect(new PermanentsOnBattlefieldCount( + StaticFilters.FILTER_CONTROLLED_CREATURES + )).setText(", then you gain 1 life for each creature you control.") + ); + + } + + private DeposeDeploy(final DeposeDeploy card) { + super(card); + } + + @Override + public DeposeDeploy copy() { + return new DeposeDeploy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeputyOfAcquittals.java b/Mage.Sets/src/mage/cards/d/DeputyOfAcquittals.java index ffdc206d10c..da6d0e5ba6d 100644 --- a/Mage.Sets/src/mage/cards/d/DeputyOfAcquittals.java +++ b/Mage.Sets/src/mage/cards/d/DeputyOfAcquittals.java @@ -26,7 +26,7 @@ public final class DeputyOfAcquittals extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/d/DeputyOfDetention.java b/Mage.Sets/src/mage/cards/d/DeputyOfDetention.java new file mode 100644 index 00000000000..d59bc25d3b7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeputyOfDetention.java @@ -0,0 +1,110 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.util.CardUtil; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DeputyOfDetention extends CardImpl { + + private static final FilterPermanent filter = new FilterNonlandPermanent("nonland permanent an opponent controls"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public DeputyOfDetention(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); + + this.subtype.add(SubType.VEDALKEN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // When Deputy of Detention enters the battlefield, exile target nonland permanent an opponent controls and all other nonland permanents that player controls with the same name as that permanent until Deputy of Detention leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new DeputyOfDetentionExileEffect(), false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private DeputyOfDetention(final DeputyOfDetention card) { + super(card); + } + + @Override + public DeputyOfDetention copy() { + return new DeputyOfDetention(this); + } +} + +class DeputyOfDetentionExileEffect extends OneShotEffect { + + DeputyOfDetentionExileEffect() { + super(Outcome.Benefit); + this.staticText = "exile target nonland permanent an opponent controls " + + "and all other nonland permanents that player controls " + + "with the same name as that permanent until {this} leaves the battlefield"; + } + + private DeputyOfDetentionExileEffect(final DeputyOfDetentionExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent targeted = game.getPermanent(source.getFirstTarget()); + + if (permanent == null || controller == null || targeted == null) { + return false; + } + + FilterPermanent filter = new FilterNonlandPermanent(); + filter.add(new ControllerIdPredicate(targeted.getControllerId())); + filter.add(new NamePredicate(targeted.getName())); + + Set toExile = new LinkedHashSet<>(); + for (Permanent creature : game.getBattlefield().getActivePermanents(filter, controller.getId(), game)) { + toExile.add(creature); + } + + if (!toExile.isEmpty()) { + controller.moveCardsToExile(toExile, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName()); + new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()).apply(game, source); + } + return true; + } + + @Override + public DeputyOfDetentionExileEffect copy() { + return new DeputyOfDetentionExileEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/d/DescendantOfSoramaro.java b/Mage.Sets/src/mage/cards/d/DescendantOfSoramaro.java index aad9696a80d..ce8cde5bd0d 100644 --- a/Mage.Sets/src/mage/cards/d/DescendantOfSoramaro.java +++ b/Mage.Sets/src/mage/cards/d/DescendantOfSoramaro.java @@ -28,7 +28,7 @@ public final class DescendantOfSoramaro extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); // {1}{U}: Look at the top X cards of your library, where X is the number of cards in your hand, then put them back in any order. - Effect effect = new LookLibraryControllerEffect(new CardsInControllerHandCount()); + Effect effect = new LookLibraryControllerEffect(CardsInControllerHandCount.instance); effect.setText("Look at the top X cards of your library, where X is the number of cards in your hand, then put them back in any order"); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{U}"))); diff --git a/Mage.Sets/src/mage/cards/d/Desert.java b/Mage.Sets/src/mage/cards/d/Desert.java index e901bdf3d17..06a6c85466a 100644 --- a/Mage.Sets/src/mage/cards/d/Desert.java +++ b/Mage.Sets/src/mage/cards/d/Desert.java @@ -27,7 +27,7 @@ public final class Desert extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public Desert(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/Desolation.java b/Mage.Sets/src/mage/cards/d/Desolation.java index bed641377a5..89418192eaf 100644 --- a/Mage.Sets/src/mage/cards/d/Desolation.java +++ b/Mage.Sets/src/mage/cards/d/Desolation.java @@ -69,7 +69,7 @@ class DesolationEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - DesolationWatcher watcher = (DesolationWatcher) game.getState().getWatchers().get(DesolationWatcher.class.getSimpleName()); + DesolationWatcher watcher = game.getState().getWatcher(DesolationWatcher.class); if (watcher != null) { for (UUID playerId : watcher.getPlayersTappedForMana()) { Player player = game.getPlayer(playerId); diff --git a/Mage.Sets/src/mage/cards/d/DesolationGiant.java b/Mage.Sets/src/mage/cards/d/DesolationGiant.java index ebe02abc01c..5ca7943adbd 100644 --- a/Mage.Sets/src/mage/cards/d/DesolationGiant.java +++ b/Mage.Sets/src/mage/cards/d/DesolationGiant.java @@ -27,8 +27,8 @@ public final class DesolationGiant extends CardImpl { private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("other creatures you control"); static { - filter.add(new AnotherPredicate()); - filter2.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); + filter2.add(AnotherPredicate.instance); filter2.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/d/DesperateGambit.java b/Mage.Sets/src/mage/cards/d/DesperateGambit.java index bce9512aa1d..80351f9dd66 100644 --- a/Mage.Sets/src/mage/cards/d/DesperateGambit.java +++ b/Mage.Sets/src/mage/cards/d/DesperateGambit.java @@ -8,7 +8,6 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.PreventionEffectImpl; -import mage.abilities.effects.common.PreventDamageBySourceEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +20,6 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.filter.FilterObject; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.players.Player; import mage.target.TargetSource; import mage.util.CardUtil; @@ -70,7 +68,7 @@ class DesperateGambitEffect extends PreventionEffectImpl { this.target.choose(Outcome.Benefit, source.getControllerId(), source.getSourceId(), game); Player you = game.getPlayer(source.getControllerId()); if(you != null) { - wonFlip = you.flipCoin(game); + wonFlip = you.flipCoin(source, game, true); super.init(source, game); } } diff --git a/Mage.Sets/src/mage/cards/d/DestinedLead.java b/Mage.Sets/src/mage/cards/d/DestinedLead.java index b07578b6e83..d9529003d25 100644 --- a/Mage.Sets/src/mage/cards/d/DestinedLead.java +++ b/Mage.Sets/src/mage/cards/d/DestinedLead.java @@ -35,7 +35,7 @@ public final class DestinedLead extends SplitCard { // to // Lead // All creatures able to block target creature this turn must do so. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); getRightHalfCard().getSpellAbility().addEffect(new MustBeBlockedByAllTargetEffect(Duration.EndOfTurn)); } diff --git a/Mage.Sets/src/mage/cards/d/Detonate.java b/Mage.Sets/src/mage/cards/d/Detonate.java index ff84de2a351..782f5af864c 100644 --- a/Mage.Sets/src/mage/cards/d/Detonate.java +++ b/Mage.Sets/src/mage/cards/d/Detonate.java @@ -1,9 +1,7 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetControllerEffect; @@ -16,33 +14,25 @@ import mage.filter.common.FilterArtifactPermanent; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetArtifactPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LoneFox */ public final class Detonate extends CardImpl { public Detonate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}"); // Destroy target artifact with converted mana cost X. It can't be regenerated. Detonate deals X damage to that artifact's controller. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); this.getSpellAbility().addTarget(new TargetArtifactPermanent(new FilterArtifactPermanent("artifact with converted mana cost X"))); - Effect effect = new DamageTargetControllerEffect(new ManacostVariableValue()); + Effect effect = new DamageTargetControllerEffect(ManacostVariableValue.instance); effect.setText("{this} deals X damage to that artifact's controller"); this.getSpellAbility().addEffect(effect); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact with converted mana cost X"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.addTarget(new TargetArtifactPermanent(filter)); - } + this.getSpellAbility().setTargetAdjuster(DetonateAdjuster.instance); } public Detonate(final Detonate card) { @@ -54,3 +44,16 @@ public final class Detonate extends CardImpl { return new Detonate(this); } } + +enum DetonateAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact with converted mana cost X"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetArtifactPermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DevastatingDreams.java b/Mage.Sets/src/mage/cards/d/DevastatingDreams.java index cebed2d85a4..ee0d2b5b276 100644 --- a/Mage.Sets/src/mage/cards/d/DevastatingDreams.java +++ b/Mage.Sets/src/mage/cards/d/DevastatingDreams.java @@ -32,10 +32,10 @@ public final class DevastatingDreams extends CardImpl { this.getSpellAbility().addCost(new DevastatingDreamsAdditionalCost()); // Each player sacrifices X lands. - this.getSpellAbility().addEffect(new SacrificeAllEffect(new GetXValue(), new FilterControlledLandPermanent("lands"))); + this.getSpellAbility().addEffect(new SacrificeAllEffect(GetXValue.instance, new FilterControlledLandPermanent("lands"))); // Devastating Dreams deals X damage to each creature. - this.getSpellAbility().addEffect(new DamageAllEffect(new GetXValue(), new FilterCreaturePermanent())); + this.getSpellAbility().addEffect(new DamageAllEffect(GetXValue.instance, new FilterCreaturePermanent())); } public DevastatingDreams(final DevastatingDreams card) { diff --git a/Mage.Sets/src/mage/cards/d/DevastatingSummons.java b/Mage.Sets/src/mage/cards/d/DevastatingSummons.java index e15ae2af9f5..c5521add77c 100644 --- a/Mage.Sets/src/mage/cards/d/DevastatingSummons.java +++ b/Mage.Sets/src/mage/cards/d/DevastatingSummons.java @@ -55,8 +55,8 @@ class DevastatingSummonsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { DevastatingSummonsElementalToken token = new DevastatingSummonsElementalToken(); - token.getPower().modifyBaseValue(new GetXValue().calculate(game, source, this)); - token.getToughness().modifyBaseValue(new GetXValue().calculate(game, source, this)); + token.getPower().modifyBaseValue(GetXValue.instance.calculate(game, source, this)); + token.getToughness().modifyBaseValue(GetXValue.instance.calculate(game, source, this)); token.putOntoBattlefield(2, game, source.getSourceId(), source.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/d/DevilsPlay.java b/Mage.Sets/src/mage/cards/d/DevilsPlay.java index 111f906c868..fad1267f4cb 100644 --- a/Mage.Sets/src/mage/cards/d/DevilsPlay.java +++ b/Mage.Sets/src/mage/cards/d/DevilsPlay.java @@ -23,7 +23,7 @@ public final class DevilsPlay extends CardImpl { // Devil's Play deals X damage to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); // Flashback {X}{R}{R}{R} this.addAbility(new FlashbackAbility(new ManaCostsImpl("{X}{R}{R}{R}"), TimingRule.SORCERY)); diff --git a/Mage.Sets/src/mage/cards/d/DevoutChaplain.java b/Mage.Sets/src/mage/cards/d/DevoutChaplain.java index 2f601ef3447..02b3d391f4d 100644 --- a/Mage.Sets/src/mage/cards/d/DevoutChaplain.java +++ b/Mage.Sets/src/mage/cards/d/DevoutChaplain.java @@ -30,7 +30,7 @@ public final class DevoutChaplain extends CardImpl { private static final FilterControlledPermanent humanFilter = new FilterControlledPermanent("untapped Human you control"); static { - humanFilter.add(Predicates.not(new TappedPredicate())); + humanFilter.add(Predicates.not(TappedPredicate.instance)); humanFilter.add(new SubtypePredicate(SubType.HUMAN)); } diff --git a/Mage.Sets/src/mage/cards/d/DevoutInvocation.java b/Mage.Sets/src/mage/cards/d/DevoutInvocation.java index b9a459fb356..ea6d47b2c79 100644 --- a/Mage.Sets/src/mage/cards/d/DevoutInvocation.java +++ b/Mage.Sets/src/mage/cards/d/DevoutInvocation.java @@ -48,7 +48,7 @@ class DevoutInvocationEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public DevoutInvocationEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DiabolicRevelation.java b/Mage.Sets/src/mage/cards/d/DiabolicRevelation.java index cd93dc22aa1..bdac351e7ba 100644 --- a/Mage.Sets/src/mage/cards/d/DiabolicRevelation.java +++ b/Mage.Sets/src/mage/cards/d/DiabolicRevelation.java @@ -58,7 +58,7 @@ class DiabolicRevelationEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int amount = new ManacostVariableValue().calculate(game, source, this); + int amount = ManacostVariableValue.instance.calculate(game, source, this); TargetCardInLibrary target = new TargetCardInLibrary(0, amount, new FilterCard()); Player player = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java b/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java index c586f768b79..b34727c950b 100644 --- a/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java +++ b/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java @@ -29,7 +29,7 @@ public final class DiamondKaleidoscope extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("a Prism token"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); filter.add(new SubtypePredicate(SubType.PRISM)); } diff --git a/Mage.Sets/src/mage/cards/d/DiamondValley.java b/Mage.Sets/src/mage/cards/d/DiamondValley.java index a1a75bb9486..530bbee905c 100644 --- a/Mage.Sets/src/mage/cards/d/DiamondValley.java +++ b/Mage.Sets/src/mage/cards/d/DiamondValley.java @@ -25,7 +25,7 @@ public final class DiamondValley extends CardImpl { public DiamondValley(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - Effect effect = new GainLifeEffect(new SacrificeCostCreaturesToughness()); + Effect effect = new GainLifeEffect(SacrificeCostCreaturesToughness.instance); effect.setText("You gain life equal to the sacrificed creature's toughness"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); diff --git a/Mage.Sets/src/mage/cards/d/Dichotomancy.java b/Mage.Sets/src/mage/cards/d/Dichotomancy.java index c788c4dc8f3..a2bcbcadb8a 100644 --- a/Mage.Sets/src/mage/cards/d/Dichotomancy.java +++ b/Mage.Sets/src/mage/cards/d/Dichotomancy.java @@ -59,7 +59,7 @@ class DichotomancyEffect extends OneShotEffect { private static final FilterNonlandPermanent filter = new FilterNonlandPermanent(); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public DichotomancyEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DiligentExcavator.java b/Mage.Sets/src/mage/cards/d/DiligentExcavator.java index 005b0a09bed..5723ceb284c 100644 --- a/Mage.Sets/src/mage/cards/d/DiligentExcavator.java +++ b/Mage.Sets/src/mage/cards/d/DiligentExcavator.java @@ -23,7 +23,7 @@ public final class DiligentExcavator extends CardImpl { private static final FilterSpell filter = new FilterSpell("a historic spell"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public DiligentExcavator(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java b/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java index 69905e94701..98bde31f8f6 100644 --- a/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java +++ b/Mage.Sets/src/mage/cards/d/DiluvianPrimordial.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -13,11 +12,7 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -29,10 +24,12 @@ import mage.game.events.ZoneChangeEvent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class DiluvianPrimordial extends CardImpl { @@ -48,24 +45,9 @@ public final class DiluvianPrimordial extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Diluvian Primordial enters the battlefield, for each opponent, you may cast up to one target instant or sorcery card from that player's graveyard without paying its mana cost. If a card cast this way would be put into a graveyard this turn, exile it instead. - this.addAbility(new EntersBattlefieldTriggeredAbility(new DiluvianPrimordialEffect(), false)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCard filter = new FilterCard("instant or sorcery card from " + opponent.getLogName() + "'s graveyard"); - filter.add(new OwnerIdPredicate(opponentId)); - filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); - TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(0, 1, filter); - ability.addTarget(target); - } - } - } + Ability ability = new EntersBattlefieldTriggeredAbility(new DiluvianPrimordialEffect(), false); + ability.setTargetAdjuster(DiluvianPrimordialAdjuster.instance); + this.addAbility(ability); } public DiluvianPrimordial(final DiluvianPrimordial card) { @@ -78,6 +60,26 @@ public final class DiluvianPrimordial extends CardImpl { } } +enum DiluvianPrimordialAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent == null) { + continue; + } + FilterCard filter = new FilterCard("instant or sorcery card from " + opponent.getLogName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(opponentId)); + filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); + TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(0, 1, filter); + ability.addTarget(target); + } + } +} + class DiluvianPrimordialEffect extends OneShotEffect { public DiluvianPrimordialEffect() { @@ -161,6 +163,6 @@ class DiluvianPrimordialReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; return zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId().equals(getTargetPointer().getFirst(game, source)); + && event.getTargetId().equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/d/DimirCutpurse.java b/Mage.Sets/src/mage/cards/d/DimirCutpurse.java index 90bdf07a64c..54476bf662f 100644 --- a/Mage.Sets/src/mage/cards/d/DimirCutpurse.java +++ b/Mage.Sets/src/mage/cards/d/DimirCutpurse.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; @@ -9,20 +7,20 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class DimirCutpurse extends CardImpl { public DimirCutpurse(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(2); @@ -30,7 +28,6 @@ public final class DimirCutpurse extends CardImpl { // Whenever Dimir Cutpurse deals combat damage to a player, that player discards a card and you draw a card. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DimirCutpurseEffect(), false, true)); - } public DimirCutpurse(final DimirCutpurse card) { diff --git a/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java b/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java index 388d4d7bfbf..e972261d61c 100644 --- a/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java +++ b/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java @@ -81,7 +81,7 @@ class DimirDoppelgangerEffect extends OneShotEffect { Cards cardsToExile = new CardsImpl(); cardsToExile.add(copyFromCard); controller.moveCards(cardsToExile, Zone.EXILED, source, game); - newBluePrint = new PermanentCard((Card) copyFromCard, source.getControllerId(), game); + newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); ApplyToPermanent applier = new DimirDoppelgangerApplier(); applier.apply(game, newBluePrint, source, dimirDoppelganger.getId()); diff --git a/Mage.Sets/src/mage/cards/d/DireFleetCaptain.java b/Mage.Sets/src/mage/cards/d/DireFleetCaptain.java index 10efe1d3897..45e32a2b7d7 100644 --- a/Mage.Sets/src/mage/cards/d/DireFleetCaptain.java +++ b/Mage.Sets/src/mage/cards/d/DireFleetCaptain.java @@ -25,7 +25,7 @@ public final class DireFleetCaptain extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PIRATE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DireFleetCaptain(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java index f49e33e7050..5302dbb2d16 100644 --- a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java +++ b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java @@ -179,7 +179,7 @@ class DireFleetDaredevilReplacementEffect extends ReplacementEffectImpl { StackObject stackObject = game.getStack().getStackObject(eventObject); if (stackObject != null) { if (stackObject instanceof Spell) { - game.rememberLKI(stackObject.getId(), Zone.STACK, (Spell) stackObject); + game.rememberLKI(stackObject.getId(), Zone.STACK, stackObject); } if (stackObject instanceof Card && stackObject.getSourceId().equals(((FixedTarget) getTargetPointer()).getTarget()) @@ -201,6 +201,6 @@ class DireFleetDaredevilReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; return zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId().equals(((FixedTarget) getTargetPointer()).getTarget()); + && event.getTargetId().equals(((FixedTarget) getTargetPointer()).getTarget()); } } diff --git a/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java b/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java index 3e97583f2dc..f9199a211b6 100644 --- a/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java +++ b/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java @@ -30,7 +30,7 @@ public final class DireFleetPoisoner extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public DireFleetPoisoner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/Disappear.java b/Mage.Sets/src/mage/cards/d/Disappear.java index 43b6fa78a8a..a02d0bf1289 100644 --- a/Mage.Sets/src/mage/cards/d/Disappear.java +++ b/Mage.Sets/src/mage/cards/d/Disappear.java @@ -70,7 +70,7 @@ class DisappearEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent aura = (Permanent) game.getPermanentOrLKIBattlefield(source.getSourceId()); + Permanent aura = game.getPermanentOrLKIBattlefield(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && aura != null diff --git a/Mage.Sets/src/mage/cards/d/Disembowel.java b/Mage.Sets/src/mage/cards/d/Disembowel.java index 3e1f1d500dc..6aa70be2abc 100644 --- a/Mage.Sets/src/mage/cards/d/Disembowel.java +++ b/Mage.Sets/src/mage/cards/d/Disembowel.java @@ -1,9 +1,7 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,30 +11,21 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LoneFox */ public final class Disembowel extends CardImpl { public Disembowel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}"); // Destroy target creature with converted mana cost X. - this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with converted mana cost X"))); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.addTarget(new TargetCreaturePermanent(filter)); - } + this.getSpellAbility().addEffect(new DestroyTargetEffect("creature with converted mana cost X")); + this.getSpellAbility().setTargetAdjuster(DisembowelAdjuster.instance); } public Disembowel(final Disembowel card) { @@ -48,3 +37,16 @@ public final class Disembowel extends CardImpl { return new Disembowel(this); } } + +enum DisembowelAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DisinformationCampaign.java b/Mage.Sets/src/mage/cards/d/DisinformationCampaign.java index ab9a61804ff..7b67d4bc805 100644 --- a/Mage.Sets/src/mage/cards/d/DisinformationCampaign.java +++ b/Mage.Sets/src/mage/cards/d/DisinformationCampaign.java @@ -1,6 +1,5 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -16,8 +15,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class DisinformationCampaign extends CardImpl { @@ -27,11 +27,9 @@ public final class DisinformationCampaign extends CardImpl { // When Disinformation Campaign enters the battlefield, you draw a card and each opponent discards a card. Ability ability = new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(1).setText("you draw a card") - ); + new DrawCardSourceControllerEffect(1, "you")); ability.addEffect(new DiscardEachPlayerEffect( - new StaticValue(1), false, TargetController.OPPONENT - ).setText("and each opponent discards a card")); + new StaticValue(1), false, TargetController.OPPONENT).concatBy("and")); this.addAbility(ability); // Whenever you surveil, return Disinformation Campaign to its owner's hand. diff --git a/Mage.Sets/src/mage/cards/d/Disintegrate.java b/Mage.Sets/src/mage/cards/d/Disintegrate.java index bcd68137633..8b0f12edb55 100644 --- a/Mage.Sets/src/mage/cards/d/Disintegrate.java +++ b/Mage.Sets/src/mage/cards/d/Disintegrate.java @@ -23,7 +23,7 @@ public final class Disintegrate extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}"); // Disintegrate deals X damage to any target. That creature can't be regenerated this turn. If the creature would die this turn, exile it instead. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addEffect(new CantRegenerateTargetEffect(Duration.EndOfTurn, "That creature")); Effect effect = new ExileTargetIfDiesEffect(); effect.setText("If the creature would die this turn, exile it instead"); diff --git a/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java b/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java index ef89d09984f..13d14c9460d 100644 --- a/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java +++ b/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java @@ -20,7 +20,7 @@ public final class DissensionInTheRanks extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("blocking creature"); static { - filter.add(new BlockingPredicate()); + filter.add(BlockingPredicate.instance); } public DissensionInTheRanks(UUID ownerId, CardSetInfo setInfo) { @@ -34,7 +34,7 @@ public final class DissensionInTheRanks extends CardImpl { FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another target blocking creature"); filter2.add(new AnotherTargetPredicate(2)); - filter2.add(new BlockingPredicate()); + filter2.add(BlockingPredicate.instance); TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); target2.setTargetTag(2); this.getSpellAbility().addTarget(target2); diff --git a/Mage.Sets/src/mage/cards/d/DistortingWake.java b/Mage.Sets/src/mage/cards/d/DistortingWake.java index 6f0491c67be..e03c667af13 100644 --- a/Mage.Sets/src/mage/cards/d/DistortingWake.java +++ b/Mage.Sets/src/mage/cards/d/DistortingWake.java @@ -1,9 +1,7 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; @@ -13,22 +11,23 @@ import mage.filter.common.FilterNonlandPermanent; import mage.game.Game; import mage.target.Target; import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class DistortingWake extends CardImpl { public DistortingWake(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}{U}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}{U}{U}"); // Return X target nonland permanents to their owners' hands. Effect effect = new ReturnToHandTargetEffect(); effect.setText("Return X target nonland permanents to their owners' hands"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetNonlandPermanent()); + this.getSpellAbility().setTargetAdjuster(DistortingWakeAdjuster.instance); } public DistortingWake(final DistortingWake card) { @@ -39,16 +38,17 @@ public final class DistortingWake extends CardImpl { public DistortingWake copy() { return new DistortingWake(this); } +} + +enum DistortingWakeAdjuster implements TargetAdjuster { + instance; @Override public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = ability.getManaCostsToPay().getX(); - Target target = new TargetNonlandPermanent(xValue, xValue, - new FilterNonlandPermanent(xValue + " target nonland permanent(s)"), false); - ability.getTargets().clear(); - ability.getTargets().add(target); - } + int xValue = ability.getManaCostsToPay().getX(); + Target target = new TargetNonlandPermanent(xValue, xValue, + new FilterNonlandPermanent(xValue + " target nonland permanent(s)"), false); + ability.getTargets().clear(); + ability.getTargets().add(target); } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java b/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java index 2e9c582c229..79ff36ae6b0 100644 --- a/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java +++ b/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java @@ -24,7 +24,7 @@ public final class DiversionaryTactics extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public DiversionaryTactics(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DivineOffering.java b/Mage.Sets/src/mage/cards/d/DivineOffering.java index 8682ffefdd8..02ddd7a87e8 100644 --- a/Mage.Sets/src/mage/cards/d/DivineOffering.java +++ b/Mage.Sets/src/mage/cards/d/DivineOffering.java @@ -23,7 +23,7 @@ public final class DivineOffering extends CardImpl { // Destroy target artifact. You gain life equal to its converted mana cost. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - Effect effect = new GainLifeEffect(new TargetConvertedManaCost()); + Effect effect = new GainLifeEffect(TargetConvertedManaCost.instance); effect.setText("You gain life equal to its converted mana cost"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetArtifactPermanent()); diff --git a/Mage.Sets/src/mage/cards/d/DivinersWand.java b/Mage.Sets/src/mage/cards/d/DivinersWand.java index b1387f89270..50087532215 100644 --- a/Mage.Sets/src/mage/cards/d/DivinersWand.java +++ b/Mage.Sets/src/mage/cards/d/DivinersWand.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DrawCardControllerTriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; @@ -23,40 +21,46 @@ import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class DivinersWand extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("a Wizard creature"); + static { filter.add(new SubtypePredicate(SubType.WIZARD)); } public DivinersWand(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.ARTIFACT}, "{3}"); this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.EQUIPMENT); - // Equipped creature has "Whenever you draw a card, this creature gets +1/+1 and gains flying until end of turn" and "{4}: Draw a card." - Ability gainedAbility = new DrawCardControllerTriggeredAbility(new BoostSourceEffect(1,1, Duration.EndOfTurn), false); - gainedAbility.addEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn)); - Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.EQUIPMENT); - effect.setText("Equipped creature has \"Whenever you draw a card, this creature gets +1/+1 and gains flying until end of turn\""); - Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); - effect = new GainAbilityAttachedEffect( - new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(4)), AttachmentType.EQUIPMENT); - effect.setText("and \"{4}: Draw a card.\""); - ability.addEffect(effect); - this.addAbility(ability); - // Whenever a Wizard creature enters the battlefield, you may attach Diviner's Wand to it. this.addAbility(new EntersBattlefieldAllTriggeredAbility( Zone.BATTLEFIELD, new AttachEffect(Outcome.Detriment, "attach {source} to it"), filter, true, SetTargetPointer.PERMANENT, null)); + // Equip {3} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3))); + + // Equipped creature has "Whenever you draw a card, this creature gets +1/+1 and gains flying until end of turn" and "{4}: Draw a card." + // new abilities + Ability newBoost = new DrawCardControllerTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false); + newBoost.addEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn).concatBy("and")); + Ability newDraw = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + // gain new abilities + Effect effectBoost = new GainAbilityAttachedEffect(newBoost, AttachmentType.EQUIPMENT) + .setText("Equipped creature has \"Whenever you draw a card, this creature gets +1/+1 and gains flying until end of turn\""); + Effect effectDraw = new GainAbilityAttachedEffect(newDraw, AttachmentType.EQUIPMENT) + .setText("\"{4}: Draw a card.\""); + // total ability + Ability totalAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, effectBoost); + totalAbility.addEffect(effectDraw.concatBy("and")); + this.addAbility(totalAbility); } public DivinersWand(final DivinersWand card) { diff --git a/Mage.Sets/src/mage/cards/d/DoggedHunter.java b/Mage.Sets/src/mage/cards/d/DoggedHunter.java index 2f5c0600365..b5e8dd7b435 100644 --- a/Mage.Sets/src/mage/cards/d/DoggedHunter.java +++ b/Mage.Sets/src/mage/cards/d/DoggedHunter.java @@ -24,7 +24,7 @@ public final class DoggedHunter extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature token"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public DoggedHunter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DolmenGate.java b/Mage.Sets/src/mage/cards/d/DolmenGate.java index b5172e1baed..24cad2f4d3d 100644 --- a/Mage.Sets/src/mage/cards/d/DolmenGate.java +++ b/Mage.Sets/src/mage/cards/d/DolmenGate.java @@ -21,7 +21,7 @@ public final class DolmenGate extends CardImpl { private static final FilterControlledCreatureInPlay filter = new FilterControlledCreatureInPlay("attacking creatures you control"); static { - filter.getCreatureFilter().add(new AttackingPredicate()); + filter.getCreatureFilter().add(AttackingPredicate.instance); } public DolmenGate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/Dominate.java b/Mage.Sets/src/mage/cards/d/Dominate.java index 7ad2e93a8cd..d9c74afb3c6 100644 --- a/Mage.Sets/src/mage/cards/d/Dominate.java +++ b/Mage.Sets/src/mage/cards/d/Dominate.java @@ -1,9 +1,6 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -15,38 +12,43 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class Dominate extends CardImpl { public Dominate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{1}{U}{U}"); // Gain control of target creature with converted mana cost X or less. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with converted mana cost X or less"))); + this.getSpellAbility().setTargetAdjuster(DominateAdjuster.instance); } public Dominate(final Dominate card) { super(card); } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X or less"); - filter.add(Predicates.not(new ConvertedManaCostPredicate(ComparisonType.MORE_THAN, xValue))); - ability.addTarget(new TargetCreaturePermanent(filter)); - } - } @Override public Dominate copy() { return new Dominate(this); } } + +enum DominateAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X or less"); + filter.add(Predicates.not(new ConvertedManaCostPredicate(ComparisonType.MORE_THAN, xValue))); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DominatorDrone.java b/Mage.Sets/src/mage/cards/d/DominatorDrone.java index 3a06feb1f12..ece62e0d2a4 100644 --- a/Mage.Sets/src/mage/cards/d/DominatorDrone.java +++ b/Mage.Sets/src/mage/cards/d/DominatorDrone.java @@ -28,8 +28,8 @@ public final class DominatorDrone extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another colorless creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public DominatorDrone(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DomineeringWill.java b/Mage.Sets/src/mage/cards/d/DomineeringWill.java index 808966caefd..384ad50460c 100644 --- a/Mage.Sets/src/mage/cards/d/DomineeringWill.java +++ b/Mage.Sets/src/mage/cards/d/DomineeringWill.java @@ -33,7 +33,7 @@ public final class DomineeringWill extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonattacking creatures"); static { - filter.add(Predicates.not(new AttackingPredicate())); + filter.add(Predicates.not(AttackingPredicate.instance)); } public DomineeringWill(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java new file mode 100644 index 00000000000..d05415185a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DomriChaosBringer.java @@ -0,0 +1,144 @@ +package mage.cards.d; + +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.game.Game; +import mage.game.command.emblems.DomriChaosBringerEmblem; +import mage.game.events.GameEvent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DomriChaosBringer extends CardImpl { + + public DomriChaosBringer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DOMRI); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); + + // +1: Add {R} or {G}. If that mana is spent on a creature spell, it gains riot. + this.addAbility(new LoyaltyAbility(new DomriChaosBringerEffect(), 1)); + + // −3: Look at the top four cards of your library. You may reveal up to two creature cards from among them and put them into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new LoyaltyAbility(new LookLibraryAndPickControllerEffect( + new StaticValue(4), false, new StaticValue(2), + StaticFilters.FILTER_CARD_CREATURE, Zone.LIBRARY, false, + true, true, Zone.HAND, false, false, false + ).setText( + "Look at the top four cards of your library. " + + "You may reveal up to two creature cards from among them " + + "and put them into your hand. Put the rest on the bottom of your library " + + "in a random order." + ), -3)); + + // −8: You get an emblem with "At the beginning of each end step, create a 4/4 red and green Beast creature token with trample." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new DomriChaosBringerEmblem()), -8)); + } + + private DomriChaosBringer(final DomriChaosBringer card) { + super(card); + } + + @Override + public DomriChaosBringer copy() { + return new DomriChaosBringer(this); + } +} + +class DomriChaosBringerEffect extends OneShotEffect { + + DomriChaosBringerEffect() { + super(Outcome.Benefit); + staticText = "Add {R} or {G}. If that mana is spent on a creature spell, it gains riot."; + } + + private DomriChaosBringerEffect(final DomriChaosBringerEffect effect) { + super(effect); + } + + @Override + public DomriChaosBringerEffect copy() { + return new DomriChaosBringerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + ManaEffect manaEffect; + if (player.chooseUse(Outcome.PutManaInPool, "Choose red or green mana", "", "Red", "Green", source, game)) { + manaEffect = new BasicManaEffect(Mana.RedMana(1)); + } else { + manaEffect = new BasicManaEffect(Mana.GreenMana(1)); + } + game.addDelayedTriggeredAbility(new DomriChaosBringerTriggeredAbility(source.getSourceId()), source); + return manaEffect.apply(game, source); + } +} + +class DomriChaosBringerTriggeredAbility extends DelayedTriggeredAbility { + + private final UUID spellId; + + DomriChaosBringerTriggeredAbility(UUID spellId) { + super(null, Duration.EndOfStep, true); + this.spellId = spellId; + this.usesStack = false; + } + + private DomriChaosBringerTriggeredAbility(final DomriChaosBringerTriggeredAbility ability) { + super(ability); + this.spellId = ability.spellId; + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.MANA_PAID; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(spellId)) { + return false; + } + MageObject mo = game.getObject(event.getTargetId()); + if (mo == null || !mo.isCreature()) { + return false; + } + this.getEffects().clear(); + FilterSpell filter = new FilterSpell(); + filter.add(new CardIdPredicate(event.getTargetId())); + this.addEffect(new GainAbilityControlledSpellsEffect(new RiotAbility(), filter)); + return true; + } + + @Override + public DomriChaosBringerTriggeredAbility copy() { + return new DomriChaosBringerTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DomriCitySmasher.java b/Mage.Sets/src/mage/cards/d/DomriCitySmasher.java new file mode 100644 index 00000000000..2475c5f7d1c --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DomriCitySmasher.java @@ -0,0 +1,69 @@ +package mage.cards.d; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetAnyTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DomriCitySmasher extends CardImpl { + + public DomriCitySmasher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DOMRI); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); + + // +2: Creatures you control get +1/+1 and gain haste until end of turn. + Ability ability = new LoyaltyAbility(new BoostControlledEffect( + 1, 1, Duration.EndOfTurn + ).setText("creatures you control get +1/+1"), 2); + ability.addEffect(new GainAbilityControlledEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("and gain haste until end of turn")); + this.addAbility(ability); + + // -3: Domri, City Smasher deals 3 damage to any target. + ability = new LoyaltyAbility(new DamageTargetEffect(3), -3); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + + // -8: Put three +1/+1 counters on each creature you control. Those creatures gain trample until end of turn. + ability = new LoyaltyAbility(new AddCountersAllEffect( + CounterType.P1P1.createInstance(3), + StaticFilters.FILTER_CONTROLLED_CREATURE + ), -8); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("Those creatures gain trample until end of turn")); + this.addAbility(ability); + } + + private DomriCitySmasher(final DomriCitySmasher card) { + super(card); + } + + @Override + public DomriCitySmasher copy() { + return new DomriCitySmasher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DomrisNodorog.java b/Mage.Sets/src/mage/cards/d/DomrisNodorog.java new file mode 100644 index 00000000000..2c289dd233a --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DomrisNodorog.java @@ -0,0 +1,51 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DomrisNodorog extends CardImpl { + + private static final FilterCard filter = new FilterCard("card named Domri, City Smasher"); + + static { + filter.add(new NamePredicate("Domri, City Smasher")); + } + + public DomrisNodorog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(5); + this.toughness = new MageInt(2); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Domri's Nodorog enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryGraveyardPutInHandEffect(filter, false, true) + )); + } + + private DomrisNodorog(final DomrisNodorog card) { + super(card); + } + + @Override + public DomrisNodorog copy() { + return new DomrisNodorog(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DoranTheSiegeTower.java b/Mage.Sets/src/mage/cards/d/DoranTheSiegeTower.java index 03c4f0c6f18..984b2342ec1 100644 --- a/Mage.Sets/src/mage/cards/d/DoranTheSiegeTower.java +++ b/Mage.Sets/src/mage/cards/d/DoranTheSiegeTower.java @@ -1,19 +1,20 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; + +import java.util.UUID; /** - * * 613.10. Some continuous effects affect game rules rather than objects. For * example, effects may modify a player's maximum hand size, or say that a * creature must attack this turn if able. These effects are applied after all @@ -22,7 +23,6 @@ import mage.game.Game; * in rule 601.2e. All other such effects are applied in timestamp order. See * also the rules for timestamp order and dependency (rules 613.6 and 613.7) * - * * @author LevelX2 */ public final class DoranTheSiegeTower extends CardImpl { @@ -37,10 +37,15 @@ public final class DoranTheSiegeTower extends CardImpl { this.toughness = new MageInt(5); // Each creature assigns combat damage equal to its toughness rather than its power. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DoranTheSiegeTowerCombatDamageRuleEffect())); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CombatDamageByToughnessEffect( + StaticFilters.FILTER_PERMANENT_CREATURE, false + ) + )); } - public DoranTheSiegeTower(final DoranTheSiegeTower card) { + private DoranTheSiegeTower(final DoranTheSiegeTower card) { super(card); } @@ -49,38 +54,3 @@ public final class DoranTheSiegeTower extends CardImpl { return new DoranTheSiegeTower(this); } } - -class DoranTheSiegeTowerCombatDamageRuleEffect extends ContinuousEffectImpl { - - public DoranTheSiegeTowerCombatDamageRuleEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Each creature assigns combat damage equal to its toughness rather than its power"; - } - - public DoranTheSiegeTowerCombatDamageRuleEffect(final DoranTheSiegeTowerCombatDamageRuleEffect effect) { - super(effect); - } - - @Override - public DoranTheSiegeTowerCombatDamageRuleEffect copy() { - return new DoranTheSiegeTowerCombatDamageRuleEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - // Change the rule - game.getCombat().setUseToughnessForDamage(true); - game.getCombat().addUseToughnessForDamageFilter(StaticFilters.FILTER_PERMANENT_CREATURES); - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.RulesEffects; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DormantVolcano.java b/Mage.Sets/src/mage/cards/d/DormantVolcano.java index d43f82f6174..8ee5e9f5bbf 100644 --- a/Mage.Sets/src/mage/cards/d/DormantVolcano.java +++ b/Mage.Sets/src/mage/cards/d/DormantVolcano.java @@ -30,7 +30,7 @@ public final class DormantVolcano extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MOUNTAIN)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public DormantVolcano(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DovinArchitectOfLaw.java b/Mage.Sets/src/mage/cards/d/DovinArchitectOfLaw.java new file mode 100644 index 00000000000..997df68c943 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DovinArchitectOfLaw.java @@ -0,0 +1,56 @@ +package mage.cards.d; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.effects.common.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DovinArchitectOfLaw extends CardImpl { + + public DovinArchitectOfLaw(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DOVIN); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); + + // +1: You gain 2 life and draw a card. + Ability ability = new LoyaltyAbility(new GainLifeEffect(2), 1); + ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and")); + this.addAbility(ability); + + // -1: Tap target creature. It doesn't untap during its controller's next untap step. + ability = new LoyaltyAbility(new TapTargetEffect(), -1); + ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("It")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // -9: Tap all permanents target opponent controls. That player skips their next untap step. + ability = new LoyaltyAbility(new TapAllTargetPlayerControlsEffect(StaticFilters.FILTER_PERMANENT), -9); + ability.addEffect(new SkipNextPlayerUntapStepEffect("That player")); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + private DovinArchitectOfLaw(final DovinArchitectOfLaw card) { + super(card); + } + + @Override + public DovinArchitectOfLaw copy() { + return new DovinArchitectOfLaw(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DovinGrandArbiter.java b/Mage.Sets/src/mage/cards/d/DovinGrandArbiter.java new file mode 100644 index 00000000000..ea2400d975b --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DovinGrandArbiter.java @@ -0,0 +1,107 @@ +package mage.cards.d; + +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ThopterColorlessToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DovinGrandArbiter extends CardImpl { + + public DovinGrandArbiter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DOVIN); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); + + // +1: Until end of turn, whenever a creature you control deals combat damage to a player, put a loyalty counter on Dovin, Grand Arbiter. + this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect( + new DovinGrandArbiterDelayedTriggeredAbility(), false + ), 1)); + + // -1: Create a 1/1 colorless Thopter artifact creature token with flying. You gain 1 life. + Ability ability = new LoyaltyAbility(new CreateTokenEffect(new ThopterColorlessToken()), -1); + ability.addEffect(new GainLifeEffect(1).setText("You gain 1 life.")); + this.addAbility(ability); + + // -7: Look at the top ten cards of your library. Put three of them into your hand and the rest on the bottom of your library in a random order. + this.addAbility(new LoyaltyAbility(new LookLibraryAndPickControllerEffect( + new StaticValue(10), false, + new StaticValue(3), StaticFilters.FILTER_CARD, + Zone.LIBRARY, false, false, false, + Zone.HAND, false, false, false + ).setBackInRandomOrder(true).setText("Look at the top ten cards of your library. " + + "Put three of them into your hand and the rest " + + "on the bottom of your library in a random order." + ), -7)); + } + + private DovinGrandArbiter(final DovinGrandArbiter card) { + super(card); + } + + @Override + public DovinGrandArbiter copy() { + return new DovinGrandArbiter(this); + } +} + +class DovinGrandArbiterDelayedTriggeredAbility extends DelayedTriggeredAbility { + + DovinGrandArbiterDelayedTriggeredAbility() { + super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance()), Duration.EndOfTurn, false); + } + + private DovinGrandArbiterDelayedTriggeredAbility(final DovinGrandArbiterDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public DovinGrandArbiterDelayedTriggeredAbility copy() { + return new DovinGrandArbiterDelayedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (((DamagedPlayerEvent) event).isCombatDamage()) { + Permanent creature = game.getPermanent(event.getSourceId()); + if (creature != null && creature.isControlledBy(controllerId)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Until end of turn, whenever a creature you control " + + "deals combat damage to a player, " + + "put a loyalty counter on {this}."; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DovinsAcuity.java b/Mage.Sets/src/mage/cards/d/DovinsAcuity.java new file mode 100644 index 00000000000..96efb5f9772 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DovinsAcuity.java @@ -0,0 +1,72 @@ +package mage.cards.d; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TurnPhase; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; + +import java.util.EnumSet; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DovinsAcuity extends CardImpl { + + private static final FilterSpell filter = new FilterSpell(); + + static { + filter.add(new CardTypePredicate(CardType.INSTANT)); + } + + public DovinsAcuity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{U}"); + + // When Dovin's Acuity enters the battlefield, you gain 2 life and draw a card. + Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2)); + ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and draw a card")); + this.addAbility(ability); + + // Whenever you cast an instant spell during your main phase, you may return Dovin's Acuity to its owner's hand. + this.addAbility(new ConditionalTriggeredAbility( + new SpellCastControllerTriggeredAbility( + new ReturnToHandSourceEffect(true), filter, true + ), DovinsAcuityCondition.instance, + "Whenever you cast an instant spell during your main phase, " + + "you may return {this} to its owner's hand." + )); + } + + private DovinsAcuity(final DovinsAcuity card) { + super(card); + } + + @Override + public DovinsAcuity copy() { + return new DovinsAcuity(this); + } +} + +enum DovinsAcuityCondition implements Condition { + + instance; + private static final Set turnPhases = EnumSet.of(TurnPhase.PRECOMBAT_MAIN, TurnPhase.POSTCOMBAT_MAIN); + + @Override + public boolean apply(Game game, Ability source) { + return game.isActivePlayer(source.getControllerId()) + && turnPhases.contains(game.getTurn().getPhase().getType()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DovinsAutomaton.java b/Mage.Sets/src/mage/cards/d/DovinsAutomaton.java new file mode 100644 index 00000000000..e1e17cde995 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DovinsAutomaton.java @@ -0,0 +1,61 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DovinsAutomaton extends CardImpl { + + private static final Condition condition + = new PermanentsOnTheBattlefieldCondition(new FilterControlledPlaneswalkerPermanent(SubType.DOVIN)); + + public DovinsAutomaton(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + + this.subtype.add(SubType.HOMUNCULUS); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // As long as you control a Dovin planeswalker, Dovin's Automaton gets +2/+2 and has vigilance. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), + condition, "As long as you control a Dovin planeswalker, {this} gets +2/+2" + ) + ); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + VigilanceAbility.getInstance(), Duration.WhileOnBattlefield + ), condition, "and has vigilance" + )); + this.addAbility(ability); + } + + private DovinsAutomaton(final DovinsAutomaton card) { + super(card); + } + + @Override + public DovinsAutomaton copy() { + return new DovinsAutomaton(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DovinsDismissal.java b/Mage.Sets/src/mage/cards/d/DovinsDismissal.java new file mode 100644 index 00000000000..598029d98b5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DovinsDismissal.java @@ -0,0 +1,49 @@ +package mage.cards.d; + +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DovinsDismissal extends CardImpl { + + private static final FilterCard filter = new FilterCard("card named Dovin, Architect of Law"); + private static final FilterPermanent filter2 = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(new NamePredicate("Dovin, Architect of Law")); + filter2.add(TappedPredicate.instance); + } + + public DovinsDismissal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}{U}"); + + // Put up to one target tapped creature on top of its owner's library. You may search your library and/or graveyard for a card named Dovin, Architect of Law, reveal it, and put it into your hand. If you search your library this way, shuffle it. + this.getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true)); + this.getSpellAbility().addEffect( + new SearchLibraryGraveyardPutInHandEffect(filter, false, true) + ); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter2, false)); + } + + private DovinsDismissal(final DovinsDismissal card) { + super(card); + } + + @Override + public DovinsDismissal copy() { + return new DovinsDismissal(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DraconicRoar.java b/Mage.Sets/src/mage/cards/d/DraconicRoar.java index 2eb1d61e95d..34102c4f395 100644 --- a/Mage.Sets/src/mage/cards/d/DraconicRoar.java +++ b/Mage.Sets/src/mage/cards/d/DraconicRoar.java @@ -1,15 +1,14 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -22,23 +21,19 @@ import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class DraconicRoar extends CardImpl { - private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)"); - - static { - filter.add(new SubtypePredicate(SubType.DRAGON)); - } - public DraconicRoar(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); // As an additional cost to cast Draconic Roar, you may reveal a Dragon card from your hand. this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); + this.getSpellAbility().setCostAdjuster(DraconicRoarAdjuster.instance); // Draconic Roar deals 3 damage to target creature. If you revealed a Dragon card or controlled a Dragon as you cast Draconic Roar, Draconic Roar deals 3 damage to that creature's controller. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); @@ -47,18 +42,6 @@ public final class DraconicRoar extends CardImpl { this.getSpellAbility().addWatcher(new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability.getAbilityType() == AbilityType.SPELL) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - if (controller.getHand().count(filter, game) > 0) { - ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0,1, filter))); - } - } - } - } - public DraconicRoar(final DraconicRoar card) { super(card); } @@ -69,6 +52,25 @@ public final class DraconicRoar extends CardImpl { } } +enum DraconicRoarAdjuster implements CostAdjuster { + instance; + + private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + } + + @Override + public void adjustCosts(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller != null) { + if (controller.getHand().count(filter, game) > 0) { + ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter))); + } + } + } +} class DraconicRoarEffect extends OneShotEffect { @@ -90,7 +92,7 @@ class DraconicRoarEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = (DragonOnTheBattlefieldWhileSpellWasCastWatcher) game.getState().getWatchers().get(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class.getSimpleName()); + DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); if (watcher != null && watcher.castWithConditionTrue(source.getId())) { Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (permanent != null) { diff --git a/Mage.Sets/src/mage/cards/d/Dracoplasm.java b/Mage.Sets/src/mage/cards/d/Dracoplasm.java index aa478448c10..974da8aa9d5 100644 --- a/Mage.Sets/src/mage/cards/d/Dracoplasm.java +++ b/Mage.Sets/src/mage/cards/d/Dracoplasm.java @@ -63,7 +63,7 @@ class DracoplasmEffect extends ReplacementEffectImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public DracoplasmEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DragonArch.java b/Mage.Sets/src/mage/cards/d/DragonArch.java index 6b9c444feeb..5a152ea0134 100644 --- a/Mage.Sets/src/mage/cards/d/DragonArch.java +++ b/Mage.Sets/src/mage/cards/d/DragonArch.java @@ -24,7 +24,7 @@ public final class DragonArch extends CardImpl { private static final FilterCreatureCard filter = new FilterCreatureCard("a multicolored creature card"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public DragonArch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java b/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java index 6ce626db3fa..f90f8c05ee4 100644 --- a/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java +++ b/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java @@ -1,11 +1,11 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.Cost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; import mage.abilities.effects.ContinuousRuleModifyingEffect; @@ -25,24 +25,20 @@ import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class DragonlordsPrerogative extends CardImpl { - private static final FilterCard filter = new FilterCard("a Dragon card from your hand"); - - static { - filter.add(new SubtypePredicate(SubType.DRAGON)); - } - public DragonlordsPrerogative(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}"); // As an additional cost to cast Dragonlord's Prerogative, you may reveal a Dragon card from your hand. this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); - + this.getSpellAbility().setCostAdjuster(DragonlordsPrerogativeAdjuster.instance); + // If you revealed a Dragon card or controlled a Dragon as you cast Dragonlord's Prerogative, Dragonlord's Prerogative can't be countered. Condition condition = new DragonlordsPrerogativeCondition(); ContinuousRuleModifyingEffect cantBeCountered = new CantBeCounteredSourceEffect(); @@ -50,22 +46,12 @@ public final class DragonlordsPrerogative extends CardImpl { conditionalCantBeCountered.setText("
If you revealed a Dragon card or controlled a Dragon as you cast {this}, this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, conditionalCantBeCountered); this.addAbility(ability); - + // Draw four cards. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4)); } - - @Override - public void adjustCosts(Ability ability, Game game) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - if (controller.getHand().count(filter, game) > 0) { - ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0,1, filter))); - } - } - } - + public DragonlordsPrerogative(final DragonlordsPrerogative card) { super(card); } @@ -76,6 +62,25 @@ public final class DragonlordsPrerogative extends CardImpl { } } +enum DragonlordsPrerogativeAdjuster implements CostAdjuster { + instance; + private static final FilterCard filter = new FilterCard("a Dragon card from your hand"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + } + + @Override + public void adjustCosts(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller != null) { + if (controller.getHand().count(filter, game) > 0) { + ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter))); + } + } + } +} + class DragonlordsPrerogativeCondition implements Condition { private final static FilterControlledPermanent filter = new FilterControlledPermanent("Dragon"); @@ -89,7 +94,7 @@ class DragonlordsPrerogativeCondition implements Condition { boolean applies = false; Spell spell = game.getStack().getSpell(source.getSourceId()); if (spell != null && spell.getSpellAbility() != null) { - for(Cost cost: spell.getSpellAbility().getCosts()) { + for (Cost cost : spell.getSpellAbility().getCosts()) { if (cost instanceof RevealTargetFromHandCost) { applies = !cost.getTargets().isEmpty(); break; diff --git a/Mage.Sets/src/mage/cards/d/Dragonrage.java b/Mage.Sets/src/mage/cards/d/Dragonrage.java index 410fe9bdc59..d378be9433a 100644 --- a/Mage.Sets/src/mage/cards/d/Dragonrage.java +++ b/Mage.Sets/src/mage/cards/d/Dragonrage.java @@ -28,7 +28,7 @@ public final class Dragonrage extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature you control"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } diff --git a/Mage.Sets/src/mage/cards/d/DragonscaleGeneral.java b/Mage.Sets/src/mage/cards/d/DragonscaleGeneral.java index e9ba1f5213d..ed089609426 100644 --- a/Mage.Sets/src/mage/cards/d/DragonscaleGeneral.java +++ b/Mage.Sets/src/mage/cards/d/DragonscaleGeneral.java @@ -24,7 +24,7 @@ public final class DragonscaleGeneral extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creatures you control"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/d/DranaKalastriaBloodchief.java b/Mage.Sets/src/mage/cards/d/DranaKalastriaBloodchief.java index 025eb357746..404fafb5f75 100644 --- a/Mage.Sets/src/mage/cards/d/DranaKalastriaBloodchief.java +++ b/Mage.Sets/src/mage/cards/d/DranaKalastriaBloodchief.java @@ -37,8 +37,8 @@ public final class DranaKalastriaBloodchief extends CardImpl { this.toughness = new MageInt(4); this.addAbility(FlyingAbility.getInstance()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(new StaticValue(0), new SignInversionDynamicValue(new ManacostVariableValue()), Duration.EndOfTurn), new ManaCostsImpl("{X}{B}{B}")); - ability.addEffect(new BoostSourceEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(new StaticValue(0), new SignInversionDynamicValue(ManacostVariableValue.instance), Duration.EndOfTurn), new ManaCostsImpl("{X}{B}{B}")); + ability.addEffect(new BoostSourceEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DranasChosen.java b/Mage.Sets/src/mage/cards/d/DranasChosen.java index 3afa5ccd687..d0dd78f5487 100644 --- a/Mage.Sets/src/mage/cards/d/DranasChosen.java +++ b/Mage.Sets/src/mage/cards/d/DranasChosen.java @@ -31,7 +31,7 @@ public final class DranasChosen extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public DranasChosen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DrasticRevelation.java b/Mage.Sets/src/mage/cards/d/DrasticRevelation.java index e6d3c98266a..faec9cf5da6 100644 --- a/Mage.Sets/src/mage/cards/d/DrasticRevelation.java +++ b/Mage.Sets/src/mage/cards/d/DrasticRevelation.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -13,18 +11,15 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class DrasticRevelation extends CardImpl { public DrasticRevelation(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}{B}{R}"); - - - - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{B}{R}"); // Discard your hand. Draw seven cards, then discard three cards at random. this.getSpellAbility().addEffect(new DrasticRevelationEffect()); @@ -54,8 +49,8 @@ class DrasticRevelationEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); - if(you != null) { - you.discardToMax(game); + if (you != null) { + you.discard(you.getHand().size(), false, source, game); you.drawCards(7, game); Cards hand = you.getHand(); for (int i = 0; i < 3; i++) { diff --git a/Mage.Sets/src/mage/cards/d/DreadCacodemon.java b/Mage.Sets/src/mage/cards/d/DreadCacodemon.java index 9b8e1ad205d..2df82acf881 100644 --- a/Mage.Sets/src/mage/cards/d/DreadCacodemon.java +++ b/Mage.Sets/src/mage/cards/d/DreadCacodemon.java @@ -32,7 +32,7 @@ public final class DreadCacodemon extends CardImpl { private static final FilterCreaturePermanent otherCreaturesYouControl = new FilterCreaturePermanent("other creatures you control"); static { otherCreaturesYouControl.add(new ControllerPredicate(TargetController.YOU)); - otherCreaturesYouControl.add(new AnotherPredicate()); + otherCreaturesYouControl.add(AnotherPredicate.instance); } public DreadCacodemon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DreadSlag.java b/Mage.Sets/src/mage/cards/d/DreadSlag.java index dd7548175b1..bebbcd720d7 100644 --- a/Mage.Sets/src/mage/cards/d/DreadSlag.java +++ b/Mage.Sets/src/mage/cards/d/DreadSlag.java @@ -32,7 +32,7 @@ public final class DreadSlag extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); // Dread Slag gets -4/-4 for each card in your hand. - DynamicValue amount = new MultipliedValue(new CardsInControllerHandCount(), -4); + DynamicValue amount = new MultipliedValue(CardsInControllerHandCount.instance, -4); Effect effect = new BoostSourceEffect(amount, amount, Duration.WhileOnBattlefield); effect.setText("{this} gets -4/-4 for each card in your hand"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/d/DreadWight.java b/Mage.Sets/src/mage/cards/d/DreadWight.java index 0bdf71c0ee8..e3225c405f5 100644 --- a/Mage.Sets/src/mage/cards/d/DreadWight.java +++ b/Mage.Sets/src/mage/cards/d/DreadWight.java @@ -98,10 +98,6 @@ class DreadWightTriggeredAbility extends TriggeredAbilityImpl { return false; } - @Override - public String getRule() { - return super.getRule(); - } } class DreadWightEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/cards/d/DreadshipReef.java b/Mage.Sets/src/mage/cards/d/DreadshipReef.java index 7073e04f11d..53a75729b99 100644 --- a/Mage.Sets/src/mage/cards/d/DreadshipReef.java +++ b/Mage.Sets/src/mage/cards/d/DreadshipReef.java @@ -36,7 +36,7 @@ public final class DreadshipReef extends CardImpl { this.addAbility(ability); // {1}, Remove X storage counters from Dreadship Reef: Add X mana in any combination of {U} and/or {B}. ability = new SimpleManaAbility(Zone.BATTLEFIELD, - new AddManaInAnyCombinationEffect(new RemovedCountersForCostValue(), ColoredManaSymbol.U, ColoredManaSymbol.B), + new AddManaInAnyCombinationEffect(RemovedCountersForCostValue.instance, ColoredManaSymbol.U, ColoredManaSymbol.B), new GenericManaCost(1)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance())); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DreamChisel.java b/Mage.Sets/src/mage/cards/d/DreamChisel.java index 705fe64cc21..8508e9b24bf 100644 --- a/Mage.Sets/src/mage/cards/d/DreamChisel.java +++ b/Mage.Sets/src/mage/cards/d/DreamChisel.java @@ -20,7 +20,7 @@ public final class DreamChisel extends CardImpl { private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public DreamChisel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DreamSalvage.java b/Mage.Sets/src/mage/cards/d/DreamSalvage.java index fcd535a32d7..6d8ad465fcc 100644 --- a/Mage.Sets/src/mage/cards/d/DreamSalvage.java +++ b/Mage.Sets/src/mage/cards/d/DreamSalvage.java @@ -49,7 +49,7 @@ class CardsDiscardedThisTurnWatcher extends Watcher { private final Map amountOfCardsDiscardedThisTurn = new HashMap<>(); public CardsDiscardedThisTurnWatcher() { - super(CardsDiscardedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(CardsDiscardedThisTurnWatcher.class, WatcherScope.GAME); } public CardsDiscardedThisTurnWatcher(final CardsDiscardedThisTurnWatcher watcher) { @@ -102,7 +102,7 @@ class DreamSalvageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - CardsDiscardedThisTurnWatcher watcher = (CardsDiscardedThisTurnWatcher) game.getState().getWatchers().get(CardsDiscardedThisTurnWatcher.class.getSimpleName()); + CardsDiscardedThisTurnWatcher watcher = game.getState().getWatcher(CardsDiscardedThisTurnWatcher.class); Player targetOpponent = game.getPlayer(source.getFirstTarget()); Player controller = game.getPlayer(source.getControllerId()); if (targetOpponent != null diff --git a/Mage.Sets/src/mage/cards/d/DreamThief.java b/Mage.Sets/src/mage/cards/d/DreamThief.java index 1be3f20e765..4777110118e 100644 --- a/Mage.Sets/src/mage/cards/d/DreamThief.java +++ b/Mage.Sets/src/mage/cards/d/DreamThief.java @@ -57,7 +57,7 @@ class CastBlueSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(source.getControllerId()); if (spells != null) { diff --git a/Mage.Sets/src/mage/cards/d/DreamTides.java b/Mage.Sets/src/mage/cards/d/DreamTides.java index 965adba3808..6f15d52bf11 100644 --- a/Mage.Sets/src/mage/cards/d/DreamTides.java +++ b/Mage.Sets/src/mage/cards/d/DreamTides.java @@ -59,7 +59,7 @@ class DreamTidesEffect extends OneShotEffect { static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN))); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } DreamTidesEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DreambornMuse.java b/Mage.Sets/src/mage/cards/d/DreambornMuse.java index 66cc27162bd..169107a55c2 100644 --- a/Mage.Sets/src/mage/cards/d/DreambornMuse.java +++ b/Mage.Sets/src/mage/cards/d/DreambornMuse.java @@ -25,7 +25,7 @@ public final class DreambornMuse extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each player's upkeep, that player puts the top X cards of their library into their graveyard, where X is the number of cards in their hand. - PutLibraryIntoGraveTargetEffect effect = new PutLibraryIntoGraveTargetEffect(new CardsInTargetPlayerHandCount()); + PutLibraryIntoGraveTargetEffect effect = new PutLibraryIntoGraveTargetEffect(CardsInTargetPlayerHandCount.instance); effect.setText("that player puts the top X cards of their library into their graveyard, where X is the number of cards in their hand."); this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.ANY, false)); diff --git a/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java b/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java index 01d62c7422f..c0550a27942 100644 --- a/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java +++ b/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java @@ -32,7 +32,7 @@ public final class DreamcallerSiren extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PIRATE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java b/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java index a819a8abf70..06412ef6bf5 100644 --- a/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java +++ b/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java @@ -1,10 +1,7 @@ - package mage.cards.d; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -16,39 +13,25 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class DregsOfSorrow extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creatures"); - - static { - filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); - } - public DregsOfSorrow(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{4}{B}"); // Destroy X target nonblack creatures. Draw X cards. this.getSpellAbility().addEffect(new DestroyTargetEffect("Destroy X target nonblack creatures")); - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new ManacostVariableValue())); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(ManacostVariableValue.instance)); + this.getSpellAbility().setTargetAdjuster(DregsOfSorrowAdjuster.instance); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetCreaturePermanent(xValue, xValue, filter, false)); - } - } - - public DregsOfSorrow(final DregsOfSorrow card) { super(card); } @@ -58,3 +41,19 @@ public final class DregsOfSorrow extends CardImpl { return new DregsOfSorrow(this); } } + +enum DregsOfSorrowAdjuster implements TargetAdjuster { + instance; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creatures"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetCreaturePermanent(xValue, xValue, filter, false)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DrillBit.java b/Mage.Sets/src/mage/cards/d/DrillBit.java new file mode 100644 index 00000000000..d229ba4d020 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DrillBit.java @@ -0,0 +1,41 @@ +package mage.cards.d; + +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; +import mage.abilities.keyword.SpectacleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DrillBit extends CardImpl { + + public DrillBit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); + + // Target player reveals their hand. You choose a nonland card from it. That player discards that card. + this.getSpellAbility().addEffect(new DiscardCardYouChooseTargetEffect( + StaticFilters.FILTER_CARD_NON_LAND, TargetController.ANY + )); + this.getSpellAbility().addTarget(new TargetPlayer()); + + // Spectacle {B} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{B}"))); + } + + private DrillBit(final DrillBit card) { + super(card); + } + + @Override + public DrillBit copy() { + return new DrillBit(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DrillSkimmer.java b/Mage.Sets/src/mage/cards/d/DrillSkimmer.java index 0b60594721b..d379e662a37 100644 --- a/Mage.Sets/src/mage/cards/d/DrillSkimmer.java +++ b/Mage.Sets/src/mage/cards/d/DrillSkimmer.java @@ -30,7 +30,7 @@ public final class DrillSkimmer extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("you control another artifact creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new CardTypePredicate(CardType.ARTIFACT)); } diff --git a/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java b/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java index a5d6b4d3f33..ed36a32932b 100644 --- a/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java +++ b/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java @@ -27,7 +27,7 @@ public final class DrippingTongueZubera extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritToken(), new ZuberasDiedDynamicValue()), false), new ZuberasDiedWatcher()); + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritToken(), ZuberasDiedDynamicValue.instance), false), new ZuberasDiedWatcher()); } public DrippingTongueZubera (final DrippingTongueZubera card) { diff --git a/Mage.Sets/src/mage/cards/d/DrivenDespair.java b/Mage.Sets/src/mage/cards/d/DrivenDespair.java index 7f9b0af2532..09d29f92ce9 100644 --- a/Mage.Sets/src/mage/cards/d/DrivenDespair.java +++ b/Mage.Sets/src/mage/cards/d/DrivenDespair.java @@ -36,7 +36,7 @@ public final class DrivenDespair extends SplitCard { // Despair {1}{B} // Sorcery // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Until end of turn, creatures you control gain menace and "Whenever this creature deals combat damage to a player, that player discards a card." getRightHalfCard().getSpellAbility().addEffect(new GainAbilityControlledEffect(new MenaceAbility(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES)); ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true); diff --git a/Mage.Sets/src/mage/cards/d/DrogskolCavalry.java b/Mage.Sets/src/mage/cards/d/DrogskolCavalry.java index 3a2c558bfaf..d0613ac5203 100644 --- a/Mage.Sets/src/mage/cards/d/DrogskolCavalry.java +++ b/Mage.Sets/src/mage/cards/d/DrogskolCavalry.java @@ -28,7 +28,7 @@ public final class DrogskolCavalry extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another Spirit"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.SPIRIT)); } diff --git a/Mage.Sets/src/mage/cards/d/DrownerOfSecrets.java b/Mage.Sets/src/mage/cards/d/DrownerOfSecrets.java index 149ce963f0a..65596971ff4 100644 --- a/Mage.Sets/src/mage/cards/d/DrownerOfSecrets.java +++ b/Mage.Sets/src/mage/cards/d/DrownerOfSecrets.java @@ -29,7 +29,7 @@ public final class DrownerOfSecrets extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MERFOLK)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public DrownerOfSecrets(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DrudgeSpell.java b/Mage.Sets/src/mage/cards/d/DrudgeSpell.java index 91a2755db40..efd94be9900 100644 --- a/Mage.Sets/src/mage/cards/d/DrudgeSpell.java +++ b/Mage.Sets/src/mage/cards/d/DrudgeSpell.java @@ -32,7 +32,7 @@ public final class DrudgeSpell extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SKELETON)); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public DrudgeSpell(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DualNature.java b/Mage.Sets/src/mage/cards/d/DualNature.java index fa4e3322710..21051057904 100644 --- a/Mage.Sets/src/mage/cards/d/DualNature.java +++ b/Mage.Sets/src/mage/cards/d/DualNature.java @@ -37,7 +37,7 @@ public final class DualNature extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public DualNature(UUID ownerId, CardSetInfo setInfo) { @@ -130,7 +130,7 @@ class DualNatureCreatureLeavesEffect extends OneShotEffect { Permanent creature = game.getPermanentOrLKIBattlefield(this.getTargetPointer().getFirst(game, source)); if (creature != null) { FilterPermanent filter = new FilterPermanent(); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); filter.add(new NamePredicate(creature.getName())); new ExileAllEffect(filter).apply(game, source); return true; diff --git a/Mage.Sets/src/mage/cards/d/DuelingGrounds.java b/Mage.Sets/src/mage/cards/d/DuelingGrounds.java index 92c0cbe0413..25418a7d7ca 100644 --- a/Mage.Sets/src/mage/cards/d/DuelingGrounds.java +++ b/Mage.Sets/src/mage/cards/d/DuelingGrounds.java @@ -74,7 +74,10 @@ class NoMoreThanOneCreatureCanAttackEachTurnEffect extends RestrictionEffect { if (!game.getCombat().getAttackers().isEmpty()) { return false; } - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); + if(watcher == null){ + return false; + } Set attackedThisTurnCreatures = watcher.getAttackedThisTurnCreatures(); return attackedThisTurnCreatures.isEmpty() || (attackedThisTurnCreatures.size() == 1 && attackedThisTurnCreatures.contains(new MageObjectReference(attacker, game))); @@ -108,7 +111,10 @@ class NoMoreThanOneCreatureCanBlockEachTurnEffect extends RestrictionEffect { if (!game.getCombat().getBlockers().isEmpty()) { return false; } - BlockedThisTurnWatcher watcher = (BlockedThisTurnWatcher) game.getState().getWatchers().get(BlockedThisTurnWatcher.class.getSimpleName()); + BlockedThisTurnWatcher watcher = game.getState().getWatcher(BlockedThisTurnWatcher.class); + if(watcher == null){ + return false; + } Set blockedThisTurnCreatures = watcher.getBlockedThisTurnCreatures(); MageObjectReference blockerReference = new MageObjectReference(blocker.getId(), blocker.getZoneChangeCounter(game), game); return blockedThisTurnCreatures.isEmpty() diff --git a/Mage.Sets/src/mage/cards/d/DuneDiviner.java b/Mage.Sets/src/mage/cards/d/DuneDiviner.java index 72e74cd8e1d..55a9939923c 100644 --- a/Mage.Sets/src/mage/cards/d/DuneDiviner.java +++ b/Mage.Sets/src/mage/cards/d/DuneDiviner.java @@ -29,7 +29,7 @@ public final class DuneDiviner extends CardImpl { static { filter.add(new SubtypePredicate(SubType.DESERT)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public DuneDiviner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DunesOfTheDead.java b/Mage.Sets/src/mage/cards/d/DunesOfTheDead.java index 26117bd3dfc..51aa92f4616 100644 --- a/Mage.Sets/src/mage/cards/d/DunesOfTheDead.java +++ b/Mage.Sets/src/mage/cards/d/DunesOfTheDead.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.mana.ColorlessManaAbility; @@ -11,21 +9,23 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.ZombieToken; +import java.util.UUID; + /** - * * @author ciaccona007 */ public final class DunesOfTheDead extends CardImpl { public DunesOfTheDead(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - + this.subtype.add(SubType.DESERT); // {T}: Add {C}. addAbility(new ColorlessManaAbility()); + // When Dunes of the Dead is put into a graveyard from the battlefield, create a 2/2 black Zombie creature token. - this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 1), false)); + this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 1))); } public DunesOfTheDead(final DunesOfTheDead card) { diff --git a/Mage.Sets/src/mage/cards/d/Duplicant.java b/Mage.Sets/src/mage/cards/d/Duplicant.java index 4abfea60c3f..0915c8c8da3 100644 --- a/Mage.Sets/src/mage/cards/d/Duplicant.java +++ b/Mage.Sets/src/mage/cards/d/Duplicant.java @@ -1,8 +1,5 @@ - package mage.cards.d; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -22,8 +19,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; +import java.util.UUID; + /** - * * @author Plopman */ public final class Duplicant extends CardImpl { @@ -31,7 +30,7 @@ public final class Duplicant extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public Duplicant(UUID ownerId, CardSetInfo setInfo) { @@ -117,6 +116,9 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { if (permanent != null) { if (!permanent.getImprinted().isEmpty()) { List imprinted = permanent.getImprinted(); + if (imprinted == null || imprinted.isEmpty()) { + return false; + } Card card = game.getCard(imprinted.get(imprinted.size() - 1)); if (card != null && card.isCreature()) { switch (layer) { @@ -134,7 +136,6 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { } } return true; - } } diff --git a/Mage.Sets/src/mage/cards/d/DuskDawn.java b/Mage.Sets/src/mage/cards/d/DuskDawn.java index 0a5469bcd40..567d818d68d 100644 --- a/Mage.Sets/src/mage/cards/d/DuskDawn.java +++ b/Mage.Sets/src/mage/cards/d/DuskDawn.java @@ -43,7 +43,7 @@ public final class DuskDawn extends SplitCard { // Dawn // Return all creature cards with power less than or equal to 2 from your graveyard to your hand. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addEffect(new DawnEffect()); } diff --git a/Mage.Sets/src/mage/cards/d/DuskLegionZealot.java b/Mage.Sets/src/mage/cards/d/DuskLegionZealot.java index ff374e32e4c..a80dddca0d5 100644 --- a/Mage.Sets/src/mage/cards/d/DuskLegionZealot.java +++ b/Mage.Sets/src/mage/cards/d/DuskLegionZealot.java @@ -1,24 +1,24 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author JayDi85 */ -public final class DuskLegionZealot extends CardImpl { +public final class DuskLegionZealot extends CardImpl { - public DuskLegionZealot (UUID ownerId, CardSetInfo setInfo) { + public DuskLegionZealot(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.VAMPIRE); @@ -27,21 +27,19 @@ public final class DuskLegionZealot extends CardImpl { this.toughness = new MageInt(1); // When Dusk Legion Zealot enters the battlefield, you draw a card and you lose 1 life. - Effect drawEffect = new DrawCardSourceControllerEffect(1); - drawEffect.setText("you draw a card"); + Effect drawEffect = new DrawCardSourceControllerEffect(1, "you"); Ability ability = new EntersBattlefieldTriggeredAbility(drawEffect); Effect lifeEffect = new LoseLifeSourceControllerEffect(1); - lifeEffect.setText("and you lose 1 life"); - ability.addEffect(lifeEffect); + ability.addEffect(lifeEffect.concatBy("and")); this.addAbility(ability); } - public DuskLegionZealot (final DuskLegionZealot card) { + public DuskLegionZealot(final DuskLegionZealot card) { super(card); } @Override - public DuskLegionZealot copy() { - return new DuskLegionZealot (this); + public DuskLegionZealot copy() { + return new DuskLegionZealot(this); } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java b/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java index 17462b8f9dc..77a3726456f 100644 --- a/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java +++ b/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java @@ -28,7 +28,7 @@ public final class DuskborneSkymarcher extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.VAMPIRE, "attacking Vampire"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public DuskborneSkymarcher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DustStalker.java b/Mage.Sets/src/mage/cards/d/DustStalker.java index c1d604b5888..4a156722407 100644 --- a/Mage.Sets/src/mage/cards/d/DustStalker.java +++ b/Mage.Sets/src/mage/cards/d/DustStalker.java @@ -28,8 +28,8 @@ public final class DustStalker extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("if you control no other colorless creatures"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public DustStalker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DwarvenBloodboiler.java b/Mage.Sets/src/mage/cards/d/DwarvenBloodboiler.java index 8d143825c2c..1638cf682b4 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenBloodboiler.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenBloodboiler.java @@ -29,7 +29,7 @@ public final class DwarvenBloodboiler extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("an untapped Dwarf you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.DWARF)); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenHold.java b/Mage.Sets/src/mage/cards/d/DwarvenHold.java index bfc1a8c95c1..5c8e97d9e2f 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenHold.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenHold.java @@ -44,7 +44,7 @@ public final class DwarvenHold extends CardImpl { // {tap}, Remove any number of storage counters from Dwarven Hold: Add {R} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.RedMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {R} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/d/DwarvenLandslide.java b/Mage.Sets/src/mage/cards/d/DwarvenLandslide.java index 1b7f92f62a9..056980f8959 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenLandslide.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenLandslide.java @@ -1,9 +1,7 @@ - package mage.cards.d; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; @@ -19,6 +17,7 @@ import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -27,34 +26,38 @@ import mage.target.common.TargetLandPermanent; public final class DwarvenLandslide extends CardImpl { public DwarvenLandslide(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Kicker-{2}{R}, Sacrifice a land. Costs kickerCosts = new CostsImpl<>(); kickerCosts.add(new ManaCostsImpl<>("{2}{R}")); kickerCosts.add(new SacrificeTargetCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land")))); this.addAbility(new KickerAbility(kickerCosts)); + // Destroy target land. If Dwarven Landslide was kicked, destroy another target land. getSpellAbility().addEffect(new DestroyTargetEffect("Destroy target land. if this spell was kicked, destroy another target land")); getSpellAbility().addTarget(new TargetLandPermanent()); + getSpellAbility().setTargetAdjuster(DwarvenLandslideAdjuster.instance); } public DwarvenLandslide(final DwarvenLandslide card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - if (KickedCondition.instance.apply(game, ability)) { - ability.getTargets().clear(); - getSpellAbility().addTarget(new TargetLandPermanent(2)); - } - } - } - @Override public DwarvenLandslide copy() { return new DwarvenLandslide(this); } } + +enum DwarvenLandslideAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + if (KickedCondition.instance.apply(game, ability)) { + ability.getTargets().clear(); + ability.addTarget(new TargetLandPermanent(2)); + } + } +} diff --git a/Mage.Sets/src/mage/cards/d/DwynenGiltLeafDaen.java b/Mage.Sets/src/mage/cards/d/DwynenGiltLeafDaen.java index 73a10a2f16e..fb4ee16fc5b 100644 --- a/Mage.Sets/src/mage/cards/d/DwynenGiltLeafDaen.java +++ b/Mage.Sets/src/mage/cards/d/DwynenGiltLeafDaen.java @@ -24,7 +24,7 @@ public final class DwynenGiltLeafDaen extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.ELF, "attacking Elf you control"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public DwynenGiltLeafDaen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/d/DwynensElite.java b/Mage.Sets/src/mage/cards/d/DwynensElite.java index 394a7071b5c..4e9e11890b2 100644 --- a/Mage.Sets/src/mage/cards/d/DwynensElite.java +++ b/Mage.Sets/src/mage/cards/d/DwynensElite.java @@ -27,7 +27,7 @@ public final class DwynensElite extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Elf"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.ELF)); } diff --git a/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java b/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java index 20259b9d8b6..37c2081f546 100644 --- a/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java +++ b/Mage.Sets/src/mage/cards/e/EarlOfSquirrel.java @@ -33,7 +33,7 @@ public final class EarlOfSquirrel extends CardImpl { static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); filter2.add(new SubtypePredicate(SubType.SQUIRREL)); } diff --git a/Mage.Sets/src/mage/cards/e/Earthcraft.java b/Mage.Sets/src/mage/cards/e/Earthcraft.java index c89ff398bc7..9db0d2926b1 100644 --- a/Mage.Sets/src/mage/cards/e/Earthcraft.java +++ b/Mage.Sets/src/mage/cards/e/Earthcraft.java @@ -29,7 +29,7 @@ public final class Earthcraft extends CardImpl { private static final FilterControlledPermanent filterLand = new FilterControlledPermanent("basic land"); static { - filterCreature.add(Predicates.not(new TappedPredicate())); + filterCreature.add(Predicates.not(TappedPredicate.instance)); filterLand.add(new CardTypePredicate(CardType.LAND)); filterLand.add(new SupertypePredicate(SuperType.BASIC)); } diff --git a/Mage.Sets/src/mage/cards/e/Earthlore.java b/Mage.Sets/src/mage/cards/e/Earthlore.java index 78808360e16..2a511fba605 100644 --- a/Mage.Sets/src/mage/cards/e/Earthlore.java +++ b/Mage.Sets/src/mage/cards/e/Earthlore.java @@ -43,7 +43,7 @@ public final class Earthlore extends CardImpl { private static final FilterPermanent filterUntapped = new FilterPermanent("enchanted land is untapped"); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } public Earthlore(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/Earthquake.java b/Mage.Sets/src/mage/cards/e/Earthquake.java index d653f3182d3..da844b150df 100644 --- a/Mage.Sets/src/mage/cards/e/Earthquake.java +++ b/Mage.Sets/src/mage/cards/e/Earthquake.java @@ -29,7 +29,7 @@ public final class Earthquake extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}"); // Hurricane deals X damage to each creature with flying and each player. - this.getSpellAbility().addEffect(new DamageEverythingEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageEverythingEffect(ManacostVariableValue.instance, filter)); } public Earthquake(final Earthquake card) { diff --git a/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java b/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java index 0d399a8ab4e..d00de4b0c05 100644 --- a/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java +++ b/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java @@ -1,38 +1,38 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.abilities.keyword.EternalizeAbility; import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.ComparisonType; import mage.constants.Duration; -import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class EarthshakerKhenra extends CardImpl { - private final UUID originalId; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power less than or equal to {this}'s power"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power less than or equal to this creature's power"); + + static { + filter.add(EarthshakerKhenraPredicate.instance); + } public EarthshakerKhenra(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -46,32 +46,20 @@ public final class EarthshakerKhenra extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Earthshaker Khenra enters the battlefield, target creature with power less than or equal to Earthshaker Khenra's power can't block this turn. - Ability ability = new EntersBattlefieldTriggeredAbility(new EarthshakerKhenraEffect()); + Ability ability = new EntersBattlefieldTriggeredAbility( + new CantBlockTargetEffect(Duration.EndOfTurn) + .setText("target creature with power less than or equal " + + "to {this}'s power can't block this turn") + ); ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); - originalId = ability.getOriginalId(); // Eternalize {4}{R}{R} this.addAbility(new EternalizeAbility(new ManaCostsImpl("{4}{R}{R}"), this)); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null) { - FilterCreaturePermanent targetFilter = new FilterCreaturePermanent("creature with power less than or equal to " + getLogName() + "'s power"); - targetFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, sourcePermanent.getPower().getValue() + 1)); - ability.getTargets().clear(); - ability.getTargets().add(new TargetCreaturePermanent(targetFilter)); - } - } } public EarthshakerKhenra(final EarthshakerKhenra card) { super(card); - this.originalId = card.originalId; } @Override @@ -80,39 +68,12 @@ public final class EarthshakerKhenra extends CardImpl { } } -class EarthshakerKhenraEffect extends OneShotEffect { - - public EarthshakerKhenraEffect() { - super(Outcome.UnboostCreature); - this.staticText = "target creature with power less than or equal to {this}'s power can't block this turn"; - } - - public EarthshakerKhenraEffect(final EarthshakerKhenraEffect effect) { - super(effect); - } +enum EarthshakerKhenraPredicate implements ObjectSourcePlayerPredicate> { + instance; @Override - public EarthshakerKhenraEffect copy() { - return new EarthshakerKhenraEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (sourceObject != null) { - Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); - /* - 27.06.2017 The target creature's power is checked when you target it with Earthshaker Khenra's ability - and when that ability resolves. Once the ability resolves, if the creature's power increases - or Earthshaker Khenra's power decreases, the target creature will still be unable to block. - */ - if (targetCreature != null && targetCreature.getPower().getValue() <= sourceObject.getPower().getValue()) { - ContinuousEffect effect = new CantBlockTargetEffect(Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(targetCreature, game)); - game.addEffect(effect, source); - } - return true; - } - return false; + public boolean apply(ObjectSourcePlayer input, Game game) { + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(input.getSourceId()); + return sourcePermanent != null && input.getObject().getPower().getValue() <= sourcePermanent.getPower().getValue(); } } diff --git a/Mage.Sets/src/mage/cards/e/EaterOfHope.java b/Mage.Sets/src/mage/cards/e/EaterOfHope.java index 7cd660c058c..0524a4b541e 100644 --- a/Mage.Sets/src/mage/cards/e/EaterOfHope.java +++ b/Mage.Sets/src/mage/cards/e/EaterOfHope.java @@ -30,7 +30,7 @@ public final class EaterOfHope extends CardImpl { private static final FilterControlledCreaturePermanent destroyFilter = new FilterControlledCreaturePermanent("two other creatures"); static { - destroyFilter.add(new AnotherPredicate()); + destroyFilter.add(AnotherPredicate.instance); } public EaterOfHope(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EbonyHorse.java b/Mage.Sets/src/mage/cards/e/EbonyHorse.java index f5bcac6c36e..610dd3291cf 100644 --- a/Mage.Sets/src/mage/cards/e/EbonyHorse.java +++ b/Mage.Sets/src/mage/cards/e/EbonyHorse.java @@ -30,7 +30,7 @@ public final class EbonyHorse extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature you control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public EbonyHorse(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EddytrailHawk.java b/Mage.Sets/src/mage/cards/e/EddytrailHawk.java index 2c312f1ba26..e7bf591e8c8 100644 --- a/Mage.Sets/src/mage/cards/e/EddytrailHawk.java +++ b/Mage.Sets/src/mage/cards/e/EddytrailHawk.java @@ -29,7 +29,7 @@ public final class EddytrailHawk extends CardImpl { private final static FilterAttackingCreature filter = new FilterAttackingCreature(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public EddytrailHawk(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EdricSpymasterOfTrest.java b/Mage.Sets/src/mage/cards/e/EdricSpymasterOfTrest.java index e43a5f513c2..57e194e74fc 100644 --- a/Mage.Sets/src/mage/cards/e/EdricSpymasterOfTrest.java +++ b/Mage.Sets/src/mage/cards/e/EdricSpymasterOfTrest.java @@ -69,7 +69,7 @@ class EdricSpymasterOfTrestTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage() && - game.getOpponents(this.controllerId).contains(((DamagedPlayerEvent) event).getPlayerId())) { + game.getOpponents(this.controllerId).contains(event.getPlayerId())) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(game.getPermanent(event.getSourceId()).getControllerId())); } diff --git a/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java b/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java index a0d9d1f5bae..0f71859daea 100644 --- a/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java +++ b/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java @@ -61,7 +61,7 @@ class EfreetWeaponmasterAbility extends TriggeredAbilityImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public EfreetWeaponmasterAbility() { diff --git a/Mage.Sets/src/mage/cards/e/EldraziAggressor.java b/Mage.Sets/src/mage/cards/e/EldraziAggressor.java index 142cfa2b255..6538c6ac1de 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziAggressor.java +++ b/Mage.Sets/src/mage/cards/e/EldraziAggressor.java @@ -29,8 +29,8 @@ public final class EldraziAggressor extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another colorless creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public EldraziAggressor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java b/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java index c5dc494d1f1..8618e6afb6b 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java +++ b/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java @@ -28,7 +28,7 @@ public final class EldraziDisplacer extends CardImpl { private static final FilterCreaturePermanent FILTER = new FilterCreaturePermanent("another target creature"); static { - FILTER.add(new AnotherPredicate()); + FILTER.add(AnotherPredicate.instance); } public EldraziDisplacer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EldraziMimic.java b/Mage.Sets/src/mage/cards/e/EldraziMimic.java index d90c7e78385..657a7a8565c 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziMimic.java +++ b/Mage.Sets/src/mage/cards/e/EldraziMimic.java @@ -28,8 +28,8 @@ public final class EldraziMimic extends CardImpl { private static final FilterCreaturePermanent FILTER = new FilterCreaturePermanent("another colorless creature"); static { - FILTER.add(new AnotherPredicate()); - FILTER.add(new ColorlessPredicate()); + FILTER.add(AnotherPredicate.instance); + FILTER.add(ColorlessPredicate.instance); } public EldraziMimic(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/Electrodominance.java b/Mage.Sets/src/mage/cards/e/Electrodominance.java new file mode 100644 index 00000000000..4b9342fcaac --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/Electrodominance.java @@ -0,0 +1,35 @@ +package mage.cards.e; + +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.cost.CastWithoutPayingManaCostEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetAnyTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Electrodominance extends CardImpl { + + public Electrodominance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}{R}"); + + // Electrodominance deals X damage to any target. You may cast a card with converted mana cost X or less from your hand without paying its mana cost. + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); + this.getSpellAbility().addTarget(new TargetAnyTarget()); + this.getSpellAbility().addEffect(new CastWithoutPayingManaCostEffect(ManacostVariableValue.instance)); + } + + private Electrodominance(final Electrodominance card) { + super(card); + } + + @Override + public Electrodominance copy() { + return new Electrodominance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EliminateTheCompetition.java b/Mage.Sets/src/mage/cards/e/EliminateTheCompetition.java index 9b6b3c855a4..34910dc22e6 100644 --- a/Mage.Sets/src/mage/cards/e/EliminateTheCompetition.java +++ b/Mage.Sets/src/mage/cards/e/EliminateTheCompetition.java @@ -1,4 +1,3 @@ - package mage.cards.e; import java.util.UUID; @@ -9,11 +8,11 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; import mage.constants.CardType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -22,7 +21,7 @@ import mage.target.common.TargetCreaturePermanent; public final class EliminateTheCompetition extends CardImpl { public EliminateTheCompetition(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}"); // As an additional cost to cast Eliminate the Competition, sacrifice X creatures. this.getSpellAbility().addCost(new SacrificeXTargetCost(new FilterControlledCreaturePermanent("creatures"), true)); @@ -32,23 +31,26 @@ public final class EliminateTheCompetition extends CardImpl { effect.setText("Destroy X target creatures"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().setTargetAdjuster(EliminateTheCompetitionAdjuster.instance); } public EliminateTheCompetition(final EliminateTheCompetition card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getAbilityType() == AbilityType.SPELL) { - ability.getTargets().clear(); - int sac = new GetXValue().calculate(game, ability, null); - ability.addTarget(new TargetCreaturePermanent(sac, sac)); - } - } - @Override public EliminateTheCompetition copy() { return new EliminateTheCompetition(this); } } + +enum EliminateTheCompetitionAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int sac = GetXValue.instance.calculate(game, ability, null); + ability.addTarget(new TargetCreaturePermanent(sac, sac)); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EliteArcanist.java b/Mage.Sets/src/mage/cards/e/EliteArcanist.java index b44d6aef399..9ca13d7fa50 100644 --- a/Mage.Sets/src/mage/cards/e/EliteArcanist.java +++ b/Mage.Sets/src/mage/cards/e/EliteArcanist.java @@ -1,12 +1,12 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -25,8 +25,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class EliteArcanist extends CardImpl { @@ -45,6 +46,7 @@ public final class EliteArcanist extends CardImpl { // {X}, {T}: Copy the exiled card. You may cast the copy without paying its mana cost. X is the converted mana cost of the exiled card. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EliteArcanistCopyEffect(), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); + ability.setCostAdjuster(EliteArcanistAdjuster.instance); this.addAbility(ability); } @@ -52,29 +54,35 @@ public final class EliteArcanist extends CardImpl { super(card); } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null && sourcePermanent.getImprinted() != null && !sourcePermanent.getImprinted().isEmpty()) { - Card imprintedInstant = game.getCard(sourcePermanent.getImprinted().get(0)); - if (imprintedInstant != null) { - int cmc = imprintedInstant.getConvertedManaCost(); - if (cmc > 0) { - ability.getManaCostsToPay().clear(); - ability.getManaCostsToPay().add(new GenericManaCost(cmc)); - } - } - } - } - } - @Override public EliteArcanist copy() { return new EliteArcanist(this); } } +enum EliteArcanistAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); + if (sourcePermanent == null + || sourcePermanent.getImprinted() == null + || sourcePermanent.getImprinted().isEmpty()) { + return; + } + Card imprintedInstant = game.getCard(sourcePermanent.getImprinted().get(0)); + if (imprintedInstant == null) { + return; + } + int cmc = imprintedInstant.getConvertedManaCost(); + if (cmc > 0) { + ability.getManaCostsToPay().clear(); + ability.getManaCostsToPay().add(new GenericManaCost(cmc)); + } + } +} + class EliteArcanistImprintEffect extends OneShotEffect { private static final FilterCard filter = new FilterCard("instant card from your hand"); diff --git a/Mage.Sets/src/mage/cards/e/EliteArrester.java b/Mage.Sets/src/mage/cards/e/EliteArrester.java new file mode 100644 index 00000000000..570589d44e1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EliteArrester.java @@ -0,0 +1,47 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EliteArrester extends CardImpl { + + public EliteArrester(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // {1}{U}, {T}: Tap target creature. + Ability ability = new SimpleActivatedAbility( + new TapTargetEffect(), new ManaCostsImpl("{1}{U}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private EliteArrester(final EliteArrester card) { + super(card); + } + + @Override + public EliteArrester copy() { + return new EliteArrester(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EliteScaleguard.java b/Mage.Sets/src/mage/cards/e/EliteScaleguard.java index 332e040f55c..b2c5911d85b 100644 --- a/Mage.Sets/src/mage/cards/e/EliteScaleguard.java +++ b/Mage.Sets/src/mage/cards/e/EliteScaleguard.java @@ -1,12 +1,10 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.keyword.BolsterEffect; import mage.cards.CardImpl; @@ -16,25 +14,29 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.CounterPredicate; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author emerald000 */ public final class EliteScaleguard extends CardImpl { - + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control with a +1/+1 counter on it"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature defending player controls"); + static { filter.add(new CounterPredicate(CounterType.P1P1)); + filter2.add(DefendingPlayerControlsPredicate.instance); } public EliteScaleguard(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); @@ -42,32 +44,16 @@ public final class EliteScaleguard extends CardImpl { // When Elite Scaleguard enters the battlefield, bolster 2. this.addAbility(new EntersBattlefieldTriggeredAbility(new BolsterEffect(2))); - + // Whenever a creature you control with a +1/+1 counter on it attacks, tap target creature defending player controls. Ability ability = new AttacksCreatureYouControlTriggeredAbility(new EliteScaleguardTapEffect(), false, filter, true); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + ability.addTarget(new TargetCreaturePermanent(filter2)); this.addAbility(ability); } public EliteScaleguard(final EliteScaleguard card) { super(card); } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof AttacksCreatureYouControlTriggeredAbility) { - FilterCreaturePermanent filterDefender = new FilterCreaturePermanent("creature defending player controls"); - for (Effect effect : ability.getEffects()) { - if (effect instanceof EliteScaleguardTapEffect) { - filterDefender.add(new ControllerIdPredicate(game.getCombat().getDefendingPlayerId(effect.getTargetPointer().getFirst(game, ability), game))); - break; - } - } - ability.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filterDefender); - ability.addTarget(target); - } - } @Override public EliteScaleguard copy() { @@ -76,20 +62,20 @@ public final class EliteScaleguard extends CardImpl { } class EliteScaleguardTapEffect extends TapTargetEffect { - + EliteScaleguardTapEffect() { super(); } - + EliteScaleguardTapEffect(final EliteScaleguardTapEffect effect) { super(effect); } - + @Override public EliteScaleguardTapEffect copy() { return new EliteScaleguardTapEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/e/ElvishScout.java b/Mage.Sets/src/mage/cards/e/ElvishScout.java index fb03e934950..01a924b85e7 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishScout.java +++ b/Mage.Sets/src/mage/cards/e/ElvishScout.java @@ -30,7 +30,7 @@ public final class ElvishScout extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature you control"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public ElvishScout(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/ElvishVanguard.java b/Mage.Sets/src/mage/cards/e/ElvishVanguard.java index a31344e7368..7591f622131 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishVanguard.java +++ b/Mage.Sets/src/mage/cards/e/ElvishVanguard.java @@ -24,7 +24,7 @@ public final class ElvishVanguard extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ELF)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ElvishVanguard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EmbalmersTools.java b/Mage.Sets/src/mage/cards/e/EmbalmersTools.java index c81514acd8f..4ca900ff9f9 100644 --- a/Mage.Sets/src/mage/cards/e/EmbalmersTools.java +++ b/Mage.Sets/src/mage/cards/e/EmbalmersTools.java @@ -35,7 +35,7 @@ public final class EmbalmersTools extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Zombie you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.ZOMBIE)); } diff --git a/Mage.Sets/src/mage/cards/e/EmberFistZubera.java b/Mage.Sets/src/mage/cards/e/EmberFistZubera.java index 0a79c71c41e..acfe8a486ca 100644 --- a/Mage.Sets/src/mage/cards/e/EmberFistZubera.java +++ b/Mage.Sets/src/mage/cards/e/EmberFistZubera.java @@ -28,7 +28,7 @@ public final class EmberFistZubera extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(new ZuberasDiedDynamicValue())); + Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(ZuberasDiedDynamicValue.instance)); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability, new ZuberasDiedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/e/EmergencyPowers.java b/Mage.Sets/src/mage/cards/e/EmergencyPowers.java index c206d8450f5..e2495e3607e 100644 --- a/Mage.Sets/src/mage/cards/e/EmergencyPowers.java +++ b/Mage.Sets/src/mage/cards/e/EmergencyPowers.java @@ -1,7 +1,8 @@ package mage.cards.e; -import mage.abilities.condition.common.MyMainPhaseCondition; -import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.Ability; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardAllEffect; import mage.abilities.effects.common.ExileSpellEffect; import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; @@ -10,8 +11,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; +import mage.constants.Outcome; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; import java.util.UUID; @@ -20,30 +23,15 @@ import java.util.UUID; */ public final class EmergencyPowers extends CardImpl { - public static final FilterPermanentCard filter - = new FilterPermanentCard("a permanent card with converted mana cost 7 or less"); - - static { - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 8)); - } - public EmergencyPowers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{W}{U}"); // Each player shuffles their hand and graveyard into their library, then draws seven cards. Exile Emergency Powers. this.getSpellAbility().addEffect(new ShuffleHandGraveyardAllEffect()); this.getSpellAbility().addEffect(new DrawCardAllEffect(7).setText(", then draws seven cards")); - this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); // Addendum — If you cast this spell during your main phase, you may put a permanent card with converted mana cost 7 or less from your hand onto the battlefield. - this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new PutCardFromHandOntoBattlefieldEffect(filter), - MyMainPhaseCondition.instance, - "
Addendum — " + - "If you cast this spell during your main phase, " + - "you may put a permanent card with converted mana cost 7 or less " + - "from your hand onto the battlefield." - )); + this.getSpellAbility().addEffect(new EmergencyPowersEffect()); } private EmergencyPowers(final EmergencyPowers card) { @@ -55,4 +43,37 @@ public final class EmergencyPowers extends CardImpl { return new EmergencyPowers(this); } } + +class EmergencyPowersEffect extends OneShotEffect { + + public static final FilterPermanentCard filter + = new FilterPermanentCard("a permanent card with converted mana cost 7 or less"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 8)); + } + + EmergencyPowersEffect() { + super(Outcome.Benefit); + staticText = "Exile {this}.
Addendum — If you cast this spell during your main phase, " + + "you may put a permanent card with converted mana cost 7 or less from your hand onto the battlefield."; + } + + private EmergencyPowersEffect(final EmergencyPowersEffect effect) { + super(effect); + } + + @Override + public EmergencyPowersEffect copy() { + return new EmergencyPowersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (AddendumCondition.instance.apply(game, source)) { + new PutCardFromHandOntoBattlefieldEffect(filter).apply(game, source); + } + return ExileSpellEffect.getInstance().apply(game, source); + } +} // I am the senate! diff --git a/Mage.Sets/src/mage/cards/e/EmmaraTandris.java b/Mage.Sets/src/mage/cards/e/EmmaraTandris.java index e51f33d7129..11d0794557e 100644 --- a/Mage.Sets/src/mage/cards/e/EmmaraTandris.java +++ b/Mage.Sets/src/mage/cards/e/EmmaraTandris.java @@ -21,7 +21,7 @@ public final class EmmaraTandris extends CardImpl { private static final FilterCreatureOrPlayer filter = new FilterCreatureOrPlayer("creature tokens you control"); static { - filter.getCreatureFilter().add(new TokenPredicate()); + filter.getCreatureFilter().add(TokenPredicate.instance); filter.getCreatureFilter().add(new ControllerPredicate(TargetController.YOU)); filter.getPlayerFilter().add(new PlayerIdPredicate(UUID.randomUUID())); } diff --git a/Mage.Sets/src/mage/cards/e/EmptyThePits.java b/Mage.Sets/src/mage/cards/e/EmptyThePits.java index f2bfbd27fb1..fb2337fd5e6 100644 --- a/Mage.Sets/src/mage/cards/e/EmptyThePits.java +++ b/Mage.Sets/src/mage/cards/e/EmptyThePits.java @@ -24,7 +24,7 @@ public final class EmptyThePits extends CardImpl { this.addAbility(new DelveAbility()); // create X 2/2 black Zombie creature tokens tapped. - this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken(), new ManacostVariableValue(), true, false)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken(), ManacostVariableValue.instance, true, false)); } public EmptyThePits(final EmptyThePits card) { diff --git a/Mage.Sets/src/mage/cards/e/EmpyrialArmor.java b/Mage.Sets/src/mage/cards/e/EmpyrialArmor.java index 9ae1b61d026..de4b1ffa237 100644 --- a/Mage.Sets/src/mage/cards/e/EmpyrialArmor.java +++ b/Mage.Sets/src/mage/cards/e/EmpyrialArmor.java @@ -38,7 +38,7 @@ public final class EmpyrialArmor extends CardImpl { this.addAbility(ability); // Enchanted creature gets +1/+1 for each card in your hand. - DynamicValue xValue = new CardsInControllerHandCount(); + DynamicValue xValue = CardsInControllerHandCount.instance; this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(xValue, xValue, Duration.WhileOnBattlefield))); } diff --git a/Mage.Sets/src/mage/cards/e/EmpyrialPlate.java b/Mage.Sets/src/mage/cards/e/EmpyrialPlate.java index d43fe32b16d..4116555856a 100644 --- a/Mage.Sets/src/mage/cards/e/EmpyrialPlate.java +++ b/Mage.Sets/src/mage/cards/e/EmpyrialPlate.java @@ -25,7 +25,7 @@ public final class EmpyrialPlate extends CardImpl { this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +1/+1 for each card in your hand. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new CardsInControllerHandCount(), new CardsInControllerHandCount()))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(CardsInControllerHandCount.instance, CardsInControllerHandCount.instance))); // Equip {2} this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); diff --git a/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java b/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java index 9d4c6f1fdb4..b08775abcbc 100644 --- a/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java +++ b/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java @@ -28,7 +28,7 @@ public final class EmrakulTheAeonsTorn extends CardImpl { private static final FilterSpell filter = new FilterSpell("colored spells"); static { - filter.add(Predicates.not(new ColorlessPredicate())); + filter.add(Predicates.not(ColorlessPredicate.instance)); } public EmrakulTheAeonsTorn(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EmrakulsEvangel.java b/Mage.Sets/src/mage/cards/e/EmrakulsEvangel.java index 15c20aff649..33faa4a9660 100644 --- a/Mage.Sets/src/mage/cards/e/EmrakulsEvangel.java +++ b/Mage.Sets/src/mage/cards/e/EmrakulsEvangel.java @@ -61,7 +61,7 @@ class EmrakulsEvangelCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("non-Eldrazi creatures you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.not(new SubtypePredicate(SubType.ELDRAZI))); } diff --git a/Mage.Sets/src/mage/cards/e/EnclaveElite.java b/Mage.Sets/src/mage/cards/e/EnclaveElite.java index 58f5df9c835..de61d1239d1 100644 --- a/Mage.Sets/src/mage/cards/e/EnclaveElite.java +++ b/Mage.Sets/src/mage/cards/e/EnclaveElite.java @@ -36,7 +36,7 @@ public final class EnclaveElite extends CardImpl { // Enclave Elite enters the battlefield with a +1/+1 counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true), + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true), "with a +1/+1 counter on it for each time it was kicked")); } diff --git a/Mage.Sets/src/mage/cards/e/EndRazeForerunners.java b/Mage.Sets/src/mage/cards/e/EndRazeForerunners.java new file mode 100644 index 00000000000..f189c0b9ab3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EndRazeForerunners.java @@ -0,0 +1,65 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EndRazeForerunners extends CardImpl { + + public EndRazeForerunners(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}{G}"); + + this.subtype.add(SubType.BOAR); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // When End-Raze Forerunners enters the battlefield, other creatures you control get +2/+2 and gain vigilance and trample until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostControlledEffect( + 2, 2, Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, true + ).setText("other creatures you control get +2/+2")); + ability.addEffect(new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, true + ).setText("and gain vigilance")); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, true + ).setText("and trample until end of turn")); + this.addAbility(ability); + } + + private EndRazeForerunners(final EndRazeForerunners card) { + super(card); + } + + @Override + public EndRazeForerunners copy() { + return new EndRazeForerunners(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EndlessSwarm.java b/Mage.Sets/src/mage/cards/e/EndlessSwarm.java index f3eac93fad2..a33c4084634 100644 --- a/Mage.Sets/src/mage/cards/e/EndlessSwarm.java +++ b/Mage.Sets/src/mage/cards/e/EndlessSwarm.java @@ -22,7 +22,7 @@ public final class EndlessSwarm extends CardImpl { // Create a 1/1 green Snake creature token for each card in your hand. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SnakeToken(), new CardsInControllerHandCount())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SnakeToken(), CardsInControllerHandCount.instance)); // Epic this.getSpellAbility().addEffect(new EpicEffect()); diff --git a/Mage.Sets/src/mage/cards/e/EnemyOfTheGuildpact.java b/Mage.Sets/src/mage/cards/e/EnemyOfTheGuildpact.java index eb2fc372c1a..ee59ff16cb6 100644 --- a/Mage.Sets/src/mage/cards/e/EnemyOfTheGuildpact.java +++ b/Mage.Sets/src/mage/cards/e/EnemyOfTheGuildpact.java @@ -20,7 +20,7 @@ public final class EnemyOfTheGuildpact extends CardImpl { private static final FilterObject filter = new FilterObject("multicolored"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public EnemyOfTheGuildpact(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EnergyBolt.java b/Mage.Sets/src/mage/cards/e/EnergyBolt.java index ef5fe784bbc..216c983a537 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyBolt.java +++ b/Mage.Sets/src/mage/cards/e/EnergyBolt.java @@ -22,10 +22,10 @@ public final class EnergyBolt extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}{W}"); // Choose one - Energy Bolt deals X damage to target player; or target player gains X life. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); Mode mode = new Mode(); - mode.addEffect(new GainLifeTargetEffect(new ManacostVariableValue())); + mode.addEffect(new GainLifeTargetEffect(ManacostVariableValue.instance)); mode.addTarget(new TargetPlayer()); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/e/EnergyTap.java b/Mage.Sets/src/mage/cards/e/EnergyTap.java index ef1aaadbf82..0b8e57fcd82 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyTap.java +++ b/Mage.Sets/src/mage/cards/e/EnergyTap.java @@ -25,7 +25,7 @@ public final class EnergyTap extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public EnergyTap(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/Enrage.java b/Mage.Sets/src/mage/cards/e/Enrage.java index 83c2876c0ca..9d83d33659c 100644 --- a/Mage.Sets/src/mage/cards/e/Enrage.java +++ b/Mage.Sets/src/mage/cards/e/Enrage.java @@ -22,7 +22,7 @@ public final class Enrage extends CardImpl { // Target creature gets +X/+0 until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/e/EnragedCeratok.java b/Mage.Sets/src/mage/cards/e/EnragedCeratok.java new file mode 100644 index 00000000000..5098f50a5de --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnragedCeratok.java @@ -0,0 +1,50 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.common.SimpleEvasionAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EnragedCeratok extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creatures with power 2 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public EnragedCeratok(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + + this.subtype.add(SubType.RHINO); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Enraged Ceratok can't be blocked by creatures with power 2 or less. + this.addAbility(new SimpleEvasionAbility( + new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield) + )); + } + + private EnragedCeratok(final EnragedCeratok card) { + super(card); + } + + @Override + public EnragedCeratok copy() { + return new EnragedCeratok(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EnshrinedMemories.java b/Mage.Sets/src/mage/cards/e/EnshrinedMemories.java index 224dcc1d44b..9dbaf7728b2 100644 --- a/Mage.Sets/src/mage/cards/e/EnshrinedMemories.java +++ b/Mage.Sets/src/mage/cards/e/EnshrinedMemories.java @@ -20,7 +20,7 @@ public final class EnshrinedMemories extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{G}"); // Reveal the top X cards of your library. Put all creature cards revealed this way into your hand and the rest on the bottom of your library in any order. - this.getSpellAbility().addEffect(new RevealLibraryPutIntoHandEffect(new ManacostVariableValue(), new FilterCreatureCard(), Zone.LIBRARY, true)); + this.getSpellAbility().addEffect(new RevealLibraryPutIntoHandEffect(ManacostVariableValue.instance, new FilterCreatureCard(), Zone.LIBRARY, true)); } public EnshrinedMemories(final EnshrinedMemories card) { diff --git a/Mage.Sets/src/mage/cards/e/EnslavedHorror.java b/Mage.Sets/src/mage/cards/e/EnslavedHorror.java index 3fbba05fa12..c8362a0ca20 100644 --- a/Mage.Sets/src/mage/cards/e/EnslavedHorror.java +++ b/Mage.Sets/src/mage/cards/e/EnslavedHorror.java @@ -32,7 +32,7 @@ public final class EnslavedHorror extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - // When Enslaved Horror enters the battlefield, each other player may return a creature card from his or her graveyard to the battlefield. + // When Enslaved Horror enters the battlefield, each other player may return a creature card from their graveyard to the battlefield. this.addAbility(new EntersBattlefieldTriggeredAbility(new EnslavedHorrorEffect())); } diff --git a/Mage.Sets/src/mage/cards/e/EntanglingVines.java b/Mage.Sets/src/mage/cards/e/EntanglingVines.java index 808eb3b5605..49bd76d564d 100644 --- a/Mage.Sets/src/mage/cards/e/EntanglingVines.java +++ b/Mage.Sets/src/mage/cards/e/EntanglingVines.java @@ -26,7 +26,7 @@ public final class EntanglingVines extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public EntanglingVines(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EntrancingMelody.java b/Mage.Sets/src/mage/cards/e/EntrancingMelody.java index 4c14d0ee0c7..5fb62884989 100644 --- a/Mage.Sets/src/mage/cards/e/EntrancingMelody.java +++ b/Mage.Sets/src/mage/cards/e/EntrancingMelody.java @@ -1,9 +1,7 @@ package mage.cards.e; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -14,38 +12,45 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class EntrancingMelody extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X"); + public EntrancingMelody(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}{U}"); // Gain control of target creature with converted mana cost X. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with converted mana cost X"))); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().setTargetAdjuster(EntrancingMelodyAdjuster.instance); } public EntrancingMelody(final EntrancingMelody card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.addTarget(new TargetCreaturePermanent(filter)); - } - } - @Override public EntrancingMelody copy() { return new EntrancingMelody(this); } } + +enum EntrancingMelodyAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost " + xValue); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EntrapmentManeuver.java b/Mage.Sets/src/mage/cards/e/EntrapmentManeuver.java index 2853d798b76..846af092c69 100644 --- a/Mage.Sets/src/mage/cards/e/EntrapmentManeuver.java +++ b/Mage.Sets/src/mage/cards/e/EntrapmentManeuver.java @@ -66,7 +66,7 @@ class EntrapmentManeuverSacrificeEffect extends OneShotEffect { return false; } FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); int realCount = game.getBattlefield().countAll(filter, player.getId(), game); if (realCount > 0) { Target target = new TargetControlledPermanent(1, 1, filter, true); diff --git a/Mage.Sets/src/mage/cards/e/EntreatTheAngels.java b/Mage.Sets/src/mage/cards/e/EntreatTheAngels.java index e398ee5b5b1..234618f3517 100644 --- a/Mage.Sets/src/mage/cards/e/EntreatTheAngels.java +++ b/Mage.Sets/src/mage/cards/e/EntreatTheAngels.java @@ -22,7 +22,7 @@ public final class EntreatTheAngels extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{W}{W}{W}"); // Create X 4/4 white Angel creature tokens with flying. - this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), ManacostVariableValue.instance)); // Miracle {X}{W}{W} this.addAbility(new MiracleAbility(this, new ManaCostsImpl("{X}{W}{W}"))); diff --git a/Mage.Sets/src/mage/cards/e/EntreatTheDead.java b/Mage.Sets/src/mage/cards/e/EntreatTheDead.java index 86d76b7b4a5..58b597c89ff 100644 --- a/Mage.Sets/src/mage/cards/e/EntreatTheDead.java +++ b/Mage.Sets/src/mage/cards/e/EntreatTheDead.java @@ -2,7 +2,6 @@ package mage.cards.e; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.MiracleAbility; @@ -14,6 +13,7 @@ import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -27,25 +27,10 @@ public final class EntreatTheDead extends CardImpl { // Return X target creature cards from your graveyard to the battlefield. this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(1, StaticFilters.FILTER_CARD_CREATURE)); + this.getSpellAbility().setTargetAdjuster(EntreatTheDeadAdjuster.instance); // Miracle {X}{B}{B} this.addAbility(new MiracleAbility(this, new ManaCostsImpl("{X}{B}{B}"))); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - String filterName = xValue - + (xValue != 1 ? " creature cards" : "creature card") - + " from your graveyard"; - Target target = new TargetCardInYourGraveyard( - xValue, new FilterCreatureCard(filterName) - ); - ability.addTarget(target); - } } public EntreatTheDead(final EntreatTheDead card) { @@ -57,3 +42,20 @@ public final class EntreatTheDead extends CardImpl { return new EntreatTheDead(this); } } + +enum EntreatTheDeadAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + String filterName = xValue + + (xValue != 1 ? " creature cards" : "creature card") + + " from your graveyard"; + Target target = new TargetCardInYourGraveyard( + xValue, new FilterCreatureCard(filterName) + ); + ability.addTarget(target); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EntropicSpecter.java b/Mage.Sets/src/mage/cards/e/EntropicSpecter.java index 1102b8e1ba3..ef504ece33d 100644 --- a/Mage.Sets/src/mage/cards/e/EntropicSpecter.java +++ b/Mage.Sets/src/mage/cards/e/EntropicSpecter.java @@ -1,7 +1,6 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -19,8 +18,9 @@ import mage.constants.*; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class EntropicSpecter extends CardImpl { @@ -42,7 +42,7 @@ public final class EntropicSpecter extends CardImpl { // Entropic Specter's power and toughness are each equal to the number of cards in the chosen player's hand. this.addAbility(new SimpleStaticAbility(Zone.ALL, // back to the graveyard or if the choosen player left the gane it's again a 0/0 - new SetPowerToughnessSourceEffect(new CardsInTargetPlayerHandCount(), Duration.WhileOnBattlefield, SubLayer.CharacteristicDefining_7a))); + new SetPowerToughnessSourceEffect(CardsInTargetPlayerHandCount.instance, Duration.WhileOnBattlefield, SubLayer.CharacteristicDefining_7a))); // Whenever Entropic Specter deals damage to a player, that player discards a card. this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1, false), false, true)); @@ -58,7 +58,8 @@ public final class EntropicSpecter extends CardImpl { } } -class CardsInTargetPlayerHandCount implements DynamicValue { +enum CardsInTargetPlayerHandCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -74,7 +75,7 @@ class CardsInTargetPlayerHandCount implements DynamicValue { @Override public DynamicValue copy() { - return new mage.abilities.dynamicvalue.common.CardsInControllerHandCount(); + return instance; } @Override diff --git a/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java b/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java index 8f149ba496b..c3ae62a97ad 100644 --- a/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java +++ b/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java @@ -70,7 +70,7 @@ enum HadAnotherCreatureEnterTheBattlefieldCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getSimpleName()); + PermanentsEnteredBattlefieldWatcher watcher = game.getState().getWatcher(PermanentsEnteredBattlefieldWatcher.class); return sourcePermanent != null && watcher != null && watcher.anotherCreatureEnteredBattlefieldUnderPlayersControlLastTurn(sourcePermanent, game); diff --git a/Mage.Sets/src/mage/cards/e/ErayoSoratamiAscendant.java b/Mage.Sets/src/mage/cards/e/ErayoSoratamiAscendant.java index 6f50051ae6c..6841c7760f4 100644 --- a/Mage.Sets/src/mage/cards/e/ErayoSoratamiAscendant.java +++ b/Mage.Sets/src/mage/cards/e/ErayoSoratamiAscendant.java @@ -78,7 +78,7 @@ class ErayoSoratamiAscendantTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); return watcher != null && watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() == 4; } @@ -134,7 +134,7 @@ class ErayosEssenceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 1) { for (Effect effect : getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage.Sets/src/mage/cards/e/ErdwalIlluminator.java b/Mage.Sets/src/mage/cards/e/ErdwalIlluminator.java index c5e6480f446..c303a87b821 100644 --- a/Mage.Sets/src/mage/cards/e/ErdwalIlluminator.java +++ b/Mage.Sets/src/mage/cards/e/ErdwalIlluminator.java @@ -66,7 +66,7 @@ class ErdwalIlluminatorTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - InvestigatedWatcher watcher = (InvestigatedWatcher) game.getState().getWatchers().get(InvestigatedWatcher.class.getSimpleName()); + InvestigatedWatcher watcher = game.getState().getWatcher(InvestigatedWatcher.class); return watcher != null && watcher.getTimesInvestigated(getControllerId()) == 1; } diff --git a/Mage.Sets/src/mage/cards/e/ErgRaiders.java b/Mage.Sets/src/mage/cards/e/ErgRaiders.java index fbf0ea92e35..01899e227c4 100644 --- a/Mage.Sets/src/mage/cards/e/ErgRaiders.java +++ b/Mage.Sets/src/mage/cards/e/ErgRaiders.java @@ -55,8 +55,8 @@ class ErgRaidersCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent raiders = game.getPermanentOrLKIBattlefield(source.getSourceId()); - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); // wasControlledFromStartOfControllerTurn should be checked during resolution I guess, but shouldn't be relevant - return raiders.wasControlledFromStartOfControllerTurn() && !watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(raiders, game)); + return raiders != null &&raiders.wasControlledFromStartOfControllerTurn() && watcher != null && !watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(raiders, game)); } } diff --git a/Mage.Sets/src/mage/cards/e/ErrantMinion.java b/Mage.Sets/src/mage/cards/e/ErrantMinion.java new file mode 100644 index 00000000000..53844a3a82d --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ErrantMinion.java @@ -0,0 +1,121 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth + */ +public final class ErrantMinion extends CardImpl { + + public ErrantMinion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of the upkeep of enchanted creature's controller, that player may pay any amount of mana. Errant Minion deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, + new ErrantMinionEffect(), + TargetController.CONTROLLER_ATTACHED_TO, + false)); + + } + + private ErrantMinion(final ErrantMinion card) { + super(card); + } + + @Override + public ErrantMinion copy() { + return new ErrantMinion(this); + } +} + +class ErrantMinionEffect extends OneShotEffect { + + public ErrantMinionEffect() { + super(Outcome.Damage); + this.staticText = "that player may pay any amount of mana. Errant Minion deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way"; + } + + public ErrantMinionEffect(final ErrantMinionEffect effect) { + super(effect); + } + + @Override + public ErrantMinionEffect copy() { + return new ErrantMinionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent errantMinion = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (errantMinion == null) { + return false; + } + Permanent enchantedCreature = game.getPermanentOrLKIBattlefield(errantMinion.getAttachedTo()); + if (enchantedCreature == null) { + return false; + } + Player controllerOfEnchantedCreature = game.getPlayer(enchantedCreature.getControllerId()); + if (controllerOfEnchantedCreature != null) { + int manaPaid = playerPaysXGenericMana(controllerOfEnchantedCreature, source, game); + PreventDamageToTargetEffect effect = new PreventDamageToTargetEffect(Duration.OneUse, manaPaid); + effect.setTargetPointer(new FixedTarget(controllerOfEnchantedCreature.getId())); + game.addEffect(effect, source); + DamageTargetEffect effect2 = new DamageTargetEffect(2); + effect2.setTargetPointer(new FixedTarget(controllerOfEnchantedCreature.getId())); + effect2.apply(game, source); + return true; + } + return false; + } + + protected static int playerPaysXGenericMana(Player player, Ability source, Game game) { + int xValue = 0; + boolean payed = false; + while (!payed) { + xValue = player.announceXMana(0, Integer.MAX_VALUE, "How much mana will you pay?", game, source); + if (xValue > 0) { + Cost cost = new GenericManaCost(xValue); + payed = cost.pay(source, game, source.getSourceId(), player.getId(), false, null); + } else { + payed = true; + } + } + game.informPlayers(player.getLogName() + " pays {" + xValue + '}'); + return xValue; + } + +} diff --git a/Mage.Sets/src/mage/cards/e/EsperStormblade.java b/Mage.Sets/src/mage/cards/e/EsperStormblade.java index a326fa966ca..04f376a441a 100644 --- a/Mage.Sets/src/mage/cards/e/EsperStormblade.java +++ b/Mage.Sets/src/mage/cards/e/EsperStormblade.java @@ -29,8 +29,8 @@ public final class EsperStormblade extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another multicolor permanent"); static { - filter.add(new MulticoloredPredicate()); - filter.add(new AnotherPredicate()); + filter.add(MulticoloredPredicate.instance); + filter.add(AnotherPredicate.instance); } public EsperStormblade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EssenceCapture.java b/Mage.Sets/src/mage/cards/e/EssenceCapture.java new file mode 100644 index 00000000000..7af749c4492 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EssenceCapture.java @@ -0,0 +1,43 @@ +package mage.cards.e; + +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.common.FilterCreatureSpell; +import mage.target.TargetSpell; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EssenceCapture extends CardImpl { + + public EssenceCapture(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}"); + + // Counter target creature spell. + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addTarget(new TargetSpell(new FilterCreatureSpell())); + + // Put a +1/+1 counter on up to one target creature you control. + this.getSpellAbility().addEffect(new AddCountersTargetEffect( + CounterType.P1P1.createInstance() + ).setTargetPointer(new SecondTargetPointer())); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1)); + } + + private EssenceCapture(final EssenceCapture card) { + super(card); + } + + @Override + public EssenceCapture copy() { + return new EssenceCapture(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EssenceWarden.java b/Mage.Sets/src/mage/cards/e/EssenceWarden.java index c66cb98aa79..d260fedbd5e 100644 --- a/Mage.Sets/src/mage/cards/e/EssenceWarden.java +++ b/Mage.Sets/src/mage/cards/e/EssenceWarden.java @@ -21,7 +21,7 @@ public final class EssenceWarden extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public EssenceWarden(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EstridTheMasked.java b/Mage.Sets/src/mage/cards/e/EstridTheMasked.java index 9cc5c30fc42..25f0afb81c3 100644 --- a/Mage.Sets/src/mage/cards/e/EstridTheMasked.java +++ b/Mage.Sets/src/mage/cards/e/EstridTheMasked.java @@ -38,8 +38,8 @@ public final class EstridTheMasked extends CardImpl { private static final FilterPermanent filter2 = new FilterPermanent("another permanent"); static { - filter.add(new EnchantedPredicate()); - filter2.add(new AnotherPredicate()); + filter.add(EnchantedPredicate.instance); + filter2.add(AnotherPredicate.instance); } public EstridTheMasked(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EtherealAbsolution.java b/Mage.Sets/src/mage/cards/e/EtherealAbsolution.java new file mode 100644 index 00000000000..49bb668e5a1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EtherealAbsolution.java @@ -0,0 +1,91 @@ +package mage.cards.e; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.BoostOpponentsEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.token.WhiteBlackSpiritToken; +import mage.players.Player; +import mage.target.common.TargetCardInOpponentsGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EtherealAbsolution extends CardImpl { + + public EtherealAbsolution(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}{B}"); + + // Creatures you control get +1/+1. + this.addAbility(new SimpleStaticAbility( + new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield) + )); + + // Creatures your opponents control get -1/-1. + this.addAbility(new SimpleStaticAbility( + new BoostOpponentsEffect(-1, -1, Duration.WhileOnBattlefield) + )); + + // {2}{W}{B}: Exile target card from an opponent's graveyard. If it was a creature card, you create a 1/1 white and black Spirit creature token with flying. + Ability ability = new SimpleActivatedAbility( + new EtherealAbsolutionEffect(), new ManaCostsImpl("{2}{W}{B}") + ); + ability.addTarget(new TargetCardInOpponentsGraveyard(StaticFilters.FILTER_CARD)); + this.addAbility(ability); + } + + private EtherealAbsolution(final EtherealAbsolution card) { + super(card); + } + + @Override + public EtherealAbsolution copy() { + return new EtherealAbsolution(this); + } +} + +class EtherealAbsolutionEffect extends OneShotEffect { + + EtherealAbsolutionEffect() { + super(Outcome.Benefit); + staticText = "Exile target card from an opponent's graveyard. " + + "If it was a creature card, you create a 1/1 white and black Spirit creature token with flying."; + } + + private EtherealAbsolutionEffect(final EtherealAbsolutionEffect effect) { + super(effect); + } + + @Override + public EtherealAbsolutionEffect copy() { + return new EtherealAbsolutionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Card card = game.getCard(source.getFirstTarget()); + if (player == null || card == null) { + return false; + } + if (card.isCreature()) { + new CreateTokenEffect(new WhiteBlackSpiritToken()).apply(game, source); + } + return player.moveCards(card, Zone.EXILED, source, game); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EtherswornCanonist.java b/Mage.Sets/src/mage/cards/e/EtherswornCanonist.java index 8c0fa6561f1..754304f2e47 100644 --- a/Mage.Sets/src/mage/cards/e/EtherswornCanonist.java +++ b/Mage.Sets/src/mage/cards/e/EtherswornCanonist.java @@ -116,7 +116,7 @@ class EtherswornCanonistReplacementEffect extends ContinuousRuleModifyingEffectI public boolean applies(GameEvent event, Ability source, Game game) { Card card = game.getCard(event.getSourceId()); if (card != null && !card.isArtifact()) { - EtherswornCanonistWatcher watcher = (EtherswornCanonistWatcher) game.getState().getWatchers().get(EtherswornCanonistWatcher.class.getSimpleName()); + EtherswornCanonistWatcher watcher = game.getState().getWatcher(EtherswornCanonistWatcher.class); return watcher != null && watcher.castNonArtifactSpell(event.getPlayerId()); } return false; diff --git a/Mage.Sets/src/mage/cards/e/EverflowingChalice.java b/Mage.Sets/src/mage/cards/e/EverflowingChalice.java index 98755ba1972..256f062d985 100644 --- a/Mage.Sets/src/mage/cards/e/EverflowingChalice.java +++ b/Mage.Sets/src/mage/cards/e/EverflowingChalice.java @@ -33,7 +33,7 @@ public final class EverflowingChalice extends CardImpl { // Everflowing Chalice enters the battlefield with a charge counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.CHARGE.createInstance(0), new MultikickerCount(), true), + new AddCountersSourceEffect(CounterType.CHARGE.createInstance(0), MultikickerCount.instance, true), "with a charge counter on it for each time it was kicked")); // {T}: Add {C} for each charge counter on Everflowing Chalice. diff --git a/Mage.Sets/src/mage/cards/e/Everglades.java b/Mage.Sets/src/mage/cards/e/Everglades.java index 13c7fb1c36d..8e2b3ceae0c 100644 --- a/Mage.Sets/src/mage/cards/e/Everglades.java +++ b/Mage.Sets/src/mage/cards/e/Everglades.java @@ -30,7 +30,7 @@ public final class Everglades extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SWAMP)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Everglades(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/ExavaRakdosBloodWitch.java b/Mage.Sets/src/mage/cards/e/ExavaRakdosBloodWitch.java index 86225e14cb9..89feff77394 100644 --- a/Mage.Sets/src/mage/cards/e/ExavaRakdosBloodWitch.java +++ b/Mage.Sets/src/mage/cards/e/ExavaRakdosBloodWitch.java @@ -29,7 +29,7 @@ public final class ExavaRakdosBloodWitch extends CardImpl { filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new CounterPredicate(CounterType.P1P1)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } static final String rule = "Each other creature you control with a +1/+1 counter on it has haste"; diff --git a/Mage.Sets/src/mage/cards/e/Excise.java b/Mage.Sets/src/mage/cards/e/Excise.java index 119914cc3be..a232c410858 100644 --- a/Mage.Sets/src/mage/cards/e/Excise.java +++ b/Mage.Sets/src/mage/cards/e/Excise.java @@ -20,7 +20,7 @@ public final class Excise extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public Excise(UUID ownerId, CardSetInfo setInfo) { @@ -28,7 +28,7 @@ public final class Excise extends CardImpl { // Excise target nonwhite attacking creature unless its controller pays {X}. this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); - this.getSpellAbility().addEffect(new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(new ExileTargetEffect(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(new ExileTargetEffect(), ManacostVariableValue.instance)); } public Excise(final Excise card) { diff --git a/Mage.Sets/src/mage/cards/e/Excoriate.java b/Mage.Sets/src/mage/cards/e/Excoriate.java index a015078ba52..fc376d02c18 100644 --- a/Mage.Sets/src/mage/cards/e/Excoriate.java +++ b/Mage.Sets/src/mage/cards/e/Excoriate.java @@ -19,7 +19,7 @@ public final class Excoriate extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public Excoriate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java b/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java index 668225ef536..dbcf5fd062d 100644 --- a/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java +++ b/Mage.Sets/src/mage/cards/e/ExecutionersSwing.java @@ -56,7 +56,7 @@ class TargetCreaturePermanentThatDealtDamageThisTurn extends TargetPermanent { @Override public boolean canTarget(UUID id, Ability source, Game game) { - SourceDidDamageWatcher watcher = (SourceDidDamageWatcher) game.getState().getWatchers().get(SourceDidDamageWatcher.class.getSimpleName()); + SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); if (watcher != null) { if (watcher.damageSources.contains(id)) { return super.canTarget(id, source, game); @@ -73,7 +73,7 @@ class TargetCreaturePermanentThatDealtDamageThisTurn extends TargetPermanent { } int count = 0; MageObject targetSource = game.getObject(sourceId); - SourceDidDamageWatcher watcher = (SourceDidDamageWatcher) game.getState().getWatchers().get(SourceDidDamageWatcher.class.getSimpleName()); + SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); if (watcher != null && targetSource != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId()) && watcher.damageSources.contains(permanent.getId())) { @@ -93,7 +93,7 @@ class TargetCreaturePermanentThatDealtDamageThisTurn extends TargetPermanent { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); Set possibleTargets = new HashSet<>(); - SourceDidDamageWatcher watcher = (SourceDidDamageWatcher) game.getState().getWatchers().get(SourceDidDamageWatcher.class.getSimpleName()); + SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); if (watcher != null) { for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage.Sets/src/mage/cards/e/Exile.java b/Mage.Sets/src/mage/cards/e/Exile.java index 13067c94399..a8d28191980 100644 --- a/Mage.Sets/src/mage/cards/e/Exile.java +++ b/Mage.Sets/src/mage/cards/e/Exile.java @@ -29,7 +29,7 @@ public final class Exile extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonwhite attacking creature"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(Predicates.not(new ColorPredicate(ObjectColor.WHITE))); } diff --git a/Mage.Sets/src/mage/cards/e/ExperimentKraj.java b/Mage.Sets/src/mage/cards/e/ExperimentKraj.java index e45f52bd337..d4c20acec30 100644 --- a/Mage.Sets/src/mage/cards/e/ExperimentKraj.java +++ b/Mage.Sets/src/mage/cards/e/ExperimentKraj.java @@ -60,7 +60,7 @@ class ExperimentKrajEffect extends ContinuousEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { filter.add(new CounterPredicate(CounterType.P1P1)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ExperimentKrajEffect() { diff --git a/Mage.Sets/src/mage/cards/e/ExposeToDaylight.java b/Mage.Sets/src/mage/cards/e/ExposeToDaylight.java new file mode 100644 index 00000000000..7de10992de1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ExposeToDaylight.java @@ -0,0 +1,35 @@ +package mage.cards.e; + +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ExposeToDaylight extends CardImpl { + + public ExposeToDaylight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Destroy target artifact or enchantment. Scry 1. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addEffect(new ScryEffect(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); + } + + private ExposeToDaylight(final ExposeToDaylight card) { + super(card); + } + + @Override + public ExposeToDaylight copy() { + return new ExposeToDaylight(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ExtractorDemon.java b/Mage.Sets/src/mage/cards/e/ExtractorDemon.java index 651e5e955b6..0576b6b22e5 100644 --- a/Mage.Sets/src/mage/cards/e/ExtractorDemon.java +++ b/Mage.Sets/src/mage/cards/e/ExtractorDemon.java @@ -27,7 +27,7 @@ public final class ExtractorDemon extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ExtractorDemon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java index 1322d056ffa..90dfa5684c4 100644 --- a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java +++ b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java @@ -32,7 +32,7 @@ public final class ExtricatorOfSin extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ExtricatorOfSin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java index 2860e35ddf2..563fb12b5ca 100644 --- a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java +++ b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java @@ -1,7 +1,5 @@ - package mage.cards.e; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; @@ -23,8 +21,9 @@ import mage.target.TargetCard; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author spjspj */ public final class EyeOfTheStorm extends CardImpl { @@ -111,7 +110,7 @@ class EyeOfTheStormEffect1 extends OneShotEffect { Card card = spell.getCard(); if (spellController == null || card == null - || !StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY.match(spell, game)) { + || !StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY.match(spell, game)) { return false; } if (!noLongerOnStack) {// the spell is still on the stack, so exile it @@ -125,11 +124,9 @@ class EyeOfTheStormEffect1 extends OneShotEffect { && !eyeOfTheStorm.getImprinted().isEmpty()) { CardsImpl copiedCards = new CardsImpl(); for (UUID uuid : eyeOfTheStorm.getImprinted()) { - card = game.getCard(uuid); - // Check if owner of card is still in game - if (card != null - && game.getPlayer(card.getOwnerId()) != null) { + card = game.getCard(uuid); + if (card != null && game.getPlayer(card.getOwnerId()) != null) { if (card.isSplitCard()) { copiedCards.add(((SplitCard) card).getLeftHalfCard()); copiedCards.add(((SplitCard) card).getRightHalfCard()); diff --git a/Mage.Sets/src/mage/cards/e/EyeOfUgin.java b/Mage.Sets/src/mage/cards/e/EyeOfUgin.java index 67223f4db30..0fef45898fe 100644 --- a/Mage.Sets/src/mage/cards/e/EyeOfUgin.java +++ b/Mage.Sets/src/mage/cards/e/EyeOfUgin.java @@ -31,8 +31,8 @@ public final class EyeOfUgin extends CardImpl { private static final FilterCard filterSpells = new FilterCard("Colorless Eldrazi spells"); static { - filter.add(new ColorlessPredicate()); - filterSpells.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); + filterSpells.add(ColorlessPredicate.instance); filterSpells.add(new SubtypePredicate(SubType.ELDRAZI)); } diff --git a/Mage.Sets/src/mage/cards/e/EyesEverywhere.java b/Mage.Sets/src/mage/cards/e/EyesEverywhere.java new file mode 100644 index 00000000000..701e6ef5606 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EyesEverywhere.java @@ -0,0 +1,53 @@ +package mage.cards.e; + +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.target.common.TargetNonlandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EyesEverywhere extends CardImpl { + + public EyesEverywhere(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // At the beginning of your upkeep, scry 1. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, new ScryEffect(1), + TargetController.YOU, false + )); + + // {5}{U}: Exchange control of Eyes Everywhere and target nonland permanent. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, + new ExchangeControlTargetEffect( + Duration.EndOfGame, "Exchange control of {this} " + + "and target nonland permanent", true + ), new ManaCostsImpl("{5}{U}") + ); + ability.addTarget(new TargetNonlandPermanent()); + this.addAbility(ability); + } + + private EyesEverywhere(final EyesEverywhere card) { + super(card); + } + + @Override + public EyesEverywhere copy() { + return new EyesEverywhere(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java b/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java index 6ade1dc5b7e..ac296ce2ddb 100644 --- a/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java +++ b/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java @@ -31,7 +31,7 @@ public final class EzuriClawOfProgress extends CardImpl { static { filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } String rule = "Whenever a creature with power 2 or less enters the battlefield under your control, you get an experience counter."; diff --git a/Mage.Sets/src/mage/cards/f/FacelessButcher.java b/Mage.Sets/src/mage/cards/f/FacelessButcher.java index f44aec4ce8c..42bc86ffe65 100644 --- a/Mage.Sets/src/mage/cards/f/FacelessButcher.java +++ b/Mage.Sets/src/mage/cards/f/FacelessButcher.java @@ -30,7 +30,7 @@ public final class FacelessButcher extends CardImpl { static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } diff --git a/Mage.Sets/src/mage/cards/f/FacelessDevourer.java b/Mage.Sets/src/mage/cards/f/FacelessDevourer.java index aa573b1fa10..4148034851d 100644 --- a/Mage.Sets/src/mage/cards/f/FacelessDevourer.java +++ b/Mage.Sets/src/mage/cards/f/FacelessDevourer.java @@ -30,7 +30,7 @@ public final class FacelessDevourer extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new AbilityPredicate(ShadowAbility.class)); } diff --git a/Mage.Sets/src/mage/cards/f/FaerieArtisans.java b/Mage.Sets/src/mage/cards/f/FaerieArtisans.java index db39e5549a3..f02fa39ba42 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieArtisans.java +++ b/Mage.Sets/src/mage/cards/f/FaerieArtisans.java @@ -32,7 +32,7 @@ public final class FaerieArtisans extends CardImpl { private static final FilterCreaturePermanent filterNontoken = new FilterCreaturePermanent("nontoken creature"); static { - filterNontoken.add(Predicates.not(new TokenPredicate())); + filterNontoken.add(Predicates.not(TokenPredicate.instance)); filterNontoken.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/f/FaerieDuelist.java b/Mage.Sets/src/mage/cards/f/FaerieDuelist.java new file mode 100644 index 00000000000..25297814548 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FaerieDuelist.java @@ -0,0 +1,50 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FaerieDuelist extends CardImpl { + + public FaerieDuelist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.FAERIE); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Faerie Duelist enters the battlefield, target creature an opponent controls gets -2/-0 until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, 0)); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + private FaerieDuelist(final FaerieDuelist card) { + super(card); + } + + @Override + public FaerieDuelist copy() { + return new FaerieDuelist(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FaerieImpostor.java b/Mage.Sets/src/mage/cards/f/FaerieImpostor.java index 1a4b526b131..f744e080133 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieImpostor.java +++ b/Mage.Sets/src/mage/cards/f/FaerieImpostor.java @@ -58,7 +58,7 @@ class FaerieImpostorEffect extends OneShotEffect { private static final String effectText = "sacrifice it unless you return another creature you control to its owner's hand"; static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } FaerieImpostorEffect() { diff --git a/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java b/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java index bedb618045e..aa826d306aa 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java +++ b/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java @@ -30,7 +30,7 @@ public final class FaerieMiscreant extends CardImpl { static { filter.add(new NamePredicate("Faerie Miscreant")); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/f/FailureComply.java b/Mage.Sets/src/mage/cards/f/FailureComply.java index 1dc66399d62..e7cdbbc5fb0 100644 --- a/Mage.Sets/src/mage/cards/f/FailureComply.java +++ b/Mage.Sets/src/mage/cards/f/FailureComply.java @@ -37,7 +37,7 @@ public final class FailureComply extends SplitCard { // to // Comply // Choose a card name. Until your next turn, your opponents can't cast spells with the chosen name - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); Effect effect = new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL); effect.setText("Choose a card name"); getRightHalfCard().getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java index 8a4959443ba..da246d46243 100644 --- a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java +++ b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java @@ -57,7 +57,7 @@ enum FairgroundsTrumpeterCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - FairgroundsTrumpeterWatcher watcher = (FairgroundsTrumpeterWatcher) game.getState().getWatchers().get(FairgroundsTrumpeterWatcher.class.getSimpleName()); + FairgroundsTrumpeterWatcher watcher = game.getState().getWatcher(FairgroundsTrumpeterWatcher.class); return watcher != null && watcher.p1p1AddedToPermanent(source.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/f/FaithsReward.java b/Mage.Sets/src/mage/cards/f/FaithsReward.java index cf449635657..1987daeffbe 100644 --- a/Mage.Sets/src/mage/cards/f/FaithsReward.java +++ b/Mage.Sets/src/mage/cards/f/FaithsReward.java @@ -57,7 +57,7 @@ class FaithsRewardEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - FaithsRewardWatcher watcher = (FaithsRewardWatcher) game.getState().getWatchers().get(FaithsRewardWatcher.class.getSimpleName()); + FaithsRewardWatcher watcher = game.getState().getWatcher(FaithsRewardWatcher.class); if (watcher != null) { for (UUID id : watcher.cards) { Card c = game.getCard(id); @@ -80,7 +80,7 @@ class FaithsRewardWatcher extends Watcher { List cards = new ArrayList<>(); public FaithsRewardWatcher() { - super(FaithsRewardWatcher.class.getSimpleName(), WatcherScope.GAME); + super(FaithsRewardWatcher.class, WatcherScope.GAME); } public FaithsRewardWatcher(final FaithsRewardWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/f/FallOfTheTitans.java b/Mage.Sets/src/mage/cards/f/FallOfTheTitans.java index 71a44fc473f..1b45b0e00f7 100644 --- a/Mage.Sets/src/mage/cards/f/FallOfTheTitans.java +++ b/Mage.Sets/src/mage/cards/f/FallOfTheTitans.java @@ -21,7 +21,7 @@ public final class FallOfTheTitans extends CardImpl { // Fall of the Titans deals X damage to each of up to two target creatures and/or players. this.getSpellAbility().addTarget(new TargetAnyTarget(0, 2)); - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); // Surge {X}{R} addAbility(new SurgeAbility(this, "{X}{R}")); diff --git a/Mage.Sets/src/mage/cards/f/FallingTimber.java b/Mage.Sets/src/mage/cards/f/FallingTimber.java index 90a39c76143..492c7e6f343 100644 --- a/Mage.Sets/src/mage/cards/f/FallingTimber.java +++ b/Mage.Sets/src/mage/cards/f/FallingTimber.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.UUID; @@ -16,38 +15,30 @@ import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * * @author LoneFox - + * */ public final class FallingTimber extends CardImpl { - private final UUID originalId; - public FallingTimber(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); // Kicker-Sacrifice a land. this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, new FilterControlledLandPermanent("a land"), true)))); + // Prevent all combat damage target creature would deal this turn. If Falling Timber was kicked, prevent all combat damage another target creature would deal this turn. Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true); effect.setText("Prevent all combat damage target creature would deal this turn. if this spell was kicked, prevent all combat damage another target creature would deal this turn."); this.getSpellAbility().addEffect(effect); - originalId = this.getSpellAbility().getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability.getOriginalId().equals(originalId)) { - ability.addTarget(new TargetCreaturePermanent(KickedCondition.instance.apply(game, ability) ? 2 : 1)); - } + this.getSpellAbility().setTargetAdjuster(FallingTimberAdjuster.instance); } public FallingTimber(final FallingTimber card) { super(card); - this.originalId = card.originalId; } @Override @@ -55,3 +46,13 @@ public final class FallingTimber extends CardImpl { return new FallingTimber(this); } } + +enum FallingTimberAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(KickedCondition.instance.apply(game, ability) ? 2 : 1)); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FalseOrders.java b/Mage.Sets/src/mage/cards/f/FalseOrders.java index f4c8066db61..7a3279720b0 100644 --- a/Mage.Sets/src/mage/cards/f/FalseOrders.java +++ b/Mage.Sets/src/mage/cards/f/FalseOrders.java @@ -104,7 +104,7 @@ class FalseOrdersUnblockEffect extends OneShotEffect { effect.apply(game, source); // Make blocked creatures unblocked - BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName()); + BlockedByOnlyOneCreatureThisCombatWatcher watcher = game.getState().getWatcher(BlockedByOnlyOneCreatureThisCombatWatcher.class); if (watcher != null) { Set combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId()); if (combatGroups != null) { diff --git a/Mage.Sets/src/mage/cards/f/FangOfThePack.java b/Mage.Sets/src/mage/cards/f/FangOfThePack.java index 71cda8c6bd9..353b13f54e1 100644 --- a/Mage.Sets/src/mage/cards/f/FangOfThePack.java +++ b/Mage.Sets/src/mage/cards/f/FangOfThePack.java @@ -26,7 +26,7 @@ public final class FangOfThePack extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FangOfThePack(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FanningTheFlames.java b/Mage.Sets/src/mage/cards/f/FanningTheFlames.java index 4fe03dc2dac..e7d224f7e5f 100644 --- a/Mage.Sets/src/mage/cards/f/FanningTheFlames.java +++ b/Mage.Sets/src/mage/cards/f/FanningTheFlames.java @@ -23,7 +23,7 @@ public final class FanningTheFlames extends CardImpl { this.addAbility(new BuybackAbility("{3}")); // Fanning the Flames deals X damage to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/f/FarmMarket.java b/Mage.Sets/src/mage/cards/f/FarmMarket.java index 3b280cd7845..53c665b919e 100644 --- a/Mage.Sets/src/mage/cards/f/FarmMarket.java +++ b/Mage.Sets/src/mage/cards/f/FarmMarket.java @@ -28,7 +28,7 @@ public final class FarmMarket extends SplitCard { // Market {2}{U} // Sorcery // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Draw two cards, then discard two cards getRightHalfCard().getSpellAbility().addEffect(new DrawDiscardControllerEffect(2, 2)); diff --git a/Mage.Sets/src/mage/cards/f/Fascination.java b/Mage.Sets/src/mage/cards/f/Fascination.java index d53a9219841..e3aa3f389d9 100644 --- a/Mage.Sets/src/mage/cards/f/Fascination.java +++ b/Mage.Sets/src/mage/cards/f/Fascination.java @@ -22,11 +22,11 @@ public final class Fascination extends CardImpl { // Choose one - // * Each player draws X cards. - this.getSpellAbility().addEffect(new DrawCardAllEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardAllEffect(ManacostVariableValue.instance)); // * Each player puts the top X cards of their library into their graveyard. Mode mode = new Mode(); - mode.addEffect(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(new ManacostVariableValue(), TargetController.ANY)); + mode.addEffect(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(ManacostVariableValue.instance, TargetController.ANY)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/f/FatalFrenzy.java b/Mage.Sets/src/mage/cards/f/FatalFrenzy.java index a3e9ebd5d32..6b074158208 100644 --- a/Mage.Sets/src/mage/cards/f/FatalFrenzy.java +++ b/Mage.Sets/src/mage/cards/f/FatalFrenzy.java @@ -35,7 +35,7 @@ public final class FatalFrenzy extends CardImpl { this.getSpellAbility().addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn) .setText("Until end of turn, target creature you control gains trample") ); - this.getSpellAbility().addEffect(new BoostTargetEffect(new TargetPermanentPowerCount(), new StaticValue(0), Duration.EndOfTurn, true) + this.getSpellAbility().addEffect(new BoostTargetEffect(TargetPermanentPowerCount.instance, new StaticValue(0), Duration.EndOfTurn, true) .setText("and gets +X/+0, where X is its power.") ); this.getSpellAbility().addEffect(new FatalFrenzyEffect()); diff --git a/Mage.Sets/src/mage/cards/f/FatefulShowdown.java b/Mage.Sets/src/mage/cards/f/FatefulShowdown.java index 02b4db6762f..11f60f05011 100644 --- a/Mage.Sets/src/mage/cards/f/FatefulShowdown.java +++ b/Mage.Sets/src/mage/cards/f/FatefulShowdown.java @@ -21,7 +21,7 @@ public final class FatefulShowdown extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}{R}"); // Fateful Showdown deals damage to any target equal to the number of cards in your hand. Discard all the cards in your hand, then draw that many cards. - Effect effect = new DamageTargetEffect(new CardsInControllerHandCount()); + Effect effect = new DamageTargetEffect(CardsInControllerHandCount.instance); effect.setText("{this} deals damage to any target equal to the number of cards in your hand"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/f/Fatestitcher.java b/Mage.Sets/src/mage/cards/f/Fatestitcher.java index dc642fbbbf4..aec4bcc54a7 100644 --- a/Mage.Sets/src/mage/cards/f/Fatestitcher.java +++ b/Mage.Sets/src/mage/cards/f/Fatestitcher.java @@ -26,7 +26,7 @@ public final class Fatestitcher extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent"); static{ - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Fatestitcher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FathomFleetBoarder.java b/Mage.Sets/src/mage/cards/f/FathomFleetBoarder.java index 90c40439fae..c697a74221e 100644 --- a/Mage.Sets/src/mage/cards/f/FathomFleetBoarder.java +++ b/Mage.Sets/src/mage/cards/f/FathomFleetBoarder.java @@ -26,7 +26,7 @@ public final class FathomFleetBoarder extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PIRATE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FathomFleetBoarder(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java b/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java index d4f6bf40264..ba624da7933 100644 --- a/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java +++ b/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java @@ -31,8 +31,8 @@ public final class FathomFleetCaptain extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PIRATE)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public FathomFleetCaptain(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FeastOfDreams.java b/Mage.Sets/src/mage/cards/f/FeastOfDreams.java index 96f547e448d..b42e154268b 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOfDreams.java +++ b/Mage.Sets/src/mage/cards/f/FeastOfDreams.java @@ -22,7 +22,7 @@ public final class FeastOfDreams extends CardImpl { static { filter.add(Predicates.or( - new EnchantedPredicate(), + EnchantedPredicate.instance, new CardTypePredicate(CardType.ENCHANTMENT) )); } diff --git a/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java b/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java index 22d1800804d..78c8edfd69e 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java +++ b/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java @@ -54,10 +54,10 @@ enum FeastOnTheFallenCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { - if (watcher.getLiveLostLastTurn(opponentId) > 0) { + if (watcher.getLifeLostLastTurn(opponentId) > 0) { return true; } } diff --git a/Mage.Sets/src/mage/cards/f/FeedThePack.java b/Mage.Sets/src/mage/cards/f/FeedThePack.java index 24957df34a6..181022e5ef0 100644 --- a/Mage.Sets/src/mage/cards/f/FeedThePack.java +++ b/Mage.Sets/src/mage/cards/f/FeedThePack.java @@ -48,7 +48,7 @@ class FeedThePackEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public FeedThePackEffect() { diff --git a/Mage.Sets/src/mage/cards/f/Feint.java b/Mage.Sets/src/mage/cards/f/Feint.java new file mode 100644 index 00000000000..bccd33ddceb --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/Feint.java @@ -0,0 +1,85 @@ + +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.PreventionEffect; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetAttackingCreature; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public final class Feint extends CardImpl { + + public Feint(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}"); + + // Tap all creatures blocking target attacking creature. Prevent all combat damage that would be dealt this turn by that creature and each creature blocking it. + this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true).setText("")); + this.getSpellAbility().addEffect(new FeintEffect()); + this.getSpellAbility().addTarget(new TargetAttackingCreature()); + } + + public Feint(final Feint card) { + super(card); + } + + @Override + public Feint copy() { + return new Feint(this); + } + +} + +class FeintEffect extends OneShotEffect { + + public FeintEffect() { + super(Outcome.ReturnToHand); + this.staticText = "Tap all creatures blocking target attacking creature. Prevent all combat damage that would be dealt this turn by that creature and each creature blocking it"; + } + + public FeintEffect(final FeintEffect effect) { + super(effect); + } + + @Override + public FeintEffect copy() { + return new FeintEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller != null && creature != null) { + for (CombatGroup combatGroup : game.getCombat().getGroups()) { + if (combatGroup.getAttackers().contains(creature.getId())) { + for (UUID blockerId : combatGroup.getBlockers()) { + Permanent blocker = game.getPermanent(blockerId); + if (blocker != null) { + blocker.tap(game); + PreventionEffect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true); + effect.setTargetPointer(new FixedTarget(blocker.getId())); + game.addEffect(effect, source); + } + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/f/FelhideBrawler.java b/Mage.Sets/src/mage/cards/f/FelhideBrawler.java index 03b687ceadb..119599817eb 100644 --- a/Mage.Sets/src/mage/cards/f/FelhideBrawler.java +++ b/Mage.Sets/src/mage/cards/f/FelhideBrawler.java @@ -24,7 +24,7 @@ public final class FelhideBrawler extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MINOTAUR)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FelhideBrawler(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java b/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java index 2360250bd87..4b7c6561837 100644 --- a/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java +++ b/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java @@ -33,7 +33,7 @@ public final class FelhideSpiritbinder extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FelhideSpiritbinder(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FelidarGuardian.java b/Mage.Sets/src/mage/cards/f/FelidarGuardian.java index 9931f38d368..cbd687eea89 100644 --- a/Mage.Sets/src/mage/cards/f/FelidarGuardian.java +++ b/Mage.Sets/src/mage/cards/f/FelidarGuardian.java @@ -25,7 +25,7 @@ public final class FelidarGuardian extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another target permanent you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FelidarGuardian(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FellShepherd.java b/Mage.Sets/src/mage/cards/f/FellShepherd.java index 626237217f5..44f9007fe64 100644 --- a/Mage.Sets/src/mage/cards/f/FellShepherd.java +++ b/Mage.Sets/src/mage/cards/f/FellShepherd.java @@ -65,7 +65,7 @@ class FellShepherdWatcher extends Watcher { private Set creatureIds = new HashSet<>(); public FellShepherdWatcher() { - super(FellShepherdWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(FellShepherdWatcher.class, WatcherScope.PLAYER); condition = true; } @@ -118,7 +118,7 @@ class FellShepherdEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - FellShepherdWatcher watcher = (FellShepherdWatcher) game.getState().getWatchers().get(FellShepherdWatcher.class.getSimpleName(), source.getControllerId()); + FellShepherdWatcher watcher = game.getState().getWatcher(FellShepherdWatcher.class, source.getControllerId()); if (watcher != null) { StringBuilder sb = new StringBuilder(); for (UUID creatureId : watcher.getCreaturesIds()) { diff --git a/Mage.Sets/src/mage/cards/f/FenStalker.java b/Mage.Sets/src/mage/cards/f/FenStalker.java index d0e606cb071..e1821d199b6 100644 --- a/Mage.Sets/src/mage/cards/f/FenStalker.java +++ b/Mage.Sets/src/mage/cards/f/FenStalker.java @@ -28,7 +28,7 @@ public final class FenStalker extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public FenStalker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FencersMagemark.java b/Mage.Sets/src/mage/cards/f/FencersMagemark.java index 593ad6407cb..60aad9afb0b 100644 --- a/Mage.Sets/src/mage/cards/f/FencersMagemark.java +++ b/Mage.Sets/src/mage/cards/f/FencersMagemark.java @@ -27,7 +27,7 @@ public final class FencersMagemark extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/f/FeralMaaka.java b/Mage.Sets/src/mage/cards/f/FeralMaaka.java new file mode 100644 index 00000000000..fabc1d3d6fb --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FeralMaaka.java @@ -0,0 +1,32 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FeralMaaka extends CardImpl { + + public FeralMaaka(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.CAT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + } + + private FeralMaaka(final FeralMaaka card) { + super(card); + } + + @Override + public FeralMaaka copy() { + return new FeralMaaka(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FestivalOfTheGuildpact.java b/Mage.Sets/src/mage/cards/f/FestivalOfTheGuildpact.java index 414368c1abb..be5027f5187 100644 --- a/Mage.Sets/src/mage/cards/f/FestivalOfTheGuildpact.java +++ b/Mage.Sets/src/mage/cards/f/FestivalOfTheGuildpact.java @@ -20,7 +20,7 @@ public final class FestivalOfTheGuildpact extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{W}"); // Prevent the next X damage that would be dealt to you this turn. - this.getSpellAbility().addEffect(new PreventDamageToControllerEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue())); + this.getSpellAbility().addEffect(new PreventDamageToControllerEffect(Duration.EndOfTurn, false, true, ManacostVariableValue.instance)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); diff --git a/Mage.Sets/src/mage/cards/f/Fettergeist.java b/Mage.Sets/src/mage/cards/f/Fettergeist.java index 63082827305..cb52e0ad48b 100644 --- a/Mage.Sets/src/mage/cards/f/Fettergeist.java +++ b/Mage.Sets/src/mage/cards/f/Fettergeist.java @@ -56,7 +56,7 @@ class FettergeistUnlessPaysEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FettergeistUnlessPaysEffect() { diff --git a/Mage.Sets/src/mage/cards/f/FickleEfreet.java b/Mage.Sets/src/mage/cards/f/FickleEfreet.java index 3d0cf974d48..4e67afe38fa 100644 --- a/Mage.Sets/src/mage/cards/f/FickleEfreet.java +++ b/Mage.Sets/src/mage/cards/f/FickleEfreet.java @@ -71,7 +71,7 @@ class FickleEfreetChangeControlEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (controller != null) { - if (!controller.flipCoin(game)) { + if (!controller.flipCoin(source, game, true)) { if (sourcePermanent != null) { Target target = new TargetOpponent(true); if (target.canChoose(source.getSourceId(), controller.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/f/FieldOfSouls.java b/Mage.Sets/src/mage/cards/f/FieldOfSouls.java index 3389be54d9a..16dd2e04da1 100644 --- a/Mage.Sets/src/mage/cards/f/FieldOfSouls.java +++ b/Mage.Sets/src/mage/cards/f/FieldOfSouls.java @@ -23,7 +23,7 @@ public final class FieldOfSouls extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static{ filter.add(new OwnerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public FieldOfSouls(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FieldSurgeon.java b/Mage.Sets/src/mage/cards/f/FieldSurgeon.java index 7931385c8e3..93b62fb1f88 100644 --- a/Mage.Sets/src/mage/cards/f/FieldSurgeon.java +++ b/Mage.Sets/src/mage/cards/f/FieldSurgeon.java @@ -28,7 +28,7 @@ public final class FieldSurgeon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public FieldSurgeon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FiendBinder.java b/Mage.Sets/src/mage/cards/f/FiendBinder.java index 64a65b75064..1cbc7e0cc79 100644 --- a/Mage.Sets/src/mage/cards/f/FiendBinder.java +++ b/Mage.Sets/src/mage/cards/f/FiendBinder.java @@ -22,7 +22,7 @@ public final class FiendBinder extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public FiendBinder(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FiendHunter.java b/Mage.Sets/src/mage/cards/f/FiendHunter.java index c1ab64d1b23..bd868bf9c8d 100644 --- a/Mage.Sets/src/mage/cards/f/FiendHunter.java +++ b/Mage.Sets/src/mage/cards/f/FiendHunter.java @@ -25,7 +25,7 @@ public final class FiendHunter extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FiendHunter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java b/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java index 3749823252d..e1a9eb05d94 100644 --- a/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java +++ b/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java @@ -94,7 +94,7 @@ class FiendslayerPaladinEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Card targetCard = game.getCard(event.getTargetId()); - StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); if (targetCard != null && stackObject != null && targetCard.getId().equals(source.getSourceId())) { if (stackObject.getColor(game).isBlack() || stackObject.getColor(game).isRed()) { if (!stackObject.isControlledBy(source.getControllerId()) diff --git a/Mage.Sets/src/mage/cards/f/FieryGambit.java b/Mage.Sets/src/mage/cards/f/FieryGambit.java index 3a5ab06bdf3..36177cf86d1 100644 --- a/Mage.Sets/src/mage/cards/f/FieryGambit.java +++ b/Mage.Sets/src/mage/cards/f/FieryGambit.java @@ -64,7 +64,7 @@ class FieryGambitEffect extends OneShotEffect { if (controller != null && sourceObject != null) { int flipsWon = 0; boolean controllerStopped = false; - while (controller.flipCoin(game)) { + while (controller.flipCoin(source, game, true)) { ++flipsWon; if (!controller.chooseUse(outcome, "You won " + flipsWon + (flipsWon == 1 ? " flip." : " flips.") + " Flip another coin?", source, game)) { diff --git a/Mage.Sets/src/mage/cards/f/FightToTheDeath.java b/Mage.Sets/src/mage/cards/f/FightToTheDeath.java index 7f958784000..b0b1ec365d7 100644 --- a/Mage.Sets/src/mage/cards/f/FightToTheDeath.java +++ b/Mage.Sets/src/mage/cards/f/FightToTheDeath.java @@ -21,8 +21,8 @@ public final class FightToTheDeath extends CardImpl { static { filter.add(Predicates.or( - new BlockingPredicate(), - new BlockedPredicate())); + BlockingPredicate.instance, + BlockedPredicate.instance)); } public FightToTheDeath(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FightWithFire.java b/Mage.Sets/src/mage/cards/f/FightWithFire.java index ebad07ad966..67b7b683a84 100644 --- a/Mage.Sets/src/mage/cards/f/FightWithFire.java +++ b/Mage.Sets/src/mage/cards/f/FightWithFire.java @@ -1,9 +1,7 @@ - package mage.cards.f; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DamageMultiEffect; @@ -16,6 +14,7 @@ import mage.game.Game; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTargetAmount; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -39,26 +38,29 @@ public final class FightWithFire extends CardImpl { + " (Those targets can include players and planeswalkers.)" )); this.getSpellAbility().addTarget(new TargetAnyTarget()); + this.getSpellAbility().setTargetAdjuster(FightWithFireAdjuster.instance); } public FightWithFire(final FightWithFire card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - if (ability instanceof SpellAbility) { - if (KickedCondition.instance.apply(game, ability)) { - ability.addTarget(new TargetAnyTargetAmount(10)); - } else { - ability.addTarget(new TargetCreaturePermanent()); - } - } - } - @Override public FightWithFire copy() { return new FightWithFire(this); } } + +enum FightWithFireAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + if (KickedCondition.instance.apply(game, ability)) { + ability.addTarget(new TargetAnyTargetAmount(10)); + } else { + ability.addTarget(new TargetCreaturePermanent()); + } + } +} diff --git a/Mage.Sets/src/mage/cards/f/FightingChance.java b/Mage.Sets/src/mage/cards/f/FightingChance.java index 896e01dcfea..d67bef03c3d 100644 --- a/Mage.Sets/src/mage/cards/f/FightingChance.java +++ b/Mage.Sets/src/mage/cards/f/FightingChance.java @@ -61,7 +61,7 @@ class FightingChanceEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); if (player != null) { for (UUID blocker : game.getCombat().getBlockers()) { - if (player.flipCoin(game)) { + if (player.flipCoin(source, game, true)) { PreventDamageByTargetEffect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true); effect.setTargetPointer(new FixedTarget(blocker)); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/f/FinalParting.java b/Mage.Sets/src/mage/cards/f/FinalParting.java index 76239b9c4bb..132b8f9f257 100644 --- a/Mage.Sets/src/mage/cards/f/FinalParting.java +++ b/Mage.Sets/src/mage/cards/f/FinalParting.java @@ -69,7 +69,7 @@ class FinalPartingEffect extends OneShotEffect { if (controller.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { Cards searched = new CardsImpl(); - for (UUID cardId : (List) target.getTargets()) { + for (UUID cardId : target.getTargets()) { Card card = controller.getLibrary().getCard(cardId, game); searched.add(card); } diff --git a/Mage.Sets/src/mage/cards/f/FinalPayment.java b/Mage.Sets/src/mage/cards/f/FinalPayment.java new file mode 100644 index 00000000000..22486309c38 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FinalPayment.java @@ -0,0 +1,60 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.costs.AlternativeCostSourceAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.OptionalAdditionalCost; +import mage.abilities.costs.OrCost; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesToughness; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +/** + * + * @author FateRevoked + */ +public final class FinalPayment extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledPermanent("a creature or enchantment"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.ENCHANTMENT))); + } + + public FinalPayment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{B}"); + + // As an additional cost to cast this spell, pay 5 life or sacrifice a creature or enchantment. + final Cost lifeCost = new PayLifeCost(5); + final Cost sacrificeCost = new SacrificeTargetCost(new TargetControlledPermanent(filter)); + + this.getSpellAbility().addCost(new OrCost(lifeCost, sacrificeCost, + "pay 5 life or sacrifice a creature or enchantment")); + + // Destroy target creature + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public FinalPayment(final FinalPayment card) { + super(card); + } + + @Override + public FinalPayment copy() { + return new FinalPayment(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FinalPunishment.java b/Mage.Sets/src/mage/cards/f/FinalPunishment.java index f4dc817ccc2..abf048a6360 100644 --- a/Mage.Sets/src/mage/cards/f/FinalPunishment.java +++ b/Mage.Sets/src/mage/cards/f/FinalPunishment.java @@ -45,7 +45,7 @@ class FinalPunishmentAmount implements DynamicValue { @Override public int calculate(Game game, Ability source, Effect effect) { AmountOfDamageAPlayerReceivedThisTurnWatcher watcher - = (AmountOfDamageAPlayerReceivedThisTurnWatcher) game.getState().getWatchers().get(AmountOfDamageAPlayerReceivedThisTurnWatcher.class.getSimpleName()); + = game.getState().getWatcher(AmountOfDamageAPlayerReceivedThisTurnWatcher.class); if(watcher != null) { return watcher.getAmountOfDamageReceivedThisTurn(source.getFirstTarget()); } diff --git a/Mage.Sets/src/mage/cards/f/FinalStrike.java b/Mage.Sets/src/mage/cards/f/FinalStrike.java index 4cd4c7f1670..6881b640206 100644 --- a/Mage.Sets/src/mage/cards/f/FinalStrike.java +++ b/Mage.Sets/src/mage/cards/f/FinalStrike.java @@ -26,7 +26,7 @@ public final class FinalStrike extends CardImpl { this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); // Final Strike deals damage to target opponent equal to the sacrificed creature's power. - Effect effect = new DamageTargetEffect(new SacrificeCostCreaturesPower()); + Effect effect = new DamageTargetEffect(SacrificeCostCreaturesPower.instance); effect.setText("{this} deals damage to target opponent or planeswalker equal to the sacrificed creature's power"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetOpponentOrPlaneswalker()); diff --git a/Mage.Sets/src/mage/cards/f/Finn.java b/Mage.Sets/src/mage/cards/f/Finn.java index b4429e90ae7..6408b55ac2c 100644 --- a/Mage.Sets/src/mage/cards/f/Finn.java +++ b/Mage.Sets/src/mage/cards/f/Finn.java @@ -28,7 +28,7 @@ public final class Finn extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public Finn(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java b/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java index 72ce9e2c9dd..92e9f2cf2a1 100644 --- a/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java +++ b/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java @@ -59,7 +59,7 @@ class FireAndBrimstonePredicate extends PlayerPredicate { if (player == null || playerId == null) { return false; } - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null) { if (!watcher.getAttackedThisTurnCreatures().isEmpty()) { return player.getId().equals(game.getActivePlayerId()); diff --git a/Mage.Sets/src/mage/cards/f/FireAnts.java b/Mage.Sets/src/mage/cards/f/FireAnts.java index 208565fb1bc..a8bed48f784 100644 --- a/Mage.Sets/src/mage/cards/f/FireAnts.java +++ b/Mage.Sets/src/mage/cards/f/FireAnts.java @@ -27,7 +27,7 @@ public final class FireAnts extends CardImpl { static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FireAnts(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FireAtWill.java b/Mage.Sets/src/mage/cards/f/FireAtWill.java index 706a5cee467..efe7a67bce6 100644 --- a/Mage.Sets/src/mage/cards/f/FireAtWill.java +++ b/Mage.Sets/src/mage/cards/f/FireAtWill.java @@ -23,8 +23,8 @@ public final class FireAtWill extends CardImpl { static { filter.add(Predicates.or( - new AttackingPredicate(), - new BlockingPredicate())); + AttackingPredicate.instance, + BlockingPredicate.instance)); } public FireAtWill(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FireCovenant.java b/Mage.Sets/src/mage/cards/f/FireCovenant.java index ae9870a467a..80f8f729097 100644 --- a/Mage.Sets/src/mage/cards/f/FireCovenant.java +++ b/Mage.Sets/src/mage/cards/f/FireCovenant.java @@ -25,7 +25,7 @@ public final class FireCovenant extends CardImpl { this.getSpellAbility().addCost(new PayVariableLifeCost(true)); // Fire Covenant deals X damage divided as you choose among any number of target creatures. - DynamicValue xValue = new GetXValue(); + DynamicValue xValue = GetXValue.instance; this.getSpellAbility().addEffect(new DamageMultiEffect(xValue)); this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue)); } diff --git a/Mage.Sets/src/mage/cards/f/Fireball.java b/Mage.Sets/src/mage/cards/f/Fireball.java index df0543c9c68..7e56cf80172 100644 --- a/Mage.Sets/src/mage/cards/f/Fireball.java +++ b/Mage.Sets/src/mage/cards/f/Fireball.java @@ -1,8 +1,8 @@ package mage.cards.f; -import java.util.*; import mage.abilities.Ability; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -14,8 +14,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import java.util.*; + /** - * * @author BetaSteward_at_googlemail.com */ public final class Fireball extends CardImpl { @@ -27,14 +28,7 @@ public final class Fireball extends CardImpl { // Fireball costs 1 more to cast for each target beyond the first. this.getSpellAbility().addTarget(new FireballTargetCreatureOrPlayer(0, Integer.MAX_VALUE)); this.getSpellAbility().addEffect(new FireballEffect()); - } - - @Override - public void adjustCosts(Ability ability, Game game) { - int numTargets = ability.getTargets().isEmpty() ? 0 : ability.getTargets().get(0).getTargets().size(); - if (numTargets > 1) { - ability.getManaCostsToPay().add(new GenericManaCost(numTargets - 1)); - } + this.getSpellAbility().setCostAdjuster(FireballAdjuster.instance); } public Fireball(final Fireball card) { @@ -47,6 +41,18 @@ public final class Fireball extends CardImpl { } } +enum FireballAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + int numTargets = ability.getTargets().isEmpty() ? 0 : ability.getTargets().get(0).getTargets().size(); + if (numTargets > 1) { + ability.getManaCostsToPay().add(new GenericManaCost(numTargets - 1)); + } + } +} + class FireballEffect extends OneShotEffect { public FireballEffect() { diff --git a/Mage.Sets/src/mage/cards/f/FirebladeArtist.java b/Mage.Sets/src/mage/cards/f/FirebladeArtist.java new file mode 100644 index 00000000000..e11b412cc7b --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FirebladeArtist.java @@ -0,0 +1,116 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.SendOptionUsedEventEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetOpponentOrPlaneswalker; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FirebladeArtist extends CardImpl { + + public FirebladeArtist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // At the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new DoIfCostPaid( + new FirebladeArtistCreateReflexiveTriggerEffect(), + new SacrificeTargetCost(new TargetControlledPermanent( + StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT + )), "Sacrifice a creature to deal 2 damage to an opponent or planeswalker?" + ).setText("you may sacrifice a creature. When you do, " + + "{this} deals 2 damage to target opponent or planeswalker."), + TargetController.YOU, false + )); + } + + private FirebladeArtist(final FirebladeArtist card) { + super(card); + } + + @Override + public FirebladeArtist copy() { + return new FirebladeArtist(this); + } +} + +class FirebladeArtistCreateReflexiveTriggerEffect extends OneShotEffect { + + FirebladeArtistCreateReflexiveTriggerEffect() { + super(Outcome.Benefit); + } + + private FirebladeArtistCreateReflexiveTriggerEffect(final FirebladeArtistCreateReflexiveTriggerEffect effect) { + super(effect); + } + + @Override + public FirebladeArtistCreateReflexiveTriggerEffect copy() { + return new FirebladeArtistCreateReflexiveTriggerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.addDelayedTriggeredAbility(new FirebladeArtistReflexiveTriggeredAbility(), source); + return new SendOptionUsedEventEffect().apply(game, source); + } +} + +class FirebladeArtistReflexiveTriggeredAbility extends DelayedTriggeredAbility { + + FirebladeArtistReflexiveTriggeredAbility() { + super(new DamageTargetEffect(2), Duration.OneUse, true); + this.addTarget(new TargetOpponentOrPlaneswalker()); + } + + private FirebladeArtistReflexiveTriggeredAbility(final FirebladeArtistReflexiveTriggeredAbility ability) { + super(ability); + } + + @Override + public FirebladeArtistReflexiveTriggeredAbility copy() { + return new FirebladeArtistReflexiveTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.OPTION_USED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && event.getSourceId().equals(this.getSourceId()); + } + + @Override + public String getRule() { + return "{this} deals 2 damage to target opponent or planeswalker."; + } +} diff --git a/Mage.Sets/src/mage/cards/f/Firestorm.java b/Mage.Sets/src/mage/cards/f/Firestorm.java index 584afbec575..b489ee21b62 100644 --- a/Mage.Sets/src/mage/cards/f/Firestorm.java +++ b/Mage.Sets/src/mage/cards/f/Firestorm.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.UUID; @@ -16,6 +15,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetAnyTarget; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -24,32 +24,36 @@ import mage.target.common.TargetAnyTarget; public final class Firestorm extends CardImpl { public Firestorm(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // As an additional cost to cast Firestorm, discard X cards. this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); // Firestorm deals X damage to each of X target creatures and/or players. this.getSpellAbility().addEffect(new FirestormEffect()); + this.getSpellAbility().setTargetAdjuster(FirestormAdjuster.instance); } public Firestorm(final Firestorm card) { super(card); } + @Override + public Firestorm copy() { + return new Firestorm(this); + } +} + +enum FirestormAdjuster implements TargetAdjuster { + instance; + @Override public void adjustTargets(Ability ability, Game game) { - int xValue = new GetXValue().calculate(game, ability, null); + int xValue = GetXValue.instance.calculate(game, ability, null); if (xValue > 0) { Target target = new TargetAnyTarget(xValue); ability.addTarget(target); } } - - @Override - public Firestorm copy() { - return new Firestorm(this); - } } class FirestormEffect extends OneShotEffect { @@ -66,7 +70,7 @@ class FirestormEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); - int amount = (new GetXValue()).calculate(game, source, this); + int amount = (GetXValue.instance).calculate(game, source, this); if (you != null) { if (!source.getTargets().isEmpty()) { for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { @@ -85,9 +89,6 @@ class FirestormEffect extends OneShotEffect { } return false; } - - - @Override public FirestormEffect copy() { diff --git a/Mage.Sets/src/mage/cards/f/FlagstonesOfTrokair.java b/Mage.Sets/src/mage/cards/f/FlagstonesOfTrokair.java index 674adbeb784..522d33e1176 100644 --- a/Mage.Sets/src/mage/cards/f/FlagstonesOfTrokair.java +++ b/Mage.Sets/src/mage/cards/f/FlagstonesOfTrokair.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.mana.WhiteManaAbility; @@ -14,8 +12,9 @@ import mage.filter.common.FilterLandCard; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class FlagstonesOfTrokair extends CardImpl { @@ -34,7 +33,7 @@ public final class FlagstonesOfTrokair extends CardImpl { this.addAbility(new WhiteManaAbility()); // When Flagstones of Trokair is put into a graveyard from the battlefield, you may search your library for a Plains card and put it onto the battlefield tapped. If you do, shuffle your library. - this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(FILTER), true, false), true)); + this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(FILTER), true, false), true, false)); } public FlagstonesOfTrokair(final FlagstonesOfTrokair card) { diff --git a/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java b/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java index f255bdf5361..73580ab86c0 100644 --- a/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java +++ b/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java @@ -29,7 +29,7 @@ public final class FlameKinWarScout extends CardImpl { private static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FlameKinWarScout(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/Flamebreak.java b/Mage.Sets/src/mage/cards/f/Flamebreak.java index f80450b3a62..1e834bd05a4 100644 --- a/Mage.Sets/src/mage/cards/f/Flamebreak.java +++ b/Mage.Sets/src/mage/cards/f/Flamebreak.java @@ -76,7 +76,7 @@ class FlamebreakCantRegenerateEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.REGENERATE) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), source.getSourceId()); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.wasDamaged(event.getTargetId(), game); } diff --git a/Mage.Sets/src/mage/cards/f/FlamerushRider.java b/Mage.Sets/src/mage/cards/f/FlamerushRider.java index e6ed2e29da3..be2c67e9fd8 100644 --- a/Mage.Sets/src/mage/cards/f/FlamerushRider.java +++ b/Mage.Sets/src/mage/cards/f/FlamerushRider.java @@ -35,8 +35,8 @@ public final class FlamerushRider extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target attacking creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new AttackingPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(AttackingPredicate.instance); } public FlamerushRider(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FlamesOfTheRazeBoar.java b/Mage.Sets/src/mage/cards/f/FlamesOfTheRazeBoar.java new file mode 100644 index 00000000000..57230b6b870 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FlamesOfTheRazeBoar.java @@ -0,0 +1,78 @@ +package mage.cards.f; + +import mage.abilities.Ability; +import mage.abilities.condition.common.FerociousCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FlamesOfTheRazeBoar extends CardImpl { + + public FlamesOfTheRazeBoar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{R}"); + + // Flames of the Raze-Boar deals 4 damage to target creature an opponent controls. Then Flames of the Raze-Boar deals 2 damage to each other creature that player controls if you control a creature with power 4 or greater. + this.getSpellAbility().addEffect(new FlamesOfTheRazeBoarEffect()); + this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent()); + } + + private FlamesOfTheRazeBoar(final FlamesOfTheRazeBoar card) { + super(card); + } + + @Override + public FlamesOfTheRazeBoar copy() { + return new FlamesOfTheRazeBoar(this); + } +} + +class FlamesOfTheRazeBoarEffect extends OneShotEffect { + + FlamesOfTheRazeBoarEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 4 damage to target creature an opponent controls. " + + "Then {this} deals 2 damage to each other creature that player controls " + + "if you control a creature with power 4 or greater."; + } + + private FlamesOfTheRazeBoarEffect(final FlamesOfTheRazeBoarEffect effect) { + super(effect); + } + + @Override + public FlamesOfTheRazeBoarEffect copy() { + return new FlamesOfTheRazeBoarEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + permanent.damage(4, source.getSourceId(), game); + if (!FerociousCondition.instance.apply(game, source)) { + return true; + } + FilterPermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(permanent.getControllerId())); + filter.add(Predicates.not(new PermanentIdPredicate(permanent.getId()))); + return new DamageAllEffect(2, filter).apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/f/FlameshadowConjuring.java b/Mage.Sets/src/mage/cards/f/FlameshadowConjuring.java index c490eb81919..9db0cd39359 100644 --- a/Mage.Sets/src/mage/cards/f/FlameshadowConjuring.java +++ b/Mage.Sets/src/mage/cards/f/FlameshadowConjuring.java @@ -33,7 +33,7 @@ public final class FlameshadowConjuring extends CardImpl { private static final FilterControlledCreaturePermanent filterNontoken = new FilterControlledCreaturePermanent("nontoken creature"); static { - filterNontoken.add(Predicates.not(new TokenPredicate())); + filterNontoken.add(Predicates.not(TokenPredicate.instance)); } public FlameshadowConjuring(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FlayerDrone.java b/Mage.Sets/src/mage/cards/f/FlayerDrone.java index 19482d906b7..548e19f0181 100644 --- a/Mage.Sets/src/mage/cards/f/FlayerDrone.java +++ b/Mage.Sets/src/mage/cards/f/FlayerDrone.java @@ -27,8 +27,8 @@ public final class FlayerDrone extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another colorless creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public FlayerDrone(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FlayingTendrils.java b/Mage.Sets/src/mage/cards/f/FlayingTendrils.java index 03e66175359..4531b660354 100644 --- a/Mage.Sets/src/mage/cards/f/FlayingTendrils.java +++ b/Mage.Sets/src/mage/cards/f/FlayingTendrils.java @@ -67,7 +67,7 @@ class FlayingTendrilsReplacementEffect extends ReplacementEffectImpl { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && permanent != null) { - return controller.moveCards((Card) permanent, Zone.EXILED, source, game); + return controller.moveCards(permanent, Zone.EXILED, source, game); } return false; } diff --git a/Mage.Sets/src/mage/cards/f/FleshAllergy.java b/Mage.Sets/src/mage/cards/f/FleshAllergy.java index fb92c9a5c14..6206824743b 100644 --- a/Mage.Sets/src/mage/cards/f/FleshAllergy.java +++ b/Mage.Sets/src/mage/cards/f/FleshAllergy.java @@ -57,7 +57,7 @@ class FleshAllergyWatcher extends Watcher { public int creaturesDiedThisTurn = 0; public FleshAllergyWatcher() { - super(FleshAllergyWatcher.class.getSimpleName(), WatcherScope.GAME); + super(FleshAllergyWatcher.class, WatcherScope.GAME); } public FleshAllergyWatcher(final FleshAllergyWatcher watcher) { @@ -105,7 +105,7 @@ class FleshAllergyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - FleshAllergyWatcher watcher = (FleshAllergyWatcher) game.getState().getWatchers().get(FleshAllergyWatcher.class.getSimpleName()); + FleshAllergyWatcher watcher = game.getState().getWatcher(FleshAllergyWatcher.class); Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (permanent != null && watcher != null) { Player player = game.getPlayer(permanent.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/f/FleshmadSteed.java b/Mage.Sets/src/mage/cards/f/FleshmadSteed.java index 491b9ce5f15..8b8a9ca914a 100644 --- a/Mage.Sets/src/mage/cards/f/FleshmadSteed.java +++ b/Mage.Sets/src/mage/cards/f/FleshmadSteed.java @@ -20,7 +20,7 @@ public final class FleshmadSteed extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public FleshmadSteed(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/Flicker.java b/Mage.Sets/src/mage/cards/f/Flicker.java index b4631281520..dd16b1d1cb0 100644 --- a/Mage.Sets/src/mage/cards/f/Flicker.java +++ b/Mage.Sets/src/mage/cards/f/Flicker.java @@ -21,7 +21,7 @@ public final class Flicker extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("nontoken permanent"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public Flicker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/Flickerwisp.java b/Mage.Sets/src/mage/cards/f/Flickerwisp.java index 828b1b8d3b5..b4af63cae71 100644 --- a/Mage.Sets/src/mage/cards/f/Flickerwisp.java +++ b/Mage.Sets/src/mage/cards/f/Flickerwisp.java @@ -33,7 +33,7 @@ public final class Flickerwisp extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Flickerwisp(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/Fling.java b/Mage.Sets/src/mage/cards/f/Fling.java index 422ec3263ee..67de60eca99 100644 --- a/Mage.Sets/src/mage/cards/f/Fling.java +++ b/Mage.Sets/src/mage/cards/f/Fling.java @@ -22,7 +22,7 @@ public final class Fling extends CardImpl { public Fling(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); - Effect effect = new DamageTargetEffect(new SacrificeCostCreaturesPower()); + Effect effect = new DamageTargetEffect(SacrificeCostCreaturesPower.instance); effect.setText("{this} deals damage equal to the sacrificed creature's power to any target"); this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); this.getSpellAbility().addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java b/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java index a5aa32a32a1..f2e77e0b509 100644 --- a/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java +++ b/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java @@ -25,7 +25,7 @@ public final class FloatingDreamZubera extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(new ZuberasDiedDynamicValue())), new ZuberasDiedWatcher()); + this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(ZuberasDiedDynamicValue.instance)), new ZuberasDiedWatcher()); } public FloatingDreamZubera(final FloatingDreamZubera card) { diff --git a/Mage.Sets/src/mage/cards/f/FlockOfRabidSheep.java b/Mage.Sets/src/mage/cards/f/FlockOfRabidSheep.java index 79ac3e5e977..018f5f3b239 100644 --- a/Mage.Sets/src/mage/cards/f/FlockOfRabidSheep.java +++ b/Mage.Sets/src/mage/cards/f/FlockOfRabidSheep.java @@ -59,7 +59,7 @@ class FlockOfRabidSheepEffect extends OneShotEffect { int repeat = source.getManaCostsToPay().getX(); int wonCount = 0; for (int i = 1; i <= repeat; i++) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { wonCount++; } } diff --git a/Mage.Sets/src/mage/cards/f/FloralSpuzzem.java b/Mage.Sets/src/mage/cards/f/FloralSpuzzem.java index c418a879265..8fde7de47c1 100644 --- a/Mage.Sets/src/mage/cards/f/FloralSpuzzem.java +++ b/Mage.Sets/src/mage/cards/f/FloralSpuzzem.java @@ -27,7 +27,7 @@ public final class FloralSpuzzem extends CardImpl { static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public FloralSpuzzem(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/FlowstoneSlide.java b/Mage.Sets/src/mage/cards/f/FlowstoneSlide.java index 479d9f124be..fe68ae63e8b 100644 --- a/Mage.Sets/src/mage/cards/f/FlowstoneSlide.java +++ b/Mage.Sets/src/mage/cards/f/FlowstoneSlide.java @@ -20,8 +20,8 @@ public final class FlowstoneSlide extends CardImpl { public FlowstoneSlide(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{2}{R}{R}"); - DynamicValue xPos = new ManacostVariableValue(); - DynamicValue xNeg = new SignInversionDynamicValue(new ManacostVariableValue()); + DynamicValue xPos = ManacostVariableValue.instance; + DynamicValue xNeg = new SignInversionDynamicValue(ManacostVariableValue.instance); // All creatures get +X/-X until end of turn. this.getSpellAbility().addEffect(new BoostAllEffect(xPos, xNeg, Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/f/Fluxcharger.java b/Mage.Sets/src/mage/cards/f/Fluxcharger.java index fecfe06e928..5f31edb2b66 100644 --- a/Mage.Sets/src/mage/cards/f/Fluxcharger.java +++ b/Mage.Sets/src/mage/cards/f/Fluxcharger.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.continuous.SwitchPowerToughnessSourceEffect; @@ -9,18 +7,19 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Fluxcharger extends CardImpl { public Fluxcharger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}"); this.subtype.add(SubType.WEIRD); this.power = new MageInt(1); @@ -29,7 +28,7 @@ public final class Fluxcharger extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever you cast an instant or sorcery spell, you may switch Fluxcharger's power and toughness until end of turn. - this.addAbility(new SpellCastControllerTriggeredAbility(new SwitchPowerToughnessSourceEffect(Duration.EndOfTurn), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, true)); + this.addAbility(new SpellCastControllerTriggeredAbility(new SwitchPowerToughnessSourceEffect(Duration.EndOfTurn), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, true)); } diff --git a/Mage.Sets/src/mage/cards/f/FontOfAgonies.java b/Mage.Sets/src/mage/cards/f/FontOfAgonies.java new file mode 100644 index 00000000000..4abcc4eb09a --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FontOfAgonies.java @@ -0,0 +1,83 @@ +package mage.cards.f; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FontOfAgonies extends CardImpl { + + public FontOfAgonies(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); + + // Whenever you pay life, put that many blood counters on Font of Agonies. + this.addAbility(new FontOfAgoniesTriggeredAbility()); + + // {1}{B}, Remove four blood counters from Font of Agonies: Destroy target creature. + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl("{1}{B}")); + ability.addCost(new RemoveCountersSourceCost(CounterType.BLOOD.createInstance(4))); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private FontOfAgonies(final FontOfAgonies card) { + super(card); + } + + @Override + public FontOfAgonies copy() { + return new FontOfAgonies(this); + } +} + +class FontOfAgoniesTriggeredAbility extends TriggeredAbilityImpl { + + FontOfAgoniesTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.BLOOD.createInstance()), false); + } + + private FontOfAgoniesTriggeredAbility(final FontOfAgoniesTriggeredAbility ability) { + super(ability); + } + + @Override + public FontOfAgoniesTriggeredAbility copy() { + return new FontOfAgoniesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.LIFE_PAID); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(controllerId) && event.getAmount() > 0) { + this.getEffects().clear(); + this.addEffect(new AddCountersSourceEffect(CounterType.BLOOD.createInstance(event.getAmount()))); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever you pay life, put that many blood counters on {this}."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/f/FootlightFiend.java b/Mage.Sets/src/mage/cards/f/FootlightFiend.java new file mode 100644 index 00000000000..6d7d41f9794 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FootlightFiend.java @@ -0,0 +1,41 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetAnyTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FootlightFiend extends CardImpl { + + public FootlightFiend(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B/R}"); + + this.subtype.add(SubType.DEVIL); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Footlight Fiend dies, it deals 1 damage to any target. + Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(1, "it")); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + private FootlightFiend(final FootlightFiend card) { + super(card); + } + + @Override + public FootlightFiend copy() { + return new FootlightFiend(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForbiddingSpirit.java b/Mage.Sets/src/mage/cards/f/ForbiddingSpirit.java new file mode 100644 index 00000000000..b96e38211d1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForbiddingSpirit.java @@ -0,0 +1,47 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.common.combat.CantAttackYouUnlessPayManaAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ForbiddingSpirit extends CardImpl { + + public ForbiddingSpirit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + + this.subtype.add(SubType.SPIRIT); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Forbidding Spirit enters the battlefield, until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures. + ContinuousEffect effect = new CantAttackYouUnlessPayManaAllEffect( + new ManaCostsImpl("{2}"), true + ); + effect.setDuration(Duration.UntilYourNextTurn); + effect.setText("until your next turn, creatures can't attack you or a planeswalker you control " + + "unless their controller pays {2} for each of those creatures."); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); + } + + private ForbiddingSpirit(final ForbiddingSpirit card) { + super(card); + } + + @Override + public ForbiddingSpirit copy() { + return new ForbiddingSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForceLightning.java b/Mage.Sets/src/mage/cards/f/ForceLightning.java index 64b07aa29d1..46793dcd5d9 100644 --- a/Mage.Sets/src/mage/cards/f/ForceLightning.java +++ b/Mage.Sets/src/mage/cards/f/ForceLightning.java @@ -24,7 +24,7 @@ public final class ForceLightning extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}{R}"); // Force Lightning deals X damage to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); // Scry X. diff --git a/Mage.Sets/src/mage/cards/f/Forcefield.java b/Mage.Sets/src/mage/cards/f/Forcefield.java index e225e7c328a..9534b45eb50 100644 --- a/Mage.Sets/src/mage/cards/f/Forcefield.java +++ b/Mage.Sets/src/mage/cards/f/Forcefield.java @@ -53,7 +53,7 @@ class ForcefieldEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("an unblocked creature"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } ForcefieldEffect() { diff --git a/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java b/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java index 710d7d12970..75685ca33fc 100644 --- a/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java +++ b/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java @@ -28,7 +28,7 @@ public final class ForerunnerOfSlaughter extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creature"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public ForerunnerOfSlaughter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheCoalition.java b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheCoalition.java index bb62690e7de..1cd38f8a524 100644 --- a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheCoalition.java +++ b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheCoalition.java @@ -26,7 +26,7 @@ public final class ForerunnerOfTheCoalition extends CardImpl { private static final FilterPermanent filterAnotherPirate = new FilterPermanent(SubType.PIRATE, "another " + SubType.PIRATE.toString()); static { - filterAnotherPirate.add(new AnotherPredicate()); + filterAnotherPirate.add(AnotherPredicate.instance); filterAnotherPirate.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheHeralds.java b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheHeralds.java index c1eef1e04dd..1a161bba1c0 100644 --- a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheHeralds.java +++ b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheHeralds.java @@ -28,7 +28,7 @@ public final class ForerunnerOfTheHeralds extends CardImpl { private static final FilterPermanent filterAnotherMerfolk = new FilterPermanent(SubType.MERFOLK, "another " + SubType.MERFOLK.toString()); static { - filterAnotherMerfolk.add(new AnotherPredicate()); + filterAnotherMerfolk.add(AnotherPredicate.instance); filterAnotherMerfolk.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheLegion.java b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheLegion.java index 2ada4b8d5a1..f5efb3eea30 100644 --- a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheLegion.java +++ b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheLegion.java @@ -26,7 +26,7 @@ public final class ForerunnerOfTheLegion extends CardImpl { private static final FilterPermanent filterAnotherVampire = new FilterPermanent(SubType.VAMPIRE, "another " + SubType.VAMPIRE.toString()); static { - filterAnotherVampire.add(new AnotherPredicate()); + filterAnotherVampire.add(AnotherPredicate.instance); filterAnotherVampire.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/f/Foreshadow.java b/Mage.Sets/src/mage/cards/f/Foreshadow.java index e1d86d5e569..01fabc683ef 100644 --- a/Mage.Sets/src/mage/cards/f/Foreshadow.java +++ b/Mage.Sets/src/mage/cards/f/Foreshadow.java @@ -29,7 +29,7 @@ public final class Foreshadow extends CardImpl { // Choose a card name, then target opponent puts the top card of their library into their graveyard. If that card has the chosen name, you draw a card. this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); - this.getSpellAbility().addEffect(new ForeshadowEffect()); + this.getSpellAbility().addEffect(new ForeshadowEffect().concatBy("then")); this.getSpellAbility().addTarget(new TargetOpponent()); // Draw a card at the beginning of the next turn's upkeep. @@ -51,7 +51,7 @@ class ForeshadowEffect extends OneShotEffect { public ForeshadowEffect() { super(Outcome.DrawCard); - this.staticText = ", then target opponent puts the top card of their library into their graveyard. If that card has the chosen name, you draw a card"; + this.staticText = "target opponent puts the top card of their library into their graveyard. If that card has the chosen name, you draw a card"; } public ForeshadowEffect(final ForeshadowEffect effect) { diff --git a/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java b/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java index e3e24edaa2c..b745f928008 100644 --- a/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java +++ b/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java @@ -29,7 +29,7 @@ public final class ForgeOfHeroes extends CardImpl { = new FilterPermanent("commander that entered the battlefield this turn"); static { - filter.add(new CommanderPredicate()); + filter.add(CommanderPredicate.instance); filter.add(new EnteredThisTurnPredicate()); } diff --git a/Mage.Sets/src/mage/cards/f/ForgottenAncient.java b/Mage.Sets/src/mage/cards/f/ForgottenAncient.java index 6693a73de18..dc8393e5afd 100644 --- a/Mage.Sets/src/mage/cards/f/ForgottenAncient.java +++ b/Mage.Sets/src/mage/cards/f/ForgottenAncient.java @@ -35,7 +35,7 @@ import java.util.UUID; public final class ForgottenAncient extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ForgottenAncient(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/f/ForgottenLore.java b/Mage.Sets/src/mage/cards/f/ForgottenLore.java index 62ec82fcf46..8798d3f7555 100644 --- a/Mage.Sets/src/mage/cards/f/ForgottenLore.java +++ b/Mage.Sets/src/mage/cards/f/ForgottenLore.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -18,14 +16,16 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetOpponent; + +import java.util.UUID; + /** - * * @author LoneFox */ public final class ForgottenLore extends CardImpl { public ForgottenLore(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); // Target opponent chooses a card in your graveyard. You may pay {G}. If you do, repeat this process except that opponent can't choose a card already chosen for Forgotten Lore. Then put the last chosen card into your hand. this.getSpellAbility().addEffect(new ForgottenLoreEffect()); @@ -62,8 +62,7 @@ class ForgottenLoreEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); - if(you != null && opponent != null) - { + if (you != null && opponent != null) { FilterCard filter = new FilterCard(); filter.add(new OwnerIdPredicate(you.getId())); Cost cost = new ManaCostsImpl("{G}"); @@ -73,31 +72,31 @@ class ForgottenLoreEffect extends OneShotEffect { do { chosenCard = new TargetCardInGraveyard(filter); chosenCard.setNotTarget(true); - if(chosenCard.canChoose(opponent.getId(), game)) { + if (chosenCard.canChoose(opponent.getId(), game)) { opponent.chooseTarget(Outcome.ReturnToHand, chosenCard, source, game); card = game.getCard(chosenCard.getFirstTarget()); - filter.add(Predicates.not(new CardIdPredicate(card.getId()))); - game.informPlayers("Forgotten Lore: " + opponent.getLogName() + " has chosen " + card.getLogName()); - } - else { + if (card != null) { + filter.add(Predicates.not(new CardIdPredicate(card.getId()))); + game.informPlayers("Forgotten Lore: " + opponent.getLogName() + " has chosen " + card.getLogName()); + } + } else { done = true; } - if(!done) { - if(cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {G} to choose a different card ?", source, game)) { + if (!done) { + if (cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {G} to choose a different card ?", source, game)) { cost.clearPaid(); - if(!cost.pay(source, game, source.getSourceId(), you.getId(), false, null)) { + if (!cost.pay(source, game, source.getSourceId(), you.getId(), false, null)) { done = true; } - } - else { + } else { done = true; } } - } while(!done); + } while (!done); - if(card != null) { + if (card != null) { Cards cardsToHand = new CardsImpl(); cardsToHand.add(card); you.moveCards(cardsToHand, Zone.HAND, source, game); diff --git a/Mage.Sets/src/mage/cards/f/FoulTongueInvocation.java b/Mage.Sets/src/mage/cards/f/FoulTongueInvocation.java index 629c797974f..cb2a1d7d70b 100644 --- a/Mage.Sets/src/mage/cards/f/FoulTongueInvocation.java +++ b/Mage.Sets/src/mage/cards/f/FoulTongueInvocation.java @@ -1,15 +1,14 @@ package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.SacrificeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -22,23 +21,19 @@ import mage.target.TargetPlayer; import mage.target.common.TargetCardInHand; import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class FoulTongueInvocation extends CardImpl { - private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)"); - - static { - filter.add(new SubtypePredicate(SubType.DRAGON)); - } - public FoulTongueInvocation(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); // As an additional cost to cast Foul-Tongue Invocation, you may reveal a Dragon card from your hand. this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); + this.getSpellAbility().setCostAdjuster(FoulTongueInvocationAdjuster.instance); // Target player sacrifices a creature. If you revealed a Dragon card or controlled a Dragon as you cast Foul-Tongue Invocation, you gain 4 life. this.getSpellAbility().addTarget(new TargetPlayer()); @@ -47,18 +42,6 @@ public final class FoulTongueInvocation extends CardImpl { this.getSpellAbility().addWatcher(new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability.getAbilityType() == AbilityType.SPELL) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - if (controller.getHand().count(filter, game) > 0) { - ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter))); - } - } - } - } - public FoulTongueInvocation(final FoulTongueInvocation card) { super(card); } @@ -69,6 +52,25 @@ public final class FoulTongueInvocation extends CardImpl { } } +enum FoulTongueInvocationAdjuster implements CostAdjuster { + instance; + private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + } + + @Override + public void adjustCosts(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller != null) { + if (controller.getHand().count(filter, game) > 0) { + ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter))); + } + } + } +} + class FoulTongueInvocationEffect extends OneShotEffect { public FoulTongueInvocationEffect() { @@ -89,7 +91,7 @@ class FoulTongueInvocationEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = (DragonOnTheBattlefieldWhileSpellWasCastWatcher) game.getState().getWatchers().get(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class.getSimpleName()); + DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); if (watcher != null && watcher.castWithConditionTrue(source.getId())) { controller.gainLife(4, game, source); } diff --git a/Mage.Sets/src/mage/cards/f/FoundryStreetDenizen.java b/Mage.Sets/src/mage/cards/f/FoundryStreetDenizen.java index 49fb7989716..e60bfdec3b7 100644 --- a/Mage.Sets/src/mage/cards/f/FoundryStreetDenizen.java +++ b/Mage.Sets/src/mage/cards/f/FoundryStreetDenizen.java @@ -27,7 +27,7 @@ public final class FoundryStreetDenizen extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another red creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new ColorPredicate(ObjectColor.RED)); } diff --git a/Mage.Sets/src/mage/cards/f/FountainOfCho.java b/Mage.Sets/src/mage/cards/f/FountainOfCho.java index 566c64e58f9..1686099ab5e 100644 --- a/Mage.Sets/src/mage/cards/f/FountainOfCho.java +++ b/Mage.Sets/src/mage/cards/f/FountainOfCho.java @@ -34,7 +34,7 @@ public final class FountainOfCho extends CardImpl { // {T}, Remove any number of storage counters from Fountain of Cho: Add {W} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.WhiteMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {W} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/f/FrayingSanity.java b/Mage.Sets/src/mage/cards/f/FrayingSanity.java index c53c85c054d..501a6e021fe 100644 --- a/Mage.Sets/src/mage/cards/f/FrayingSanity.java +++ b/Mage.Sets/src/mage/cards/f/FrayingSanity.java @@ -113,7 +113,7 @@ class FrayingSanityEffect extends OneShotEffect { } Player enchantedPlayer = game.getPlayer(enchantment.getAttachedTo()); if (enchantedPlayer != null) { - CardsPutIntoGraveyardWatcher watcher = (CardsPutIntoGraveyardWatcher) game.getState().getWatchers().get(CardsPutIntoGraveyardWatcher.class.getSimpleName()); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); if (watcher != null) { xAmount = watcher.getAmountCardsPutToGraveyard(enchantedPlayer.getId()); } diff --git a/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java b/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java index 47310ccc4b2..2bc8ed23a36 100644 --- a/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java +++ b/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java @@ -75,7 +75,7 @@ class FreeRangeChickenEffect extends OneShotEffect { if (firstRoll == secondRoll) { game.addEffect(new BoostSourceEffect(firstRoll, firstRoll, Duration.EndOfTurn), source); } - FreeRangeChickenWatcher watcher = (FreeRangeChickenWatcher) game.getState().getWatchers().get(FreeRangeChickenWatcher.class.getSimpleName()); + FreeRangeChickenWatcher watcher = game.getState().getWatcher(FreeRangeChickenWatcher.class); if (watcher != null) { int totalRoll = firstRoll + secondRoll; Permanent sourcePermanent = game.getPermanent(source.getSourceId()); @@ -98,7 +98,7 @@ class FreeRangeChickenWatcher extends Watcher { private final Map totalRolls = new HashMap<>(); public FreeRangeChickenWatcher() { - super(FreeRangeChickenWatcher.class.getSimpleName(), WatcherScope.GAME); + super(FreeRangeChickenWatcher.class, WatcherScope.GAME); } public FreeRangeChickenWatcher(final FreeRangeChickenWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/f/FreneticEfreet.java b/Mage.Sets/src/mage/cards/f/FreneticEfreet.java index b2f407420be..e5d37014a01 100644 --- a/Mage.Sets/src/mage/cards/f/FreneticEfreet.java +++ b/Mage.Sets/src/mage/cards/f/FreneticEfreet.java @@ -69,7 +69,7 @@ class FreneticEfreetEffect extends OneShotEffect { if (controller == null) { return false; } - boolean flip = controller.flipCoin(game); + boolean flip = controller.flipCoin(source, game, true); if (permanent == null) { return false; } diff --git a/Mage.Sets/src/mage/cards/f/FreneticSliver.java b/Mage.Sets/src/mage/cards/f/FreneticSliver.java index 6655f21dbd4..e054ecb968f 100644 --- a/Mage.Sets/src/mage/cards/f/FreneticSliver.java +++ b/Mage.Sets/src/mage/cards/f/FreneticSliver.java @@ -76,7 +76,7 @@ class FreneticSliverEffect extends OneShotEffect { if (player == null || perm == null) { return false; } - if (player.flipCoin(game)) { + if (player.flipCoin(source, game, true)) { return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true).apply(game, source); } else { return perm.sacrifice(source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/f/FreshMeat.java b/Mage.Sets/src/mage/cards/f/FreshMeat.java index 886d76becdd..99386549264 100644 --- a/Mage.Sets/src/mage/cards/f/FreshMeat.java +++ b/Mage.Sets/src/mage/cards/f/FreshMeat.java @@ -41,7 +41,7 @@ class FreshMeatDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - CreaturesDiedWatcher watcher = (CreaturesDiedWatcher) game.getState().getWatchers().get(CreaturesDiedWatcher.class.getSimpleName()); + CreaturesDiedWatcher watcher = game.getState().getWatcher(CreaturesDiedWatcher.class); if (watcher != null) { return watcher.getAmountOfCreaturesDiedThisTurnByController(sourceAbility.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/f/FretworkColony.java b/Mage.Sets/src/mage/cards/f/FretworkColony.java index 6c08fb8a163..5521f29bbb6 100644 --- a/Mage.Sets/src/mage/cards/f/FretworkColony.java +++ b/Mage.Sets/src/mage/cards/f/FretworkColony.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -16,14 +14,15 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.counters.CounterType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class FretworkColony extends CardImpl { public FretworkColony(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.INSECT); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -34,8 +33,7 @@ public final class FretworkColony extends CardImpl { // At the beginning of your upkeep, put a +1/+1 counter on Fretwork Colony and you lose 1 life. Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false); Effect effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - ability.addEffect(effect); + ability.addEffect(effect.concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FreyaliseSupplicant.java b/Mage.Sets/src/mage/cards/f/FreyaliseSupplicant.java new file mode 100644 index 00000000000..92a0ce7e204 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FreyaliseSupplicant.java @@ -0,0 +1,61 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.HalfValue; +import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesPower; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public final class FreyaliseSupplicant extends CardImpl { + + private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("red or white creature"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.RED), + new ColorPredicate(ObjectColor.WHITE))); + } + + public FreyaliseSupplicant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {tap}, Sacrifice a red or white creature: Freyalise Supplicant deals damage to any target equal to half the sacrificed creature's power, rounded down. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new HalfValue(SacrificeCostCreaturesPower.instance, false)), new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + + } + + private FreyaliseSupplicant(final FreyaliseSupplicant card) { + super(card); + } + + @Override + public FreyaliseSupplicant copy() { + return new FreyaliseSupplicant(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FreyalisesCharm.java b/Mage.Sets/src/mage/cards/f/FreyalisesCharm.java index 2690555929c..35a573cb4fe 100644 --- a/Mage.Sets/src/mage/cards/f/FreyalisesCharm.java +++ b/Mage.Sets/src/mage/cards/f/FreyalisesCharm.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; @@ -15,8 +13,9 @@ import mage.constants.CardType; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class FreyalisesCharm extends CardImpl { @@ -33,7 +32,7 @@ public final class FreyalisesCharm extends CardImpl { // Whenever an opponent casts a black spell, you may pay {G}{G}. If you do, you draw a card. this.addAbility(new SpellCastOpponentTriggeredAbility( new DoIfCostPaid( - new DrawCardSourceControllerEffect(1), + new DrawCardSourceControllerEffect(1, "you"), new ManaCostsImpl("{G}{G}") ), filter, false )); diff --git a/Mage.Sets/src/mage/cards/f/FreyalisesWinds.java b/Mage.Sets/src/mage/cards/f/FreyalisesWinds.java new file mode 100644 index 00000000000..1c5b0a09220 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FreyalisesWinds.java @@ -0,0 +1,93 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BecomesTappedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author jeffwadsworth + */ +public final class FreyalisesWinds extends CardImpl { + + public FreyalisesWinds(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}"); + + // Whenever a permanent becomes tapped, put a wind counter on it. + Effect effect = new AddCountersTargetEffect(CounterType.WIND.createInstance()); + effect.setText("put a wind counter on it."); + this.addAbility(new BecomesTappedTriggeredAbility(effect, false, new FilterPermanent("a permanent"), true)); + + // If a permanent with a wind counter on it would untap during its controller's untap step, remove all wind counters from it instead. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new FreyalisesWindsReplacementEffect())); + + } + + private FreyalisesWinds(final FreyalisesWinds card) { + super(card); + } + + @Override + public FreyalisesWinds copy() { + return new FreyalisesWinds(this); + } +} + +class FreyalisesWindsReplacementEffect extends ReplacementEffectImpl { + + FreyalisesWindsReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If a permanent with a wind counter on it would untap during its controller's untap step, remove all wind counters from it instead"; + } + + FreyalisesWindsReplacementEffect(final FreyalisesWindsReplacementEffect effect) { + super(effect); + } + + @Override + public FreyalisesWindsReplacementEffect copy() { + return new FreyalisesWindsReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent permanentUntapping = game.getPermanent(event.getTargetId()); + permanentUntapping.removeCounters(CounterType.WIND.createInstance(), game); + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return (event.getType() == GameEvent.EventType.UNTAP + && game.getPhase().getStep().getType() == PhaseStep.UNTAP); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanentUntapping = game.getPermanent(event.getTargetId()); + return (permanentUntapping != null + && event.getPlayerId().equals(permanentUntapping.getControllerId()) + && permanentUntapping.getCounters(game).getCount(CounterType.WIND) > 0); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FrilledMystic.java b/Mage.Sets/src/mage/cards/f/FrilledMystic.java new file mode 100644 index 00000000000..c8332b4a853 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FrilledMystic.java @@ -0,0 +1,48 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.TargetSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FrilledMystic extends CardImpl { + + public FrilledMystic(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}{U}{U}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.LIZARD); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // When Frilled Mystic enters the battlefield, you may counter target spell. + Ability ability = new EntersBattlefieldTriggeredAbility(new CounterTargetEffect(), true); + ability.addTarget(new TargetSpell()); + this.addAbility(ability); + } + + private FrilledMystic(final FrilledMystic card) { + super(card); + } + + @Override + public FrilledMystic copy() { + return new FrilledMystic(this); + } +} +// nonagon infinity opens the door \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/f/FungalReaches.java b/Mage.Sets/src/mage/cards/f/FungalReaches.java index 92598fdd615..69f0a3cbe66 100644 --- a/Mage.Sets/src/mage/cards/f/FungalReaches.java +++ b/Mage.Sets/src/mage/cards/f/FungalReaches.java @@ -38,7 +38,7 @@ public final class FungalReaches extends CardImpl { // {1}, Remove X storage counters from Fungal Reaches: Add X mana in any combination of {R} and/or {G}. ability = new SimpleManaAbility(Zone.BATTLEFIELD, - new AddManaInAnyCombinationEffect(new RemovedCountersForCostValue(), ColoredManaSymbol.R, ColoredManaSymbol.G), + new AddManaInAnyCombinationEffect(RemovedCountersForCostValue.instance, ColoredManaSymbol.R, ColoredManaSymbol.G), new GenericManaCost(1)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance())); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/f/FungalSprouting.java b/Mage.Sets/src/mage/cards/f/FungalSprouting.java index d363b9a9ed4..66923625376 100644 --- a/Mage.Sets/src/mage/cards/f/FungalSprouting.java +++ b/Mage.Sets/src/mage/cards/f/FungalSprouting.java @@ -19,7 +19,7 @@ public final class FungalSprouting extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); // create X 1/1 green Saproling creature tokens, where X is the greatest power among creatures you control. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new GreatestPowerAmongControlledCreaturesValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), GreatestPowerAmongControlledCreaturesValue.instance)); } public FungalSprouting(final FungalSprouting card) { diff --git a/Mage.Sets/src/mage/cards/f/FyndhornDruid.java b/Mage.Sets/src/mage/cards/f/FyndhornDruid.java index 78c6ef165ea..a1b1fb15afa 100644 --- a/Mage.Sets/src/mage/cards/f/FyndhornDruid.java +++ b/Mage.Sets/src/mage/cards/f/FyndhornDruid.java @@ -50,7 +50,7 @@ class SourceWasBlockedThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - WasBlockedThisTurnWatcher watcher = (WasBlockedThisTurnWatcher) game.getState().getWatchers().get(WasBlockedThisTurnWatcher.class.getSimpleName()); - return sourcePermanent != null && watcher.getWasBlockedThisTurnCreatures().contains(new MageObjectReference(sourcePermanent, game)); + WasBlockedThisTurnWatcher watcher = game.getState().getWatcher(WasBlockedThisTurnWatcher.class); + return sourcePermanent != null && watcher != null && watcher.getWasBlockedThisTurnCreatures().contains(new MageObjectReference(sourcePermanent, game)); } } diff --git a/Mage.Sets/src/mage/cards/g/GOTOJAIL.java b/Mage.Sets/src/mage/cards/g/GOTOJAIL.java index 90a1fcb9fc8..f7eea87ac1b 100644 --- a/Mage.Sets/src/mage/cards/g/GOTOJAIL.java +++ b/Mage.Sets/src/mage/cards/g/GOTOJAIL.java @@ -118,7 +118,7 @@ class GoToJailTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals((UUID) game.getState().getValue(this.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY)); + return event.getPlayerId().equals(game.getState().getValue(this.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY)); } @Override diff --git a/Mage.Sets/src/mage/cards/g/GaeasLiege.java b/Mage.Sets/src/mage/cards/g/GaeasLiege.java index b5c0f24259f..0b4a5d87def 100644 --- a/Mage.Sets/src/mage/cards/g/GaeasLiege.java +++ b/Mage.Sets/src/mage/cards/g/GaeasLiege.java @@ -1,6 +1,6 @@ - package mage.cards.g; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -28,14 +28,12 @@ import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; import mage.target.common.TargetLandPermanent; -import java.util.UUID; - /** * * @author anonymous */ public final class GaeasLiege extends CardImpl { - + final static FilterControlledPermanent filterLands = new FilterControlledPermanent("Forests you control"); static { @@ -44,7 +42,7 @@ public final class GaeasLiege extends CardImpl { public GaeasLiege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}{G}"); - + this.subtype.add(SubType.AVATAR); this.power = new MageInt(0); this.toughness = new MageInt(0); @@ -55,8 +53,8 @@ public final class GaeasLiege extends CardImpl { new SetPowerToughnessSourceEffect(new DefendersForestCount(), Duration.EndOfCombat), new InvertCondition(SourceAttackingCondition.instance), "As long as {this} isn't attacking, its power and toughness are each equal to the number of Forests you control. As long as {this} is attacking, its power and toughness are each equal to the number of Forests defending player controls."))); - // {tap}: Target land becomes a Forest until Gaea's Liege leaves the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesBasicLandTargetEffect(Duration.WhileOnBattlefield, SubType.FOREST), new TapSourceCost()); + // {T}: Target land becomes a Forest until Gaea's Liege leaves the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesBasicLandTargetEffect(Duration.UntilSourceLeavesBattlefield, SubType.FOREST), new TapSourceCost()); ability.addTarget(new TargetLandPermanent()); this.addAbility(ability); } @@ -75,7 +73,7 @@ class DefendersForestCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - for (CombatGroup group :game.getCombat().getGroups()) { + for (CombatGroup group : game.getCombat().getGroups()) { if (group.getAttackers().contains(sourceAbility.getSourceId())) { UUID defenderId = group.getDefenderId(); if (group.isDefenderIsPlaneswalker()) { @@ -84,7 +82,7 @@ class DefendersForestCount implements DynamicValue { defenderId = permanent.getControllerId(); } } - + FilterLandPermanent filter = new FilterLandPermanent("forest"); filter.add(new SubtypePredicate(SubType.FOREST)); return game.getBattlefield().countAll(filter, defenderId, game); diff --git a/Mage.Sets/src/mage/cards/g/GalecasterColossus.java b/Mage.Sets/src/mage/cards/g/GalecasterColossus.java index 93ed2f360e3..9c00fb80e7d 100644 --- a/Mage.Sets/src/mage/cards/g/GalecasterColossus.java +++ b/Mage.Sets/src/mage/cards/g/GalecasterColossus.java @@ -34,7 +34,7 @@ public final class GalecasterColossus extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.NOT_YOU)); filter2.add(new SubtypePredicate(SubType.WIZARD)); - filter2.add(Predicates.not(new TappedPredicate())); + filter2.add(Predicates.not(TappedPredicate.instance)); } public GalecasterColossus(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GalepowderMage.java b/Mage.Sets/src/mage/cards/g/GalepowderMage.java index 28a2c19cce9..f59ef1f9271 100644 --- a/Mage.Sets/src/mage/cards/g/GalepowderMage.java +++ b/Mage.Sets/src/mage/cards/g/GalepowderMage.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -15,8 +13,8 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; @@ -26,8 +24,9 @@ import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GalepowderMage extends CardImpl { @@ -35,11 +34,11 @@ public final class GalepowderMage extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GalepowderMage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.KITHKIN); this.subtype.add(SubType.WIZARD); @@ -87,10 +86,10 @@ class GalepowderMageEffect extends OneShotEffect { if (controller != null && sourceObject != null) { if (getTargetPointer().getFirst(game, source) != null) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (permanent != null) { UUID exileId = UUID.randomUUID(); if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card != null) { Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId()))); diff --git a/Mage.Sets/src/mage/cards/g/Galestrike.java b/Mage.Sets/src/mage/cards/g/Galestrike.java index 372e5bcb889..01a3fd7702d 100644 --- a/Mage.Sets/src/mage/cards/g/Galestrike.java +++ b/Mage.Sets/src/mage/cards/g/Galestrike.java @@ -20,7 +20,7 @@ public final class Galestrike extends CardImpl { private static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public Galestrike(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GallopingLizrog.java b/Mage.Sets/src/mage/cards/g/GallopingLizrog.java new file mode 100644 index 00000000000..34362d524e8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GallopingLizrog.java @@ -0,0 +1,87 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.RemoveVariableCountersTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GallopingLizrog extends CardImpl { + + public GallopingLizrog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{U}"); + + this.subtype.add(SubType.FROG); + this.subtype.add(SubType.LIZARD); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Galloping Lizrog enters the battlefield, you may remove any number of +1/+1 counters from among creatures you control. If you do, put twice that many +1/+1 counters on Galloping Lizrog. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GallopingLizrogEffect(), true)); + } + + private GallopingLizrog(final GallopingLizrog card) { + super(card); + } + + @Override + public GallopingLizrog copy() { + return new GallopingLizrog(this); + } +} + +class GallopingLizrogEffect extends OneShotEffect { + + GallopingLizrogEffect() { + super(Outcome.Benefit); + staticText = "remove any number of +1/+1 counters from among creatures you control. " + + "If you do, put twice that many +1/+1 counters on {this}"; + } + + private GallopingLizrogEffect(final GallopingLizrogEffect effect) { + super(effect); + } + + @Override + public GallopingLizrogEffect copy() { + return new GallopingLizrogEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + RemoveVariableCountersTargetCost variableCost + = new RemoveVariableCountersTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE, CounterType.P1P1); + int toPay = variableCost.announceXValue(source, game); + Cost cost = variableCost.getFixedCostsFromAnnouncedValue(toPay); + if (!cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) { + return false; + } + return new AddCountersSourceEffect( + CounterType.P1P1.createInstance(2 * toPay) + ).apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java b/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java index c8ca0944f9a..c7ce35b44fd 100644 --- a/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java +++ b/Mage.Sets/src/mage/cards/g/GallowsAtWillowHill.java @@ -35,7 +35,7 @@ public final class GallowsAtWillowHill extends CardImpl { private static final FilterControlledPermanent humanFilter = new FilterControlledPermanent("untapped Human you control"); static { - humanFilter.add(Predicates.not(new TappedPredicate())); + humanFilter.add(Predicates.not(TappedPredicate.instance)); humanFilter.add(new SubtypePredicate(SubType.HUMAN)); } diff --git a/Mage.Sets/src/mage/cards/g/GameOfChaos.java b/Mage.Sets/src/mage/cards/g/GameOfChaos.java index 6c5f2f9386c..53010b05fa4 100644 --- a/Mage.Sets/src/mage/cards/g/GameOfChaos.java +++ b/Mage.Sets/src/mage/cards/g/GameOfChaos.java @@ -63,7 +63,7 @@ class GameOfChaosEffect extends OneShotEffect { if (you != null && targetOpponent != null) { boolean continueFlipping = true; - boolean youWonFlip = you.flipCoin(game); // controller flips first + boolean youWonFlip = you.flipCoin(source, game, true); // controller flips first boolean youWonLastFlip = false; // tracks if you won the flip last, negation of it means opponent won last int lifeAmount = 1; // starts stakes with 1 life @@ -88,7 +88,7 @@ class GameOfChaosEffect extends OneShotEffect { if (continueFlipping) { lifeAmount *= 2; // double the life each time - youWonFlip = youWonLastFlip ? you.flipCoin(game) : !targetOpponent.flipCoin(game); // negate the opponent's results for proper evaluation of if you won in next iteration + youWonFlip = youWonLastFlip ? you.flipCoin(source, game, true) : !targetOpponent.flipCoin(source, game, true); // negate the opponent's results for proper evaluation of if you won in next iteration } } diff --git a/Mage.Sets/src/mage/cards/g/GangUp.java b/Mage.Sets/src/mage/cards/g/GangUp.java index 7c68d54158b..a49f70ff1d3 100644 --- a/Mage.Sets/src/mage/cards/g/GangUp.java +++ b/Mage.Sets/src/mage/cards/g/GangUp.java @@ -1,9 +1,7 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.AssistAbility; import mage.cards.CardImpl; @@ -14,9 +12,11 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class GangUp extends CardImpl { @@ -28,27 +28,29 @@ public final class GangUp extends CardImpl { this.addAbility(new AssistAbility()); // Destroy target creature with power X or less. - this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with power X or less"))); + this.getSpellAbility().addEffect(new DestroyTargetEffect("destroy target creature with power X or less")); + this.getSpellAbility().setTargetAdjuster(GangUpAdjuster.instance); } public GangUp(final GangUp card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power " + xValue + " or less"); - filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1)); - ability.addTarget(new TargetCreaturePermanent(filter)); - } - } - @Override public GangUp copy() { return new GangUp(this); } } + +enum GangUpAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + ability.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power " + xValue + " or less"); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java b/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java index d7a31647a16..31c0bbbcf4b 100644 --- a/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java +++ b/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java @@ -51,7 +51,7 @@ public final class GargantuanGorilla extends CardImpl { // {T}: Gargantuan Gorilla deals damage equal to its power to another target creature. That creature deals damage equal to its power to Gargantuan Gorilla. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GargantuanGorillaFightEffect(), new TapSourceCost()); FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java b/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java index 74585b1ffe8..45dbfaa66c0 100644 --- a/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java +++ b/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java @@ -80,7 +80,7 @@ class GarnaTheBloodflameEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - GarnaTheBloodflameWatcher watcher = (GarnaTheBloodflameWatcher) game.getState().getWatchers().get(GarnaTheBloodflameWatcher.class.getSimpleName()); + GarnaTheBloodflameWatcher watcher = game.getState().getWatcher(GarnaTheBloodflameWatcher.class); if (watcher != null) { Set toHand = new HashSet<>(); for (UUID cardId : watcher.getCardsPutToGraveyardThisTurn()) { diff --git a/Mage.Sets/src/mage/cards/g/GarrukApexPredator.java b/Mage.Sets/src/mage/cards/g/GarrukApexPredator.java index 58e8d5284b5..c3675b96765 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukApexPredator.java +++ b/Mage.Sets/src/mage/cards/g/GarrukApexPredator.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; @@ -12,7 +10,10 @@ import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.GetEmblemTargetPlayerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.permanent.AnotherPredicate; @@ -25,8 +26,9 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GarrukApexPredator extends CardImpl { @@ -35,7 +37,7 @@ public final class GarrukApexPredator extends CardImpl { static { filter.add(new CardTypePredicate(CardType.PLANESWALKER)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GarrukApexPredator(UUID ownerId, CardSetInfo setInfo) { @@ -62,7 +64,6 @@ public final class GarrukApexPredator extends CardImpl { // -8: Target opponent gets an emblem with "Whenever a creature attacks you, it gets +5/+5 and gains trample until end of turn." Effect effect = new GetEmblemTargetPlayerEffect(new GarrukApexPredatorEmblem()); - effect.setText("Target opponent gets an emblem with \"Whenever a creature attacks you, it gets +5/+5 and gains trample until end of turn.\""); ability = new LoyaltyAbility(effect, -8); ability.addTarget(new TargetOpponent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/g/GarruksPackleader.java b/Mage.Sets/src/mage/cards/g/GarruksPackleader.java index 52fbd222054..92a47c10164 100644 --- a/Mage.Sets/src/mage/cards/g/GarruksPackleader.java +++ b/Mage.Sets/src/mage/cards/g/GarruksPackleader.java @@ -25,7 +25,7 @@ public final class GarruksPackleader extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another creature with power 3 or greater"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 2)); } diff --git a/Mage.Sets/src/mage/cards/g/GateColossus.java b/Mage.Sets/src/mage/cards/g/GateColossus.java index 161b449d1dc..0855be3d71c 100644 --- a/Mage.Sets/src/mage/cards/g/GateColossus.java +++ b/Mage.Sets/src/mage/cards/g/GateColossus.java @@ -65,7 +65,7 @@ public final class GateColossus extends CardImpl { class GateColossusCostReductionEffect extends CostModificationEffectImpl { - static final FilterControlledPermanent filter = new FilterControlledPermanent(); + static final FilterControlledPermanent filter = new FilterControlledPermanent("a Gate"); static { filter.add(new SubtypePredicate(SubType.GATE)); diff --git a/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java b/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java index 8bc4dba224e..5ffff388271 100644 --- a/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java +++ b/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java @@ -42,7 +42,7 @@ public final class GateToTheAfterlife extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public GateToTheAfterlife(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GatebreakerRam.java b/Mage.Sets/src/mage/cards/g/GatebreakerRam.java new file mode 100644 index 00000000000..5a9a159ea42 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GatebreakerRam.java @@ -0,0 +1,76 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GatebreakerRam extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(new SubtypePredicate(SubType.GATE)); + } + + private static final DynamicValue xValue + = new PermanentsOnBattlefieldCount(filter); + private static final Condition condition + = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + + public GatebreakerRam(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.SHEEP); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Gatebreaker Ram gets +1/+1 for each Gate you control. + this.addAbility(new SimpleStaticAbility( + new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield) + .setText("{this} gets +1/+1 for each Gate you control.") + )); + + // As long as you control two or more Gates, Gatebreaker Ram has vigilance and trample. + Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(VigilanceAbility.getInstance()), + condition, "As long as you control two or more Gates, {this} has vigilance" + )); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(TrampleAbility.getInstance()), + condition, "and trample" + )); + this.addAbility(ability); + } + + private GatebreakerRam(final GatebreakerRam card) { + super(card); + } + + @Override + public GatebreakerRam copy() { + return new GatebreakerRam(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GatesAblaze.java b/Mage.Sets/src/mage/cards/g/GatesAblaze.java new file mode 100644 index 00000000000..780aa83f1af --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GatesAblaze.java @@ -0,0 +1,46 @@ +package mage.cards.g; + +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DamageAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GatesAblaze extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledPermanent("the number of Gates you control"); + + static { + filter.add(new SubtypePredicate(SubType.GATE)); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + + public GatesAblaze(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); + + // Gates Ablaze deals X damage to each creature, where X is the number of Gates you control. + this.getSpellAbility().addEffect(new DamageAllEffect(xValue, StaticFilters.FILTER_PERMANENT_CREATURE)); + } + + private GatesAblaze(final GatesAblaze card) { + super(card); + } + + @Override + public GatesAblaze copy() { + return new GatesAblaze(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GatewayShade.java b/Mage.Sets/src/mage/cards/g/GatewayShade.java index 684d873a8e2..cb36365322d 100644 --- a/Mage.Sets/src/mage/cards/g/GatewayShade.java +++ b/Mage.Sets/src/mage/cards/g/GatewayShade.java @@ -28,7 +28,7 @@ public final class GatewayShade extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("untapped Gate you control"); static { filter.add(new SubtypePredicate(SubType.GATE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public GatewayShade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GatewaySneak.java b/Mage.Sets/src/mage/cards/g/GatewaySneak.java new file mode 100644 index 00000000000..9d0596cb775 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GatewaySneak.java @@ -0,0 +1,51 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GatewaySneak extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(SubType.GATE, "a Gate"); + + public GatewaySneak(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.VEDALKEN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever a Gate enters the battlefield under your control, Gateway Sneak can't be blocked this turn. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new CantBeBlockedSourceEffect(Duration.EndOfTurn), filter + )); + + // Whenever Gateway Sneak deals combat damage to a player, draw a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new DrawCardSourceControllerEffect(1), false + )); + } + + private GatewaySneak(final GatewaySneak card) { + super(card); + } + + @Override + public GatewaySneak copy() { + return new GatewaySneak(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GatherSpecimens.java b/Mage.Sets/src/mage/cards/g/GatherSpecimens.java index 812e8a993e5..9efc66b27bd 100644 --- a/Mage.Sets/src/mage/cards/g/GatherSpecimens.java +++ b/Mage.Sets/src/mage/cards/g/GatherSpecimens.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.Card; @@ -16,14 +14,15 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class GatherSpecimens extends CardImpl { public GatherSpecimens(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{U}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}{U}"); // If a creature would enter the battlefield under an opponent's control this turn, it enters the battlefield under your control instead. this.getSpellAbility().addEffect(new GatherSpecimensReplacementEffect()); @@ -70,7 +69,7 @@ class GatherSpecimensReplacementEffect extends ReplacementEffectImpl { if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone().match(Zone.BATTLEFIELD)) { Card card = game.getCard(event.getTargetId()); - if (card.isCreature()) { // TODO: Bestow Card cast as Enchantment probably not handled correctly + if (card != null && card.isCreature()) { // TODO: Bestow Card cast as Enchantment probably not handled correctly Player controller = game.getPlayer(source.getControllerId()); if (controller != null && controller.hasOpponent(event.getPlayerId(), game)) { return true; @@ -79,9 +78,7 @@ class GatherSpecimensReplacementEffect extends ReplacementEffectImpl { } if (event.getType() == GameEvent.EventType.CREATE_TOKEN && event.getFlag()) { // flag indicates if it's a creature token Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && controller.hasOpponent(event.getPlayerId(), game)) { - return true; - } + return controller != null && controller.hasOpponent(event.getPlayerId(), game); } return false; } diff --git a/Mage.Sets/src/mage/cards/g/GavonyUnhallowed.java b/Mage.Sets/src/mage/cards/g/GavonyUnhallowed.java index f8d8ce3d8e5..17b8d03727f 100644 --- a/Mage.Sets/src/mage/cards/g/GavonyUnhallowed.java +++ b/Mage.Sets/src/mage/cards/g/GavonyUnhallowed.java @@ -24,7 +24,7 @@ public final class GavonyUnhallowed extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/g/GazeOfJustice.java b/Mage.Sets/src/mage/cards/g/GazeOfJustice.java index 4735ad605b7..10b93cd0ba4 100644 --- a/Mage.Sets/src/mage/cards/g/GazeOfJustice.java +++ b/Mage.Sets/src/mage/cards/g/GazeOfJustice.java @@ -28,7 +28,7 @@ public final class GazeOfJustice extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public GazeOfJustice(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java index ecdd1863e5f..c2889337d5c 100644 --- a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java +++ b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java @@ -98,7 +98,7 @@ class GazeOfTheGorgonEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null && targetCreature != null) { - BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher watcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (watcher != null) { List toDestroy = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { diff --git a/Mage.Sets/src/mage/cards/g/GeneralHux.java b/Mage.Sets/src/mage/cards/g/GeneralHux.java index 653a5381f2a..42bfd880d24 100644 --- a/Mage.Sets/src/mage/cards/g/GeneralHux.java +++ b/Mage.Sets/src/mage/cards/g/GeneralHux.java @@ -29,7 +29,7 @@ public final class GeneralHux extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public GeneralHux(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GeneratorServant.java b/Mage.Sets/src/mage/cards/g/GeneratorServant.java index 567c43884d7..9ecc3a190dd 100644 --- a/Mage.Sets/src/mage/cards/g/GeneratorServant.java +++ b/Mage.Sets/src/mage/cards/g/GeneratorServant.java @@ -63,7 +63,7 @@ class GeneratorServantWatcher extends Watcher { public List creatures = new ArrayList<>(); public GeneratorServantWatcher() { - super(GeneratorServantWatcher.class.getSimpleName(), WatcherScope.CARD); + super(GeneratorServantWatcher.class, WatcherScope.CARD); } public GeneratorServantWatcher(final GeneratorServantWatcher watcher) { @@ -114,7 +114,7 @@ class GeneratorServantHasteEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - GeneratorServantWatcher watcher = (GeneratorServantWatcher) game.getState().getWatchers().get(GeneratorServantWatcher.class.getSimpleName(), source.getSourceId()); + GeneratorServantWatcher watcher = game.getState().getWatcher(GeneratorServantWatcher.class, source.getSourceId()); if (watcher != null) { for (Permanent perm : game.getBattlefield().getAllActivePermanents()) { if (watcher.creatures.contains(perm.getId())) { diff --git a/Mage.Sets/src/mage/cards/g/GenesisChamber.java b/Mage.Sets/src/mage/cards/g/GenesisChamber.java index 709aa2b5237..a739a91f3c9 100644 --- a/Mage.Sets/src/mage/cards/g/GenesisChamber.java +++ b/Mage.Sets/src/mage/cards/g/GenesisChamber.java @@ -30,7 +30,7 @@ public final class GenesisChamber extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public GenesisChamber(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GeodeGolem.java b/Mage.Sets/src/mage/cards/g/GeodeGolem.java index f4842176da5..d35482b02e4 100644 --- a/Mage.Sets/src/mage/cards/g/GeodeGolem.java +++ b/Mage.Sets/src/mage/cards/g/GeodeGolem.java @@ -1,6 +1,5 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -20,8 +19,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author spjspj */ public final class GeodeGolem extends CardImpl { @@ -68,7 +68,6 @@ class GeodeGolemEffect extends OneShotEffect { for (UUID commanderId : controller.getCommandersIds()) { if (game.getState().getZone(commanderId) == Zone.COMMAND) { Card commander = game.getCard(commanderId); - if (commander != null && game.getState().getZone(commanderId) == Zone.COMMAND) { SpellAbility ability = commander.getSpellAbility(); SpellAbility newAbility = commander.getSpellAbility().copy(); diff --git a/Mage.Sets/src/mage/cards/g/GeralfsMasterpiece.java b/Mage.Sets/src/mage/cards/g/GeralfsMasterpiece.java index 629686108cc..f5137eb43b0 100644 --- a/Mage.Sets/src/mage/cards/g/GeralfsMasterpiece.java +++ b/Mage.Sets/src/mage/cards/g/GeralfsMasterpiece.java @@ -41,7 +41,7 @@ public final class GeralfsMasterpiece extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Geralf's Masterpiece gets -1/-1 for each card in your hand. - DynamicValue count = new SignInversionDynamicValue(new CardsInControllerHandCount()); + DynamicValue count = new SignInversionDynamicValue(CardsInControllerHandCount.instance); Effect effect = new BoostSourceEffect(count, count, Duration.WhileOnBattlefield); effect.setText("{this} gets -1/-1 for each card in your hand"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/g/GerrardsWisdom.java b/Mage.Sets/src/mage/cards/g/GerrardsWisdom.java index 23e378f90a5..27694f04d26 100644 --- a/Mage.Sets/src/mage/cards/g/GerrardsWisdom.java +++ b/Mage.Sets/src/mage/cards/g/GerrardsWisdom.java @@ -20,7 +20,7 @@ public final class GerrardsWisdom extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{W}{W}"); // You gain 2 life for each card in your hand. - this.getSpellAbility().addEffect(new GainLifeEffect(new MultipliedValue(new CardsInControllerHandCount(), 2), + this.getSpellAbility().addEffect(new GainLifeEffect(new MultipliedValue(CardsInControllerHandCount.instance, 2), "You gain 2 life for each card in your hand")); } diff --git a/Mage.Sets/src/mage/cards/g/GetThePoint.java b/Mage.Sets/src/mage/cards/g/GetThePoint.java new file mode 100644 index 00000000000..1e618822375 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GetThePoint.java @@ -0,0 +1,34 @@ +package mage.cards.g; + +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GetThePoint extends CardImpl { + + public GetThePoint(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{R}"); + + // Destroy target creature. Scry 1. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addEffect(new ScryEffect(1)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private GetThePoint(final GetThePoint card) { + super(card); + } + + @Override + public GetThePoint copy() { + return new GetThePoint(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GhirapurAetherGrid.java b/Mage.Sets/src/mage/cards/g/GhirapurAetherGrid.java index da3c5fdb830..68ee5462a09 100644 --- a/Mage.Sets/src/mage/cards/g/GhirapurAetherGrid.java +++ b/Mage.Sets/src/mage/cards/g/GhirapurAetherGrid.java @@ -26,7 +26,7 @@ public final class GhirapurAetherGrid extends CardImpl { static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public GhirapurAetherGrid(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GhituFire.java b/Mage.Sets/src/mage/cards/g/GhituFire.java index 4da3bde52b3..02c5fb90c3d 100644 --- a/Mage.Sets/src/mage/cards/g/GhituFire.java +++ b/Mage.Sets/src/mage/cards/g/GhituFire.java @@ -23,7 +23,7 @@ public final class GhituFire extends CardImpl { public GhituFire(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}"); - Effect effect = new DamageTargetEffect(new ManacostVariableValue()); + Effect effect = new DamageTargetEffect(ManacostVariableValue.instance); // You may cast Ghitu Fire as though it had flash if you pay {2} more to cast it. Ability ability = new PayMoreToCastAsThoughtItHadFlashAbility(this, new ManaCostsImpl("{2}")); ability.addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/g/GhituJourneymage.java b/Mage.Sets/src/mage/cards/g/GhituJourneymage.java index 2c7c677c62f..8075d92fd95 100644 --- a/Mage.Sets/src/mage/cards/g/GhituJourneymage.java +++ b/Mage.Sets/src/mage/cards/g/GhituJourneymage.java @@ -26,7 +26,7 @@ public final class GhituJourneymage extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Wizard"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.WIZARD)); } diff --git a/Mage.Sets/src/mage/cards/g/GhorClanWrecker.java b/Mage.Sets/src/mage/cards/g/GhorClanWrecker.java new file mode 100644 index 00000000000..eaa24ff1726 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GhorClanWrecker.java @@ -0,0 +1,41 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.keyword.MenaceAbility; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GhorClanWrecker extends CardImpl { + + public GhorClanWrecker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Riot + this.addAbility(new RiotAbility()); + + // Menace + this.addAbility(new MenaceAbility()); + } + + private GhorClanWrecker(final GhorClanWrecker card) { + super(card); + } + + @Override + public GhorClanWrecker copy() { + return new GhorClanWrecker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GhostlyWings.java b/Mage.Sets/src/mage/cards/g/GhostlyWings.java index 68832eec277..0451e1a3879 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyWings.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyWings.java @@ -80,7 +80,7 @@ class GhostlyWingsReturnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) game.getPermanentOrLKIBattlefield(source.getSourceId()); + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && permanent != null && permanent.getAttachedTo() != null) { Permanent enchantedCreature = game.getPermanent(permanent.getAttachedTo()); diff --git a/Mage.Sets/src/mage/cards/g/Ghostway.java b/Mage.Sets/src/mage/cards/g/Ghostway.java index 5f965b71af6..957731373be 100644 --- a/Mage.Sets/src/mage/cards/g/Ghostway.java +++ b/Mage.Sets/src/mage/cards/g/Ghostway.java @@ -76,7 +76,7 @@ class GhostwayEffect extends OneShotEffect { Cards cardsToReturn = new CardsImpl(); for (Card exiled : toExile) { - if (((Permanent) exiled).getZoneChangeCounter(game) == game.getState().getZoneChangeCounter(exiled.getId()) - 1) { + if (exiled.getZoneChangeCounter(game) == game.getState().getZoneChangeCounter(exiled.getId()) - 1) { cardsToReturn.add(exiled); } } diff --git a/Mage.Sets/src/mage/cards/g/GhoulcallerGisa.java b/Mage.Sets/src/mage/cards/g/GhoulcallerGisa.java index 273ee197600..89b9458fc49 100644 --- a/Mage.Sets/src/mage/cards/g/GhoulcallerGisa.java +++ b/Mage.Sets/src/mage/cards/g/GhoulcallerGisa.java @@ -40,7 +40,7 @@ public final class GhoulcallerGisa extends CardImpl { this.toughness = new MageInt(4); // {B}, {tap}, Sacrifice another creature: create X 2/2 black Zombie creature tokens, where X is the sacrificed creature's power. - DynamicValue xValue = new SacrificeCostCreaturesPower(); + DynamicValue xValue = SacrificeCostCreaturesPower.instance; Token zombie = new ZombieToken(); zombie.setTokenType(2); Effect effect = new CreateTokenEffect(zombie, xValue); diff --git a/Mage.Sets/src/mage/cards/g/GiantOyster.java b/Mage.Sets/src/mage/cards/g/GiantOyster.java index 53e103906b8..6b4dacd0288 100644 --- a/Mage.Sets/src/mage/cards/g/GiantOyster.java +++ b/Mage.Sets/src/mage/cards/g/GiantOyster.java @@ -37,7 +37,7 @@ public final class GiantOyster extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public GiantOyster(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GiantSlug.java b/Mage.Sets/src/mage/cards/g/GiantSlug.java new file mode 100644 index 00000000000..8cfc8d42f3d --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GiantSlug.java @@ -0,0 +1,104 @@ + +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.LandwalkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceBasicLandType; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author L_J + */ +public final class GiantSlug extends CardImpl { + + public GiantSlug(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + this.subtype.add(SubType.SLUG); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {5}: At the beginning of your next upkeep, choose a basic land type. Giant Slug gains landwalk of the chosen type until the end of that turn. + AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility ability = new AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility(new GiantSlugEffect()); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateDelayedTriggeredAbilityEffect(ability), new ManaCostsImpl("{5}"))); + } + + public GiantSlug(final GiantSlug card) { + super(card); + } + + @Override + public GiantSlug copy() { + return new GiantSlug(this); + } + +} + +class GiantSlugEffect extends OneShotEffect { + + public GiantSlugEffect() { + super(Outcome.AddAbility); + this.staticText = "At the beginning of your next upkeep, choose a basic land type. {this} gains landwalk of the chosen type until the end of that turn"; + } + + public GiantSlugEffect(final GiantSlugEffect effect) { + super(effect); + } + + @Override + public GiantSlugEffect copy() { + return new GiantSlugEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + ChoiceImpl choices = new ChoiceBasicLandType(); + if (controller.choose(outcome, choices, game)) { + game.informPlayers(sourcePermanent.getName() + ": Chosen basic land type is " + choices.getChoice()); + FilterLandPermanent filter = new FilterLandPermanent(choices.getChoice()); + if (choices.getChoice().equals("Plains")) { + filter.add(new SubtypePredicate(SubType.PLAINS)); + } + if (choices.getChoice().equals("Island")) { + filter.add(new SubtypePredicate(SubType.ISLAND)); + } + if (choices.getChoice().equals("Swamp")) { + filter.add(new SubtypePredicate(SubType.SWAMP)); + } + if (choices.getChoice().equals("Mountain")) { + filter.add(new SubtypePredicate(SubType.MOUNTAIN)); + } + if (choices.getChoice().equals("Forest")) { + filter.add(new SubtypePredicate(SubType.FOREST)); + } + Ability landwalkAbility = new LandwalkAbility(filter); + game.addEffect(new GainAbilitySourceEffect(landwalkAbility, Duration.EndOfTurn, false), source); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GiantTurtle.java b/Mage.Sets/src/mage/cards/g/GiantTurtle.java index 6d0e100c751..fb72e5c8488 100644 --- a/Mage.Sets/src/mage/cards/g/GiantTurtle.java +++ b/Mage.Sets/src/mage/cards/g/GiantTurtle.java @@ -63,7 +63,7 @@ class CantAttackIfAttackedLastTurnEffect extends RestrictionEffect { @Override public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game) { - AttackedLastTurnWatcher watcher = (AttackedLastTurnWatcher) game.getState().getWatchers().get(AttackedLastTurnWatcher.class.getSimpleName()); + AttackedLastTurnWatcher watcher = game.getState().getWatcher(AttackedLastTurnWatcher.class); if (watcher != null) { Set attackingCreatures = watcher.getAttackedLastTurnCreatures(attacker.getControllerId()); MageObjectReference mor = new MageObjectReference(attacker, game); diff --git a/Mage.Sets/src/mage/cards/g/GideonJura.java b/Mage.Sets/src/mage/cards/g/GideonJura.java index d18f5028910..12c783c9ed9 100644 --- a/Mage.Sets/src/mage/cards/g/GideonJura.java +++ b/Mage.Sets/src/mage/cards/g/GideonJura.java @@ -35,7 +35,7 @@ public final class GideonJura extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public GideonJura(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/Gigantoplasm.java b/Mage.Sets/src/mage/cards/g/Gigantoplasm.java index 2b0eab220b3..df6f0f4eaee 100644 --- a/Mage.Sets/src/mage/cards/g/Gigantoplasm.java +++ b/Mage.Sets/src/mage/cards/g/Gigantoplasm.java @@ -57,7 +57,7 @@ class GigantoplasmApplyToPermanent extends ApplyToPermanent { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { - DynamicValue variableMana = new ManacostVariableValue(); + DynamicValue variableMana = ManacostVariableValue.instance; Effect effect = new SetPowerToughnessSourceEffect(variableMana, Duration.WhileOnBattlefield, SubLayer.SetPT_7b); effect.setText("This creature has base power and toughness X/X"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); @@ -67,7 +67,7 @@ class GigantoplasmApplyToPermanent extends ApplyToPermanent { @Override public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { - DynamicValue variableMana = new ManacostVariableValue(); + DynamicValue variableMana = ManacostVariableValue.instance; Effect effect = new SetPowerToughnessSourceEffect(variableMana, Duration.WhileOnBattlefield, SubLayer.SetPT_7b); effect.setText("This creature has base power and toughness X/X"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); diff --git a/Mage.Sets/src/mage/cards/g/GildedCerodon.java b/Mage.Sets/src/mage/cards/g/GildedCerodon.java index c2abfda6960..f89e51e141e 100644 --- a/Mage.Sets/src/mage/cards/g/GildedCerodon.java +++ b/Mage.Sets/src/mage/cards/g/GildedCerodon.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.UUID; @@ -66,12 +65,8 @@ class GildedCerodonCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null - && (!game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).isEmpty() - || controller.getGraveyard().count(filter2, game) > 0)) { - return true; - } - return false; + return (!game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).isEmpty() + || !controller.getGraveyard().getCards(filter2, game).isEmpty()); } @Override diff --git a/Mage.Sets/src/mage/cards/g/GiltspireAvenger.java b/Mage.Sets/src/mage/cards/g/GiltspireAvenger.java index 82ac97ef3c9..1c0fd0e8693 100644 --- a/Mage.Sets/src/mage/cards/g/GiltspireAvenger.java +++ b/Mage.Sets/src/mage/cards/g/GiltspireAvenger.java @@ -68,7 +68,7 @@ class GiltspireAvengerTarget extends TargetPermanent { @Override public boolean canTarget(UUID id, Ability source, Game game) { - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), source.getControllerId()); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, source.getControllerId()); if (watcher != null && watcher.hasSourceDoneDamage(id, game)) { return super.canTarget(id, source, game); } @@ -79,7 +79,7 @@ class GiltspireAvengerTarget extends TargetPermanent { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); Set possibleTargets = new HashSet<>(); - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), sourceControllerId); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId); for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); if (permanent != null && watcher != null && watcher.hasSourceDoneDamage(targetId, game)) { @@ -97,7 +97,7 @@ class GiltspireAvengerTarget extends TargetPermanent { } int count = 0; MageObject targetSource = game.getObject(sourceId); - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), sourceControllerId); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java b/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java index 66e7d23cbd8..78c98594496 100644 --- a/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java +++ b/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java @@ -120,8 +120,8 @@ class GisaAndGeralfCastFromGraveyardEffect extends AsThoughEffectImpl { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { if (objectId.equals(getTargetPointer().getFirst(game, source))) { if (affectedControllerId.equals(source.getControllerId())) { - GisaAndGeralfWatcher watcher = (GisaAndGeralfWatcher) game.getState().getWatchers().get(GisaAndGeralfWatcher.class.getSimpleName(), source.getSourceId()); - return !watcher.isAbilityUsed(); + GisaAndGeralfWatcher watcher = game.getState().getWatcher(GisaAndGeralfWatcher.class, source.getSourceId()); + return watcher != null && !watcher.isAbilityUsed(); } } return false; @@ -145,7 +145,7 @@ class GisaAndGeralfWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.GRAVEYARD) { Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell.isCreature() && spell.hasSubtype(SubType.ZOMBIE, game)) { + if (spell != null && spell.isCreature() && spell.hasSubtype(SubType.ZOMBIE, game)) { abilityUsed = true; } } diff --git a/Mage.Sets/src/mage/cards/g/Glaciers.java b/Mage.Sets/src/mage/cards/g/Glaciers.java new file mode 100644 index 00000000000..6d2ae05de93 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/Glaciers.java @@ -0,0 +1,133 @@ +package mage.cards.g; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; + +/** + * + * @author jmharmon + */ +public final class Glaciers extends CardImpl { + + public Glaciers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{U}"); + + // At the beginning of your upkeep, sacrifice Glaciers unless you pay {W}{U}. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{W}{U}")), TargetController.YOU, false)); + + // All Mountains are Plains. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GlaciersEffect())); + } + + public Glaciers(final Glaciers card) { + super(card); + } + + @Override + public Glaciers copy() { + return new Glaciers(this); + } + + static class GlaciersEffect extends ContinuousEffectImpl { + + GlaciersEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + this.staticText = "All Mountains are Plains"; + } + + GlaciersEffect(final GlaciersEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public GlaciersEffect copy() { + return new GlaciersEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + for (Permanent land : game.getBattlefield().getAllActivePermanents(CardType.LAND)) { + switch (layer) { + case TypeChangingEffects_4: + if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + land.getSubtype(game).clear(); + land.getSubtype(game).add(SubType.PLAINS); + game.getState().setValue("glaciers" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game), "true"); + } + break; + case AbilityAddingRemovingEffects_6: + if (game.getState().getValue("glaciers" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game)) != null + && game.getState().getValue("glaciers" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game)).equals("true")) { + land.removeAllAbilities(source.getSourceId(), game); + if (land.getSubtype(game).contains(SubType.FOREST)) { + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.PLAINS)) { + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.ISLAND)) { + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.SWAMP)) { + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + } + } + break; + } + } + return true; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.TypeChangingEffects_4; + } + + @Override + public Set isDependentTo(List allEffectsInLayer) { + return allEffectsInLayer + .stream() + .filter(effect -> effect.getDependencyTypes().contains(DependencyType.BecomePlains)) + .map(Effect::getId) + .collect(Collectors.toSet()); + } + } +} diff --git a/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java b/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java index 372a87e19dd..8683602db50 100644 --- a/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java +++ b/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java @@ -28,7 +28,7 @@ public final class GlareOfSubdual extends CardImpl { private static final FilterPermanent filterTarget = new FilterPermanent("artifact or creature"); static { - filterCost.add(Predicates.not(new TappedPredicate())); + filterCost.add(Predicates.not(TappedPredicate.instance)); filterTarget.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE))); diff --git a/Mage.Sets/src/mage/cards/g/GlassOfTheGuildpact.java b/Mage.Sets/src/mage/cards/g/GlassOfTheGuildpact.java new file mode 100644 index 00000000000..a5e095017ff --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GlassOfTheGuildpact.java @@ -0,0 +1,43 @@ +package mage.cards.g; + +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.MulticoloredPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GlassOfTheGuildpact extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("multicolored creatures"); + + static { + filter.add(MulticoloredPredicate.instance); + } + + public GlassOfTheGuildpact(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + // Multicolored creatures you control get +1/+1. + this.addAbility(new SimpleStaticAbility( + new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter) + )); + } + + private GlassOfTheGuildpact(final GlassOfTheGuildpact card) { + super(card); + } + + @Override + public GlassOfTheGuildpact copy() { + return new GlassOfTheGuildpact(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GlassdustHulk.java b/Mage.Sets/src/mage/cards/g/GlassdustHulk.java index 419a50f73a4..69c9f6c2bd5 100644 --- a/Mage.Sets/src/mage/cards/g/GlassdustHulk.java +++ b/Mage.Sets/src/mage/cards/g/GlassdustHulk.java @@ -30,7 +30,7 @@ public final class GlassdustHulk extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GlassdustHulk(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GlazeFiend.java b/Mage.Sets/src/mage/cards/g/GlazeFiend.java index b4e70d85d34..ca91ea31291 100644 --- a/Mage.Sets/src/mage/cards/g/GlazeFiend.java +++ b/Mage.Sets/src/mage/cards/g/GlazeFiend.java @@ -24,7 +24,7 @@ public final class GlazeFiend extends CardImpl { private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("another artifact"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/g/Gleancrawler.java b/Mage.Sets/src/mage/cards/g/Gleancrawler.java index 9b183e132c5..1daa26ff289 100644 --- a/Mage.Sets/src/mage/cards/g/Gleancrawler.java +++ b/Mage.Sets/src/mage/cards/g/Gleancrawler.java @@ -73,7 +73,7 @@ class GleancrawlerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = (CardsPutIntoGraveyardWatcher) game.getState().getWatchers().get(CardsPutIntoGraveyardWatcher.class.getSimpleName()); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && watcher != null) { Set cardsToGraveyardThisTurn = watcher.getCardsPutToGraveyardFromBattlefield(); diff --git a/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java b/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java index 55bfd2f7493..ced28deab94 100644 --- a/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java +++ b/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java @@ -26,7 +26,7 @@ public final class GlimmerdustNap extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public GlimmerdustNap(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GlimmerpointStag.java b/Mage.Sets/src/mage/cards/g/GlimmerpointStag.java index d4b7a1630c2..4258c96d373 100644 --- a/Mage.Sets/src/mage/cards/g/GlimmerpointStag.java +++ b/Mage.Sets/src/mage/cards/g/GlimmerpointStag.java @@ -33,7 +33,7 @@ public final class GlimmerpointStag extends CardImpl { private final static FilterPermanent filter = new FilterPermanent("another target permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GlimmerpointStag(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GlimpseTheSunGod.java b/Mage.Sets/src/mage/cards/g/GlimpseTheSunGod.java index 4ab2832a675..f0c457aa4fe 100644 --- a/Mage.Sets/src/mage/cards/g/GlimpseTheSunGod.java +++ b/Mage.Sets/src/mage/cards/g/GlimpseTheSunGod.java @@ -1,20 +1,21 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; /** - * * @author LevelX2 */ public final class GlimpseTheSunGod extends CardImpl { @@ -24,26 +25,27 @@ public final class GlimpseTheSunGod extends CardImpl { // Tap X target creatures. Scry 1. this.getSpellAbility().addEffect(new TapTargetEffect("X target creatures")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, FILTER_PERMANENT_CREATURES, false)); this.getSpellAbility().addEffect(new ScryEffect(1)); + this.getSpellAbility().setTargetAdjuster(GlimpseTheSunGodAdjuster.instance); } public GlimpseTheSunGod(final GlimpseTheSunGod card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numberToTap = ability.getManaCostsToPay().getX(); - numberToTap = Math.min(game.getBattlefield().count(FILTER_PERMANENT_CREATURES, ability.getSourceId(), ability.getControllerId(), game), numberToTap); - ability.addTarget(new TargetCreaturePermanent(numberToTap, numberToTap, FILTER_PERMANENT_CREATURES, false)); - } - } - @Override public GlimpseTheSunGod copy() { return new GlimpseTheSunGod(this); } } + +enum GlimpseTheSunGodAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numberToTap = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetCreaturePermanent(numberToTap, numberToTap, FILTER_PERMANENT_CREATURES, false)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GlintHawkIdol.java b/Mage.Sets/src/mage/cards/g/GlintHawkIdol.java index 5352599b85e..ceb983bfbf0 100644 --- a/Mage.Sets/src/mage/cards/g/GlintHawkIdol.java +++ b/Mage.Sets/src/mage/cards/g/GlintHawkIdol.java @@ -28,7 +28,7 @@ public final class GlintHawkIdol extends CardImpl { private static final FilterPermanent filter = new FilterArtifactPermanent("another artifact"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GlintHawkIdol (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GlintSleeveSiphoner.java b/Mage.Sets/src/mage/cards/g/GlintSleeveSiphoner.java index 09d2a2af102..27d9623720a 100644 --- a/Mage.Sets/src/mage/cards/g/GlintSleeveSiphoner.java +++ b/Mage.Sets/src/mage/cards/g/GlintSleeveSiphoner.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; @@ -19,8 +17,9 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author fireshoes */ public final class GlintSleeveSiphoner extends CardImpl { @@ -42,8 +41,7 @@ public final class GlintSleeveSiphoner extends CardImpl { // At the beginning of your upkeep, you may pay {E}{E}. If you do, draw a card and you lose 1 life. DoIfCostPaid doIfCostPaidEffect = new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new PayEnergyCost(2)); Effect effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - doIfCostPaidEffect.addEffect(effect); + doIfCostPaidEffect.addEffect(effect.concatBy("and")); this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, doIfCostPaidEffect, TargetController.YOU, false, false, "At the beginning of your upkeep, ")); } diff --git a/Mage.Sets/src/mage/cards/g/GlissaTheTraitor.java b/Mage.Sets/src/mage/cards/g/GlissaTheTraitor.java index 35a5e605402..04337ad939d 100644 --- a/Mage.Sets/src/mage/cards/g/GlissaTheTraitor.java +++ b/Mage.Sets/src/mage/cards/g/GlissaTheTraitor.java @@ -64,7 +64,7 @@ class GlissaTheTraitorTriggeredAbility extends TriggeredAbilityImpl { } GlissaTheTraitorTriggeredAbility() { - super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect()); + super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), true); this.addTarget(new TargetCardInYourGraveyard(filter)); } @@ -95,6 +95,6 @@ class GlissaTheTraitorTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a creature an opponent controls is put into a graveyard from the battlefield, you may " + super.getRule(); + return "Whenever a creature an opponent controls is put into a graveyard from the battlefield, " + super.getRule(); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/g/GlitteringWish.java b/Mage.Sets/src/mage/cards/g/GlitteringWish.java index 9b063c47ff8..355eb718f94 100644 --- a/Mage.Sets/src/mage/cards/g/GlitteringWish.java +++ b/Mage.Sets/src/mage/cards/g/GlitteringWish.java @@ -19,7 +19,7 @@ public final class GlitteringWish extends CardImpl { private static final FilterCard filter = new FilterCard("a multicolored card"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public GlitteringWish(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphKeeper.java b/Mage.Sets/src/mage/cards/g/GlyphKeeper.java index 697acf46964..69d358409e1 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphKeeper.java +++ b/Mage.Sets/src/mage/cards/g/GlyphKeeper.java @@ -79,7 +79,7 @@ class GlyphKeeperAbility extends TriggeredAbilityImpl { if (event.getTargetId().equals(this.getSourceId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature()) { - NumberOfTimesPermanentTargetedATurnWatcher watcher = (NumberOfTimesPermanentTargetedATurnWatcher) game.getState().getWatchers().get(NumberOfTimesPermanentTargetedATurnWatcher.class.getSimpleName()); + NumberOfTimesPermanentTargetedATurnWatcher watcher = game.getState().getWatcher(NumberOfTimesPermanentTargetedATurnWatcher.class); if (watcher != null && watcher.notMoreThanOnceTargetedThisTurn(permanent, game)) { for (Effect effect : getEffects()) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java b/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java index 29a587f8cd9..016c25f35a5 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java @@ -25,7 +25,7 @@ public final class GlyphOfDestruction extends CardImpl { static { filter.add(new SubtypePredicate(SubType.WALL)); - filter.add(new BlockingPredicate()); + filter.add(BlockingPredicate.instance); } public GlyphOfDestruction(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java index ea23f5b02b7..5862096bd5d 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java @@ -106,7 +106,7 @@ class GlyphOfDoomEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null && targetCreature != null) { - BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher watcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (watcher != null) { List toDestroy = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java b/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java new file mode 100644 index 00000000000..94068e41efb --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java @@ -0,0 +1,129 @@ + +package mage.cards.g; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.condition.common.AfterCombatCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.other.OwnerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.BlockedAttackerWatcher; + +/** + * + * @author L_J + */ +public final class GlyphOfReincarnation extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Wall creature"); + + static { + filter.add(new SubtypePredicate(SubType.WALL)); + } + + public GlyphOfReincarnation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); + + // Cast this spell only after combat. + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, AfterCombatCondition.instance, "Cast this spell only after combat")); + + // Destroy all creatures that were blocked by target Wall this turn. They can’t be regenerated. For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall onto the battlefield under its owner’s control. + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new GlyphOfReincarnationEffect()); + this.getSpellAbility().addWatcher(new BlockedAttackerWatcher()); + } + + public GlyphOfReincarnation(final GlyphOfReincarnation card) { + super(card); + } + + @Override + public GlyphOfReincarnation copy() { + return new GlyphOfReincarnation(this); + } +} + +class GlyphOfReincarnationEffect extends OneShotEffect { + + public GlyphOfReincarnationEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Destroy all creatures that were blocked by target Wall this turn. They can’t be regenerated. For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall onto the battlefield under its owner’s control"; + } + + public GlyphOfReincarnationEffect(final GlyphOfReincarnationEffect effect) { + super(effect); + } + + @Override + public GlyphOfReincarnationEffect copy() { + return new GlyphOfReincarnationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent targetWall = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); + if (controller != null && targetWall != null) { + BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + if (watcher != null) { + Map destroyed = new HashMap<>(); + for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { + if (!creature.getId().equals(targetWall.getId())) { + if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(targetWall, game), game)) { + if (creature.destroy(source.getSourceId(), game, true) + && game.getState().getZone(creature.getId()) == Zone.GRAVEYARD) { // If a commander is replaced to command zone, the creature does not die + Player permController = game.getPlayer(creature.getControllerId()); + if (permController != null) { + destroyed.put(creature.getId(), permController); + } + } + } + } + } + // For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall + // onto the battlefield under its owner’s control + for (Map.Entry entry : destroyed.entrySet()) { + Permanent permanent = (Permanent) game.getLastKnownInformation(entry.getKey(), Zone.BATTLEFIELD); + Player player = entry.getValue(); + if (permanent != null && player != null) { + FilterCreatureCard filter = new FilterCreatureCard("a creature card from " + player.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(player.getId())); + Target targetCreature = new TargetCardInGraveyard(filter); + targetCreature.setNotTarget(true); + if (targetCreature.canChoose(source.getSourceId(), controller.getId(), game) + && controller.chooseTarget(outcome, targetCreature, source, game)) { + Card card = game.getCard(targetCreature.getFirstTarget()); + if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null); + } + } + } + } + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GnarlidPack.java b/Mage.Sets/src/mage/cards/g/GnarlidPack.java index 24ce6b741ac..63e7c60edb7 100644 --- a/Mage.Sets/src/mage/cards/g/GnarlidPack.java +++ b/Mage.Sets/src/mage/cards/g/GnarlidPack.java @@ -31,7 +31,7 @@ public final class GnarlidPack extends CardImpl { // Gnarlid Pack enters the battlefield with a +1/+1 counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true), + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true), "with a +1/+1 counter on it for each time it was kicked")); } diff --git a/Mage.Sets/src/mage/cards/g/GnarlrootTrapper.java b/Mage.Sets/src/mage/cards/g/GnarlrootTrapper.java index 69e6f81b231..a58d85839da 100644 --- a/Mage.Sets/src/mage/cards/g/GnarlrootTrapper.java +++ b/Mage.Sets/src/mage/cards/g/GnarlrootTrapper.java @@ -38,7 +38,7 @@ public final class GnarlrootTrapper extends CardImpl { private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking ELf you control"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(new SubtypePredicate(SubType.ELF)); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinArchaeologist.java b/Mage.Sets/src/mage/cards/g/GoblinArchaeologist.java index 78a1c2c1944..5b04f0b8fe5 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinArchaeologist.java +++ b/Mage.Sets/src/mage/cards/g/GoblinArchaeologist.java @@ -75,7 +75,7 @@ class GoblinArchaeologistEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (player != null && permanent != null) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { permanent.sacrifice(source.getSourceId(), game); }else{ Permanent targetArtifact = game.getPermanent(source.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/g/GoblinArtisans.java b/Mage.Sets/src/mage/cards/g/GoblinArtisans.java index 97b830bea1a..876e1ee6dc8 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinArtisans.java +++ b/Mage.Sets/src/mage/cards/g/GoblinArtisans.java @@ -78,7 +78,7 @@ class GoblinArtisansEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { controller.drawCards(1, game); } else { List artifacts = game.getBattlefield().getActivePermanents(new FilterControlledArtifactPermanent(), source.getControllerId(), game); diff --git a/Mage.Sets/src/mage/cards/g/GoblinAssassin.java b/Mage.Sets/src/mage/cards/g/GoblinAssassin.java index d872d6b038e..c94cb90e398 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinAssassin.java +++ b/Mage.Sets/src/mage/cards/g/GoblinAssassin.java @@ -99,7 +99,7 @@ class GoblinAssassinTriggeredEffect extends OneShotEffect { if (controller != null) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - if (player != null && !player.flipCoin(game)) { + if (player != null && !player.flipCoin(source, game, false)) { TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); target.setNotTarget(true); if (target.canChoose(player.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinBangchuckers.java b/Mage.Sets/src/mage/cards/g/GoblinBangchuckers.java index 2f7b0c8669f..ff27db96dae 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBangchuckers.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBangchuckers.java @@ -63,7 +63,7 @@ class GoblinBangchuckersEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); if (permanent != null) { permanent.damage(2, source.getSourceId(), game, false, true); diff --git a/Mage.Sets/src/mage/cards/g/GoblinBarrage.java b/Mage.Sets/src/mage/cards/g/GoblinBarrage.java index cfc82c92486..57f2fef6e78 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBarrage.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBarrage.java @@ -1,7 +1,6 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.KickedCondition; import mage.abilities.costs.common.SacrificeTargetCost; @@ -19,19 +18,28 @@ import mage.game.Game; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class GoblinBarrage extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or Goblin"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new SubtypePredicate(SubType.GOBLIN) + )); + } + public GoblinBarrage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Kicker—Sacrifice an artifact or Goblin. - FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or Goblin"); - filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new SubtypePredicate(SubType.GOBLIN))); this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(filter)))); // Goblin Barrage deals 4 damage to target creature. If this spell was kicked, it also deals 4 damage to target player or planeswalker. @@ -40,13 +48,7 @@ public final class GoblinBarrage extends CardImpl { + "it also deals 4 damage to target player or planeswalker") ); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (KickedCondition.instance.apply(game, ability)) { - ability.addTarget(new TargetPlayerOrPlaneswalker()); - } + this.getSpellAbility().setTargetAdjuster(GoblinBarrageAdjuster.instance); } public GoblinBarrage(final GoblinBarrage card) { @@ -58,3 +60,14 @@ public final class GoblinBarrage extends CardImpl { return new GoblinBarrage(this); } } + +enum GoblinBarrageAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + if (KickedCondition.instance.apply(game, ability)) { + ability.addTarget(new TargetPlayerOrPlaneswalker()); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GoblinBomb.java b/Mage.Sets/src/mage/cards/g/GoblinBomb.java index fdab4e863cb..a8ced2d7823 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBomb.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBomb.java @@ -72,7 +72,7 @@ class GoblinBombEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { game.informPlayers("Goblin Bomb: Won flip. Put a fuse counter on Goblin Bomb."); new AddCountersSourceEffect(CounterType.FUSE.createInstance(1)).apply(game, source); return true; diff --git a/Mage.Sets/src/mage/cards/g/GoblinBoomKeg.java b/Mage.Sets/src/mage/cards/g/GoblinBoomKeg.java index 14007b84d9f..25eece23e9b 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBoomKeg.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBoomKeg.java @@ -1,11 +1,8 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -14,20 +11,21 @@ import mage.constants.CardType; import mage.constants.TargetController; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GoblinBoomKeg extends CardImpl { public GoblinBoomKeg(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // At the beginning of your upkeep, sacrifice Goblin Boom Keg. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect(), TargetController.YOU, false)); // When Goblin Boom Keg is put into a graveyard from the battlefield, it deals 3 damage to any target. - Ability ability = new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DamageTargetEffect(3, "it"), false); + Ability ability = new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DamageTargetEffect(3, "it")); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinCohort.java b/Mage.Sets/src/mage/cards/g/GoblinCohort.java index 592c7e67594..452b58b2bc5 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinCohort.java +++ b/Mage.Sets/src/mage/cards/g/GoblinCohort.java @@ -69,7 +69,7 @@ class GoblinCohortEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(source.getSourceId())) { - PlayerCastCreatureWatcher watcher = (PlayerCastCreatureWatcher) game.getState().getWatchers().get(PlayerCastCreatureWatcher.class.getSimpleName()); + PlayerCastCreatureWatcher watcher = game.getState().getWatcher(PlayerCastCreatureWatcher.class); if (watcher != null && !watcher.playerDidCastCreatureThisTurn(source.getControllerId())) { return true; } diff --git a/Mage.Sets/src/mage/cards/g/GoblinCratermaker.java b/Mage.Sets/src/mage/cards/g/GoblinCratermaker.java index ae1334c38e1..9b54aac730e 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinCratermaker.java +++ b/Mage.Sets/src/mage/cards/g/GoblinCratermaker.java @@ -29,7 +29,7 @@ public final class GoblinCratermaker extends CardImpl { = new FilterNonlandPermanent("colorless nonland permanent"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public GoblinCratermaker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinDynamo.java b/Mage.Sets/src/mage/cards/g/GoblinDynamo.java index 557ca2341d0..207bfd0dfb8 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinDynamo.java +++ b/Mage.Sets/src/mage/cards/g/GoblinDynamo.java @@ -35,7 +35,7 @@ public final class GoblinDynamo extends CardImpl { this.addAbility(ability); //{X}{R}, {T}, Sacrifice Goblin Dynamo: Goblin Dynamo deals X damage to any target. - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{R}")); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{R}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/g/GoblinFestival.java b/Mage.Sets/src/mage/cards/g/GoblinFestival.java index 9c4b52b88f2..e8e202928f3 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinFestival.java +++ b/Mage.Sets/src/mage/cards/g/GoblinFestival.java @@ -68,7 +68,7 @@ class GoblinFestivalChangeControlEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (controller != null) { - if (!controller.flipCoin(game)) { + if (!controller.flipCoin(source, game, true)) { if (sourcePermanent != null) { Target target = new TargetOpponent(true); if (target.canChoose(source.getSourceId(), controller.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinGathering.java b/Mage.Sets/src/mage/cards/g/GoblinGathering.java new file mode 100644 index 00000000000..3c6dec39ae2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinGathering.java @@ -0,0 +1,78 @@ +package mage.cards.g; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.game.permanent.token.GoblinToken; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GoblinGathering extends CardImpl { + + public GoblinGathering(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); + + // Create a number of 1/1 red Goblin creature tokens equal to two plus the number of cards named Goblin Gathering in your graveyard. + this.getSpellAbility().addEffect(new CreateTokenEffect( + new GoblinToken(), GoblinGatheringDynamicValue.instance + )); + } + + private GoblinGathering(final GoblinGathering card) { + super(card); + } + + @Override + public GoblinGathering copy() { + return new GoblinGathering(this); + } +} + +enum GoblinGatheringDynamicValue implements DynamicValue { + + instance; + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(new NamePredicate("Goblin Gathering")); + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + int amount = 0; + Player player = game.getPlayer(sourceAbility.getControllerId()); + if (player != null) { + amount += player.getGraveyard().count( + filter, sourceAbility.getSourceId(), + sourceAbility.getControllerId(), game + ); + } + return amount + 2; + } + + @Override + public GoblinGatheringDynamicValue copy() { + return instance; + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "two plus the number of cards named Goblin Gathering in your graveyard"; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinGoliath.java b/Mage.Sets/src/mage/cards/g/GoblinGoliath.java index b8ac5dc92cf..a6a7c02f607 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinGoliath.java +++ b/Mage.Sets/src/mage/cards/g/GoblinGoliath.java @@ -34,7 +34,7 @@ public final class GoblinGoliath extends CardImpl { this.toughness = new MageInt(4); // When Goblin Goliath enters the battlefield, create a number of 1/1 red Goblin creature tokens equal to the number of opponents you have. - Effect effect = new CreateTokenEffect(new GoblinToken(), new OpponentsCount()); + Effect effect = new CreateTokenEffect(new GoblinToken(), OpponentsCount.instance); effect.setText("create a number of 1/1 red Goblin creature tokens equal to the number of opponents you have"); this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); diff --git a/Mage.Sets/src/mage/cards/g/GoblinKaboomist.java b/Mage.Sets/src/mage/cards/g/GoblinKaboomist.java index 16db093cebf..2df939fa0da 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinKaboomist.java +++ b/Mage.Sets/src/mage/cards/g/GoblinKaboomist.java @@ -70,7 +70,7 @@ class GoblinKaboomistFlipCoinEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (player != null && permanent != null) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { String message = permanent.getLogName() + " deals 2 damage to itself"; game.informPlayers(message); permanent.damage(2, source.getSourceId(), game, false, true); diff --git a/Mage.Sets/src/mage/cards/g/GoblinKites.java b/Mage.Sets/src/mage/cards/g/GoblinKites.java index 1f3216e8e3b..cc2e03fef09 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinKites.java +++ b/Mage.Sets/src/mage/cards/g/GoblinKites.java @@ -69,7 +69,7 @@ class GoblinKitesEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { return true; } else { new SacrificeSourceEffect().apply(game, source); diff --git a/Mage.Sets/src/mage/cards/g/GoblinLyre.java b/Mage.Sets/src/mage/cards/g/GoblinLyre.java index e06192a2a50..1626668511f 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinLyre.java +++ b/Mage.Sets/src/mage/cards/g/GoblinLyre.java @@ -65,7 +65,7 @@ class GoblinLyreEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayerOrPlaneswalkerController(getTargetPointer().getFirst(game, source)); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { int damage = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent()).calculate(game, source, this); if (opponent != null) { return game.damagePlayerOrPlaneswalker(source.getFirstTarget(), damage, source.getSourceId(), game, false, true) > 0; diff --git a/Mage.Sets/src/mage/cards/g/GoblinMutant.java b/Mage.Sets/src/mage/cards/g/GoblinMutant.java index 9bc7a1e2663..aaa38655474 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinMutant.java +++ b/Mage.Sets/src/mage/cards/g/GoblinMutant.java @@ -30,7 +30,7 @@ public final class GoblinMutant extends CardImpl { static final private FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creatures with power 3 or greater"); static { - filter.add(Predicates.and(new PowerPredicate(ComparisonType.MORE_THAN, 2), Predicates.not(new TappedPredicate()))); + filter.add(Predicates.and(new PowerPredicate(ComparisonType.MORE_THAN, 2), Predicates.not(TappedPredicate.instance))); filter2.add(new PowerPredicate(ComparisonType.MORE_THAN, 2)); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinOffensive.java b/Mage.Sets/src/mage/cards/g/GoblinOffensive.java index 58cb3f35e5e..326309a34a2 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinOffensive.java +++ b/Mage.Sets/src/mage/cards/g/GoblinOffensive.java @@ -19,7 +19,7 @@ public final class GoblinOffensive extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{1}{R}{R}"); // create X 1/1 red Goblin creature tokens. - this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(), ManacostVariableValue.instance)); } public GoblinOffensive(final GoblinOffensive card) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinPiledriver.java b/Mage.Sets/src/mage/cards/g/GoblinPiledriver.java index bdf07184766..1c355d90913 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinPiledriver.java +++ b/Mage.Sets/src/mage/cards/g/GoblinPiledriver.java @@ -28,7 +28,7 @@ public final class GoblinPiledriver extends CardImpl { static { filter.add(new SubtypePredicate(SubType.GOBLIN)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GoblinPiledriver(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java b/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java index 611aab051c4..e2499125198 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java +++ b/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java @@ -60,7 +60,7 @@ class GoblinPsychopathEffect extends ReplacementEffectImpl { @Override public void init(Ability source, Game game) { - this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game); + this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(source, game, true); super.init(source, game); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinRabblemaster.java b/Mage.Sets/src/mage/cards/g/GoblinRabblemaster.java index 8c844215c66..813b051f727 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRabblemaster.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRabblemaster.java @@ -32,11 +32,11 @@ public final class GoblinRabblemaster extends CardImpl { private static final FilterCreaturePermanent attackingFilter = new FilterCreaturePermanent(SubType.GOBLIN, "other attacking Goblin"); static { - otherGoblinFilter.add(new AnotherPredicate()); + otherGoblinFilter.add(AnotherPredicate.instance); otherGoblinFilter.add(new ControllerPredicate(TargetController.YOU)); - attackingFilter.add(new AttackingPredicate()); - attackingFilter.add(new AnotherPredicate()); + attackingFilter.add(AttackingPredicate.instance); + attackingFilter.add(AnotherPredicate.instance); } public GoblinRabblemaster(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java b/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java index a4c3c44b11e..c70dbf9aacd 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java @@ -1,8 +1,6 @@ package mage.cards.g; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -12,16 +10,21 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author TheElk801 */ public final class GoblinRacketeer extends CardImpl { - private final UUID originalId; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(DefendingPlayerControlsPredicate.instance); + } public GoblinRacketeer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); @@ -33,27 +36,12 @@ public final class GoblinRacketeer extends CardImpl { // Whenever Goblin Racketeer attacks, you may goad target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new GoadTargetEffect(), true, "Whenever {this} attacks, you may goad target creature defending player controls"); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } public GoblinRacketeer(final GoblinRacketeer card) { super(card); - this.originalId = card.originalId; - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - ability.addTarget(target); - } } @Override diff --git a/Mage.Sets/src/mage/cards/g/GoblinRockSled.java b/Mage.Sets/src/mage/cards/g/GoblinRockSled.java index fa2d9fd3782..6c3defd2244 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRockSled.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRockSled.java @@ -96,7 +96,7 @@ class DontUntapIfAttackedLastTurnSourceEffect extends ContinuousRuleModifyingEff && event.getTargetId().equals(source.getSourceId())) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && permanent.isControlledBy(game.getActivePlayerId())) { - AttackedLastTurnWatcher watcher = (AttackedLastTurnWatcher) game.getState().getWatchers().get(AttackedLastTurnWatcher.class.getSimpleName()); + AttackedLastTurnWatcher watcher = game.getState().getWatcher(AttackedLastTurnWatcher.class); if (watcher != null) { Set attackingCreatures = watcher.getAttackedLastTurnCreatures(permanent.getControllerId()); MageObjectReference mor = new MageObjectReference(permanent, game); diff --git a/Mage.Sets/src/mage/cards/g/GodheadOfAwe.java b/Mage.Sets/src/mage/cards/g/GodheadOfAwe.java index 153484a72db..44a6fde8fd5 100644 --- a/Mage.Sets/src/mage/cards/g/GodheadOfAwe.java +++ b/Mage.Sets/src/mage/cards/g/GodheadOfAwe.java @@ -27,7 +27,7 @@ public final class GodheadOfAwe extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GodheadOfAwe(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GodhunterOctopus.java b/Mage.Sets/src/mage/cards/g/GodhunterOctopus.java index 1817d450213..b3b5bd14eca 100644 --- a/Mage.Sets/src/mage/cards/g/GodhunterOctopus.java +++ b/Mage.Sets/src/mage/cards/g/GodhunterOctopus.java @@ -26,7 +26,7 @@ public final class GodhunterOctopus extends CardImpl { static { filter.add(Predicates.or( new CardTypePredicate(CardType.ENCHANTMENT), - new EnchantedPredicate())); + EnchantedPredicate.instance)); } public GodhunterOctopus(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GodoBanditWarlord.java b/Mage.Sets/src/mage/cards/g/GodoBanditWarlord.java index e57e96692dd..8087a50f4c6 100644 --- a/Mage.Sets/src/mage/cards/g/GodoBanditWarlord.java +++ b/Mage.Sets/src/mage/cards/g/GodoBanditWarlord.java @@ -32,7 +32,7 @@ public final class GodoBanditWarlord extends CardImpl { static { filter.add(new SubtypePredicate(SubType.EQUIPMENT)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public GodoBanditWarlord(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GodsEyeGateToTheReikai.java b/Mage.Sets/src/mage/cards/g/GodsEyeGateToTheReikai.java index 675f616ec23..52055a07e13 100644 --- a/Mage.Sets/src/mage/cards/g/GodsEyeGateToTheReikai.java +++ b/Mage.Sets/src/mage/cards/g/GodsEyeGateToTheReikai.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.mana.ColorlessManaAbility; @@ -11,19 +9,22 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.game.permanent.token.SpiritToken; +import java.util.UUID; + /** - * * @author Loki */ public final class GodsEyeGateToTheReikai extends CardImpl { public GodsEyeGateToTheReikai(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); addSuperType(SuperType.LEGENDARY); + // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); + // When Gods' Eye, Gate to the Reikai is put into a graveyard from the battlefield, create a 1/1 colorless Spirit creature token. - this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new CreateTokenEffect(new SpiritToken(), 1), false)); + this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new CreateTokenEffect(new SpiritToken(), 1))); } public GodsEyeGateToTheReikai(final GodsEyeGateToTheReikai card) { diff --git a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java index c96c531112d..3ec9d69dd6e 100644 --- a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java @@ -38,7 +38,7 @@ public final class GoldenGuardian extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GoldenGuardian(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GoldnightRedeemer.java b/Mage.Sets/src/mage/cards/g/GoldnightRedeemer.java index 6291d17185c..856e6dfbc37 100644 --- a/Mage.Sets/src/mage/cards/g/GoldnightRedeemer.java +++ b/Mage.Sets/src/mage/cards/g/GoldnightRedeemer.java @@ -24,7 +24,7 @@ public final class GoldnightRedeemer extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GoldnightRedeemer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GolgariGermination.java b/Mage.Sets/src/mage/cards/g/GolgariGermination.java index bbcfdc53ee4..f6890106e67 100644 --- a/Mage.Sets/src/mage/cards/g/GolgariGermination.java +++ b/Mage.Sets/src/mage/cards/g/GolgariGermination.java @@ -24,7 +24,7 @@ public final class GolgariGermination extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public GolgariGermination(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GolgothianSylex.java b/Mage.Sets/src/mage/cards/g/GolgothianSylex.java index c2b9261d128..1bf1c09124d 100644 --- a/Mage.Sets/src/mage/cards/g/GolgothianSylex.java +++ b/Mage.Sets/src/mage/cards/g/GolgothianSylex.java @@ -51,7 +51,7 @@ class GolgothianSylexEffect extends OneShotEffect { static { filter.add(Predicates.and( new ExpansionSetPredicate("ATQ"), - Predicates.not(new TokenPredicate()) + Predicates.not(TokenPredicate.instance) )); } diff --git a/Mage.Sets/src/mage/cards/g/Gomazoa.java b/Mage.Sets/src/mage/cards/g/Gomazoa.java index f609015e0f4..c6b38885841 100644 --- a/Mage.Sets/src/mage/cards/g/Gomazoa.java +++ b/Mage.Sets/src/mage/cards/g/Gomazoa.java @@ -86,7 +86,7 @@ class GomazoaEffect extends OneShotEffect { players.add(gomazoa.getOwnerId()); } - BlockedByWatcher watcher = (BlockedByWatcher) game.getState().getWatchers().get(BlockedByWatcher.class.getSimpleName(), source.getSourceId()); + BlockedByWatcher watcher = game.getState().getWatcher(BlockedByWatcher.class, source.getSourceId()); creaturesBlocked = watcher.blockedByWatcher; for (UUID blockedById : creaturesBlocked) { diff --git a/Mage.Sets/src/mage/cards/g/GontisMachinations.java b/Mage.Sets/src/mage/cards/g/GontisMachinations.java index 513d8867123..270526ad693 100644 --- a/Mage.Sets/src/mage/cards/g/GontisMachinations.java +++ b/Mage.Sets/src/mage/cards/g/GontisMachinations.java @@ -68,7 +68,7 @@ class GontisMachinationsTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(getControllerId())) { GontisMachinationsFirstLostLifeThisTurnWatcher watcher - = (GontisMachinationsFirstLostLifeThisTurnWatcher) game.getState().getWatchers().get(GontisMachinationsFirstLostLifeThisTurnWatcher.class.getSimpleName()); + = game.getState().getWatcher(GontisMachinationsFirstLostLifeThisTurnWatcher.class); if (watcher != null && watcher.timesLostLifeThisTurn(event.getTargetId()) < 2) { return true; } @@ -92,7 +92,7 @@ class GontisMachinationsFirstLostLifeThisTurnWatcher extends Watcher { private final Map playersLostLife = new HashMap<>(); public GontisMachinationsFirstLostLifeThisTurnWatcher() { - super(GontisMachinationsFirstLostLifeThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(GontisMachinationsFirstLostLifeThisTurnWatcher.class, WatcherScope.GAME); } public GontisMachinationsFirstLostLifeThisTurnWatcher(final GontisMachinationsFirstLostLifeThisTurnWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/g/GossamerChains.java b/Mage.Sets/src/mage/cards/g/GossamerChains.java index de7c0d7e2c1..0d253b122be 100644 --- a/Mage.Sets/src/mage/cards/g/GossamerChains.java +++ b/Mage.Sets/src/mage/cards/g/GossamerChains.java @@ -24,7 +24,7 @@ public final class GossamerChains extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked creature"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } public GossamerChains(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java b/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java index e49428ecb09..edf5a2ab8dc 100644 --- a/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java +++ b/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java @@ -23,7 +23,7 @@ public final class GovernTheGuildless extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("monocolored creature"); static { - filter.add(new MonocoloredPredicate()); + filter.add(MonocoloredPredicate.instance); } public GovernTheGuildless(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GracefulAntelope.java b/Mage.Sets/src/mage/cards/g/GracefulAntelope.java index ec579769380..2269ccbcf65 100644 --- a/Mage.Sets/src/mage/cards/g/GracefulAntelope.java +++ b/Mage.Sets/src/mage/cards/g/GracefulAntelope.java @@ -1,6 +1,6 @@ - package mage.cards.g; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; @@ -11,11 +11,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.target.Target; import mage.target.common.TargetLandPermanent; -import java.util.UUID; - /** * * @author cbt33, Loki (Contaminated Ground), Plopman (Larceny) @@ -23,7 +20,7 @@ import java.util.UUID; public final class GracefulAntelope extends CardImpl { public GracefulAntelope(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); this.subtype.add(SubType.ANTELOPE); this.power = new MageInt(1); @@ -32,9 +29,8 @@ public final class GracefulAntelope extends CardImpl { // Plainswalk this.addAbility(new PlainswalkAbility()); // Whenever Graceful Antelope deals combat damage to a player, you may have target land become a Plains until Graceful Antelope leaves the battlefield. - Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new BecomesBasicLandTargetEffect(Duration.WhileOnBattlefield, SubType.PLAINS), true); - Target target = new TargetLandPermanent(); - ability.addTarget(target); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new BecomesBasicLandTargetEffect(Duration.UntilSourceLeavesBattlefield, SubType.PLAINS), true); + ability.addTarget(new TargetLandPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GrandArchitect.java b/Mage.Sets/src/mage/cards/g/GrandArchitect.java index e599814dfc4..3060d391378 100644 --- a/Mage.Sets/src/mage/cards/g/GrandArchitect.java +++ b/Mage.Sets/src/mage/cards/g/GrandArchitect.java @@ -105,7 +105,7 @@ class GrandArchitectManaAbility extends ActivatedManaAbilityImpl { static { filter.add(new ColorPredicate(ObjectColor.BLUE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } GrandArchitectManaAbility() { diff --git a/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java b/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java index 508844bc913..5f06e04c4fe 100644 --- a/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java +++ b/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java @@ -65,7 +65,7 @@ class CreaturesAttackedWatcher extends Watcher { public final Set attackedThisTurnCreatures = new HashSet<>(); public CreaturesAttackedWatcher() { - super(CreaturesAttackedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(CreaturesAttackedWatcher.class, WatcherScope.GAME); } public CreaturesAttackedWatcher(final CreaturesAttackedWatcher watcher) { @@ -153,7 +153,7 @@ class GrandWarlordRadhaEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - CreaturesAttackedWatcher watcher = (CreaturesAttackedWatcher) game.getState().getWatchers().get(CreaturesAttackedWatcher.class.getSimpleName()); + CreaturesAttackedWatcher watcher = game.getState().getWatcher(CreaturesAttackedWatcher.class); if (watcher != null) { int attackingCreatures = 0; for (MageObjectReference attacker : watcher.getAttackedThisTurnCreatures()) { diff --git a/Mage.Sets/src/mage/cards/g/GraspOfFate.java b/Mage.Sets/src/mage/cards/g/GraspOfFate.java index 271b67e7304..3fbb8169049 100644 --- a/Mage.Sets/src/mage/cards/g/GraspOfFate.java +++ b/Mage.Sets/src/mage/cards/g/GraspOfFate.java @@ -1,7 +1,6 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; @@ -23,10 +22,12 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author fireshoes */ public final class GraspOfFate extends CardImpl { @@ -36,8 +37,8 @@ public final class GraspOfFate extends CardImpl { // When Grasp of Fate enters the battlefield, for each opponent, exile up to one target nonland permanent that player controls until Grasp of Fate leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new GraspOfFateExileEffect()); - ability.addTarget(new TargetPermanent()); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); + ability.setTargetAdjuster(GraspOfFateAdjuster.instance); this.addAbility(ability); } @@ -45,29 +46,32 @@ public final class GraspOfFate extends CardImpl { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterPermanent filter = new FilterPermanent("nonland permanent from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - TargetPermanent target = new TargetPermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - } - } - @Override public GraspOfFate copy() { return new GraspOfFate(this); } } +enum GraspOfFateAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent == null) { + continue; + } + FilterPermanent filter = new FilterPermanent("nonland permanent from opponent " + opponent.getLogName()); + filter.add(new ControllerIdPredicate(opponentId)); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + TargetPermanent target = new TargetPermanent(0, 1, filter, false); + ability.addTarget(target); + } + } +} + class GraspOfFateExileEffect extends OneShotEffect { public GraspOfFateExileEffect() { diff --git a/Mage.Sets/src/mage/cards/g/GraspingThrull.java b/Mage.Sets/src/mage/cards/g/GraspingThrull.java new file mode 100644 index 00000000000..c383888f514 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GraspingThrull.java @@ -0,0 +1,48 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GraspingThrull extends CardImpl { + + public GraspingThrull(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{B}"); + + this.subtype.add(SubType.THRULL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Grasping Thrull enters the battlefield, it deals 2 damage to each opponent and you gain 2 life. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect( + 2, TargetController.OPPONENT, "it" + )); + ability.addEffect(new GainLifeEffect(2).setText("and you gain 2 life")); + this.addAbility(ability); + } + + private GraspingThrull(final GraspingThrull card) { + super(card); + } + + @Override + public GraspingThrull copy() { + return new GraspingThrull(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GraveBetrayal.java b/Mage.Sets/src/mage/cards/g/GraveBetrayal.java index 888925283e9..fb1ccc708ad 100644 --- a/Mage.Sets/src/mage/cards/g/GraveBetrayal.java +++ b/Mage.Sets/src/mage/cards/g/GraveBetrayal.java @@ -162,7 +162,7 @@ class GraveBetrayalReplacementEffect extends ReplacementEffectImpl { ContinuousEffect effect = new BecomesBlackZombieAdditionEffect(); effect.setTargetPointer(new FixedTarget(creature.getId(), creature.getZoneChangeCounter(game) + 1)); game.addEffect(effect, source); - discard(); + //discard(); why? } return false; } diff --git a/Mage.Sets/src/mage/cards/g/GravelHideGoblin.java b/Mage.Sets/src/mage/cards/g/GravelHideGoblin.java new file mode 100644 index 00000000000..1d5f4f2e1ce --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GravelHideGoblin.java @@ -0,0 +1,42 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GravelHideGoblin extends CardImpl { + + public GravelHideGoblin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {3}{G}: Gravel-Hide Goblin gets +2/+2 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(2, 2, Duration.EndOfTurn), new ManaCostsImpl("{3}{G}") + )); + } + + private GravelHideGoblin(final GravelHideGoblin card) { + super(card); + } + + @Override + public GravelHideGoblin copy() { + return new GravelHideGoblin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GravenAbomination.java b/Mage.Sets/src/mage/cards/g/GravenAbomination.java index c48c21d1234..18f67304719 100644 --- a/Mage.Sets/src/mage/cards/g/GravenAbomination.java +++ b/Mage.Sets/src/mage/cards/g/GravenAbomination.java @@ -1,7 +1,6 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -11,20 +10,22 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.FilterCard; -import mage.filter.predicate.other.OwnerIdPredicate; -import mage.game.Game; -import mage.players.Player; +import mage.filter.predicate.permanent.DefendingPlayerOwnsCardPredicate; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class GravenAbomination extends CardImpl { - private final UUID originalId; + private static final String rule = "Whenever {this} attacks, exile target card from defending player's graveyard."; + private static final FilterCard filter = new FilterCard("card from defending player's graveyard"); - private final static String rule = "Whenever {this} attacks, exile target card from defending player's graveyard."; + static { + filter.add(new DefendingPlayerOwnsCardPredicate()); + } public GravenAbomination(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); @@ -35,30 +36,12 @@ public final class GravenAbomination extends CardImpl { // Whenever Graven Abomination attacks, exile target card from defending player's graveyard. Ability ability = new AttacksTriggeredAbility(new ExileTargetEffect(), false, rule); - ability.addTarget(new TargetCardInGraveyard()); + ability.addTarget(new TargetCardInGraveyard(filter)); this.addAbility(ability); - originalId = ability.getOriginalId(); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - UUID gravenAbominationId = ability.getSourceId(); - FilterCard filter = new FilterCard("target card from defending player's graveyard"); - if (ability.getOriginalId().equals(originalId)) { - UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(gravenAbominationId, game); - Player defendingPlayer = game.getPlayer(defendingPlayerId); - if (defendingPlayer != null) { - filter.add(new OwnerIdPredicate(defendingPlayerId)); - ability.getTargets().clear(); - ability.getTargets().add(new TargetCardInGraveyard(filter)); - } - } } public GravenAbomination(final GravenAbomination card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/g/GravenDominator.java b/Mage.Sets/src/mage/cards/g/GravenDominator.java index eb01ba0deeb..39db2926a72 100644 --- a/Mage.Sets/src/mage/cards/g/GravenDominator.java +++ b/Mage.Sets/src/mage/cards/g/GravenDominator.java @@ -23,7 +23,7 @@ public final class GravenDominator extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GravenDominator(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java b/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java index 4a8f32c2c88..dad0cec4b61 100644 --- a/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java +++ b/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java @@ -30,7 +30,7 @@ public final class GravespawnSovereign extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ZOMBIE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public GravespawnSovereign(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GravityNegator.java b/Mage.Sets/src/mage/cards/g/GravityNegator.java index 77632558d05..17673de97b7 100644 --- a/Mage.Sets/src/mage/cards/g/GravityNegator.java +++ b/Mage.Sets/src/mage/cards/g/GravityNegator.java @@ -28,7 +28,7 @@ public final class GravityNegator extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GravityNegator(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GreatDefender.java b/Mage.Sets/src/mage/cards/g/GreatDefender.java index 44d18590fe4..369c3eafd6f 100644 --- a/Mage.Sets/src/mage/cards/g/GreatDefender.java +++ b/Mage.Sets/src/mage/cards/g/GreatDefender.java @@ -22,7 +22,7 @@ public final class GreatDefender extends CardImpl { // Target creature gets +0/+X until end of turn, where X is its converted mana cost. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true) + this.getSpellAbility().addEffect(new BoostTargetEffect(new StaticValue(0), TargetConvertedManaCost.instance, Duration.EndOfTurn, true) .setText("Target creature gets +0/+X until end of turn, where X is its converted mana cost.") ); } diff --git a/Mage.Sets/src/mage/cards/g/GreaterAuramancy.java b/Mage.Sets/src/mage/cards/g/GreaterAuramancy.java index befbb73a1b4..76c8afdeb80 100644 --- a/Mage.Sets/src/mage/cards/g/GreaterAuramancy.java +++ b/Mage.Sets/src/mage/cards/g/GreaterAuramancy.java @@ -31,7 +31,7 @@ public final class GreaterAuramancy extends CardImpl { filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); filter2.add(new ControllerPredicate(TargetController.YOU)); filter2.add(new CardTypePredicate(CardType.CREATURE)); - filter2.add(new EnchantedPredicate()); + filter2.add(EnchantedPredicate.instance); } public GreaterAuramancy(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GreaterGood.java b/Mage.Sets/src/mage/cards/g/GreaterGood.java index 7aa69e4d2bf..7fc94447bc5 100644 --- a/Mage.Sets/src/mage/cards/g/GreaterGood.java +++ b/Mage.Sets/src/mage/cards/g/GreaterGood.java @@ -26,7 +26,7 @@ public final class GreaterGood extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}"); // Sacrifice a creature: Draw cards equal to the sacrificed creature's power, then discard three cards. - Effect effect = new DrawCardSourceControllerEffect(new SacrificeCostCreaturesPower()); + Effect effect = new DrawCardSourceControllerEffect(SacrificeCostCreaturesPower.instance); effect.setText("Draw cards equal to the sacrificed creature's power"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); diff --git a/Mage.Sets/src/mage/cards/g/GreelMindRaker.java b/Mage.Sets/src/mage/cards/g/GreelMindRaker.java index f3543a1950d..bc79a60e01e 100644 --- a/Mage.Sets/src/mage/cards/g/GreelMindRaker.java +++ b/Mage.Sets/src/mage/cards/g/GreelMindRaker.java @@ -36,7 +36,7 @@ public final class GreelMindRaker extends CardImpl { this.toughness = new MageInt(3); // {X}{B}, {tap}, Discard two cards: Target player discards X cards at random. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(new ManacostVariableValue(), true), new ManaCostsImpl("{X}{B}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(ManacostVariableValue.instance, true), new ManaCostsImpl("{X}{B}")); ability.addCost(new TapSourceCost()); ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, new FilterCard()))); ability.addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/g/GreenManaBattery.java b/Mage.Sets/src/mage/cards/g/GreenManaBattery.java index d0bf8cdfc0b..9669605db22 100644 --- a/Mage.Sets/src/mage/cards/g/GreenManaBattery.java +++ b/Mage.Sets/src/mage/cards/g/GreenManaBattery.java @@ -36,7 +36,7 @@ public final class GreenManaBattery extends CardImpl { // {tap}, Remove any number of charge counters from Green Mana Battery: Add {G}, then add an additional {G} for each charge counter removed this way. ability = new DynamicManaAbility( Mana.GreenMana(1), - new IntPlusDynamicValue(1, new RemovedCountersForCostValue()), + new IntPlusDynamicValue(1, RemovedCountersForCostValue.instance), new TapSourceCost(), "Add {G}, then add {G} for each charge counter removed this way", true, new CountersSourceCount(CounterType.CHARGE)); diff --git a/Mage.Sets/src/mage/cards/g/Gridlock.java b/Mage.Sets/src/mage/cards/g/Gridlock.java index a94c6e78489..23c6be94f65 100644 --- a/Mage.Sets/src/mage/cards/g/Gridlock.java +++ b/Mage.Sets/src/mage/cards/g/Gridlock.java @@ -1,9 +1,7 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,41 +9,40 @@ import mage.constants.CardType; import mage.filter.common.FilterNonlandPermanent; import mage.game.Game; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class Gridlock extends CardImpl { - private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanents"); public Gridlock(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); // Tap X target nonland permanents. - this.getSpellAbility().addEffect(new TapTargetEffect()); - // Correct number of targets will be set in adjustTargets - this.getSpellAbility().addTarget(new TargetPermanent(0, 1,filter, false)); - + this.getSpellAbility().addEffect(new TapTargetEffect("X target nonland permanents")); + this.getSpellAbility().setTargetAdjuster(GridlockAdjuster.instance); } public Gridlock(final Gridlock card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numberToTap = ability.getManaCostsToPay().getX(); - numberToTap = Math.min(game.getBattlefield().count(filter, ability.getSourceId(), ability.getControllerId(), game), numberToTap); - ability.addTarget(new TargetPermanent(numberToTap, filter)); - } - } - @Override public Gridlock copy() { return new Gridlock(this); } } + +enum GridlockAdjuster implements TargetAdjuster { + instance; + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanents"); + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetPermanent(ability.getManaCostsToPay().getX(), filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GrimHaruspex.java b/Mage.Sets/src/mage/cards/g/GrimHaruspex.java index 858cdc62dfe..bf0c9d478ba 100644 --- a/Mage.Sets/src/mage/cards/g/GrimHaruspex.java +++ b/Mage.Sets/src/mage/cards/g/GrimHaruspex.java @@ -28,8 +28,8 @@ public final class GrimHaruspex extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another nontoken creature you control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public GrimHaruspex(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GrimPoppet.java b/Mage.Sets/src/mage/cards/g/GrimPoppet.java index 4d2318472a1..2e4004752c9 100644 --- a/Mage.Sets/src/mage/cards/g/GrimPoppet.java +++ b/Mage.Sets/src/mage/cards/g/GrimPoppet.java @@ -28,7 +28,7 @@ public final class GrimPoppet extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GrimPoppet(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GrimReminder.java b/Mage.Sets/src/mage/cards/g/GrimReminder.java index 6ad9da49df4..d25a47eed4c 100644 --- a/Mage.Sets/src/mage/cards/g/GrimReminder.java +++ b/Mage.Sets/src/mage/cards/g/GrimReminder.java @@ -93,7 +93,7 @@ class GrimReminderEffect extends OneShotEffect { Cards cardsToReveal = new CardsImpl(card); controller.revealCards(sourceObject.getIdName(), cardsToReveal, game); String cardName = card.getName(); - GrimReminderWatcher watcher = (GrimReminderWatcher) game.getState().getWatchers().get(GrimReminderWatcher.class.getSimpleName()); + GrimReminderWatcher watcher = game.getState().getWatcher(GrimReminderWatcher.class); if (watcher != null) { for (UUID playerId : watcher.getPlayersCastSpell(cardName)) { Player player = game.getPlayer(playerId); @@ -116,7 +116,7 @@ class GrimReminderWatcher extends Watcher { private final Map> playersCastSpell = new HashMap<>(); public GrimReminderWatcher() { - super(GrimReminderWatcher.class.getSimpleName(), WatcherScope.GAME); + super(GrimReminderWatcher.class, WatcherScope.GAME); } public GrimReminderWatcher(final GrimReminderWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/g/GrimReturn.java b/Mage.Sets/src/mage/cards/g/GrimReturn.java index 19e46ebcaa0..9fb55552e82 100644 --- a/Mage.Sets/src/mage/cards/g/GrimReturn.java +++ b/Mage.Sets/src/mage/cards/g/GrimReturn.java @@ -1,9 +1,6 @@ package mage.cards.g; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.Effect; @@ -17,10 +14,14 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardIdPredicate; import mage.game.Game; import mage.target.common.TargetCardInGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import mage.watchers.common.CardsPutIntoGraveyardWatcher; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GrimReturn extends CardImpl { @@ -28,13 +29,13 @@ public final class GrimReturn extends CardImpl { private static final String textFilter = "creature card in a graveyard that was put there from the battlefield this turn"; public GrimReturn(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); // Choose target creature card in a graveyard that was put there from the battlefield this turn. Put that card onto the battlefield under your control. Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); effect.setText("Choose target creature card in a graveyard that was put there from the battlefield this turn. Put that card onto the battlefield under your control"); this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard(textFilter))); + this.getSpellAbility().setTargetAdjuster(GrimReturnAdjuster.instance); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); } @@ -46,22 +47,27 @@ public final class GrimReturn extends CardImpl { public GrimReturn copy() { return new GrimReturn(this); } +} + +enum GrimReturnAdjuster implements TargetAdjuster { + instance; + private static final String textFilter = "creature card in a graveyard that was put there from the battlefield this turn"; @Override public void adjustTargets(Ability ability, Game game) { - CardsPutIntoGraveyardWatcher watcher = (CardsPutIntoGraveyardWatcher) game.getState().getWatchers().get(CardsPutIntoGraveyardWatcher.class.getSimpleName()); - if (watcher != null) { - FilterCard filter = new FilterCreatureCard(textFilter); - List uuidPredicates = new ArrayList<>(); - for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { - if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { - uuidPredicates.add(new CardIdPredicate(mor.getSourceId())); - } - } - filter.add(Predicates.or(uuidPredicates)); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInGraveyard(filter)); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); + if (watcher == null) { + return; } - + FilterCard filter = new FilterCreatureCard(textFilter); + List uuidPredicates = new ArrayList<>(); + for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { + if (mor.zoneCounterIsCurrent(game)) { + uuidPredicates.add(new CardIdPredicate(mor.getSourceId())); + } + } + filter.add(Predicates.or(uuidPredicates)); + ability.getTargets().clear(); + ability.addTarget(new TargetCardInGraveyard(filter)); } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GrimStrider.java b/Mage.Sets/src/mage/cards/g/GrimStrider.java index 52027151678..816259aad66 100644 --- a/Mage.Sets/src/mage/cards/g/GrimStrider.java +++ b/Mage.Sets/src/mage/cards/g/GrimStrider.java @@ -29,7 +29,7 @@ public final class GrimStrider extends CardImpl { this.toughness = new MageInt(6); // Grim Strider gets -1/-1 for each card in your hand. - DynamicValue count = new SignInversionDynamicValue(new CardsInControllerHandCount()); + DynamicValue count = new SignInversionDynamicValue(CardsInControllerHandCount.instance); Effect effect = new BoostSourceEffect(count, count, Duration.WhileOnBattlefield); effect.setText("{this} gets -1/-1 for each card in your hand"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java b/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java index 26548048daf..3fd572c4713 100644 --- a/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java +++ b/Mage.Sets/src/mage/cards/g/GrimlockDinobotLeader.java @@ -38,7 +38,7 @@ public final class GrimlockDinobotLeader extends CardImpl{ static { filter2.add(Predicates.not(new SubtypePredicate(SubType.DINOSAUR))); filter2.add(Predicates.not(new SubtypePredicate(SubType.VEHICLE))); - filter2.add(Predicates.or(new AbilityPredicate(TransformAbility.class), new TransformedPredicate())); + filter2.add(Predicates.or(new AbilityPredicate(TransformAbility.class), TransformedPredicate.instance)); } public GrimlockDinobotLeader(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GrindDust.java b/Mage.Sets/src/mage/cards/g/GrindDust.java index 28941ffe2c0..f6ca8ccfa39 100644 --- a/Mage.Sets/src/mage/cards/g/GrindDust.java +++ b/Mage.Sets/src/mage/cards/g/GrindDust.java @@ -34,7 +34,7 @@ public final class GrindDust extends SplitCard { // Dust // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Exile any number of target creatures that have -1/-1 counters on them. getRightHalfCard().getSpellAbility().addEffect(new ExileTargetEffect()); FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures that have -1/-1 counters on them"); diff --git a/Mage.Sets/src/mage/cards/g/GrixisGrimblade.java b/Mage.Sets/src/mage/cards/g/GrixisGrimblade.java index 3a6d2b65f77..9f47971b9b0 100644 --- a/Mage.Sets/src/mage/cards/g/GrixisGrimblade.java +++ b/Mage.Sets/src/mage/cards/g/GrixisGrimblade.java @@ -29,8 +29,8 @@ public final class GrixisGrimblade extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another multicolor permanent"); static { - filter.add(new MulticoloredPredicate()); - filter.add(new AnotherPredicate()); + filter.add(MulticoloredPredicate.instance); + filter.add(AnotherPredicate.instance); } public GrixisGrimblade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java index 543b5807b10..b1715bac1f4 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java @@ -55,7 +55,7 @@ class GrizzledAnglerEffect extends OneShotEffect { private static final FilterCreatureCard filter = new FilterCreatureCard("a colorless creature card in your graveyard"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public GrizzledAnglerEffect() { diff --git a/Mage.Sets/src/mage/cards/g/GrotesqueDemise.java b/Mage.Sets/src/mage/cards/g/GrotesqueDemise.java new file mode 100644 index 00000000000..8abc7e0bcf6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GrotesqueDemise.java @@ -0,0 +1,42 @@ +package mage.cards.g; + +import mage.abilities.effects.common.ExileTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GrotesqueDemise extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with power 3 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4)); + } + + public GrotesqueDemise(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); + + // Exile target creature with power 3 or less. + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + } + + private GrotesqueDemise(final GrotesqueDemise card) { + super(card); + } + + @Override + public GrotesqueDemise copy() { + return new GrotesqueDemise(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java b/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java index 27a39841c3c..d5013b28788 100644 --- a/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java +++ b/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java @@ -64,7 +64,7 @@ class GrothamaAllDevouringGainAbilityEffect extends GainAbilityAllEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } GrothamaAllDevouringGainAbilityEffect() { @@ -148,7 +148,7 @@ class GrothamaAllDevouringDrawCardsEffect extends OneShotEffect { if (controller == null) { return false; } - GrothamaAllDevouringWatcher watcher = (GrothamaAllDevouringWatcher) game.getState().getWatchers().get(GrothamaAllDevouringWatcher.class.getSimpleName()); + GrothamaAllDevouringWatcher watcher = game.getState().getWatcher(GrothamaAllDevouringWatcher.class); if (watcher == null) { return false; } @@ -171,7 +171,7 @@ class GrothamaAllDevouringWatcher extends Watcher { Map> damageMap = new HashMap<>(); GrothamaAllDevouringWatcher() { - super(GrothamaAllDevouringWatcher.class.getSimpleName(), WatcherScope.GAME); + super(GrothamaAllDevouringWatcher.class, WatcherScope.GAME); } GrothamaAllDevouringWatcher(final GrothamaAllDevouringWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java b/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java index f5ae5cbfd91..d7c445de70d 100644 --- a/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java @@ -33,7 +33,7 @@ public final class GroveOfTheGuardian extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public GroveOfTheGuardian(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GrowthChamberGuardian.java b/Mage.Sets/src/mage/cards/g/GrowthChamberGuardian.java new file mode 100644 index 00000000000..07e23ab62a1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GrowthChamberGuardian.java @@ -0,0 +1,53 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.common.OneOrMoreCountersAddedTriggeredAbility; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GrowthChamberGuardian extends CardImpl { + + private static final FilterCard filter + = new FilterCard("a card named Growth-Chamber Guardian"); + + static { + filter.add(new NamePredicate("Growth-Chamber Guardian")); + } + + public GrowthChamberGuardian(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.CRAB); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {2}{G}: Adapt 2. + this.addAbility(new AdaptAbility(2, "{2}{G}")); + + // Whenever one or more +1/+1 counters are put on Growth-Chamber Guardian, you may search your library for a card named Growth-Chamber Guardian, reveal it, put it into your hand, then shuffle your library. + this.addAbility(new OneOrMoreCountersAddedTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true), true)); + } + + private GrowthChamberGuardian(final GrowthChamberGuardian card) { + super(card); + } + + @Override + public GrowthChamberGuardian copy() { + return new GrowthChamberGuardian(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GruesomeSlaughter.java b/Mage.Sets/src/mage/cards/g/GruesomeSlaughter.java index 9e7c23ffeea..944d82dd9d5 100644 --- a/Mage.Sets/src/mage/cards/g/GruesomeSlaughter.java +++ b/Mage.Sets/src/mage/cards/g/GruesomeSlaughter.java @@ -27,7 +27,7 @@ public final class GruesomeSlaughter extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creatures you control"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public GruesomeSlaughter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GruulBeastmaster.java b/Mage.Sets/src/mage/cards/g/GruulBeastmaster.java new file mode 100644 index 00000000000..c0e203c35b0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GruulBeastmaster.java @@ -0,0 +1,64 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GruulBeastmaster extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("another target creature you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + private static final DynamicValue xValue = new SourcePermanentPowerCount(false); + + public GruulBeastmaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Riot + this.addAbility(new RiotAbility()); + + // Whenever Gruul Beastmaster attacks, another target creature you control gets +X/+0 until end of turn, where X is Gruul Beastmaster's power. + Ability ability = new AttacksTriggeredAbility(new BoostTargetEffect( + xValue, StaticValue.getZeroValue(), Duration.EndOfTurn, true + ), false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private GruulBeastmaster(final GruulBeastmaster card) { + super(card); + } + + @Override + public GruulBeastmaster copy() { + return new GruulBeastmaster(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GruulLocket.java b/Mage.Sets/src/mage/cards/g/GruulLocket.java new file mode 100644 index 00000000000..465cbb52f34 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GruulLocket.java @@ -0,0 +1,45 @@ +package mage.cards.g; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class GruulLocket extends CardImpl { + + public GruulLocket(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {T}: Add {R} or {G}. + this.addAbility(new RedManaAbility()); + this.addAbility(new GreenManaAbility()); + + // {R/G}{R/G}{R/G}{R/G}, {T}, Sacrifice Gruul Locket: Draw two cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), new ManaCostsImpl<>("{R/G}{R/G}{R/G}{R/G}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public GruulLocket(final GruulLocket card) { + super(card); + } + + @Override + public GruulLocket copy() { + return new GruulLocket(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GruulWarChant.java b/Mage.Sets/src/mage/cards/g/GruulWarChant.java index ca508dd10c7..d403a4a3670 100644 --- a/Mage.Sets/src/mage/cards/g/GruulWarChant.java +++ b/Mage.Sets/src/mage/cards/g/GruulWarChant.java @@ -26,7 +26,7 @@ public final class GruulWarChant extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creatures you control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public GruulWarChant(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GuanYus1000LiMarch.java b/Mage.Sets/src/mage/cards/g/GuanYus1000LiMarch.java index 6a5e9d1f594..5d4d4adb66c 100644 --- a/Mage.Sets/src/mage/cards/g/GuanYus1000LiMarch.java +++ b/Mage.Sets/src/mage/cards/g/GuanYus1000LiMarch.java @@ -18,7 +18,7 @@ public final class GuanYus1000LiMarch extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creatures"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public GuanYus1000LiMarch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GuardianOfTheGuildpact.java b/Mage.Sets/src/mage/cards/g/GuardianOfTheGuildpact.java index e70bbd7cd59..d912fe35185 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianOfTheGuildpact.java +++ b/Mage.Sets/src/mage/cards/g/GuardianOfTheGuildpact.java @@ -20,7 +20,7 @@ public final class GuardianOfTheGuildpact extends CardImpl { private static final FilterCard filter = new FilterCard("monocolored"); static { - filter.add(new MonocoloredPredicate()); + filter.add(MonocoloredPredicate.instance); } public GuardianOfTheGuildpact(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GuardianProject.java b/Mage.Sets/src/mage/cards/g/GuardianProject.java new file mode 100644 index 00000000000..fe7ac3aa846 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GuardianProject.java @@ -0,0 +1,153 @@ +package mage.cards.g; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.other.OwnerIdPredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GuardianProject extends CardImpl { + + public GuardianProject(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + // Whenever a nontoken creature enters the battlefield under your control, if that creature does not have the same name as another creature you control or a creature card in your graveyard, draw a card. + this.addAbility(new GuardianProjectTriggeredAbility()); + } + + private GuardianProject(final GuardianProject card) { + super(card); + } + + @Override + public GuardianProject copy() { + return new GuardianProject(this); + } +} + +class GuardianProjectTriggeredAbility extends EntersBattlefieldAllTriggeredAbility { + + public static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(Predicates.not(TokenPredicate.instance)); + } + + GuardianProjectTriggeredAbility() { + super(new GuardianProjectEffect(null), filter); + } + + private GuardianProjectTriggeredAbility(final GuardianProjectTriggeredAbility ability) { + super(ability); + } + + @Override + public GuardianProjectTriggeredAbility copy() { + return new GuardianProjectTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); + if (!filter.match(permanent, sourceId, controllerId, game)) { + return false; + } + + if (checkCondition(permanent, controllerId, game)) { + this.getEffects().clear(); + this.addEffect(new GuardianProjectEffect(new MageObjectReference(permanent, game))); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever a nontoken creature enters the battlefield under your control, " + + "if that creature does not have the same name as another creature you control " + + "or a creature card in your graveyard, draw a card."; + } + + // This is needed as checkInterveningIfClause can't access trigger event information + static boolean checkCondition(Permanent permanent, UUID controllerId, Game game) { + Player player = game.getPlayer(controllerId); + if (player == null) { + return false; + } + if (!permanent.getName().isEmpty()) { + FilterCard filterCard = new FilterCard(); + filterCard.add(new NamePredicate(permanent.getName())); + filterCard.add(new OwnerIdPredicate(controllerId)); + if (player.getGraveyard().count(filterCard, game) > 0) { + return false; + } + } + FilterPermanent filterPermanent = new FilterCreaturePermanent(); + filterPermanent.add(new NamePredicate(permanent.getName())); + filterPermanent.add(Predicates.not(new CardIdPredicate(permanent.getId()))); + filterPermanent.add(new ControllerIdPredicate(controllerId)); + if (game.getBattlefield().getActivePermanents(filterPermanent, controllerId, game).size() > 0) { + return false; + } + return true; + } +} + +class GuardianProjectEffect extends OneShotEffect { + + private final MageObjectReference mor; + + GuardianProjectEffect(MageObjectReference mor) { + super(Outcome.Benefit); + this.mor = mor; + } + + private GuardianProjectEffect(final GuardianProjectEffect effect) { + super(effect); + this.mor = effect.mor; + } + + @Override + public GuardianProjectEffect copy() { + return new GuardianProjectEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + if (GuardianProjectTriggeredAbility.checkCondition( + mor.getPermanentOrLKIBattlefield(game), source.getControllerId(), game) + ) { + player.drawCards(1, game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java b/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java index b880b36706c..944497e356d 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java +++ b/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java @@ -26,7 +26,7 @@ public final class GuardianShieldBearer extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public GuardianShieldBearer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GuardiansMagemark.java b/Mage.Sets/src/mage/cards/g/GuardiansMagemark.java index e3f44eb59d6..b16ee18b66b 100644 --- a/Mage.Sets/src/mage/cards/g/GuardiansMagemark.java +++ b/Mage.Sets/src/mage/cards/g/GuardiansMagemark.java @@ -25,7 +25,7 @@ public final class GuardiansMagemark extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java b/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java index 792cbaca872..01d08304a57 100644 --- a/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java +++ b/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java @@ -26,8 +26,8 @@ public final class GuardiansOfKoilos extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another historic permanent you control"); static { - filter.add(new AnotherPredicate()); - filter.add(new HistoricPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(HistoricPredicate.instance); } public GuardiansOfKoilos(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/GuildSummit.java b/Mage.Sets/src/mage/cards/g/GuildSummit.java index a6d18e5a067..5f66810b15e 100644 --- a/Mage.Sets/src/mage/cards/g/GuildSummit.java +++ b/Mage.Sets/src/mage/cards/g/GuildSummit.java @@ -64,7 +64,7 @@ class GuildSummitEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.GATE)); } diff --git a/Mage.Sets/src/mage/cards/g/GuildmagesForum.java b/Mage.Sets/src/mage/cards/g/GuildmagesForum.java index 1a1792352e0..e87d34e10d0 100644 --- a/Mage.Sets/src/mage/cards/g/GuildmagesForum.java +++ b/Mage.Sets/src/mage/cards/g/GuildmagesForum.java @@ -88,11 +88,6 @@ class GuildmagesForumWatcher extends Watcher { } } - @Override - public void reset() { - super.reset(); - } - } class GuildmagesForumEntersBattlefieldEffect extends ReplacementEffectImpl { diff --git a/Mage.Sets/src/mage/cards/g/GuildscornWard.java b/Mage.Sets/src/mage/cards/g/GuildscornWard.java index d5b36ac2c5b..926493ff835 100644 --- a/Mage.Sets/src/mage/cards/g/GuildscornWard.java +++ b/Mage.Sets/src/mage/cards/g/GuildscornWard.java @@ -24,7 +24,7 @@ public final class GuildscornWard extends CardImpl { private static final FilterObject filter = new FilterObject("multicolored"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public GuildscornWard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/g/Gutterbones.java b/Mage.Sets/src/mage/cards/g/Gutterbones.java new file mode 100644 index 00000000000..fe3aefee96c --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/Gutterbones.java @@ -0,0 +1,69 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.watchers.common.PlayerLostLifeWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Gutterbones extends CardImpl { + + public Gutterbones(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.SKELETON); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Gutterbones enters the battlefield tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {1}{B}: Return Gutterbones from your graveyard to your hand. Activate this ability only during your turn and only if an opponent lost life this turn. + this.addAbility(new ConditionalActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl("{1}{B}"), GutterbonesCondition.instance + )); + } + + private Gutterbones(final Gutterbones card) { + super(card); + } + + @Override + public Gutterbones copy() { + return new Gutterbones(this); + } +} + +enum GutterbonesCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + if (game.isActivePlayer(source.getControllerId())) { + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); + return watcher != null && watcher.getAllOppLifeLost(source.getControllerId(), game) > 0; + } + return false; + } + + @Override + public String toString() { + return "during your turn and only if an opponent lost life this turn"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GyreEngineer.java b/Mage.Sets/src/mage/cards/g/GyreEngineer.java new file mode 100644 index 00000000000..94ee946a7d4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GyreEngineer.java @@ -0,0 +1,40 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.Mana; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GyreEngineer extends CardImpl { + + public GyreEngineer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}"); + + this.subtype.add(SubType.VEDALKEN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {T}: Add {G}{U}. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new Mana(0, 1, 1, 0, 0, 0, 0, 0), new TapSourceCost())); + } + + private GyreEngineer(final GyreEngineer card) { + super(card); + } + + @Override + public GyreEngineer copy() { + return new GyreEngineer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java b/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java index b7224b44243..298ef39c257 100644 --- a/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java +++ b/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java @@ -57,7 +57,7 @@ public final class GyrusWakerOfCorpses extends CardImpl { this.toughness = new MageInt(0); // Gyrus, Walker of Corpses enters the battlefield with a number of +1/+1 counters on it equal to the amount of mana spent to cast it. - Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new ManaSpentToCastCount(), true); + Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), ManaSpentToCastCount.instance, true); effect.setText("with a number of +1/+1 counters on it equal to the amount of mana spent to cast it"); this.addAbility(new EntersBattlefieldAbility(effect)); diff --git a/Mage.Sets/src/mage/cards/h/HaazdaOfficer.java b/Mage.Sets/src/mage/cards/h/HaazdaOfficer.java new file mode 100644 index 00000000000..1f657213043 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HaazdaOfficer.java @@ -0,0 +1,42 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HaazdaOfficer extends CardImpl { + + public HaazdaOfficer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Haazda Officer enters the battlefield, target creature you control gets +1/+1 until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(1, 1)); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + private HaazdaOfficer(final HaazdaOfficer card) { + super(card); + } + + @Override + public HaazdaOfficer copy() { + return new HaazdaOfficer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/Hackrobat.java b/Mage.Sets/src/mage/cards/h/Hackrobat.java new file mode 100644 index 00000000000..c2ad3229d6f --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/Hackrobat.java @@ -0,0 +1,58 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.SpectacleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Hackrobat extends CardImpl { + + public Hackrobat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Spectacle {B}{R} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{B}{R}"))); + + // {B}: Hackrobat gains deathtouch until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new GainAbilitySourceEffect( + DeathtouchAbility.getInstance(), + Duration.EndOfTurn + ), new ColoredManaCost(ColoredManaSymbol.B) + )); + + // {R}: Hackrobat gets +2/-2 until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(2, -2, Duration.EndOfTurn), + new ColoredManaCost(ColoredManaSymbol.R) + )); + } + + private Hackrobat(final Hackrobat card) { + super(card); + } + + @Override + public Hackrobat copy() { + return new Hackrobat(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HailOfArrows.java b/Mage.Sets/src/mage/cards/h/HailOfArrows.java index 6fadd26e165..90020cd2c28 100644 --- a/Mage.Sets/src/mage/cards/h/HailOfArrows.java +++ b/Mage.Sets/src/mage/cards/h/HailOfArrows.java @@ -20,8 +20,8 @@ public final class HailOfArrows extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{W}"); // Hail of Arrows deals X damage divided as you choose among any number of target attacking creatures. - this.getSpellAbility().addEffect(new DamageMultiEffect(new ManacostVariableValue())); - this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(new ManacostVariableValue(), new FilterAttackingCreature())); + this.getSpellAbility().addEffect(new DamageMultiEffect(ManacostVariableValue.instance)); + this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(ManacostVariableValue.instance, new FilterAttackingCreature())); } public HailOfArrows(final HailOfArrows card) { diff --git a/Mage.Sets/src/mage/cards/h/HairStrungKoto.java b/Mage.Sets/src/mage/cards/h/HairStrungKoto.java index 9851b3a7a65..461113571c5 100644 --- a/Mage.Sets/src/mage/cards/h/HairStrungKoto.java +++ b/Mage.Sets/src/mage/cards/h/HairStrungKoto.java @@ -52,7 +52,7 @@ public final class HairStrungKoto extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public HairStrungKoto (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/Halfdane.java b/Mage.Sets/src/mage/cards/h/Halfdane.java index 9c0972d6112..d837c5c9b7b 100644 --- a/Mage.Sets/src/mage/cards/h/Halfdane.java +++ b/Mage.Sets/src/mage/cards/h/Halfdane.java @@ -27,7 +27,7 @@ public final class Halfdane extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature other than Halfdane"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Halfdane(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java b/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java index 90ccbbcf021..4665df8897a 100644 --- a/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java +++ b/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java @@ -83,7 +83,7 @@ class HallowedMoonlightEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) event; if (entersTheBattlefieldEvent.getTarget().isCreature()) { - CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get(CreatureWasCastWatcher.class.getSimpleName()); + CreatureWasCastWatcher watcher = game.getState().getWatcher(CreatureWasCastWatcher.class); if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { return true; } diff --git a/Mage.Sets/src/mage/cards/h/HallsOfMist.java b/Mage.Sets/src/mage/cards/h/HallsOfMist.java index 1896bc612a1..72cb16de38c 100644 --- a/Mage.Sets/src/mage/cards/h/HallsOfMist.java +++ b/Mage.Sets/src/mage/cards/h/HallsOfMist.java @@ -62,7 +62,7 @@ class CantAttackIfAttackedLastTurnAllEffect extends RestrictionEffect { @Override public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game) { - AttackedLastTurnWatcher watcher = (AttackedLastTurnWatcher) game.getState().getWatchers().get(AttackedLastTurnWatcher.class.getSimpleName()); + AttackedLastTurnWatcher watcher = game.getState().getWatcher(AttackedLastTurnWatcher.class); if (watcher != null) { Set attackingCreatures = watcher.getAttackedLastTurnCreatures(attacker.getControllerId()); MageObjectReference mor = new MageObjectReference(attacker, game); diff --git a/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java b/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java index 4fcedfed348..c24bc7ef690 100644 --- a/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java +++ b/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java @@ -28,7 +28,7 @@ public final class HammerheadCorvette extends CardImpl { static { filter.add(new SubtypePredicate(SubType.STARSHIP)); - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public HammerheadCorvette(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java b/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java index 9508f8e3189..27a92480897 100644 --- a/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java +++ b/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java @@ -31,7 +31,7 @@ public final class HanSoloScrumrat extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HanSoloScrumrat(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HandOfJustice.java b/Mage.Sets/src/mage/cards/h/HandOfJustice.java index 31dceaa7837..cb8f234b8aa 100644 --- a/Mage.Sets/src/mage/cards/h/HandOfJustice.java +++ b/Mage.Sets/src/mage/cards/h/HandOfJustice.java @@ -31,7 +31,7 @@ public final class HandOfJustice extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public HandOfJustice(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HarbingerOfTheHunt.java b/Mage.Sets/src/mage/cards/h/HarbingerOfTheHunt.java index 48abb7cf9a3..59df8b1227e 100644 --- a/Mage.Sets/src/mage/cards/h/HarbingerOfTheHunt.java +++ b/Mage.Sets/src/mage/cards/h/HarbingerOfTheHunt.java @@ -29,7 +29,7 @@ public final class HarbingerOfTheHunt extends CardImpl { static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); filter2.add(new AbilityPredicate(FlyingAbility.class)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public HarbingerOfTheHunt(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java b/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java index c2f3051f35b..407f1fe645c 100644 --- a/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java +++ b/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java @@ -27,7 +27,7 @@ public final class HarbingerOfTheTides extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature an opponent controls"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/h/HardenedBerserker.java b/Mage.Sets/src/mage/cards/h/HardenedBerserker.java index 5793f80ee18..dbcc074bfbc 100644 --- a/Mage.Sets/src/mage/cards/h/HardenedBerserker.java +++ b/Mage.Sets/src/mage/cards/h/HardenedBerserker.java @@ -62,7 +62,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI @Override public void init(Ability source, Game game) { super.init(source, game); - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()); } @@ -76,7 +76,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) > spellsCast) { discard(); // only one use diff --git a/Mage.Sets/src/mage/cards/h/HarmonyOfNature.java b/Mage.Sets/src/mage/cards/h/HarmonyOfNature.java index 6a7f17e1d4d..33bcb4b7a72 100644 --- a/Mage.Sets/src/mage/cards/h/HarmonyOfNature.java +++ b/Mage.Sets/src/mage/cards/h/HarmonyOfNature.java @@ -49,7 +49,7 @@ class HarmonyOfNatureEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public HarmonyOfNatureEffect() { diff --git a/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java b/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java index 165ef34ebb7..d7eb201d296 100644 --- a/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java +++ b/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java @@ -61,7 +61,7 @@ class HarnessTheStormTriggeredAbility extends SpellCastControllerTriggeredAbilit @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - CastFromHandWatcher watcher = (CastFromHandWatcher) game.getState().getWatchers().get(CastFromHandWatcher.class.getSimpleName()); + CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class); if (watcher != null && watcher.spellWasCastFromHand(event.getSourceId())) { Spell spell = game.getState().getStack().getSpell(event.getSourceId()); if (spell != null) { diff --git a/Mage.Sets/src/mage/cards/h/HarshJustice.java b/Mage.Sets/src/mage/cards/h/HarshJustice.java index 6f763f7f431..b65e020c9bd 100644 --- a/Mage.Sets/src/mage/cards/h/HarshJustice.java +++ b/Mage.Sets/src/mage/cards/h/HarshJustice.java @@ -63,7 +63,7 @@ class HarshJusticeTriggeredAbility extends DelayedTriggeredAbility { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public HarshJusticeTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/h/HarshMentor.java b/Mage.Sets/src/mage/cards/h/HarshMentor.java index 44fe93aa0a0..7a01484d2a9 100644 --- a/Mage.Sets/src/mage/cards/h/HarshMentor.java +++ b/Mage.Sets/src/mage/cards/h/HarshMentor.java @@ -1,7 +1,5 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.dynamicvalue.common.StaticValue; @@ -20,8 +18,9 @@ import mage.game.events.GameEvent.EventType; import mage.game.stack.StackAbility; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author spjspj */ public final class HarshMentor extends CardImpl { @@ -51,7 +50,7 @@ public final class HarshMentor extends CardImpl { class HarshMentorTriggeredAbility extends TriggeredAbilityImpl { HarshMentorTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(new StaticValue(2), false, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(new StaticValue(2), true, "that player", true)); } HarshMentorTriggeredAbility(final HarshMentorTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/h/HarvestPyre.java b/Mage.Sets/src/mage/cards/h/HarvestPyre.java index 859ec2c1325..1c4f36caecd 100644 --- a/Mage.Sets/src/mage/cards/h/HarvestPyre.java +++ b/Mage.Sets/src/mage/cards/h/HarvestPyre.java @@ -26,7 +26,7 @@ public final class HarvestPyre extends CardImpl { // Harvest Pyre deals X damage to target creature. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new DamageTargetEffect(new GetXValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance)); } public HarvestPyre(final HarvestPyre card) { diff --git a/Mage.Sets/src/mage/cards/h/HarvestSeason.java b/Mage.Sets/src/mage/cards/h/HarvestSeason.java index f0652a5db11..02bbfdf85a8 100644 --- a/Mage.Sets/src/mage/cards/h/HarvestSeason.java +++ b/Mage.Sets/src/mage/cards/h/HarvestSeason.java @@ -50,7 +50,7 @@ class HarvestSeasonEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("tapped creature you control"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } HarvestSeasonEffect() { diff --git a/Mage.Sets/src/mage/cards/h/HarvesterOfSouls.java b/Mage.Sets/src/mage/cards/h/HarvesterOfSouls.java index 92bf69c0b24..487f203ec76 100644 --- a/Mage.Sets/src/mage/cards/h/HarvesterOfSouls.java +++ b/Mage.Sets/src/mage/cards/h/HarvesterOfSouls.java @@ -23,8 +23,8 @@ public final class HarvesterOfSouls extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); - filter.add(new AnotherPredicate()); + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); } public HarvesterOfSouls(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HatchingPlans.java b/Mage.Sets/src/mage/cards/h/HatchingPlans.java index 586b5f0db62..ce66f5a1312 100644 --- a/Mage.Sets/src/mage/cards/h/HatchingPlans.java +++ b/Mage.Sets/src/mage/cards/h/HatchingPlans.java @@ -1,27 +1,26 @@ - - package mage.cards.h; -import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import java.util.UUID; + /** - * * @author Loki */ public final class HatchingPlans extends CardImpl { - public HatchingPlans (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}"); + public HatchingPlans(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + // When Hatching Plans is put into a graveyard from the battlefield, draw three cards. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DrawCardSourceControllerEffect(3))); } - public HatchingPlans (final HatchingPlans card) { + public HatchingPlans(final HatchingPlans card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/h/Hatred.java b/Mage.Sets/src/mage/cards/h/Hatred.java index fd01727fbda..1d096e1cb6a 100644 --- a/Mage.Sets/src/mage/cards/h/Hatred.java +++ b/Mage.Sets/src/mage/cards/h/Hatred.java @@ -26,7 +26,7 @@ public final class Hatred extends CardImpl { this.getSpellAbility().addCost(new PayVariableLifeCost(true)); // Target creature gets +X/+0 until end of turn. - DynamicValue xValue = new GetXValue(); + DynamicValue xValue = GetXValue.instance; this.getSpellAbility().addEffect(new BoostTargetEffect(xValue, new StaticValue(0), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/h/HauntingHymn.java b/Mage.Sets/src/mage/cards/h/HauntingHymn.java index a4f09875fb3..4ab5f76652f 100644 --- a/Mage.Sets/src/mage/cards/h/HauntingHymn.java +++ b/Mage.Sets/src/mage/cards/h/HauntingHymn.java @@ -2,7 +2,7 @@ package mage.cards.h; import java.util.UUID; -import mage.abilities.condition.common.MyMainPhaseCondition; +import mage.abilities.condition.common.AddendumCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; @@ -23,7 +23,7 @@ public final class HauntingHymn extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new DiscardTargetEffect(4), new DiscardTargetEffect(2), - MyMainPhaseCondition.instance, + AddendumCondition.instance, "Target player discards two cards. If you cast this spell during your main phase, that player discards four cards instead")); this.getSpellAbility().addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/h/HauntingMisery.java b/Mage.Sets/src/mage/cards/h/HauntingMisery.java index aa4f0f4de2d..a6a2d25197f 100644 --- a/Mage.Sets/src/mage/cards/h/HauntingMisery.java +++ b/Mage.Sets/src/mage/cards/h/HauntingMisery.java @@ -24,7 +24,7 @@ public final class HauntingMisery extends CardImpl { this.getSpellAbility().addCost(new ExileXFromYourGraveCost(new FilterCreatureCard())); // Haunting Misery deals X damage to target player. this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); - this.getSpellAbility().addEffect(new DamageTargetEffect(new GetXValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance)); } public HauntingMisery(final HauntingMisery card) { diff --git a/Mage.Sets/src/mage/cards/h/HavengulSkaab.java b/Mage.Sets/src/mage/cards/h/HavengulSkaab.java index 6953a576d72..7cd46a2b7c0 100644 --- a/Mage.Sets/src/mage/cards/h/HavengulSkaab.java +++ b/Mage.Sets/src/mage/cards/h/HavengulSkaab.java @@ -50,7 +50,7 @@ class HavengulSkaabAbility extends TriggeredAbilityImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HavengulSkaabAbility() { diff --git a/Mage.Sets/src/mage/cards/h/HazyHomunculus.java b/Mage.Sets/src/mage/cards/h/HazyHomunculus.java index 6a7ad243d61..67e4877ae4b 100644 --- a/Mage.Sets/src/mage/cards/h/HazyHomunculus.java +++ b/Mage.Sets/src/mage/cards/h/HazyHomunculus.java @@ -27,7 +27,7 @@ public final class HazyHomunculus extends CardImpl { private static final FilterPermanent filter = new FilterLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public HazyHomunculus(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HeadstrongBrute.java b/Mage.Sets/src/mage/cards/h/HeadstrongBrute.java index e2cf1d102dd..d04c6920f60 100644 --- a/Mage.Sets/src/mage/cards/h/HeadstrongBrute.java +++ b/Mage.Sets/src/mage/cards/h/HeadstrongBrute.java @@ -29,7 +29,7 @@ public final class HeadstrongBrute extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PIRATE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HeadstrongBrute(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HearthCharm.java b/Mage.Sets/src/mage/cards/h/HearthCharm.java index 5b6e3d7aece..af7d92eea0e 100644 --- a/Mage.Sets/src/mage/cards/h/HearthCharm.java +++ b/Mage.Sets/src/mage/cards/h/HearthCharm.java @@ -28,7 +28,7 @@ public final class HearthCharm extends CardImpl { private static final FilterCreaturePermanent filter3 = new FilterCreaturePermanent("creature with power 2 or less"); static { filter1.add(new CardTypePredicate(CardType.ARTIFACT)); - filter2.add(new AttackingPredicate()); + filter2.add(AttackingPredicate.instance); filter3.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); } diff --git a/Mage.Sets/src/mage/cards/h/HeatRay.java b/Mage.Sets/src/mage/cards/h/HeatRay.java index d05f13cf840..571dcae460c 100644 --- a/Mage.Sets/src/mage/cards/h/HeatRay.java +++ b/Mage.Sets/src/mage/cards/h/HeatRay.java @@ -19,7 +19,7 @@ public final class HeatRay extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}"); - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/h/HeatStroke.java b/Mage.Sets/src/mage/cards/h/HeatStroke.java index 130b465e313..6d4a1982bc6 100644 --- a/Mage.Sets/src/mage/cards/h/HeatStroke.java +++ b/Mage.Sets/src/mage/cards/h/HeatStroke.java @@ -66,8 +66,9 @@ class HeatStrokeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - BlockedThisTurnWatcher blockedWatcher = (BlockedThisTurnWatcher) game.getState().getWatchers().get(BlockedThisTurnWatcher.class.getSimpleName()); - WasBlockedThisTurnWatcher wasBlockedThisTurnWatcher = (WasBlockedThisTurnWatcher) game.getState().getWatchers().get(WasBlockedThisTurnWatcher.class.getSimpleName()); + BlockedThisTurnWatcher blockedWatcher = game.getState().getWatcher(BlockedThisTurnWatcher.class); + WasBlockedThisTurnWatcher wasBlockedThisTurnWatcher = game.getState().getWatcher(WasBlockedThisTurnWatcher.class); + Set inROI = new HashSet<>(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)); boolean toRet = false; Set toDestroy = new HashSet<>(); diff --git a/Mage.Sets/src/mage/cards/h/HeavenEarth.java b/Mage.Sets/src/mage/cards/h/HeavenEarth.java index 86dfdf57f59..51dad694db3 100644 --- a/Mage.Sets/src/mage/cards/h/HeavenEarth.java +++ b/Mage.Sets/src/mage/cards/h/HeavenEarth.java @@ -33,13 +33,13 @@ public final class HeavenEarth extends SplitCard { // Falling // Falling deals X damage to each creature with flying. - getLeftHalfCard().getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filterFlying)); + getLeftHalfCard().getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, filterFlying)); // to // Earth // Earth deals X damage to each creature without flying. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); - getRightHalfCard().getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filterWithouFlying)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, filterWithouFlying)); } public HeavenEarth(final HeavenEarth card) { diff --git a/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java b/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java index 853fb730b87..1f3f0386ce2 100644 --- a/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java +++ b/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java @@ -24,7 +24,7 @@ public final class HeavenlyQilin extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HeavenlyQilin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/Hecatomb.java b/Mage.Sets/src/mage/cards/h/Hecatomb.java index 30efd3863b8..ed9b77932cf 100644 --- a/Mage.Sets/src/mage/cards/h/Hecatomb.java +++ b/Mage.Sets/src/mage/cards/h/Hecatomb.java @@ -32,7 +32,7 @@ public final class Hecatomb extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SWAMP)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Hecatomb(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HelixPinnacle.java b/Mage.Sets/src/mage/cards/h/HelixPinnacle.java index dc62fe13770..268d7f125b0 100644 --- a/Mage.Sets/src/mage/cards/h/HelixPinnacle.java +++ b/Mage.Sets/src/mage/cards/h/HelixPinnacle.java @@ -34,7 +34,7 @@ public final class HelixPinnacle extends CardImpl { // {X}: Put X tower counters on Helix Pinnacle. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new AddCountersSourceEffect(CounterType.TOWER.createInstance(), new ManacostVariableValue(), true), + new AddCountersSourceEffect(CounterType.TOWER.createInstance(), ManacostVariableValue.instance, true), new ManaCostsImpl("{X}"))); // At the beginning of your upkeep, if there are 100 or more tower counters on Helix Pinnacle, you win the game. diff --git a/Mage.Sets/src/mage/cards/h/Helldozer.java b/Mage.Sets/src/mage/cards/h/Helldozer.java index 71f73bb478f..b1f5860b863 100644 --- a/Mage.Sets/src/mage/cards/h/Helldozer.java +++ b/Mage.Sets/src/mage/cards/h/Helldozer.java @@ -1,4 +1,3 @@ - package mage.cards.h; import java.util.UUID; @@ -33,7 +32,10 @@ public final class Helldozer extends CardImpl { this.toughness = new MageInt(5); // {B}{B}{B}, {tap}: Destroy target land. If that land was nonbasic, untap Helldozer. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HelldozerEffect(), new ManaCostsImpl("{B}{B}{B}")); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new HelldozerEffect(), + new ManaCostsImpl("{B}{B}{B}")); ability.addTarget(new TargetLandPermanent()); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -70,13 +72,13 @@ class HelldozerEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent helldozer = game.getPermanent(source.getSourceId()); Permanent landTarget = game.getPermanent(source.getFirstTarget()); - if (landTarget == null) { - return false; - } - boolean wasNonBasic = !landTarget.isBasic(); - landTarget.destroy(id, game, false); - if (wasNonBasic && helldozer != null) { - return helldozer.untap(game); + if (landTarget != null) { + boolean wasNonBasic = !landTarget.isBasic(); + landTarget.destroy(source.getSourceId(), game, false); + if (wasNonBasic + && helldozer != null) { + return helldozer.untap(game); + } } return false; } diff --git a/Mage.Sets/src/mage/cards/h/HellkiteWhelp.java b/Mage.Sets/src/mage/cards/h/HellkiteWhelp.java index 3baa8970d36..902555e718a 100644 --- a/Mage.Sets/src/mage/cards/h/HellkiteWhelp.java +++ b/Mage.Sets/src/mage/cards/h/HellkiteWhelp.java @@ -25,7 +25,7 @@ public final class HellkiteWhelp extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public HellkiteWhelp(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java index 4221686f3a2..bad8be25926 100644 --- a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java +++ b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java @@ -49,7 +49,7 @@ public final class HelmOfObedience extends CardImpl { class HelmOfObedienceEffect extends OneShotEffect { - private static final ManacostVariableValue amount = new ManacostVariableValue(); + private static final ManacostVariableValue amount = ManacostVariableValue.instance; public HelmOfObedienceEffect() { super(Outcome.Detriment); diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfDromoka.java b/Mage.Sets/src/mage/cards/h/HeraldOfDromoka.java index a5308cf18de..8e2fe33826a 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldOfDromoka.java +++ b/Mage.Sets/src/mage/cards/h/HeraldOfDromoka.java @@ -28,7 +28,7 @@ public final class HeraldOfDromoka extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new SubtypePredicate(SubType.WARRIOR)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HeraldOfDromoka(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfKozilek.java b/Mage.Sets/src/mage/cards/h/HeraldOfKozilek.java index c83c25f0aa3..eb589cc5f70 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldOfKozilek.java +++ b/Mage.Sets/src/mage/cards/h/HeraldOfKozilek.java @@ -23,7 +23,7 @@ public final class HeraldOfKozilek extends CardImpl { private static final FilterCard filter = new FilterCard("Colorless spells"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public HeraldOfKozilek(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HerdGnarr.java b/Mage.Sets/src/mage/cards/h/HerdGnarr.java index 4bc79e2edc9..8fe90b62c83 100644 --- a/Mage.Sets/src/mage/cards/h/HerdGnarr.java +++ b/Mage.Sets/src/mage/cards/h/HerdGnarr.java @@ -23,7 +23,7 @@ public final class HerdGnarr extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HerdGnarr(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HerdchaserDragon.java b/Mage.Sets/src/mage/cards/h/HerdchaserDragon.java index 3f41bf6ec21..b8970974f37 100644 --- a/Mage.Sets/src/mage/cards/h/HerdchaserDragon.java +++ b/Mage.Sets/src/mage/cards/h/HerdchaserDragon.java @@ -27,7 +27,7 @@ public final class HerdchaserDragon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other Dragon creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/h/HeritageDruid.java b/Mage.Sets/src/mage/cards/h/HeritageDruid.java index 546f91ed037..01419463c65 100644 --- a/Mage.Sets/src/mage/cards/h/HeritageDruid.java +++ b/Mage.Sets/src/mage/cards/h/HeritageDruid.java @@ -25,7 +25,7 @@ public final class HeritageDruid extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Elves you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.ELF)); } diff --git a/Mage.Sets/src/mage/cards/h/HeroOfPrecinctOne.java b/Mage.Sets/src/mage/cards/h/HeroOfPrecinctOne.java new file mode 100644 index 00000000000..925e811c209 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeroOfPrecinctOne.java @@ -0,0 +1,42 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.HumanToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HeroOfPrecinctOne extends CardImpl { + + public HeroOfPrecinctOne(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever you cast a multicolored spell, create a 1/1 white Human creature token. + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new HumanToken()), StaticFilters.FILTER_SPELL_A_MULTICOLORED, false + )); + } + + private HeroOfPrecinctOne(final HeroOfPrecinctOne card) { + super(card); + } + + @Override + public HeroOfPrecinctOne copy() { + return new HeroOfPrecinctOne(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HiddenRetreat.java b/Mage.Sets/src/mage/cards/h/HiddenRetreat.java index b90d3d088a3..9569a11ab6e 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenRetreat.java +++ b/Mage.Sets/src/mage/cards/h/HiddenRetreat.java @@ -9,15 +9,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import java.util.UUID; import mage.filter.StaticFilters; +import mage.game.Game; import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; import mage.target.TargetSpell; +import java.util.UUID; + /** - * * @author bunchOfDevs */ public class HiddenRetreat extends CardImpl { @@ -27,7 +27,7 @@ public class HiddenRetreat extends CardImpl { //Put a card from your hand on top of your library: Prevent all damage that would be dealt by target instant or sorcery spell this turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HiddenRetreatEffect(), new PutCardFromHandOnTopOfLibraryCost()); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HighAlert.java b/Mage.Sets/src/mage/cards/h/HighAlert.java new file mode 100644 index 00000000000..c846241de82 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HighAlert.java @@ -0,0 +1,60 @@ +package mage.cards.h; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderAllEffect; +import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HighAlert extends CardImpl { + + public HighAlert(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{U}"); + + + // Each creature you control assigns combat damage equal to its toughness rather than its power. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CombatDamageByToughnessEffect( + StaticFilters.FILTER_PERMANENT_CREATURE, true + ) + )); + + // Creatures you control can attack as though they didn't have defender. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CanAttackAsThoughItDidntHaveDefenderAllEffect( + Duration.WhileOnBattlefield, + StaticFilters.FILTER_CONTROLLED_CREATURES + ) + )); + + // {2}{W}{U}: Untap target creature. + Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new ManaCostsImpl("{2}{W}{U}")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private HighAlert(final HighAlert card) { + super(card); + } + + @Override + public HighAlert copy() { + return new HighAlert(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HighSentinelsOfArashin.java b/Mage.Sets/src/mage/cards/h/HighSentinelsOfArashin.java index 9f9da602608..44a2ab40721 100644 --- a/Mage.Sets/src/mage/cards/h/HighSentinelsOfArashin.java +++ b/Mage.Sets/src/mage/cards/h/HighSentinelsOfArashin.java @@ -32,7 +32,7 @@ public final class HighSentinelsOfArashin extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creature you control with a +1/+1 counter on it"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new CounterPredicate(CounterType.P1P1)); } diff --git a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java index 745149db0bb..1d299587214 100644 --- a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java +++ b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java @@ -1,14 +1,8 @@ - package mage.cards.h; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.FilterCard; @@ -16,9 +10,11 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetCardInHand; +import mage.util.CardUtil; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class HintOfInsanity extends CardImpl { @@ -26,7 +22,7 @@ public final class HintOfInsanity extends CardImpl { public HintOfInsanity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); - // Target player reveals his or her hand. That player discards all nonland cards with the same name as another card in his or her hand. + // Target player reveals their hand. That player discards all nonland cards with the same name as another card in their hand. this.getSpellAbility().addEffect(new HintOfInsanityEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); @@ -62,7 +58,6 @@ class HintOfInsanityEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { FilterCard filter = new FilterCard("card from your hand"); Player targetPlayer = game.getPlayer(source.getFirstTarget()); - String nameOfChosenCard; Card chosenCard; if (targetPlayer != null) { TargetCardInHand targetCard = new TargetCardInHand(filter); @@ -73,10 +68,8 @@ class HintOfInsanityEffect extends OneShotEffect { if (!cardsInHand.isEmpty() && targetPlayer.choose(Outcome.Discard, targetCard, source.getSourceId(), game)) { chosenCard = game.getCard(targetCard.getFirstTarget()); - nameOfChosenCard = chosenCard.getName(); for (Card card : cardsInHand.getCards(game)) { - if (card.getName().equals(nameOfChosenCard) - && !card.isLand()) { + if (CardUtil.haveSameNames(card, chosenCard) && !card.isLand()) { targetPlayer.discard(card, source, game); } } diff --git a/Mage.Sets/src/mage/cards/h/HisokasGuard.java b/Mage.Sets/src/mage/cards/h/HisokasGuard.java index c8479a741a9..0d11887e2aa 100644 --- a/Mage.Sets/src/mage/cards/h/HisokasGuard.java +++ b/Mage.Sets/src/mage/cards/h/HisokasGuard.java @@ -45,7 +45,7 @@ public final class HisokasGuard extends CardImpl { // {1}{U}, {T}: Target creature you control other than Hisoka's Guard has shroud for as long as Hisoka's Guard remains tapped. (It can't be the target of spells or abilities.) FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HisokasGuardGainAbilityTargetEffect(), new ManaCostsImpl("{1}{U}")); ability.addCost(new TapSourceCost()); Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); diff --git a/Mage.Sets/src/mage/cards/h/HiveMind.java b/Mage.Sets/src/mage/cards/h/HiveMind.java index 179a64073b6..4dd55146622 100644 --- a/Mage.Sets/src/mage/cards/h/HiveMind.java +++ b/Mage.Sets/src/mage/cards/h/HiveMind.java @@ -68,7 +68,7 @@ class HiveMindTriggeredAbility extends TriggeredAbilityImpl { || spell.isSorcery())) { for (Effect effect : getEffects()) { if (effect instanceof HiveMindEffect) { - ((HiveMindEffect) effect).setTargetPointer(new FixedTarget(spell.getId())); + effect.setTargetPointer(new FixedTarget(spell.getId())); } } return true; diff --git a/Mage.Sets/src/mage/cards/h/HivisOfTheScale.java b/Mage.Sets/src/mage/cards/h/HivisOfTheScale.java index 6e4b9110a0e..70b093b32b7 100644 --- a/Mage.Sets/src/mage/cards/h/HivisOfTheScale.java +++ b/Mage.Sets/src/mage/cards/h/HivisOfTheScale.java @@ -37,7 +37,7 @@ public final class HivisOfTheScale extends CardImpl { private static final String rule = "Gain control of target Dragon for as long as you control Hivis and Hivis remains tapped."; static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); filterDragon.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/h/HoldoutSettlement.java b/Mage.Sets/src/mage/cards/h/HoldoutSettlement.java index 89f2c60b91d..cbf0f1ea91d 100644 --- a/Mage.Sets/src/mage/cards/h/HoldoutSettlement.java +++ b/Mage.Sets/src/mage/cards/h/HoldoutSettlement.java @@ -23,7 +23,7 @@ public final class HoldoutSettlement extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public HoldoutSettlement(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HollowOne.java b/Mage.Sets/src/mage/cards/h/HollowOne.java index 6796e8ad3b9..495f14dd6fc 100644 --- a/Mage.Sets/src/mage/cards/h/HollowOne.java +++ b/Mage.Sets/src/mage/cards/h/HollowOne.java @@ -66,7 +66,7 @@ class HollowOneReductionEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - CardsCycledOrDiscardedThisTurnWatcher watcher = (CardsCycledOrDiscardedThisTurnWatcher) game.getState().getWatchers().get(CardsCycledOrDiscardedThisTurnWatcher.class.getSimpleName()); + CardsCycledOrDiscardedThisTurnWatcher watcher = game.getState().getWatcher(CardsCycledOrDiscardedThisTurnWatcher.class); if (watcher != null) { CardUtil.reduceCost(abilityToModify, watcher.getNumberOfCardsCycledOrDiscardedThisTurn(source.getControllerId()) * 2); return true; diff --git a/Mage.Sets/src/mage/cards/h/HollowTrees.java b/Mage.Sets/src/mage/cards/h/HollowTrees.java index 8213814aa0d..9922ba6e365 100644 --- a/Mage.Sets/src/mage/cards/h/HollowTrees.java +++ b/Mage.Sets/src/mage/cards/h/HollowTrees.java @@ -44,7 +44,7 @@ public final class HollowTrees extends CardImpl { // {tap}, Remove any number of storage counters from Hollow Trees: Add {G} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.GreenMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {G} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/h/HollowWarrior.java b/Mage.Sets/src/mage/cards/h/HollowWarrior.java index d6a60e31123..66164064afa 100644 --- a/Mage.Sets/src/mage/cards/h/HollowWarrior.java +++ b/Mage.Sets/src/mage/cards/h/HollowWarrior.java @@ -55,9 +55,9 @@ class HollowWarriorCostToAttackBlockEffect extends PayCostToAttackBlockEffectImp private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control not declared as an attacking or blocking creature"); static { - filter.add(Predicates.not(new AttackingPredicate())); - filter.add(Predicates.not(new BlockingPredicate())); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(AttackingPredicate.instance)); + filter.add(Predicates.not(BlockingPredicate.instance)); + filter.add(Predicates.not(TappedPredicate.instance)); } HollowWarriorCostToAttackBlockEffect() { diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java index 2575371fa1b..cfd0e442012 100644 --- a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java +++ b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java @@ -10,6 +10,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.WatcherScope; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; @@ -73,7 +74,7 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(this.controllerId)) { - Watcher watcher = game.getState().getWatchers().get("HomicidalBruteWatcher", sourceId); + Watcher watcher = game.getState().getWatcher(HomicidalBruteWatcher.class, sourceId); if (watcher == null || !watcher.conditionMet()) { return true; } @@ -87,3 +88,5 @@ class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { } } + + diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java b/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java new file mode 100644 index 00000000000..c92ff72fcd7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HomicidalBruteWatcher.java @@ -0,0 +1,32 @@ +package mage.cards.h; + +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +public class HomicidalBruteWatcher extends Watcher { + + public HomicidalBruteWatcher() { + super(HomicidalBruteWatcher.class.getSimpleName(), WatcherScope.CARD); + } + + public HomicidalBruteWatcher(final HomicidalBruteWatcher watcher) { + super(watcher); + } + + @Override + public HomicidalBruteWatcher copy() { + return new HomicidalBruteWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (condition) { + return; + } + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { + condition = true; + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HonorWornShaku.java b/Mage.Sets/src/mage/cards/h/HonorWornShaku.java index bcd3f9aca53..b47eb2533a5 100644 --- a/Mage.Sets/src/mage/cards/h/HonorWornShaku.java +++ b/Mage.Sets/src/mage/cards/h/HonorWornShaku.java @@ -27,7 +27,7 @@ public final class HonorWornShaku extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped legendary permanent"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SupertypePredicate(SuperType.LEGENDARY)); } diff --git a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java index 5df2aeefb87..fbc81094ee8 100644 --- a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java +++ b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java @@ -128,7 +128,7 @@ class HopeOfGhirapurPlayerLostLifePredicate implements ObjectSourcePlayerPredica if (targetPlayer == null) { return false; } - HopeOfGhirapurCombatDamageWatcher watcher = (HopeOfGhirapurCombatDamageWatcher) game.getState().getWatchers().get(HopeOfGhirapurCombatDamageWatcher.class.getSimpleName()); + HopeOfGhirapurCombatDamageWatcher watcher = game.getState().getWatcher(HopeOfGhirapurCombatDamageWatcher.class); if (watcher != null) { return watcher.playerGotCombatDamage(input.getSourceId(), input.getObject().getId(), game); } diff --git a/Mage.Sets/src/mage/cards/h/HostageTaker.java b/Mage.Sets/src/mage/cards/h/HostageTaker.java index 9a5c0a29697..bf8e4cd7ba6 100644 --- a/Mage.Sets/src/mage/cards/h/HostageTaker.java +++ b/Mage.Sets/src/mage/cards/h/HostageTaker.java @@ -41,7 +41,7 @@ public final class HostageTaker extends CardImpl { private final static FilterPermanent filter = new FilterPermanent("another target artifact or creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE))); diff --git a/Mage.Sets/src/mage/cards/h/HotheadedGiant.java b/Mage.Sets/src/mage/cards/h/HotheadedGiant.java index 10100831b64..d5ac4b036f3 100644 --- a/Mage.Sets/src/mage/cards/h/HotheadedGiant.java +++ b/Mage.Sets/src/mage/cards/h/HotheadedGiant.java @@ -62,7 +62,7 @@ class CastRedSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - HotHeadedGiantWatcher watcher = (HotHeadedGiantWatcher) game.getState().getWatchers().get(HotHeadedGiantWatcher.class.getSimpleName(), source.getControllerId()); + HotHeadedGiantWatcher watcher = game.getState().getWatcher(HotHeadedGiantWatcher.class, source.getControllerId()); if (watcher != null) { return watcher.conditionMet(); } diff --git a/Mage.Sets/src/mage/cards/h/HourOfEternity.java b/Mage.Sets/src/mage/cards/h/HourOfEternity.java index ed2ced04216..918d40620dc 100644 --- a/Mage.Sets/src/mage/cards/h/HourOfEternity.java +++ b/Mage.Sets/src/mage/cards/h/HourOfEternity.java @@ -1,12 +1,8 @@ package mage.cards.h; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -21,10 +17,14 @@ import mage.game.permanent.token.EmptyToken; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import mage.util.CardUtil; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author emerald000 */ public final class HourOfEternity extends CardImpl { @@ -34,17 +34,7 @@ public final class HourOfEternity extends CardImpl { // Exile X target creature cards from your graveyard. For each card exiled this way, create a token that's a copy of that card, except it's a 4/4 black Zombie. this.getSpellAbility().addEffect(new HourOfEternityEffect()); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, new FilterCreatureCard("creature cards from your graveyard"))); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard((xValue != 1 ? " creature cards" : "creature card") + " from your graveyard")); - ability.addTarget(target); - } + this.getSpellAbility().setTargetAdjuster(HourOfEternityAdjuster.instance); } public HourOfEternity(final HourOfEternity card) { @@ -57,11 +47,25 @@ public final class HourOfEternity extends CardImpl { } } +enum HourOfEternityAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard((xValue != 1 ? " creature cards" : "creature card") + " from your graveyard")); + ability.addTarget(target); + } +} + class HourOfEternityEffect extends OneShotEffect { HourOfEternityEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Exile X target creature cards from your graveyard. For each card exiled this way, create a token that's a copy of that card, except it's a 4/4 black Zombie"; + this.staticText = "Exile X target creature cards from your graveyard. " + + "For each card exiled this way, create a token that's a copy of that card, " + + "except it's a 4/4 black Zombie"; } HourOfEternityEffect(final HourOfEternityEffect effect) { diff --git a/Mage.Sets/src/mage/cards/h/HourOfReckoning.java b/Mage.Sets/src/mage/cards/h/HourOfReckoning.java index 9287b5b8fc9..aca3d75b13b 100644 --- a/Mage.Sets/src/mage/cards/h/HourOfReckoning.java +++ b/Mage.Sets/src/mage/cards/h/HourOfReckoning.java @@ -20,7 +20,7 @@ public final class HourOfReckoning extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creatures"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public HourOfReckoning(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HowlFromBeyond.java b/Mage.Sets/src/mage/cards/h/HowlFromBeyond.java index b580479cfbf..ec2c6e9dd4a 100644 --- a/Mage.Sets/src/mage/cards/h/HowlFromBeyond.java +++ b/Mage.Sets/src/mage/cards/h/HowlFromBeyond.java @@ -23,7 +23,7 @@ public final class HowlFromBeyond extends CardImpl { // Target creature gets +X/+0 until end of turn. - this.getSpellAbility().addEffect(new BoostTargetEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/h/HowlpackWolf.java b/Mage.Sets/src/mage/cards/h/HowlpackWolf.java index 9adf3013f0f..4f9376a4ff2 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackWolf.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackWolf.java @@ -25,7 +25,7 @@ public final class HowlpackWolf extends CardImpl { static { filter.add(Predicates.or(new SubtypePredicate(SubType.WOLF), new SubtypePredicate(SubType.WEREWOLF))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public HowlpackWolf(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java b/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java index 2cc5bf6d79b..2cf27ec2004 100644 --- a/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java +++ b/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java @@ -45,7 +45,7 @@ public final class HuatliWarriorPoet extends CardImpl { this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); // +2: You gain life equal to the greatest power among creatures you control. - this.addAbility(new LoyaltyAbility(new GainLifeEffect(new GreatestPowerAmongControlledCreaturesValue(), "You gain life equal to the greatest power among creatures you control"), 2)); + this.addAbility(new LoyaltyAbility(new GainLifeEffect(GreatestPowerAmongControlledCreaturesValue.instance, "You gain life equal to the greatest power among creatures you control"), 2)); // 0: Create a 3/3 green Dinosaur creature token with trample. this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new DinosaurToken()), 0)); diff --git a/Mage.Sets/src/mage/cards/h/Humongulus.java b/Mage.Sets/src/mage/cards/h/Humongulus.java new file mode 100644 index 00000000000..63ffdadc366 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/Humongulus.java @@ -0,0 +1,36 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Humongulus extends CardImpl { + + public Humongulus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); + + this.subtype.add(SubType.HOMUNCULUS); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // Hexproof + this.addAbility(HexproofAbility.getInstance()); + } + + private Humongulus(final Humongulus card) { + super(card); + } + + @Override + public Humongulus copy() { + return new Humongulus(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java b/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java index 9b0d2ccff81..f208a572986 100644 --- a/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java +++ b/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java @@ -30,7 +30,7 @@ public final class HundredTalonStrike extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new ColorPredicate(ObjectColor.WHITE)); } diff --git a/Mage.Sets/src/mage/cards/h/HuntDown.java b/Mage.Sets/src/mage/cards/h/HuntDown.java index f03e5c2107b..419db8da28b 100644 --- a/Mage.Sets/src/mage/cards/h/HuntDown.java +++ b/Mage.Sets/src/mage/cards/h/HuntDown.java @@ -68,9 +68,9 @@ class HuntDownEffect extends RequirementEffect { Permanent blocker = game.getPermanent(source.getTargets().get(0).getFirstTarget()); if (blocker != null && blocker.canBlock(source.getTargets().get(1).getFirstTarget(), game)) { - Permanent attacker = (Permanent) game.getPermanent(source.getTargets().get(1).getFirstTarget()); + Permanent attacker = game.getPermanent(source.getTargets().get(1).getFirstTarget()); if (attacker != null) { - BlockedAttackerWatcher blockedAttackerWatcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher blockedAttackerWatcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attacker, blocker, game)) { // has already blocked this turn, so no need to do again diff --git a/Mage.Sets/src/mage/cards/h/HuntToExtinction.java b/Mage.Sets/src/mage/cards/h/HuntToExtinction.java index 33ba56f4003..772bd5dce90 100644 --- a/Mage.Sets/src/mage/cards/h/HuntToExtinction.java +++ b/Mage.Sets/src/mage/cards/h/HuntToExtinction.java @@ -34,10 +34,10 @@ public final class HuntToExtinction extends CardImpl { this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent(0, 1)); // Hunt to Extinction deals X damage to each creature. - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), new FilterCreaturePermanent())); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, new FilterCreaturePermanent())); // Hunt to Exctinction deals an additional X damage to each creature with a bounty counter on it. - Effect effect = new DamageAllEffect(new ManacostVariableValue(), new FilterCreaturePermanent(filter)); + Effect effect = new DamageAllEffect(ManacostVariableValue.instance, new FilterCreaturePermanent(filter)); effect.setText("Hunt to Exctinction deals an additional X damage to each creature with a bounty counter on it"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java b/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java index 48a36abe116..4b1b6ccae27 100644 --- a/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java +++ b/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java @@ -33,7 +33,7 @@ public final class HunterOfEyeblights extends CardImpl { static { filter1.add(new ControllerPredicate(TargetController.NOT_YOU)); - filter2.add(new CounterAnyPredicate()); + filter2.add(CounterAnyPredicate.instance); } diff --git a/Mage.Sets/src/mage/cards/h/Hurricane.java b/Mage.Sets/src/mage/cards/h/Hurricane.java index cc1418ce236..b6630989b26 100644 --- a/Mage.Sets/src/mage/cards/h/Hurricane.java +++ b/Mage.Sets/src/mage/cards/h/Hurricane.java @@ -28,7 +28,7 @@ public final class Hurricane extends CardImpl { // Hurricane deals X damage to each creature with flying and each player. - this.getSpellAbility().addEffect(new DamageEverythingEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageEverythingEffect(ManacostVariableValue.instance, filter)); } public Hurricane(final Hurricane card) { diff --git a/Mage.Sets/src/mage/cards/h/HydroidKrasis.java b/Mage.Sets/src/mage/cards/h/HydroidKrasis.java new file mode 100644 index 00000000000..85012dac512 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HydroidKrasis.java @@ -0,0 +1,93 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HydroidKrasis extends CardImpl { + + public HydroidKrasis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{G}{U}"); + + this.subtype.add(SubType.JELLYFISH); + this.subtype.add(SubType.HYDRA); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // When you cast this spell, you gain half X life and draw half X cards. Round down each time. + this.addAbility(new CastSourceTriggeredAbility(new HydroidKrasisEffect(), false)); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Hydroid Krasis enters the battlefield with X +1/+1 counters on it. + this.addAbility(new EntersBattlefieldAbility( + new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()) + )); + } + + private HydroidKrasis(final HydroidKrasis card) { + super(card); + } + + @Override + public HydroidKrasis copy() { + return new HydroidKrasis(this); + } +} + +class HydroidKrasisEffect extends OneShotEffect { + + HydroidKrasisEffect() { + super(Outcome.Benefit); + staticText = "you gain half X life and draw half X cards. Round down each time."; + } + + private HydroidKrasisEffect(final HydroidKrasisEffect effect) { + super(effect); + } + + @Override + public HydroidKrasisEffect copy() { + return new HydroidKrasisEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Object obj = getValue(CastSourceTriggeredAbility.SOURCE_CAST_SPELL_ABILITY); + if (!(obj instanceof SpellAbility)) { + return false; + } + int halfCost = Math.floorDiv(((SpellAbility) obj).getManaCostsToPay().getX(), 2); + player.drawCards(halfCost, game); + player.gainLife(halfCost, game, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/i/IbHalfheartGoblinTactician.java b/Mage.Sets/src/mage/cards/i/IbHalfheartGoblinTactician.java index 9f710caeca9..eaf0a24a51c 100644 --- a/Mage.Sets/src/mage/cards/i/IbHalfheartGoblinTactician.java +++ b/Mage.Sets/src/mage/cards/i/IbHalfheartGoblinTactician.java @@ -37,7 +37,7 @@ public final class IbHalfheartGoblinTactician extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MOUNTAIN)); filterGoblin.add(new SubtypePredicate(SubType.GOBLIN)); - filterGoblin.add(new AnotherPredicate()); + filterGoblin.add(AnotherPredicate.instance); filterGoblin.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/i/IcatianStore.java b/Mage.Sets/src/mage/cards/i/IcatianStore.java index 6e9aa335462..91a3dfecb24 100644 --- a/Mage.Sets/src/mage/cards/i/IcatianStore.java +++ b/Mage.Sets/src/mage/cards/i/IcatianStore.java @@ -44,7 +44,7 @@ public final class IcatianStore extends CardImpl { // {tap}, Remove any number of storage counters from Icatian Store: Add {W} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.WhiteMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {W} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/i/IcefeatherAven.java b/Mage.Sets/src/mage/cards/i/IcefeatherAven.java index 215d29b039e..faec12790b0 100644 --- a/Mage.Sets/src/mage/cards/i/IcefeatherAven.java +++ b/Mage.Sets/src/mage/cards/i/IcefeatherAven.java @@ -26,7 +26,7 @@ public final class IcefeatherAven extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public IcefeatherAven(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/IcyBlast.java b/Mage.Sets/src/mage/cards/i/IcyBlast.java index cd37dd0a74b..2df2b53a355 100644 --- a/Mage.Sets/src/mage/cards/i/IcyBlast.java +++ b/Mage.Sets/src/mage/cards/i/IcyBlast.java @@ -1,9 +1,7 @@ package mage.cards.i; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.common.FerociousCondition; import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; @@ -13,12 +11,13 @@ import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author emerald000 */ public final class IcyBlast extends CardImpl { @@ -28,7 +27,6 @@ public final class IcyBlast extends CardImpl { // Tap X target creatures. this.getSpellAbility().addEffect(new TapTargetEffect("X target creatures")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false)); // Ferocious — If you control a creature with power 4 or greater, those creatures don't untap during their controllers' next untap steps. Effect effect = new ConditionalContinuousRuleModifyingEffect( @@ -36,24 +34,25 @@ public final class IcyBlast extends CardImpl { new LockedInCondition(FerociousCondition.instance)); effect.setText("
Ferocious — If you control a creature with power 4 or greater, those creatures don't untap during their controllers' next untap steps"); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().setTargetAdjuster(IcyBlastAdjuster.instance); } public IcyBlast(final IcyBlast card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numberToTap = ability.getManaCostsToPay().getX(); - numberToTap = Math.min(game.getBattlefield().count(StaticFilters.FILTER_PERMANENT_CREATURE, ability.getSourceId(), ability.getControllerId(), game), numberToTap); - ability.addTarget(new TargetCreaturePermanent(numberToTap)); - } - } - @Override public IcyBlast copy() { return new IcyBlast(this); } } + +enum IcyBlastAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/IdentityThief.java b/Mage.Sets/src/mage/cards/i/IdentityThief.java index 9047dc09554..cfa04ef2f5f 100644 --- a/Mage.Sets/src/mage/cards/i/IdentityThief.java +++ b/Mage.Sets/src/mage/cards/i/IdentityThief.java @@ -37,7 +37,7 @@ public final class IdentityThief extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("target nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public IdentityThief(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/IgnitionTeam.java b/Mage.Sets/src/mage/cards/i/IgnitionTeam.java index bc10230d9d6..2272e352a4d 100644 --- a/Mage.Sets/src/mage/cards/i/IgnitionTeam.java +++ b/Mage.Sets/src/mage/cards/i/IgnitionTeam.java @@ -73,7 +73,7 @@ class TappedLandsCount implements DynamicValue { public int calculate(Game game, Ability sourceAbility, Effect effect) { if (sourceAbility != null) { FilterLandPermanent filter = new FilterLandPermanent("tapped lands on the battlefield"); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); return game.getBattlefield().count(filter, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game); } return 0; diff --git a/Mage.Sets/src/mage/cards/i/IllGottenInheritance.java b/Mage.Sets/src/mage/cards/i/IllGottenInheritance.java new file mode 100644 index 00000000000..1c01c6a3c74 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IllGottenInheritance.java @@ -0,0 +1,54 @@ +package mage.cards.i; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class IllGottenInheritance extends CardImpl { + + public IllGottenInheritance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); + + // At the beginning of your upkeep, Ill-Gotten Inheritance deals 1 damage to each opponent and you gain 1 life. + Ability ability = new BeginningOfUpkeepTriggeredAbility( + new DamagePlayersEffect(1, TargetController.OPPONENT), + TargetController.YOU, false + ); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); + this.addAbility(ability); + + // {5}{B}, Sacrifice Ill-Gotten Inheritance: It deals 4 damage to target opponent and you gain 4 life. + ability = new SimpleActivatedAbility( + new DamageTargetEffect(4, "it"), + new ManaCostsImpl("{5}{B}") + ); + ability.addEffect(new GainLifeEffect(4).concatBy("and")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + private IllGottenInheritance(final IllGottenInheritance card) { + super(card); + } + + @Override + public IllGottenInheritance copy() { + return new IllGottenInheritance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/IllnessInTheRanks.java b/Mage.Sets/src/mage/cards/i/IllnessInTheRanks.java index b33417778bc..9ac0a172bdc 100644 --- a/Mage.Sets/src/mage/cards/i/IllnessInTheRanks.java +++ b/Mage.Sets/src/mage/cards/i/IllnessInTheRanks.java @@ -20,7 +20,7 @@ public final class IllnessInTheRanks extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creature tokens"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public IllnessInTheRanks(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/Illuminate.java b/Mage.Sets/src/mage/cards/i/Illuminate.java index 642379fd37b..558226bcf18 100644 --- a/Mage.Sets/src/mage/cards/i/Illuminate.java +++ b/Mage.Sets/src/mage/cards/i/Illuminate.java @@ -28,14 +28,14 @@ public final class Illuminate extends CardImpl { kickerAbility.addKickerCost("{3}{U}"); this.addAbility(kickerAbility); // Illuminate deals X damage to target creature. If Illuminate was kicked with its {2}{R} kicker, it deals X damage to that creature's controller. If Illuminate was kicked with its {3}{U} kicker, you draw X cards. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageTargetControllerEffect(new ManacostVariableValue()), + new DamageTargetControllerEffect(ManacostVariableValue.instance), new KickedCostCondition("{2}{R}"), "if this spell was kicked with its {2}{R} kicker, it deals X damage to that creature's controller.")); this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DrawCardSourceControllerEffect(new ManacostVariableValue()), + new DrawCardSourceControllerEffect(ManacostVariableValue.instance), new KickedCostCondition("{3}{U}"), " if this spell was kicked with its {3}{U} kicker, you draw X cards.")); diff --git a/Mage.Sets/src/mage/cards/i/IllusionaryPresence.java b/Mage.Sets/src/mage/cards/i/IllusionaryPresence.java new file mode 100644 index 00000000000..b8adf4654f1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IllusionaryPresence.java @@ -0,0 +1,111 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.constants.SubType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseBasicLandTypeEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.abilities.keyword.ForestwalkAbility; +import mage.abilities.keyword.IslandwalkAbility; +import mage.abilities.keyword.MountainwalkAbility; +import mage.abilities.keyword.PlainswalkAbility; +import mage.abilities.keyword.SwampwalkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; + +/** + * + * @author jeffwadsworth + */ +public final class IllusionaryPresence extends CardImpl { + + public IllusionaryPresence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); + + this.subtype.add(SubType.ILLUSION); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Cumulative upkeep {U} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{U}"))); + + // At the beginning of your upkeep, choose a land type. Illusionary Presence gains landwalk of the chosen type until end of turn. + Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new ChooseBasicLandTypeEffect(Outcome.Neutral), TargetController.YOU, false); + ability.addEffect(new IllusionaryPresenceEffect()); + this.addAbility(ability); + + } + + private IllusionaryPresence(final IllusionaryPresence card) { + super(card); + } + + @Override + public IllusionaryPresence copy() { + return new IllusionaryPresence(this); + } +} + +class IllusionaryPresenceEffect extends OneShotEffect { + + Ability gainedAbility; + + public IllusionaryPresenceEffect() { + super(Outcome.Benefit); + this.staticText = "{this} gains landwalk of the chosen type until end of turn"; + } + + public IllusionaryPresenceEffect(final IllusionaryPresenceEffect effect) { + super(effect); + } + + @Override + public IllusionaryPresenceEffect copy() { + return new IllusionaryPresenceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + SubType landTypeChoice = SubType.byDescription((String) game.getState().getValue(mageObject.getId().toString() + "BasicLandType")); + if (landTypeChoice != null) { + switch (landTypeChoice) { + case PLAINS: + gainedAbility = new PlainswalkAbility(); + break; + case FOREST: + gainedAbility = new ForestwalkAbility(); + break; + case SWAMP: + gainedAbility = new SwampwalkAbility(); + break; + case ISLAND: + gainedAbility = new IslandwalkAbility(); + break; + case MOUNTAIN: + gainedAbility = new MountainwalkAbility(); + break; + } + if (gainedAbility != null) { + GainAbilitySourceEffect effect = new GainAbilitySourceEffect(gainedAbility, Duration.EndOfTurn); + game.addEffect(effect, source); + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java b/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java new file mode 100644 index 00000000000..d61f2916e11 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IllusionaryTerrain.java @@ -0,0 +1,202 @@ +package mage.cards.i; + +import java.util.List; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceBasicLandType; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.AbilityAddingRemovingEffects_6; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author jeffwadsworth + */ +public final class IllusionaryTerrain extends CardImpl { + + public IllusionaryTerrain(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}"); + + // Cumulative upkeep {2} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{2}"))); + + // As Illusionary Terrain enters the battlefield, choose two basic land types. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseTwoBasicLandTypesEffect(Outcome.Neutral))); + + // Basic lands of the first chosen type are the second chosen type. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IllusionaryTerrainEffect())); + + } + + private IllusionaryTerrain(final IllusionaryTerrain card) { + super(card); + } + + @Override + public IllusionaryTerrain copy() { + return new IllusionaryTerrain(this); + } +} + +class IllusionaryTerrainEffect extends ContinuousEffectImpl { + + public IllusionaryTerrainEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "Basic lands of the first chosen type are the second chosen type"; + } + + public IllusionaryTerrainEffect(final IllusionaryTerrainEffect effect) { + super(effect); + } + + @Override + public IllusionaryTerrainEffect copy() { + return new IllusionaryTerrainEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + SubType firstChoice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "firstChoice")); + SubType secondChoice = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "secondChoice")); + List lands = game.getBattlefield().getAllActivePermanents(CardType.LAND); + if (controller != null + && firstChoice != null + && secondChoice != null) { + for (Permanent land : lands) { + if (land.isBasic()) { + switch (layer) { + case TypeChangingEffects_4: + if (land.getSubtype(game).contains(firstChoice)) { + land.getSubtype(game).clear(); + land.getSubtype(game).add(secondChoice); + game.getState().setValue("illusionaryTerrain" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game), + "true"); + } + break; + case AbilityAddingRemovingEffects_6: + if (game.getState().getValue("illusionaryTerrain" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game)) != null + && game.getState().getValue("illusionaryTerrain" + + source.getId() + + land.getId() + + land.getZoneChangeCounter(game)).equals("true")) { + land.removeAllAbilities(source.getSourceId(), game); + if (land.getSubtype(game).contains(SubType.FOREST)) { + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.PLAINS)) { + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.MOUNTAIN)) { + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.ISLAND)) { + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); + } + if (land.getSubtype(game).contains(SubType.SWAMP)) { + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); + } + break; + } + } + } + } + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4 + || layer == Layer.AbilityAddingRemovingEffects_6; + + } +} + +class ChooseTwoBasicLandTypesEffect extends OneShotEffect { + + String choiceOne; + String choiceTwo; + + public ChooseTwoBasicLandTypesEffect(Outcome outcome) { + super(outcome); + this.staticText = "choose two basic land types"; + } + + public ChooseTwoBasicLandTypesEffect(final ChooseTwoBasicLandTypesEffect effect) { + super(effect); + } + + @Override + public ChooseTwoBasicLandTypesEffect copy() { + return new ChooseTwoBasicLandTypesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject mageObject = game.getPermanentEntering(source.getSourceId()); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null + && mageObject != null) { + ChoiceImpl choices = new ChoiceBasicLandType(); + if (controller.choose(Outcome.Neutral, choices, game)) { + game.informPlayers(mageObject.getName() + ": First chosen basic land type is " + choices.getChoice()); + game.getState().setValue(mageObject.getId().toString() + "firstChoice", choices.getChoice()); + choiceOne = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "firstChoice")).getDescription(); + } + if (controller.choose(Outcome.Neutral, choices, game)) { + game.informPlayers(mageObject.getName() + ": Second chosen basic land type is " + choices.getChoice()); + game.getState().setValue(mageObject.getId().toString() + "secondChoice", choices.getChoice()); + choiceTwo = SubType.byDescription((String) game.getState().getValue(source.getSourceId().toString() + "secondChoice")).getDescription(); + if (mageObject instanceof Permanent + && choiceOne != null + && choiceTwo != null) { + ((Permanent) mageObject).addInfo("Chosen Types", CardUtil.addToolTipMarkTags("First chosen basic land type: " + choiceOne + + "\n Second chosen basic land type: " + choiceTwo), game); + } + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/i/ImmolationShaman.java b/Mage.Sets/src/mage/cards/i/ImmolationShaman.java new file mode 100644 index 00000000000..7a9f275cf11 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/ImmolationShaman.java @@ -0,0 +1,111 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.abilities.mana.ActivatedManaAbilityImpl; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.StackAbility; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ImmolationShaman extends CardImpl { + + public ImmolationShaman(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever an opponent activates an ability of an artifact, creature, or land that isn't a mana ability, Immolation Shaman deals 1 damage to that player. + this.addAbility(new ImmolationShamanTriggeredAbility()); + + // {3}{R}{R}: Immolation Shaman gets +3/+3 and gains menace until end of turn. + Ability ability = new LimitedTimesPerTurnActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect( + 3, 3, Duration.EndOfTurn + ).setText("{this} gets +3/+3"), + new ManaCostsImpl("{3}{R}{R}") + ); + ability.addEffect(new GainAbilitySourceEffect( + new MenaceAbility(), Duration.EndOfTurn + ).setText("and gains menace until end of turn")); + this.addAbility(ability); + } + + private ImmolationShaman(final ImmolationShaman card) { + super(card); + } + + @Override + public ImmolationShaman copy() { + return new ImmolationShaman(this); + } +} + +class ImmolationShamanTriggeredAbility extends TriggeredAbilityImpl { + + ImmolationShamanTriggeredAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(new StaticValue(1), true, "that player", true)); + } + + private ImmolationShamanTriggeredAbility(final ImmolationShamanTriggeredAbility ability) { + super(ability); + } + + @Override + public ImmolationShamanTriggeredAbility copy() { + return new ImmolationShamanTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getPlayerId().equals(getControllerId())) { + Card source = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (source != null && (source.isArtifact() || source.isCreature() || source.isLand())) { + StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); + if (!(stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl)) { + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + } + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent activates an ability of an artifact, creature, or land on the battlefield, " + + "if it isn't a mana ability, {this} deals 1 damage to that player."; + } +} diff --git a/Mage.Sets/src/mage/cards/i/ImpactResonance.java b/Mage.Sets/src/mage/cards/i/ImpactResonance.java index 3f445d26136..e917a081d29 100644 --- a/Mage.Sets/src/mage/cards/i/ImpactResonance.java +++ b/Mage.Sets/src/mage/cards/i/ImpactResonance.java @@ -62,7 +62,7 @@ enum GreatestAmountOfDamageDealtValue implements DynamicValue, MageSingleton { } public int calculate(Game game, UUID controllerId) { - GreatestAmountOfDamageWatcher watcher = (GreatestAmountOfDamageWatcher) game.getState().getWatchers().get(GreatestAmountOfDamageWatcher.class.getSimpleName()); + GreatestAmountOfDamageWatcher watcher = game.getState().getWatcher(GreatestAmountOfDamageWatcher.class); if (watcher != null) { return watcher.getGreatestAmountOfDamage(); } @@ -90,7 +90,7 @@ class GreatestAmountOfDamageWatcher extends Watcher { private int damageAmount; public GreatestAmountOfDamageWatcher() { - super(GreatestAmountOfDamageWatcher.class.getSimpleName(), WatcherScope.GAME); + super(GreatestAmountOfDamageWatcher.class, WatcherScope.GAME); } public GreatestAmountOfDamageWatcher(final GreatestAmountOfDamageWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/i/ImpassionedOrator.java b/Mage.Sets/src/mage/cards/i/ImpassionedOrator.java new file mode 100644 index 00000000000..ef1a2f0991e --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/ImpassionedOrator.java @@ -0,0 +1,48 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ImpassionedOrator extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("another creature you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + public ImpassionedOrator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever another creature enters the battlefield under your control, you gain 1 life. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new GainLifeEffect(1), filter)); + } + + private ImpassionedOrator(final ImpassionedOrator card) { + super(card); + } + + @Override + public ImpassionedOrator copy() { + return new ImpassionedOrator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/Impatience.java b/Mage.Sets/src/mage/cards/i/Impatience.java index 7e40923e117..6b15719662d 100644 --- a/Mage.Sets/src/mage/cards/i/Impatience.java +++ b/Mage.Sets/src/mage/cards/i/Impatience.java @@ -46,8 +46,8 @@ class ImpatienceCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); - return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(game.getActivePlayerId()) == 0; + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); + return watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(game.getActivePlayerId()) == 0; } public String toString() { diff --git a/Mage.Sets/src/mage/cards/i/ImpelledGiant.java b/Mage.Sets/src/mage/cards/i/ImpelledGiant.java index 0cbe3db9560..0baf4fff2c7 100644 --- a/Mage.Sets/src/mage/cards/i/ImpelledGiant.java +++ b/Mage.Sets/src/mage/cards/i/ImpelledGiant.java @@ -39,9 +39,9 @@ public final class ImpelledGiant extends CardImpl { static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped red creature you control other than Impelled Giant"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new ColorPredicate(ObjectColor.RED)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ImpelledGiant(UUID ownerId, CardSetInfo setInfo) { @@ -87,7 +87,7 @@ class ImpelledGiantCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { - for (UUID targetId: (List)target.getTargets()) { + for (UUID targetId: target.getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent == null) return false; diff --git a/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java b/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java index 448afcc630d..1353a50288b 100644 --- a/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java +++ b/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java @@ -29,7 +29,7 @@ public final class ImperialAerosaur extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ImperialAerosaur(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/ImperialMask.java b/Mage.Sets/src/mage/cards/i/ImperialMask.java index 11b2f5b0a1e..0052e614027 100644 --- a/Mage.Sets/src/mage/cards/i/ImperialMask.java +++ b/Mage.Sets/src/mage/cards/i/ImperialMask.java @@ -26,7 +26,7 @@ public final class ImperialMask extends CardImpl { private static final FilterPermanent filter = new FilterPermanent(); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public ImperialMask(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java b/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java index a87a5545b94..eb774710b57 100644 --- a/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java +++ b/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java @@ -57,7 +57,7 @@ class ImpetuousProtegeEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/i/Imprison.java b/Mage.Sets/src/mage/cards/i/Imprison.java index 6d094bdb9d6..7f1b8c062b8 100644 --- a/Mage.Sets/src/mage/cards/i/Imprison.java +++ b/Mage.Sets/src/mage/cards/i/Imprison.java @@ -145,7 +145,7 @@ class ImprisonUnblockEffect extends OneShotEffect { effect.apply(game, source); // Make blocked creatures unblocked - BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName()); + BlockedByOnlyOneCreatureThisCombatWatcher watcher = game.getState().getWatcher(BlockedByOnlyOneCreatureThisCombatWatcher.class); if (watcher != null) { Set combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId()); if (combatGroups != null) { diff --git a/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java b/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java index 9f243cf8453..1e2ec98a84c 100644 --- a/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java +++ b/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java @@ -6,8 +6,6 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AttacksAllTriggeredAbility; import mage.abilities.effects.PreventionEffectImpl; -import mage.abilities.effects.common.PreventDamageBySourceEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -16,9 +14,7 @@ import mage.constants.SetTargetPointer; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.filter.StaticFilters; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.players.Player; import mage.util.CardUtil; @@ -61,7 +57,7 @@ class ImpulsiveManeuversEffect extends PreventionEffectImpl { @Override public void init(Ability source, Game game) { - this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game); + this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(source, game, true); super.init(source, game); } diff --git a/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java b/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java index 418cb142f60..be50ef6f7a3 100644 --- a/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java +++ b/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java @@ -49,10 +49,10 @@ public final class InallaArchmageRitualist extends CardImpl { static { filter.add(new SubtypePredicate(SubType.WIZARD)); - filter.add(Predicates.not(new TokenPredicate())); - filter.add(new AnotherPredicate()); + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); filter2.add(new SubtypePredicate(SubType.WIZARD)); - filter2.add(Predicates.not(new TappedPredicate())); + filter2.add(Predicates.not(TappedPredicate.instance)); } public InallaArchmageRitualist(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/Incinerate.java b/Mage.Sets/src/mage/cards/i/Incinerate.java index 0fa3368ffb0..4a0a926243b 100644 --- a/Mage.Sets/src/mage/cards/i/Incinerate.java +++ b/Mage.Sets/src/mage/cards/i/Incinerate.java @@ -70,7 +70,7 @@ class IncinerateEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), source.getSourceId()); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.wasDamaged(event.getTargetId(), game); } diff --git a/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java b/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java index fc62cc74c37..f342eba3e9d 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java @@ -77,7 +77,7 @@ class IncreasingAmbitionEffect extends SearchEffect { } if (player.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { - for (UUID cardId: (List)target.getTargets()) { + for (UUID cardId: target.getTargets()) { Card card = player.getLibrary().remove(cardId, game); if (card != null) { card.moveToZone(Zone.HAND, source.getSourceId(), game, false); diff --git a/Mage.Sets/src/mage/cards/i/IncubationDruid.java b/Mage.Sets/src/mage/cards/i/IncubationDruid.java new file mode 100644 index 00000000000..ea6cc5017ac --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IncubationDruid.java @@ -0,0 +1,218 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.Mana; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.abilities.mana.ActivatedManaAbilityImpl; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.Choice; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class IncubationDruid extends CardImpl { + + public IncubationDruid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // {T}: Add one mana of any type that a land you control could produce. If Incubation Druid has a +1/+1 counter on it, add three mana of that type instead. + this.addAbility(new SimpleManaAbility( + Zone.BATTLEFIELD, new AnyColorLandsProduceManaEffect(), new TapSourceCost() + )); + + // {3}{G}{G}: Adapt 3. + this.addAbility(new AdaptAbility(3, "{3}{G}{G}")); + } + + private IncubationDruid(final IncubationDruid card) { + super(card); + } + + @Override + public IncubationDruid copy() { + return new IncubationDruid(this); + } +} + +class AnyColorLandsProduceManaEffect extends ManaEffect { + + private boolean inManaTypeCalculation = false; + + AnyColorLandsProduceManaEffect() { + super(); + staticText = "Add one mana of any type that a land you control could produce. " + + "If {this} has a +1/+1 counter on it, add three mana of that type instead."; + } + + private AnyColorLandsProduceManaEffect(final AnyColorLandsProduceManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + checkToFirePossibleEvents(getMana(game, source), game, source); + controller.getManaPool().addMana(getMana(game, source), game, source); + return true; + } + return false; + } + + @Override + public Mana produceMana(boolean netMana, Game game, Ability source) { + int manaAmount = getManaAmount(game, source); + Mana mana = new Mana(); + Mana types = getManaTypes(game, source); + Choice choice = new ChoiceColor(true); + choice.getChoices().clear(); + choice.setMessage("Pick a mana color"); + if (types.getBlack() > 0) { + choice.getChoices().add("Black"); + } + if (types.getRed() > 0) { + choice.getChoices().add("Red"); + } + if (types.getBlue() > 0) { + choice.getChoices().add("Blue"); + } + if (types.getGreen() > 0) { + choice.getChoices().add("Green"); + } + if (types.getWhite() > 0) { + choice.getChoices().add("White"); + } + if (types.getColorless() > 0) { + choice.getChoices().add("Colorless"); + } + if (types.getAny() > 0) { + choice.getChoices().add("Black"); + choice.getChoices().add("Red"); + choice.getChoices().add("Blue"); + choice.getChoices().add("Green"); + choice.getChoices().add("White"); + choice.getChoices().add("Colorless"); + } + if (!choice.getChoices().isEmpty()) { + Player player = game.getPlayer(source.getControllerId()); + if (choice.getChoices().size() == 1) { + choice.setChoice(choice.getChoices().iterator().next()); + } else if (player == null || !player.choose(outcome, choice, game)) { + return null; + } + if (choice.getChoice() != null) { + switch (choice.getChoice()) { + case "Black": + mana.setBlack(manaAmount); + break; + case "Blue": + mana.setBlue(manaAmount); + break; + case "Red": + mana.setRed(manaAmount); + break; + case "Green": + mana.setGreen(manaAmount); + break; + case "White": + mana.setWhite(manaAmount); + break; + case "Colorless": + mana.setColorless(manaAmount); + break; + } + } + } + return mana; + } + + @Override + public List getNetMana(Game game, Ability source) { + int manaAmount = getManaAmount(game, source); + List netManas = new ArrayList(); + Mana types = getManaTypes(game, source); + if (types.getRed() > 0) { + netManas.add(new Mana(manaAmount, 0, 0, 0, 0, 0, 0, 0)); + } + if (types.getGreen() > 0) { + netManas.add(new Mana(0, manaAmount, 0, 0, 0, 0, 0, 0)); + } + if (types.getBlue() > 0) { + netManas.add(new Mana(0, 0, manaAmount, 0, 0, 0, 0, 0)); + } + if (types.getWhite() > 0) { + netManas.add(new Mana(0, 0, 0, manaAmount, 0, 0, 0, 0)); + } + if (types.getBlack() > 0) { + netManas.add(new Mana(0, 0, 0, 0, manaAmount, 0, 0, 0)); + } + if (types.getColorless() > 0) { + netManas.add(new Mana(0, 0, 0, 0, 0, 0, 0, manaAmount)); + } + if (types.getAny() > 0) { + netManas.add(new Mana(0, 0, 0, 0, 0, 0, manaAmount, 0)); + } + return netManas; + } + + @Override + public AnyColorLandsProduceManaEffect copy() { + return new AnyColorLandsProduceManaEffect(this); + } + + private int getManaAmount(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null && permanent.getCounters(game).getCount(CounterType.P1P1) > 0) { + return 3; + } + return 1; + } + + private Mana getManaTypes(Game game, Ability source) { + Mana types = new Mana(); + if (game == null || game.getPhase() == null) { + return types; + } + if (inManaTypeCalculation) { + return types; + } + inManaTypeCalculation = true; + List lands = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), source.getSourceId(), game); + for (Permanent land : lands) { + Abilities mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD); + for (ActivatedManaAbilityImpl ability : mana) { + if (!ability.equals(source) && ability.definesMana(game)) { + for (Mana netMana : ability.getNetMana(game)) { + types.add(netMana); + } + } + } + } + inManaTypeCalculation = false; + return types; + } +} diff --git a/Mage.Sets/src/mage/cards/i/IncursionSpecialist.java b/Mage.Sets/src/mage/cards/i/IncursionSpecialist.java index 756b250d111..77df46b955f 100644 --- a/Mage.Sets/src/mage/cards/i/IncursionSpecialist.java +++ b/Mage.Sets/src/mage/cards/i/IncursionSpecialist.java @@ -69,7 +69,7 @@ class IncursionTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(controllerId)) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) { return true; } diff --git a/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java b/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java index cc65732992b..dd209468576 100644 --- a/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java +++ b/Mage.Sets/src/mage/cards/i/IndomitableCreativity.java @@ -2,7 +2,6 @@ package mage.cards.i; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.*; import mage.constants.CardType; @@ -16,53 +15,64 @@ import mage.game.permanent.Permanent; import mage.players.Library; import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; /** - * * @author LevelX2 */ public final class IndomitableCreativity extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("artifacts and/or creatures"); - - static { - filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE))); - } public IndomitableCreativity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}{R}{R}"); // Destroy X target artifacts and/or creatures. For each permanent destroyed this way, its controller reveals cards from the top of their library until an artifact or creature card is revealed and exiles that card. Those players put the exiled card onto the battlefield, then shuffle their libraries. - getSpellAbility().addEffect(new IndomitableCreativityEffect()); - this.getSpellAbility().addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addEffect(new IndomitableCreativityEffect()); + this.getSpellAbility().setTargetAdjuster(IndomitableCreativityAdjuster.instance); } public IndomitableCreativity(final IndomitableCreativity card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetPermanent(xValue, xValue, filter, false)); - } - } - @Override public IndomitableCreativity copy() { return new IndomitableCreativity(this); } } +enum IndomitableCreativityAdjuster implements TargetAdjuster { + instance; + private static final FilterPermanent filter = new FilterPermanent("artifacts and/or creatures"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE) + )); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetPermanent(xValue, xValue, filter, false)); + } +} + class IndomitableCreativityEffect extends OneShotEffect { public IndomitableCreativityEffect() { super(Outcome.Benefit); - this.staticText = "Destroy X target artifacts and/or creatures. For each permanent destroyed this way, its controller reveals cards from the top of their library until an artifact or creature card is revealed and exiles that card. Those players put the exiled card onto the battlefield, then shuffle their libraries"; + this.staticText = "Destroy X target artifacts and/or creatures. " + + "For each permanent destroyed this way, " + + "its controller reveals cards from the top of their library" + + " until an artifact or creature card is revealed and exiles that card. " + + "Those players put the exiled card onto the battlefield, then shuffle their libraries"; } public IndomitableCreativityEffect(final IndomitableCreativityEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/InfernalReckoning.java b/Mage.Sets/src/mage/cards/i/InfernalReckoning.java index 6c2a2146024..1d1cc6ded2e 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalReckoning.java +++ b/Mage.Sets/src/mage/cards/i/InfernalReckoning.java @@ -23,7 +23,7 @@ public final class InfernalReckoning extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creature"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public InfernalReckoning(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/InfernalTribute.java b/Mage.Sets/src/mage/cards/i/InfernalTribute.java index 028994e1913..51a53d5c831 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalTribute.java +++ b/Mage.Sets/src/mage/cards/i/InfernalTribute.java @@ -25,7 +25,7 @@ public final class InfernalTribute extends CardImpl { private final static FilterControlledPermanent filter = new FilterControlledPermanent("a nontoken permanent"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public InfernalTribute(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/InfernoHellion.java b/Mage.Sets/src/mage/cards/i/InfernoHellion.java index ed2b3254f70..859049b4c3e 100644 --- a/Mage.Sets/src/mage/cards/i/InfernoHellion.java +++ b/Mage.Sets/src/mage/cards/i/InfernoHellion.java @@ -66,8 +66,8 @@ enum InfernoHellionCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - AttackedThisTurnWatcher watcherAttacked = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); - BlockedThisTurnWatcher watcherBlocked = (BlockedThisTurnWatcher) game.getState().getWatchers().get(BlockedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcherAttacked = game.getState().getWatcher(AttackedThisTurnWatcher.class); + BlockedThisTurnWatcher watcherBlocked = game.getState().getWatcher(BlockedThisTurnWatcher.class); MageObjectReference mor = new MageObjectReference(source.getSourceId(), game); if (watcherAttacked == null || watcherBlocked == null) { return false; diff --git a/Mage.Sets/src/mage/cards/i/InfernoTrap.java b/Mage.Sets/src/mage/cards/i/InfernoTrap.java index 8ac6aa5364f..f85d962e140 100644 --- a/Mage.Sets/src/mage/cards/i/InfernoTrap.java +++ b/Mage.Sets/src/mage/cards/i/InfernoTrap.java @@ -53,7 +53,7 @@ enum InfernoTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - InfernoTrapWatcher watcher = (InfernoTrapWatcher) game.getState().getWatchers().get(InfernoTrapWatcher.class.getSimpleName()); + InfernoTrapWatcher watcher = game.getState().getWatcher(InfernoTrapWatcher.class); if (watcher != null) { Set damagingCreatures = watcher.getDamagingCreatures(source.getControllerId()); return damagingCreatures.size() > 1; @@ -72,7 +72,7 @@ class InfernoTrapWatcher extends Watcher { Map> playerDamagedByCreature = new HashMap<>(); public InfernoTrapWatcher() { - super(InfernoTrapWatcher.class.getSimpleName(), WatcherScope.GAME); + super(InfernoTrapWatcher.class, WatcherScope.GAME); } public InfernoTrapWatcher(final InfernoTrapWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/i/InfiltratorsMagemark.java b/Mage.Sets/src/mage/cards/i/InfiltratorsMagemark.java index 66291875c5a..319a3cf2420 100644 --- a/Mage.Sets/src/mage/cards/i/InfiltratorsMagemark.java +++ b/Mage.Sets/src/mage/cards/i/InfiltratorsMagemark.java @@ -35,7 +35,7 @@ public final class InfiltratorsMagemark extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/i/InfusedArrows.java b/Mage.Sets/src/mage/cards/i/InfusedArrows.java index 5975fdc4fa6..904cde89546 100644 --- a/Mage.Sets/src/mage/cards/i/InfusedArrows.java +++ b/Mage.Sets/src/mage/cards/i/InfusedArrows.java @@ -32,7 +32,7 @@ public final class InfusedArrows extends CardImpl { // Sunburst this.addAbility(new SunburstAbility(this)); // {tap}, Remove X charge counters from Infused Arrows: Target creature gets -X/-X until end of turn. - DynamicValue value = new SignInversionDynamicValue(new RemovedCountersForCostValue()); + DynamicValue value = new SignInversionDynamicValue(RemovedCountersForCostValue.instance); Effect effect = new BoostTargetEffect(value, value, Duration.EndOfTurn); effect.setText("Target creature gets -X/-X until end of turn"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/i/InkfathomWitch.java b/Mage.Sets/src/mage/cards/i/InkfathomWitch.java index 384933ba5b8..aaeb94fa175 100644 --- a/Mage.Sets/src/mage/cards/i/InkfathomWitch.java +++ b/Mage.Sets/src/mage/cards/i/InkfathomWitch.java @@ -24,7 +24,7 @@ public final class InkfathomWitch extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each unblocked creature"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } public InkfathomWitch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/InnerCalmOuterStrength.java b/Mage.Sets/src/mage/cards/i/InnerCalmOuterStrength.java index 90e6f848e8a..7dbf40bb737 100644 --- a/Mage.Sets/src/mage/cards/i/InnerCalmOuterStrength.java +++ b/Mage.Sets/src/mage/cards/i/InnerCalmOuterStrength.java @@ -25,7 +25,7 @@ public final class InnerCalmOuterStrength extends CardImpl { this.subtype.add(SubType.ARCANE); // Target creature gets +X/+X until end of turn, where X is the number of cards in your hand. - DynamicValue xValue= new CardsInControllerHandCount(); + DynamicValue xValue= CardsInControllerHandCount.instance; Effect effect = new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn, true); effect.setText("Target creature gets +X/+X until end of turn, where X is the number of cards in your hand"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/i/InnerFire.java b/Mage.Sets/src/mage/cards/i/InnerFire.java index d7f2671f735..42a4da2dd46 100644 --- a/Mage.Sets/src/mage/cards/i/InnerFire.java +++ b/Mage.Sets/src/mage/cards/i/InnerFire.java @@ -20,7 +20,7 @@ public final class InnerFire extends CardImpl { // Add {R} for each card in your hand. - this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana(1), new CardsInControllerHandCount())); + this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana(1), CardsInControllerHandCount.instance)); } public InnerFire(final InnerFire card) { diff --git a/Mage.Sets/src/mage/cards/i/InsatiableRakghoul.java b/Mage.Sets/src/mage/cards/i/InsatiableRakghoul.java index e62ce559f34..f3553aef621 100644 --- a/Mage.Sets/src/mage/cards/i/InsatiableRakghoul.java +++ b/Mage.Sets/src/mage/cards/i/InsatiableRakghoul.java @@ -62,7 +62,7 @@ class InsatiableRakghoulEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - NonArtifactCreaturesDiedWatcher watcher = (NonArtifactCreaturesDiedWatcher) game.getState().getWatchers().get(NonArtifactCreaturesDiedWatcher.class.getSimpleName()); + NonArtifactCreaturesDiedWatcher watcher = game.getState().getWatcher(NonArtifactCreaturesDiedWatcher.class); if (watcher != null && watcher.conditionMet()) { Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent != null) { @@ -83,7 +83,7 @@ class InsatiableRakghoulEffect extends OneShotEffect { class NonArtifactCreaturesDiedWatcher extends Watcher { public NonArtifactCreaturesDiedWatcher() { - super(NonArtifactCreaturesDiedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(NonArtifactCreaturesDiedWatcher.class, WatcherScope.GAME); } public NonArtifactCreaturesDiedWatcher(final NonArtifactCreaturesDiedWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/i/InsidiousDreams.java b/Mage.Sets/src/mage/cards/i/InsidiousDreams.java index 43047ff9729..b163be9b12d 100644 --- a/Mage.Sets/src/mage/cards/i/InsidiousDreams.java +++ b/Mage.Sets/src/mage/cards/i/InsidiousDreams.java @@ -74,13 +74,13 @@ class InsidiousDreamsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); - int amount = new GetXValue().calculate(game, source, this); + int amount = GetXValue.instance.calculate(game, source, this); if (controller != null && sourceObject != null) { TargetCardInLibrary target = new TargetCardInLibrary(0, amount, new FilterCard()); if (controller.searchLibrary(target, game)) { Cards chosen = new CardsImpl(); - for (UUID cardId : (List) target.getTargets()) { + for (UUID cardId : target.getTargets()) { Card card = controller.getLibrary().remove(cardId, game); chosen.add(card); } diff --git a/Mage.Sets/src/mage/cards/i/Insist.java b/Mage.Sets/src/mage/cards/i/Insist.java index 5c79086b5ef..7531dfdccf7 100644 --- a/Mage.Sets/src/mage/cards/i/Insist.java +++ b/Mage.Sets/src/mage/cards/i/Insist.java @@ -65,7 +65,7 @@ class InsistEffect extends ContinuousRuleModifyingEffectImpl { @Override public void init(Ability source, Game game) { super.init(source, game); - InsistWatcher watcher = (InsistWatcher) game.getState().getWatchers().get(InsistWatcher.class.getSimpleName(), source.getControllerId()); + InsistWatcher watcher = game.getState().getWatcher(InsistWatcher.class, source.getControllerId()); if (watcher != null) { watcher.setReady(); } @@ -93,7 +93,7 @@ class InsistEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - InsistWatcher watcher = (InsistWatcher) game.getState().getWatchers().get(InsistWatcher.class.getSimpleName(), source.getControllerId()); + InsistWatcher watcher = game.getState().getWatcher(InsistWatcher.class, source.getControllerId()); return spell != null && watcher != null && watcher.isUncounterable(spell.getId()); } } @@ -104,7 +104,7 @@ class InsistWatcher extends Watcher { protected UUID uncounterableSpell; InsistWatcher() { - super(InsistWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(InsistWatcher.class, WatcherScope.PLAYER); } InsistWatcher(final InsistWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/i/InspiredSphinx.java b/Mage.Sets/src/mage/cards/i/InspiredSphinx.java index f3e793d77e6..22e2f94442c 100644 --- a/Mage.Sets/src/mage/cards/i/InspiredSphinx.java +++ b/Mage.Sets/src/mage/cards/i/InspiredSphinx.java @@ -33,7 +33,7 @@ public final class InspiredSphinx extends CardImpl { // When Inspired Sphinx enters the battlefield, draw cards equal to the number of opponents you have. this.addAbility(new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(new OpponentsCount()).setText("draw cards equal to the number of opponents you have") + new DrawCardSourceControllerEffect(OpponentsCount.instance).setText("draw cards equal to the number of opponents you have") )); // {3}{U}: Create a colorless 1/1 Thopter artifact creature token with flying. diff --git a/Mage.Sets/src/mage/cards/i/InspiringCommander.java b/Mage.Sets/src/mage/cards/i/InspiringCommander.java index ad50beeafcd..073076f25e6 100644 --- a/Mage.Sets/src/mage/cards/i/InspiringCommander.java +++ b/Mage.Sets/src/mage/cards/i/InspiringCommander.java @@ -27,7 +27,7 @@ public final class InspiringCommander extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another creature with power 2 or less"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); } diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java index 43f13ffdce0..5250fa9ba3d 100644 --- a/Mage.Sets/src/mage/cards/i/InsultInjury.java +++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java @@ -38,7 +38,7 @@ public final class InsultInjury extends SplitCard { // to // Injury // Injury deals 2 damage to target creature and 2 damage to target player. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); getRightHalfCard().getSpellAbility().addEffect(new InjuryEffect()); diff --git a/Mage.Sets/src/mage/cards/i/IntangibleVirtue.java b/Mage.Sets/src/mage/cards/i/IntangibleVirtue.java index 7ac02d66583..8bc764d587d 100644 --- a/Mage.Sets/src/mage/cards/i/IntangibleVirtue.java +++ b/Mage.Sets/src/mage/cards/i/IntangibleVirtue.java @@ -23,7 +23,7 @@ public final class IntangibleVirtue extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creature tokens"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public IntangibleVirtue(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/IntrepidProvisioner.java b/Mage.Sets/src/mage/cards/i/IntrepidProvisioner.java index e7c88c04160..35baafc5e97 100644 --- a/Mage.Sets/src/mage/cards/i/IntrepidProvisioner.java +++ b/Mage.Sets/src/mage/cards/i/IntrepidProvisioner.java @@ -25,7 +25,7 @@ public final class IntrepidProvisioner extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.HUMAN, "another target Human you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public IntrepidProvisioner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/InvasiveSpecies.java b/Mage.Sets/src/mage/cards/i/InvasiveSpecies.java index 193d45dbd9c..3a2302b9373 100644 --- a/Mage.Sets/src/mage/cards/i/InvasiveSpecies.java +++ b/Mage.Sets/src/mage/cards/i/InvasiveSpecies.java @@ -21,7 +21,7 @@ public final class InvasiveSpecies extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another permanent you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public InvasiveSpecies(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/InvokeTheFiremind.java b/Mage.Sets/src/mage/cards/i/InvokeTheFiremind.java index 9e74d88bb52..a61d8a4d1f8 100644 --- a/Mage.Sets/src/mage/cards/i/InvokeTheFiremind.java +++ b/Mage.Sets/src/mage/cards/i/InvokeTheFiremind.java @@ -21,9 +21,9 @@ public final class InvokeTheFiremind extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}{U}{R}"); - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(ManacostVariableValue.instance)); Mode mode = new Mode(); - mode.addEffect(new DamageTargetEffect(new ManacostVariableValue())); + mode.addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); mode.addTarget(new TargetAnyTarget()); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/i/IroasGodOfVictory.java b/Mage.Sets/src/mage/cards/i/IroasGodOfVictory.java index d152a61be41..b964156ea1d 100644 --- a/Mage.Sets/src/mage/cards/i/IroasGodOfVictory.java +++ b/Mage.Sets/src/mage/cards/i/IroasGodOfVictory.java @@ -29,7 +29,7 @@ public final class IroasGodOfVictory extends CardImpl { private static final FilterControlledCreatureInPlay filterAttacking = new FilterControlledCreatureInPlay("attacking creatures you control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filterAttacking.getCreatureFilter().add(new AttackingPredicate()); + filterAttacking.getCreatureFilter().add(AttackingPredicate.instance); } public IroasGodOfVictory(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java b/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java index e417bed22c9..25d5ee7a915 100644 --- a/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java +++ b/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java @@ -79,7 +79,7 @@ class IsperiaTheInscrutableEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - Object object = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + Object object = game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (player != null && object instanceof String) { player.revealCards(player.getLogName() + " hand", player.getHand(), game, true); String namedCard = (String) object; diff --git a/Mage.Sets/src/mage/cards/i/ItThatBetrays.java b/Mage.Sets/src/mage/cards/i/ItThatBetrays.java index fda419264fa..e559bed72e7 100644 --- a/Mage.Sets/src/mage/cards/i/ItThatBetrays.java +++ b/Mage.Sets/src/mage/cards/i/ItThatBetrays.java @@ -23,7 +23,7 @@ public final class ItThatBetrays extends CardImpl { private static final FilterPermanent FILTER = new FilterPermanent("nontoken permanent"); static { - FILTER.add(Predicates.not(new TokenPredicate())); + FILTER.add(Predicates.not(TokenPredicate.instance)); } public ItThatBetrays(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/IvoryGuardians.java b/Mage.Sets/src/mage/cards/i/IvoryGuardians.java index 8bbb182421d..5298e44ca4d 100644 --- a/Mage.Sets/src/mage/cards/i/IvoryGuardians.java +++ b/Mage.Sets/src/mage/cards/i/IvoryGuardians.java @@ -33,7 +33,7 @@ public final class IvoryGuardians extends CardImpl { static { controlFilter.add(new ColorPredicate(ObjectColor.RED)); - controlFilter.add(Predicates.not(new TokenPredicate())); + controlFilter.add(Predicates.not(TokenPredicate.instance)); boostFilter.add(new NamePredicate("Ivory Guardians")); } diff --git a/Mage.Sets/src/mage/cards/i/IvyLaneDenizen.java b/Mage.Sets/src/mage/cards/i/IvyLaneDenizen.java index 56e556a59e9..b914b2dc360 100644 --- a/Mage.Sets/src/mage/cards/i/IvyLaneDenizen.java +++ b/Mage.Sets/src/mage/cards/i/IvyLaneDenizen.java @@ -27,7 +27,7 @@ public final class IvyLaneDenizen extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another green creature"); static { filter.add(new ColorPredicate(ObjectColor.GREEN)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public IvyLaneDenizen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/IxalansBinding.java b/Mage.Sets/src/mage/cards/i/IxalansBinding.java index 471a3ada5c4..95be9e826b8 100644 --- a/Mage.Sets/src/mage/cards/i/IxalansBinding.java +++ b/Mage.Sets/src/mage/cards/i/IxalansBinding.java @@ -1,7 +1,5 @@ - package mage.cards.i; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -12,11 +10,7 @@ import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterNonlandPermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.ExileZone; @@ -26,8 +20,9 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class IxalansBinding extends CardImpl { @@ -80,10 +75,10 @@ class IxalansBindingReplacementEffect extends ContinuousRuleModifyingEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - Card card = game.getCard(event.getSourceId()); - if(event.getPlayerId().equals(source.getControllerId())){ + if (event.getPlayerId().equals(source.getControllerId())) { return false; } + Card card = game.getCard(event.getSourceId()); if (sourcePermanent != null && card != null) { UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (exileZone != null) { diff --git a/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java b/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java index 8871c562f0d..615e5646910 100644 --- a/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java +++ b/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java @@ -26,8 +26,8 @@ public final class IxidorRealitySculptor extends CardImpl { private static final FilterCreaturePermanent filterTarget = new FilterCreaturePermanent("face-down creature"); static { - filter.add(new FaceDownPredicate()); - filterTarget.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); + filterTarget.add(FaceDownPredicate.instance); } public IxidorRealitySculptor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/i/Ixidron.java b/Mage.Sets/src/mage/cards/i/Ixidron.java index 89fbe738556..a84f448357e 100644 --- a/Mage.Sets/src/mage/cards/i/Ixidron.java +++ b/Mage.Sets/src/mage/cards/i/Ixidron.java @@ -31,9 +31,9 @@ public final class Ixidron extends CardImpl { private static final FilterCreaturePermanent filterTurnFaceDown = new FilterCreaturePermanent("other nontoken creatures"); static { - filter.add(new FaceDownPredicate()); - filterTurnFaceDown.add(new AnotherPredicate()); - filterTurnFaceDown.add(Predicates.not(new TokenPredicate())); + filter.add(FaceDownPredicate.instance); + filterTurnFaceDown.add(AnotherPredicate.instance); + filterTurnFaceDown.add(Predicates.not(TokenPredicate.instance)); } public Ixidron(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java b/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java index 7aaaf9cf64f..8ef446b6dab 100644 --- a/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java +++ b/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java @@ -198,7 +198,7 @@ class JaceArchitectOfThoughtEffect2 extends OneShotEffect { boolean pileChoice = player.choosePile(Outcome.Neutral, "Choose a pile to to put into your hand.", new ArrayList<>(pile1.getCards(game)), - new ArrayList<>(allCards.getCards(game)), game); + new ArrayList<>(pile2.getCards(game)), game); game.informPlayers(player.getLogName() + " chose pile" + (pileChoice ? "1" : "2")); player.moveCards(pileChoice ? pile1 : pile2, Zone.HAND, source, game); player.putCardsOnBottomOfLibrary(pileChoice ? pile2 : pile1, game, source, true); diff --git a/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java b/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java index 089eb700031..762da47ab12 100644 --- a/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java +++ b/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java @@ -30,7 +30,7 @@ public final class JaceTheLivingGuildpact extends CardImpl { private static final FilterPermanent filter = new FilterNonlandPermanent("another target nonland permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JaceTheLivingGuildpact(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java b/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java index 74b680ba40d..ea713bf87d8 100644 --- a/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java +++ b/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java @@ -53,7 +53,7 @@ class JaddiLifestriderEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public JaddiLifestriderEffect() { diff --git a/Mage.Sets/src/mage/cards/j/JadeBearer.java b/Mage.Sets/src/mage/cards/j/JadeBearer.java index 9401aac3d9d..422df6fc88a 100644 --- a/Mage.Sets/src/mage/cards/j/JadeBearer.java +++ b/Mage.Sets/src/mage/cards/j/JadeBearer.java @@ -24,7 +24,7 @@ public final class JadeBearer extends CardImpl { private static final FilterCreaturePermanent filterYourAnotherMerfolk = new FilterCreaturePermanent(); static { - filterYourAnotherMerfolk.add(new AnotherPredicate()); + filterYourAnotherMerfolk.add(AnotherPredicate.instance); filterYourAnotherMerfolk.add(new SubtypePredicate(SubType.MERFOLK)); filterYourAnotherMerfolk.add(new ControllerPredicate(TargetController.YOU)); filterYourAnotherMerfolk.setMessage("another " + SubType.MERFOLK.toString() + " you control"); diff --git a/Mage.Sets/src/mage/cards/j/JandorsRing.java b/Mage.Sets/src/mage/cards/j/JandorsRing.java index 6a8425521fc..4ebfcfcc659 100644 --- a/Mage.Sets/src/mage/cards/j/JandorsRing.java +++ b/Mage.Sets/src/mage/cards/j/JandorsRing.java @@ -71,7 +71,7 @@ class JandorsRingEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - JandorsRingWatcher watcher = (JandorsRingWatcher) game.getState().getWatchers().get(JandorsRingWatcher.class.getSimpleName()); + JandorsRingWatcher watcher = game.getState().getWatcher(JandorsRingWatcher.class); if (watcher != null) { UUID cardId = watcher.getLastDrewCard(source.getControllerId()); Card card = game.getCard(cardId); @@ -97,7 +97,7 @@ class JandorsRingWatcher extends Watcher { Map lastDrawnCards = new HashMap<>(); public JandorsRingWatcher() { - super(JandorsRingWatcher.class.getSimpleName(), WatcherScope.GAME); + super(JandorsRingWatcher.class, WatcherScope.GAME); } public JandorsRingWatcher(final JandorsRingWatcher watcher) { @@ -134,7 +134,7 @@ enum WatchedCardInHandCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - JandorsRingWatcher watcher = (JandorsRingWatcher) game.getState().getWatchers().get(JandorsRingWatcher.class.getSimpleName()); + JandorsRingWatcher watcher = game.getState().getWatcher(JandorsRingWatcher.class); return watcher != null && watcher.lastDrawnCards != null && game.getPlayer(source.getControllerId()).getHand().contains(watcher.getLastDrewCard(source.getControllerId())); diff --git a/Mage.Sets/src/mage/cards/j/JaradGolgariLichLord.java b/Mage.Sets/src/mage/cards/j/JaradGolgariLichLord.java index f3226b55642..e895731ea58 100644 --- a/Mage.Sets/src/mage/cards/j/JaradGolgariLichLord.java +++ b/Mage.Sets/src/mage/cards/j/JaradGolgariLichLord.java @@ -53,7 +53,7 @@ public final class JaradGolgariLichLord extends CardImpl { this.addAbility(ability); // {1}{B}{G}, Sacrifice another creature: Each opponent loses life equal to the sacrificed creature's power. - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeOpponentsEffect(new SacrificeCostCreaturesPower()), new ManaCostsImpl("{1}{B}{G}")); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeOpponentsEffect(SacrificeCostCreaturesPower.instance), new ManaCostsImpl("{1}{B}{G}")); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, false))); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/j/JaradsOrders.java b/Mage.Sets/src/mage/cards/j/JaradsOrders.java index 4f3d01ef3fa..e1f9ff9a8b0 100644 --- a/Mage.Sets/src/mage/cards/j/JaradsOrders.java +++ b/Mage.Sets/src/mage/cards/j/JaradsOrders.java @@ -68,7 +68,7 @@ class JaradsOrdersEffect extends OneShotEffect { if (controller.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { Cards revealed = new CardsImpl(); - for (UUID cardId: (List)target.getTargets()) { + for (UUID cardId: target.getTargets()) { Card card = controller.getLibrary().getCard(cardId, game); revealed.add(card); } diff --git a/Mage.Sets/src/mage/cards/j/JayaBallardTaskMage.java b/Mage.Sets/src/mage/cards/j/JayaBallardTaskMage.java index c6198ccf282..2939117b8bf 100644 --- a/Mage.Sets/src/mage/cards/j/JayaBallardTaskMage.java +++ b/Mage.Sets/src/mage/cards/j/JayaBallardTaskMage.java @@ -103,7 +103,7 @@ class CantRegenerateEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.REGENERATE) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), source.getSourceId()); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.wasDamaged(event.getTargetId(), game); } diff --git a/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java b/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java index b1e6320f946..7f04db05596 100644 --- a/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java +++ b/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java @@ -25,7 +25,7 @@ public final class JayasImmolatingInferno extends CardImpl { this.addAbility(new LegendarySpellAbility()); // Jaya's Immolating Inferno deals X damage to each of up to three targets. - Effect effect = new DamageTargetEffect(new ManacostVariableValue()); + Effect effect = new DamageTargetEffect(ManacostVariableValue.instance); effect.setText("{this} deals X damage to each of up to three targets"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetAnyTarget(1, 3)); diff --git a/Mage.Sets/src/mage/cards/j/JediInstructor.java b/Mage.Sets/src/mage/cards/j/JediInstructor.java index 4665dabb37a..bcdfd16169b 100644 --- a/Mage.Sets/src/mage/cards/j/JediInstructor.java +++ b/Mage.Sets/src/mage/cards/j/JediInstructor.java @@ -25,7 +25,7 @@ public final class JediInstructor extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JediInstructor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JediSentinel.java b/Mage.Sets/src/mage/cards/j/JediSentinel.java index 6fd1a7eda82..95eeddae9fe 100644 --- a/Mage.Sets/src/mage/cards/j/JediSentinel.java +++ b/Mage.Sets/src/mage/cards/j/JediSentinel.java @@ -30,7 +30,7 @@ public final class JediSentinel extends CardImpl { private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature you don't control"); static { - filter1.add(new AnotherPredicate()); + filter1.add(AnotherPredicate.instance); filter2.add(new ControllerPredicate(TargetController.NOT_YOU)); } diff --git a/Mage.Sets/src/mage/cards/j/JeeringInstigator.java b/Mage.Sets/src/mage/cards/j/JeeringInstigator.java index d0c8ab237b8..1e76e9844c8 100644 --- a/Mage.Sets/src/mage/cards/j/JeeringInstigator.java +++ b/Mage.Sets/src/mage/cards/j/JeeringInstigator.java @@ -31,7 +31,7 @@ public final class JeeringInstigator extends CardImpl { static final private FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JeeringInstigator(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java b/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java index 2af20fd0760..1177abe7f80 100644 --- a/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java +++ b/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java @@ -84,7 +84,7 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); - JelevaNephaliasWatcher watcher = (JelevaNephaliasWatcher) game.getState().getWatchers().get(JelevaNephaliasWatcher.class.getSimpleName()); + JelevaNephaliasWatcher watcher = game.getState().getWatcher(JelevaNephaliasWatcher.class); if (controller != null && sourceObject != null && watcher != null) { int xValue = watcher.getManaSpentToCastLastTime(sourceObject.getId(), sourceObject.getZoneChangeCounter(game) - 1); if (xValue > 0) { @@ -144,7 +144,7 @@ class JelevaNephaliasWatcher extends Watcher { private final Map manaSpendToCast = new HashMap<>(); // cast public JelevaNephaliasWatcher() { - super(JelevaNephaliasWatcher.class.getSimpleName(), WatcherScope.GAME); + super(JelevaNephaliasWatcher.class, WatcherScope.GAME); } public JelevaNephaliasWatcher(final JelevaNephaliasWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java b/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java index fa0dc3dfe63..061d5edb646 100644 --- a/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java +++ b/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java @@ -27,7 +27,7 @@ public final class JeskaiBarricade extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/j/JhoiraOfTheGhitu.java b/Mage.Sets/src/mage/cards/j/JhoiraOfTheGhitu.java index 4211de5922e..bc09e9f0d0a 100644 --- a/Mage.Sets/src/mage/cards/j/JhoiraOfTheGhitu.java +++ b/Mage.Sets/src/mage/cards/j/JhoiraOfTheGhitu.java @@ -1,9 +1,5 @@ - package mage.cards.j; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -17,25 +13,24 @@ import mage.abilities.keyword.SuspendAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterNonlandCard; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class JhoiraOfTheGhitu extends CardImpl { public JhoiraOfTheGhitu(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -83,13 +78,17 @@ class JhoiraOfTheGhituSuspendEffect extends OneShotEffect { return false; } List cards = new ArrayList<>(); - for (Cost cost: source.getCosts()) { + for (Cost cost : source.getCosts()) { if (cost instanceof ExileFromHandCost) { cards = ((ExileFromHandCost) cost).getCards(); } } if (cards != null && !cards.isEmpty()) { + // always one card to exile Card card = game.getCard(cards.get(0).getId()); + if (card == null) { + return false; + } boolean hasSuspend = card.getAbilities().containsClass(SuspendAbility.class); UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game); diff --git a/Mage.Sets/src/mage/cards/j/Jihad.java b/Mage.Sets/src/mage/cards/j/Jihad.java index 68035106cac..12ac2407346 100644 --- a/Mage.Sets/src/mage/cards/j/Jihad.java +++ b/Mage.Sets/src/mage/cards/j/Jihad.java @@ -84,7 +84,7 @@ class JihadTriggeredAbility extends StateTriggeredAbility { UUID chosenOpponent = (UUID) game.getState().getValue(getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY); FilterPermanent filter = new FilterPermanent(); filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(getSourceId() + "_color"))); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); return game.getBattlefield().countAll(filter, chosenOpponent, game) == 0; } @@ -101,7 +101,7 @@ class JihadOpponentCondition implements Condition { UUID chosenOpponent = (UUID) game.getState().getValue(source.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY); FilterPermanent filter = new FilterPermanent(); filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(source.getSourceId() + "_color"))); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); return game.getBattlefield().countAll(filter, chosenOpponent, game) > 0; } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/j/Jilt.java b/Mage.Sets/src/mage/cards/j/Jilt.java index f1ab8a2f697..a66b94bdde7 100644 --- a/Mage.Sets/src/mage/cards/j/Jilt.java +++ b/Mage.Sets/src/mage/cards/j/Jilt.java @@ -1,9 +1,7 @@ - package mage.cards.j; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.Effect; @@ -18,6 +16,7 @@ import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.SecondTargetPointer; /** @@ -43,18 +42,7 @@ public final class Jilt extends CardImpl { Target target = new TargetCreaturePermanent(); target.setTargetTag(1); this.getSpellAbility().addTarget(target); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility && KickedCondition.instance.apply(game, ability)) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("Another creature: Damaged"); - filter.add(new AnotherTargetPredicate(2)); - Target target = new TargetCreaturePermanent(filter); - target.setTargetTag(2); - ability.addTarget(target); - } - + this.getSpellAbility().setTargetAdjuster(JiltAdjuster.instance); } public Jilt(final Jilt card) { @@ -66,3 +54,20 @@ public final class Jilt extends CardImpl { return new Jilt(this); } } + +enum JiltAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + if (!KickedCondition.instance.apply(game, ability)) { + return; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent("Another creature: Damaged"); + filter.add(new AnotherTargetPredicate(2)); + Target target = new TargetCreaturePermanent(filter); + target.setTargetTag(2); + ability.addTarget(target); + } + +} diff --git a/Mage.Sets/src/mage/cards/j/JinxedRing.java b/Mage.Sets/src/mage/cards/j/JinxedRing.java index c2f58dd8e81..ead7bf52e4a 100644 --- a/Mage.Sets/src/mage/cards/j/JinxedRing.java +++ b/Mage.Sets/src/mage/cards/j/JinxedRing.java @@ -34,7 +34,7 @@ public final class JinxedRing extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("a nontoken permanent"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public JinxedRing(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java b/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java index fb3d834a8e4..e72e7debbfe 100644 --- a/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java +++ b/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java @@ -44,13 +44,13 @@ public final class JiwariTheEarthAflame extends CardImpl { this.toughness = new MageInt(3); // {X}{R}, {tap}: Jiwari, the Earth Aflame deals X damage to target creature without flying. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{R}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); // Channel - {X}{R}{R}{R}, Discard Jiwari: Jiwari deals X damage to each creature without flying. - this.addAbility(new ChannelAbility("{X}{R}{R}{R}", new DamageAllEffect(new ManacostVariableValue(), filter))); + this.addAbility(new ChannelAbility("{X}{R}{R}{R}", new DamageAllEffect(ManacostVariableValue.instance, filter))); } public JiwariTheEarthAflame(final JiwariTheEarthAflame card) { diff --git a/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java b/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java index 9ee16402ee5..7c888ff6bd7 100644 --- a/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java +++ b/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java @@ -25,7 +25,7 @@ public final class JoragaAuxiliary extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other target creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JoragaAuxiliary(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JoragaWarcaller.java b/Mage.Sets/src/mage/cards/j/JoragaWarcaller.java index 6b89b86a4ba..ca2464b6589 100644 --- a/Mage.Sets/src/mage/cards/j/JoragaWarcaller.java +++ b/Mage.Sets/src/mage/cards/j/JoragaWarcaller.java @@ -32,7 +32,7 @@ public final class JoragaWarcaller extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new SubtypePredicate(SubType.ELF)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JoragaWarcaller(UUID ownerId, CardSetInfo setInfo) { @@ -48,7 +48,7 @@ public final class JoragaWarcaller extends CardImpl { // Joraga Warcaller enters the battlefield with a +1/+1 counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true), + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true), "with a +1/+1 counter on it for each time it was kicked")); diff --git a/Mage.Sets/src/mage/cards/j/JoriEnRuinDiver.java b/Mage.Sets/src/mage/cards/j/JoriEnRuinDiver.java index 5d817801997..dd11de050fa 100644 --- a/Mage.Sets/src/mage/cards/j/JoriEnRuinDiver.java +++ b/Mage.Sets/src/mage/cards/j/JoriEnRuinDiver.java @@ -67,7 +67,7 @@ class JoriEnTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(controllerId)) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) { return true; } diff --git a/Mage.Sets/src/mage/cards/j/JourneyToNowhere.java b/Mage.Sets/src/mage/cards/j/JourneyToNowhere.java index d0253e3bde5..c10249f3ece 100644 --- a/Mage.Sets/src/mage/cards/j/JourneyToNowhere.java +++ b/Mage.Sets/src/mage/cards/j/JourneyToNowhere.java @@ -27,7 +27,7 @@ public final class JourneyToNowhere extends CardImpl { // When Journey to Nowhere enters the battlefield, exile target creature. FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); Ability ability1 = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), false); Target target = new TargetPermanent(filter); ability1.addTarget(target); diff --git a/Mage.Sets/src/mage/cards/j/JovensFerrets.java b/Mage.Sets/src/mage/cards/j/JovensFerrets.java index a4df82c443c..8454e048112 100644 --- a/Mage.Sets/src/mage/cards/j/JovensFerrets.java +++ b/Mage.Sets/src/mage/cards/j/JovensFerrets.java @@ -82,7 +82,7 @@ class JovensFerretsEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (controller != null && sourcePermanent != null) { - BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher watcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (watcher != null) { List toTap = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { diff --git a/Mage.Sets/src/mage/cards/j/JubilantMascot.java b/Mage.Sets/src/mage/cards/j/JubilantMascot.java index 5e7df4e0496..299f93ea3df 100644 --- a/Mage.Sets/src/mage/cards/j/JubilantMascot.java +++ b/Mage.Sets/src/mage/cards/j/JubilantMascot.java @@ -27,7 +27,7 @@ public final class JubilantMascot extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other target creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JubilantMascot(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JudithTheScourgeDiva.java b/Mage.Sets/src/mage/cards/j/JudithTheScourgeDiva.java new file mode 100644 index 00000000000..8495a10b955 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JudithTheScourgeDiva.java @@ -0,0 +1,62 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.common.TargetAnyTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JudithTheScourgeDiva extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("nontoken creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(TokenPredicate.instance)); + } + + public JudithTheScourgeDiva(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Other creatures you control get +1/+0. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield, true) + )); + + // Whenever a nontoken creature you control dies, Judith, the Scourge Diva deals 1 damage to any target. + Ability ability = new DiesCreatureTriggeredAbility(new DamageTargetEffect(1), false, filter); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + private JudithTheScourgeDiva(final JudithTheScourgeDiva card) { + super(card); + } + + @Override + public JudithTheScourgeDiva copy() { + return new JudithTheScourgeDiva(this); + } +} diff --git a/Mage.Sets/src/mage/cards/j/JundHackblade.java b/Mage.Sets/src/mage/cards/j/JundHackblade.java index 21427f6d9f8..c8c36209893 100644 --- a/Mage.Sets/src/mage/cards/j/JundHackblade.java +++ b/Mage.Sets/src/mage/cards/j/JundHackblade.java @@ -29,8 +29,8 @@ public final class JundHackblade extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another multicolor permanent"); static { - filter.add(new MulticoloredPredicate()); - filter.add(new AnotherPredicate()); + filter.add(MulticoloredPredicate.instance); + filter.add(AnotherPredicate.instance); } public JundHackblade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JungleBasin.java b/Mage.Sets/src/mage/cards/j/JungleBasin.java index c486b5dce38..e2ceca75b64 100644 --- a/Mage.Sets/src/mage/cards/j/JungleBasin.java +++ b/Mage.Sets/src/mage/cards/j/JungleBasin.java @@ -30,7 +30,7 @@ public final class JungleBasin extends CardImpl { static { filter.add(new SubtypePredicate(SubType.FOREST)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public JungleBasin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JunglePatrol.java b/Mage.Sets/src/mage/cards/j/JunglePatrol.java index db42b08508f..31e9ecade3f 100644 --- a/Mage.Sets/src/mage/cards/j/JunglePatrol.java +++ b/Mage.Sets/src/mage/cards/j/JunglePatrol.java @@ -32,7 +32,7 @@ public final class JunglePatrol extends CardImpl { static { filter.add(new NamePredicate("Wood")); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public JunglePatrol(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JuniperOrderRanger.java b/Mage.Sets/src/mage/cards/j/JuniperOrderRanger.java index f6efdbf90d3..4c343d6b5fb 100644 --- a/Mage.Sets/src/mage/cards/j/JuniperOrderRanger.java +++ b/Mage.Sets/src/mage/cards/j/JuniperOrderRanger.java @@ -25,7 +25,7 @@ public final class JuniperOrderRanger extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public JuniperOrderRanger(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/j/JushiApprentice.java b/Mage.Sets/src/mage/cards/j/JushiApprentice.java index 88ac5754ba5..c6f19a2652c 100644 --- a/Mage.Sets/src/mage/cards/j/JushiApprentice.java +++ b/Mage.Sets/src/mage/cards/j/JushiApprentice.java @@ -71,7 +71,7 @@ class TomoyaTheRevealer extends TokenImpl { toughness = new MageInt(3); // {3}{U}{U},{T} : Target player draws X cards, where X is the number of cards in your hand. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(new CardsInControllerHandCount()), new ManaCostsImpl("{3}{U}{U}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(CardsInControllerHandCount.instance), new ManaCostsImpl("{3}{U}{U}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/j/JusticiarsPortal.java b/Mage.Sets/src/mage/cards/j/JusticiarsPortal.java new file mode 100644 index 00000000000..7dfc2956ba3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JusticiarsPortal.java @@ -0,0 +1,71 @@ +package mage.cards.j; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetForSourceEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JusticiarsPortal extends CardImpl { + + public JusticiarsPortal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Exile target creature you control, then return that card to the battlefield under its owner's control. It gains first strike until end of turn. + this.getSpellAbility().addEffect(new JusticiarsPortalEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + private JusticiarsPortal(final JusticiarsPortal card) { + super(card); + } + + @Override + public JusticiarsPortal copy() { + return new JusticiarsPortal(this); + } +} + +class JusticiarsPortalEffect extends OneShotEffect { + + JusticiarsPortalEffect() { + super(Outcome.Benefit); + staticText = "Exile target creature you control, then return that card to the battlefield " + + "under its owner's control. It gains first strike until end of turn."; + } + + private JusticiarsPortalEffect(final JusticiarsPortalEffect effect) { + super(effect); + } + + @Override + public JusticiarsPortalEffect copy() { + return new JusticiarsPortalEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID targetId = source.getFirstTarget(); + new ExileTargetForSourceEffect().apply(game, source); + new ReturnToBattlefieldUnderYourControlTargetEffect(true).apply(game, source); + ContinuousEffect effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(targetId, game)); + game.addEffect(effect, source); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/j/Juxtapose.java b/Mage.Sets/src/mage/cards/j/Juxtapose.java index 6c0cddb15ca..a5464c16ed1 100644 --- a/Mage.Sets/src/mage/cards/j/Juxtapose.java +++ b/Mage.Sets/src/mage/cards/j/Juxtapose.java @@ -1,13 +1,5 @@ - package mage.cards.j; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; @@ -15,12 +7,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.Cards; import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; @@ -31,8 +18,9 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.TargetPlayer; +import java.util.*; + /** - * * @author Quercitron */ public final class Juxtapose extends CardImpl { @@ -89,7 +77,6 @@ class JuxtaposeEffect extends ContinuousEffectImpl { public void init(Ability source, Game game) { Player you = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - MageObject sourceObject = game.getCard(source.getSourceId()); if (you != null && targetPlayer != null) { Permanent permanent1 = chooseOnePermanentsWithTheHighestCMC(game, you, filter); @@ -109,6 +96,7 @@ class JuxtaposeEffect extends ContinuousEffectImpl { permanent1.changeControllerId(targetPlayer.getId(), game); permanent2.changeControllerId(you.getId(), game); + MageObject sourceObject = game.getCard(source.getSourceId()); game.informPlayers((sourceObject != null ? sourceObject.getLogName() : "") + ": " + you.getLogName() + " and " + targetPlayer.getLogName() + " exchange control of " + permanent1.getLogName() + " and " + permanent2.getName()); diff --git a/Mage.Sets/src/mage/cards/j/JwariShapeshifter.java b/Mage.Sets/src/mage/cards/j/JwariShapeshifter.java index e742dfd1acb..7eb7db49eb0 100644 --- a/Mage.Sets/src/mage/cards/j/JwariShapeshifter.java +++ b/Mage.Sets/src/mage/cards/j/JwariShapeshifter.java @@ -25,7 +25,7 @@ public final class JwariShapeshifter extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new AnotherPredicate()); // needed because during enters_the_battlefield event the creature is already targetable although it shouldn't + filter.add(AnotherPredicate.instance); // needed because during enters_the_battlefield event the creature is already targetable although it shouldn't } public JwariShapeshifter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KaerveksPurge.java b/Mage.Sets/src/mage/cards/k/KaerveksPurge.java index 591f109a1b3..077111812ae 100644 --- a/Mage.Sets/src/mage/cards/k/KaerveksPurge.java +++ b/Mage.Sets/src/mage/cards/k/KaerveksPurge.java @@ -1,9 +1,7 @@ package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,9 +15,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author sinsedrix */ public final class KaerveksPurge extends CardImpl { @@ -28,19 +28,8 @@ public final class KaerveksPurge extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{R}"); // Destroy target creature with converted mana cost X. If that creature dies this way, Kaervek's Purge deals damage equal to the creature's power to the creature's controller. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with converted mana cost X"))); this.getSpellAbility().addEffect(new KaerveksPurgeEffect()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost X"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.addTarget(new TargetCreaturePermanent(filter)); - } + this.getSpellAbility().setTargetAdjuster(KaerveksPurgeAdjuster.instance); } public KaerveksPurge(final KaerveksPurge card) { @@ -53,11 +42,27 @@ public final class KaerveksPurge extends CardImpl { } } +enum KaerveksPurgeAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with converted mana cost " + xValue); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} + class KaerveksPurgeEffect extends OneShotEffect { public KaerveksPurgeEffect() { super(Outcome.DestroyPermanent); - this.staticText = "Destroy target creature with converted mana cost X. If that creature dies this way, {this} deals damage equal to the creature's power to the creature's controller"; + this.staticText = "Destroy target creature with converted mana cost X. " + + "If that creature dies this way, " + + "{this} deals damage equal to the creature's power" + + " to the creature's controller"; } public KaerveksPurgeEffect(final KaerveksPurgeEffect effect) { diff --git a/Mage.Sets/src/mage/cards/k/KaerveksTorch.java b/Mage.Sets/src/mage/cards/k/KaerveksTorch.java index 9c299f3f2d2..f003c596253 100644 --- a/Mage.Sets/src/mage/cards/k/KaerveksTorch.java +++ b/Mage.Sets/src/mage/cards/k/KaerveksTorch.java @@ -34,7 +34,7 @@ public final class KaerveksTorch extends CardImpl { // As long as Kaervek's Torch is on the stack, spells that target it cost {2} more to cast. this.addAbility(new SimpleStaticAbility(Zone.STACK, new KaerveksTorchCostIncreaseEffect())); // Kaervek's Torch deals X damage to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/k/KagemaroFirstToSuffer.java b/Mage.Sets/src/mage/cards/k/KagemaroFirstToSuffer.java index a8249cef2d2..06e5e8d550b 100644 --- a/Mage.Sets/src/mage/cards/k/KagemaroFirstToSuffer.java +++ b/Mage.Sets/src/mage/cards/k/KagemaroFirstToSuffer.java @@ -37,7 +37,7 @@ public final class KagemaroFirstToSuffer extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - DynamicValue xValue = new CardsInControllerHandCount(); + DynamicValue xValue = CardsInControllerHandCount.instance; // Kagemaro, First to Suffer's power and toughness are each equal to the number of cards in your hand. this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame))); // {B}, Sacrifice Kagemaro: All creatures get -X/-X until end of turn, where X is the number of cards in your hand. diff --git a/Mage.Sets/src/mage/cards/k/KagemarosClutch.java b/Mage.Sets/src/mage/cards/k/KagemarosClutch.java index 1736f8cd3ee..679f3bfc1aa 100644 --- a/Mage.Sets/src/mage/cards/k/KagemarosClutch.java +++ b/Mage.Sets/src/mage/cards/k/KagemarosClutch.java @@ -40,7 +40,7 @@ public final class KagemarosClutch extends CardImpl { this.addAbility(ability); // Enchanted creature gets -X/-X, where X is the number of cards in your hand. - DynamicValue xMinusValue = new SignInversionDynamicValue(new CardsInControllerHandCount()); + DynamicValue xMinusValue = new SignInversionDynamicValue(CardsInControllerHandCount.instance); Effect effect = new BoostEnchantedEffect(xMinusValue, xMinusValue, Duration.WhileOnBattlefield); effect.setText("Enchanted creature gets -X/-X, where X is the number of cards in your hand"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/k/KalitasTraitorOfGhet.java b/Mage.Sets/src/mage/cards/k/KalitasTraitorOfGhet.java index ff0708de288..a8dc5ad7567 100644 --- a/Mage.Sets/src/mage/cards/k/KalitasTraitorOfGhet.java +++ b/Mage.Sets/src/mage/cards/k/KalitasTraitorOfGhet.java @@ -37,7 +37,7 @@ public final class KalitasTraitorOfGhet extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Vampire or Zombie"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.or(new SubtypePredicate(SubType.VAMPIRE), (new SubtypePredicate(SubType.ZOMBIE)))); } diff --git a/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java b/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java index fcc5372b8c3..cdf9e48aaf3 100644 --- a/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java +++ b/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java @@ -36,7 +36,7 @@ public final class KangeeAerieKeeper extends CardImpl { static { filter.add(new SubtypePredicate(SubType.BIRD)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public KangeeAerieKeeper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java index aba7458be3e..db01b9f2226 100644 --- a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java +++ b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java @@ -150,8 +150,8 @@ class KaradorGhostChieftainCastFromGraveyardEffect extends AsThoughEffectImpl { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { if (objectId.equals(getTargetPointer().getFirst(game, source))) { if (affectedControllerId.equals(source.getControllerId())) { - KaradorGhostChieftainWatcher watcher = (KaradorGhostChieftainWatcher) game.getState().getWatchers().get(KaradorGhostChieftainWatcher.class.getSimpleName(), source.getSourceId()); - return !watcher.isAbilityUsed(); + KaradorGhostChieftainWatcher watcher = game.getState().getWatcher(KaradorGhostChieftainWatcher.class, source.getSourceId()); + return watcher != null && !watcher.isAbilityUsed(); } } return false; @@ -163,7 +163,7 @@ class KaradorGhostChieftainWatcher extends Watcher { boolean abilityUsed = false; KaradorGhostChieftainWatcher() { - super(KaradorGhostChieftainWatcher.class.getSimpleName(), WatcherScope.CARD); + super(KaradorGhostChieftainWatcher.class, WatcherScope.CARD); } KaradorGhostChieftainWatcher(final KaradorGhostChieftainWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/k/KarnLiberated.java b/Mage.Sets/src/mage/cards/k/KarnLiberated.java index 2cecf73c709..5d969273956 100644 --- a/Mage.Sets/src/mage/cards/k/KarnLiberated.java +++ b/Mage.Sets/src/mage/cards/k/KarnLiberated.java @@ -1,9 +1,5 @@ - package mage.cards.k; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -11,18 +7,11 @@ import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetForSourceEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.cards.*; +import mage.constants.*; import mage.game.ExileZone; import mage.game.Game; +import mage.game.GameImpl; import mage.game.command.Commander; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -34,8 +23,11 @@ import mage.target.TargetPlayer; import mage.target.common.TargetCardInHand; import mage.util.CardUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author bunchOfDevs */ public final class KarnLiberated extends CardImpl { @@ -102,6 +94,9 @@ class KarnLiberatedEffect extends OneShotEffect { } } game.getState().clear(); + // default watchers init, TODO: remove all restart/init code to game + ((GameImpl) game).initGameDefaultWatchers(); + for (Card card : game.getCards()) { game.getState().addCard(card); } @@ -122,6 +117,7 @@ class KarnLiberatedEffect extends OneShotEffect { } } } + ((GameImpl) game).initPlayerDefaultWatchers(player.getId()); player.init(game); } } diff --git a/Mage.Sets/src/mage/cards/k/Karoo.java b/Mage.Sets/src/mage/cards/k/Karoo.java index f9b95d496d7..61cb7560d3b 100644 --- a/Mage.Sets/src/mage/cards/k/Karoo.java +++ b/Mage.Sets/src/mage/cards/k/Karoo.java @@ -30,7 +30,7 @@ public final class Karoo extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PLAINS)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Karoo(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KarplusanGiant.java b/Mage.Sets/src/mage/cards/k/KarplusanGiant.java index 8d2b1424c3a..9c1caee8165 100644 --- a/Mage.Sets/src/mage/cards/k/KarplusanGiant.java +++ b/Mage.Sets/src/mage/cards/k/KarplusanGiant.java @@ -27,7 +27,7 @@ public final class KarplusanGiant extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("untapped snow land you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SupertypePredicate(SuperType.SNOW)); } diff --git a/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java b/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java index eda2fdad620..922fd7146f8 100644 --- a/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java +++ b/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java @@ -1,12 +1,11 @@ package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.CumulativeUpkeepAbility; import mage.cards.CardImpl; @@ -16,14 +15,17 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; +import mage.game.events.CoinFlippedEvent; import mage.game.events.GameEvent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetOpponent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author L_J */ public final class KarplusanMinotaur extends CardImpl { @@ -39,36 +41,10 @@ public final class KarplusanMinotaur extends CardImpl { this.addAbility(new CumulativeUpkeepAbility(new KarplusanMinotaurCost())); // Whenever you win a coin flip, Karplusan Minotaur deals 1 damage to any target. - Ability abilityWin = new KarplusanMinotaurFlipWinTriggeredAbility(); - abilityWin.addTarget(new TargetAnyTarget()); - this.addAbility(abilityWin); + this.addAbility(new KarplusanMinotaurFlipWinTriggeredAbility()); - //TODO: Make ability properly copiable // Whenever you lose a coin flip, Karplusan Minotaur deals 1 damage to any target of an opponent's choice. - Ability abilityLose = new KarplusanMinotaurFlipLoseTriggeredAbility(); - abilityLose.addTarget(new TargetAnyTarget()); - this.addAbility(abilityLose); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof KarplusanMinotaurFlipLoseTriggeredAbility) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - UUID opponentId = null; - if (game.getOpponents(controller.getId()).size() > 1) { - Target target = new TargetOpponent(true); - if (controller.chooseTarget(Outcome.Neutral, target, ability, game)) { - opponentId = target.getFirstTarget(); - } - } else { - opponentId = game.getOpponents(controller.getId()).iterator().next(); - } - if (opponentId != null) { - ability.getTargets().get(0).setTargetController(opponentId); - } - } - } + this.addAbility(new KarplusanMinotaurFlipLoseTriggeredAbility()); } public KarplusanMinotaur(final KarplusanMinotaur card) { @@ -85,6 +61,7 @@ class KarplusanMinotaurFlipWinTriggeredAbility extends TriggeredAbilityImpl { public KarplusanMinotaurFlipWinTriggeredAbility() { super(Zone.BATTLEFIELD, new DamageTargetEffect(1), false); + this.addTarget(new TargetAnyTarget()); } public KarplusanMinotaurFlipWinTriggeredAbility(final KarplusanMinotaurFlipWinTriggeredAbility ability) { @@ -103,7 +80,10 @@ class KarplusanMinotaurFlipWinTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return this.isControlledBy(event.getPlayerId()) && event.getFlag(); + CoinFlippedEvent flipEvent = (CoinFlippedEvent) event; + return flipEvent.getPlayerId().equals(controllerId) + && flipEvent.isWinnable() + && (flipEvent.getChosen() == flipEvent.getResult()); } @Override @@ -116,6 +96,8 @@ class KarplusanMinotaurFlipLoseTriggeredAbility extends TriggeredAbilityImpl { public KarplusanMinotaurFlipLoseTriggeredAbility() { super(Zone.BATTLEFIELD, new DamageTargetEffect(1), false); + this.addTarget(new TargetAnyTarget()); + targetAdjuster = KarplusanMinotaurAdjuster.instance; } public KarplusanMinotaurFlipLoseTriggeredAbility(final KarplusanMinotaurFlipLoseTriggeredAbility ability) { @@ -134,7 +116,10 @@ class KarplusanMinotaurFlipLoseTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return this.isControlledBy(event.getPlayerId()) && !event.getFlag(); + CoinFlippedEvent flipEvent = (CoinFlippedEvent) event; + return flipEvent.getPlayerId().equals(controllerId) + && flipEvent.isWinnable() + && (flipEvent.getChosen() != flipEvent.getResult()); } @Override @@ -153,7 +138,7 @@ class KarplusanMinotaurCost extends CostImpl { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { Player controller = game.getPlayer(controllerId); if (controller != null) { - controller.flipCoin(game); + controller.flipCoin(ability, game, true); this.paid = true; return true; } @@ -176,3 +161,27 @@ class KarplusanMinotaurCost extends CostImpl { return new KarplusanMinotaurCost(); } } + +enum KarplusanMinotaurAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller == null) { + return; + } + UUID opponentId = null; + if (game.getOpponents(controller.getId()).size() > 1) { + Target target = new TargetOpponent(true); + if (controller.chooseTarget(Outcome.Neutral, target, ability, game)) { + opponentId = target.getFirstTarget(); + } + } else { + opponentId = game.getOpponents(controller.getId()).iterator().next(); + } + if (opponentId != null) { + ability.getTargets().get(0).setTargetController(opponentId); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/k/KarrthusTyrantOfJund.java b/Mage.Sets/src/mage/cards/k/KarrthusTyrantOfJund.java index d11a4fd48bf..949e636e44f 100644 --- a/Mage.Sets/src/mage/cards/k/KarrthusTyrantOfJund.java +++ b/Mage.Sets/src/mage/cards/k/KarrthusTyrantOfJund.java @@ -33,7 +33,7 @@ public final class KarrthusTyrantOfJund extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Dragon creatures you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/k/KavuMauler.java b/Mage.Sets/src/mage/cards/k/KavuMauler.java index ddfc95785e8..5b949f2284c 100644 --- a/Mage.Sets/src/mage/cards/k/KavuMauler.java +++ b/Mage.Sets/src/mage/cards/k/KavuMauler.java @@ -26,7 +26,7 @@ public final class KavuMauler extends CardImpl { static { filter.add(new SubtypePredicate(SubType.KAVU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public KavuMauler(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KavuMonarch.java b/Mage.Sets/src/mage/cards/k/KavuMonarch.java index 9221978de69..0aebfe4a2cd 100644 --- a/Mage.Sets/src/mage/cards/k/KavuMonarch.java +++ b/Mage.Sets/src/mage/cards/k/KavuMonarch.java @@ -31,7 +31,7 @@ public final class KavuMonarch extends CardImpl { static { filter1.add(new SubtypePredicate(SubType.KAVU)); filter2.add(new SubtypePredicate(SubType.KAVU)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public KavuMonarch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KayaOrzhovUsurper.java b/Mage.Sets/src/mage/cards/k/KayaOrzhovUsurper.java new file mode 100644 index 00000000000..31b447b6e10 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KayaOrzhovUsurper.java @@ -0,0 +1,145 @@ +package mage.cards.k; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.cards.*; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInASingleGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KayaOrzhovUsurper extends CardImpl { + + private static final FilterPermanent filter + = new FilterNonlandPermanent("nonland permanent with converted mana cost 1 or less"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 2)); + } + + public KayaOrzhovUsurper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{W}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.KAYA); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); + + // +1: Exile up to two target cards from a single graveyard. You gain 2 life if at least one creature card was exiled this way. + Ability ability = new LoyaltyAbility(new KayaOrzhovUsurperExileEffect(), 1); + ability.addTarget(new TargetCardInASingleGraveyard(0, 2, StaticFilters.FILTER_CARD)); + this.addAbility(ability); + + // -1: Exile target nonland permanent with converted mana cost 1 or less. + ability = new LoyaltyAbility(new ExileTargetEffect(), -1); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + + // -5: Kaya, Orzhov Usurper deals damage to target player equal to the number of cards that player owns in exile and you gain that much life. + ability = new LoyaltyAbility(new KayaOrzhovUsurperDamageEffect(), -5); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + private KayaOrzhovUsurper(final KayaOrzhovUsurper card) { + super(card); + } + + @Override + public KayaOrzhovUsurper copy() { + return new KayaOrzhovUsurper(this); + } +} + +class KayaOrzhovUsurperExileEffect extends OneShotEffect { + + KayaOrzhovUsurperExileEffect() { + super(Outcome.Benefit); + staticText = "Exile up to two target cards from a single graveyard. " + + "You gain 2 life if at least one creature card was exiled this way."; + } + + private KayaOrzhovUsurperExileEffect(final KayaOrzhovUsurperExileEffect effect) { + super(effect); + } + + @Override + public KayaOrzhovUsurperExileEffect copy() { + return new KayaOrzhovUsurperExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Cards cards = new CardsImpl(); + for (Target target : source.getTargets()) { + for (UUID targetId : target.getTargets()) { + Card card = game.getCard(targetId); + if (card != null) { + cards.add(card); + } + } + } + player.moveCards(cards, Zone.EXILED, source, game); + for (Card card : cards.getCards(game)) { + if (card != null && card.isCreature()) { + player.gainLife(2, game, source); + break; + } + } + return false; + } +} + +class KayaOrzhovUsurperDamageEffect extends OneShotEffect { + + KayaOrzhovUsurperDamageEffect() { + super(Outcome.Benefit); + staticText = "{this} deals damage to target player equal to the number of cards " + + "that player owns in exile and you gain that much life."; + } + + private KayaOrzhovUsurperDamageEffect(final KayaOrzhovUsurperDamageEffect effect) { + super(effect); + } + + @Override + public KayaOrzhovUsurperDamageEffect copy() { + return new KayaOrzhovUsurperDamageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(source.getFirstTarget()); + if (controller == null || player == null) { + return false; + } + int count = 0; + for (Card card : game.getExile().getAllCards(game)) { + if (card != null && card.getOwnerId().equals(player.getId())) { + count += 1; + } + } + player.damage(count, source.getSourceId(), game, false, true); + controller.gainLife(count, game, source); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/k/KayasWrath.java b/Mage.Sets/src/mage/cards/k/KayasWrath.java new file mode 100644 index 00000000000..e1019f9e0aa --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KayasWrath.java @@ -0,0 +1,69 @@ +package mage.cards.k; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KayasWrath extends CardImpl { + + public KayasWrath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}{W}{B}{B}"); + + // Destroy all creatures. You gain life equal to the number of creatures you controlled that were destroyed this way. + this.getSpellAbility().addEffect(new KayasWrathEffect()); + } + + private KayasWrath(final KayasWrath card) { + super(card); + } + + @Override + public KayasWrath copy() { + return new KayasWrath(this); + } +} + +class KayasWrathEffect extends OneShotEffect { + + KayasWrathEffect() { + super(Outcome.Benefit); + staticText = "Destroy all creatures. You gain life equal to the number of " + + "creatures you controlled that were destroyed this way."; + } + + private KayasWrathEffect(final KayasWrathEffect effect) { + super(effect); + } + + @Override + public KayasWrathEffect copy() { + return new KayasWrathEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int counter = 0; + for (Permanent permanent : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURE, + source.getControllerId(), source.getSourceId(), game + )) { + boolean isMine = permanent != null && permanent.isControlledBy(source.getControllerId()); + if (permanent.destroy(source.getSourceId(), game, false) && isMine) { + counter++; + } + } + return new GainLifeEffect(counter).apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/k/KederektLeviathan.java b/Mage.Sets/src/mage/cards/k/KederektLeviathan.java index cf0e32d9b95..b394b26e44a 100644 --- a/Mage.Sets/src/mage/cards/k/KederektLeviathan.java +++ b/Mage.Sets/src/mage/cards/k/KederektLeviathan.java @@ -22,7 +22,7 @@ public final class KederektLeviathan extends CardImpl { private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("all other nonland permanents"); static{ - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public KederektLeviathan(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java index bffa37ce840..87ec804db36 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheLens.java @@ -53,7 +53,7 @@ class KeeperOfTheLensLookFaceDownAbility extends ActivatedAbilityImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature you don't control"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); filter.add(new ControllerPredicate(TargetController.NOT_YOU)); } diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java index 087fe044f66..eda3e048b1e 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java @@ -27,7 +27,6 @@ */ package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -35,32 +34,25 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.FilterOpponent; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; -import mage.target.common.TargetOpponent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public class KeeperOfTheMind extends CardImpl { - public final UUID originalId; - private static final FilterOpponent filter = new FilterOpponent(); - - static { - filter.add(new KeeperOfTheMindPredicate()); - } - - public KeeperOfTheMind(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{U}"); @@ -74,28 +66,12 @@ public class KeeperOfTheMind extends CardImpl { effect.setText("Choose target opponent who had at least two more cards in hand than you did as you activated this ability. Draw a card."); Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl("{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetOpponent()); + ability.setTargetAdjuster(KeeperOfTheMindAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - ability.getTargets().clear(); - TargetPlayer target = new TargetPlayer(1, 1, false, filter); - target.setTargetController(activePlayer.getId()); - ability.getTargets().add(target); - } - } } public KeeperOfTheMind(final KeeperOfTheMind card) { super(card); - this.originalId = card.originalId; } @Override @@ -104,6 +80,28 @@ public class KeeperOfTheMind extends CardImpl { } } +enum KeeperOfTheMindAdjuster implements TargetAdjuster { + instance; + + private static final FilterOpponent filter = new FilterOpponent(); + + static { + filter.add(new KeeperOfTheMindPredicate()); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer == null) { + return; + } + ability.getTargets().clear(); + TargetPlayer target = new TargetPlayer(1, 1, false, filter); + target.setTargetController(activePlayer.getId()); + ability.addTarget(target); + } +} + class KeeperOfTheMindPredicate implements ObjectSourcePlayerPredicate> { @Override diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheNineGales.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheNineGales.java index 6fd6128be87..9ced360768d 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheNineGales.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheNineGales.java @@ -30,7 +30,7 @@ public final class KeeperOfTheNineGales extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Birds you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.BIRD)); } diff --git a/Mage.Sets/src/mage/cards/k/KeldonBattlewagon.java b/Mage.Sets/src/mage/cards/k/KeldonBattlewagon.java index 65455f5a3f4..091a1b32927 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonBattlewagon.java +++ b/Mage.Sets/src/mage/cards/k/KeldonBattlewagon.java @@ -40,7 +40,7 @@ public final class KeldonBattlewagon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public KeldonBattlewagon(UUID ownerId, CardSetInfo setInfo) { @@ -90,7 +90,7 @@ class KeldonBattlewagonCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { - for (UUID targetId: (List)target.getTargets()) { + for (UUID targetId: target.getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent == null) return false; diff --git a/Mage.Sets/src/mage/cards/k/KeldonBerserker.java b/Mage.Sets/src/mage/cards/k/KeldonBerserker.java index f2cf9c195ce..62b80407f09 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonBerserker.java +++ b/Mage.Sets/src/mage/cards/k/KeldonBerserker.java @@ -26,7 +26,7 @@ public final class KeldonBerserker extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("untapped lands"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public KeldonBerserker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KeldonTwilight.java b/Mage.Sets/src/mage/cards/k/KeldonTwilight.java index 2931cd68459..e5a6468735b 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonTwilight.java +++ b/Mage.Sets/src/mage/cards/k/KeldonTwilight.java @@ -54,7 +54,7 @@ class KeldonTwilightCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null) { return watcher.getAttackedThisTurnCreatures().isEmpty(); } diff --git a/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java b/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java index 3590d941232..fbcec941d28 100644 --- a/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java +++ b/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java @@ -94,7 +94,7 @@ class KeranosGodOfStormsTriggeredAbility extends TriggeredAbilityImpl { if (event.getPlayerId().equals(this.getControllerId())) { if (game.isActivePlayer(this.getControllerId())) { CardsAmountDrawnThisTurnWatcher watcher = - (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.class.getSimpleName()); + game.getState().getWatcher(CardsAmountDrawnThisTurnWatcher.class); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) != 1) { return false; } diff --git a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java index bc3cc94473f..f8c4011548a 100644 --- a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java +++ b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java @@ -1,14 +1,15 @@ - package mage.cards.k; -import java.util.Optional; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.UUID; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.FlyingAbility; @@ -18,22 +19,16 @@ import mage.cards.CardSetInfo; import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Layer; import mage.constants.Outcome; -import mage.constants.SubLayer; import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.WatcherScope; import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.stack.Spell; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; /** @@ -55,7 +50,9 @@ public final class KessDissidentMage extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // During each of your turns, you may cast an instant or sorcery card from your graveyard. If a card cast this way would be put into your graveyard this turn, exile it instead. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KessDissidentMageContinuousEffect()), new KessDissidentMageWatcher()); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new KessDissidentMageCastFromGraveyardEffect()); + ability.addEffect(new KessDissidentMageReplacementEffect()); + this.addAbility(ability, new KessDissidentMageWatcher()); } public KessDissidentMage(final KessDissidentMage card) { @@ -68,56 +65,11 @@ public final class KessDissidentMage extends CardImpl { } } -class KessDissidentMageContinuousEffect extends ContinuousEffectImpl { - - private static final FilterCard filter = new FilterCard("Instant or sorcery spell"); - - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY) - )); - } - - KessDissidentMageContinuousEffect() { - super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); - staticText = "During each of your turns, you may cast an instant or sorcery card from your graveyard. If a card cast this way would be put into your graveyard, exile it instead"; - } - - KessDissidentMageContinuousEffect(final KessDissidentMageContinuousEffect effect) { - super(effect); - } - - @Override - public KessDissidentMageContinuousEffect copy() { - return new KessDissidentMageContinuousEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - if (!game.isActivePlayer(player.getId())) { - return false; - } - for (Card card : player.getGraveyard().getCards(filter, game)) { - ContinuousEffect effect = new KessDissidentMageCastFromGraveyardEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, source); - effect = new KessDissidentMageReplacementEffect(card.getId()); - game.addEffect(effect, source); - } - return true; - } - return false; - } -} - class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl { KessDissidentMageCastFromGraveyardEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may cast an instant or sorcery card from your graveyard"; + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "During each of your turns, you may cast an instant or sorcery card from your graveyard"; } KessDissidentMageCastFromGraveyardEffect(final KessDissidentMageCastFromGraveyardEffect effect) { @@ -136,14 +88,13 @@ class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectId.equals(getTargetPointer().getFirst(game, source))) { - if (affectedControllerId.equals(source.getControllerId())) { - if (game.isActivePlayer(source.getControllerId())) { - KessDissidentMageWatcher watcher = (KessDissidentMageWatcher) game.getState().getWatchers().get(KessDissidentMageWatcher.class.getSimpleName(), source.getSourceId()); - if (!(source instanceof FlashbackAbility)) { - return !watcher.isAbilityUsed(); - } - } + if (!(source instanceof FlashbackAbility) && affectedControllerId.equals(source.getControllerId()) && game.isActivePlayer(source.getControllerId())) { + Card card = game.getCard(objectId); + if (card != null && (card.isInstant() || card.isSorcery()) + && game.getState().getZone(objectId).equals(Zone.GRAVEYARD)) { + // check if not already a card was cast this turn with this ability + KessDissidentMageWatcher watcher = game.getState().getWatcher(KessDissidentMageWatcher.class); + return watcher != null && !watcher.isAbilityUsed(new MageObjectReference(source.getSourceId(), game)); } } return false; @@ -152,17 +103,13 @@ class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl { class KessDissidentMageReplacementEffect extends ReplacementEffectImpl { - private final UUID cardId; - - KessDissidentMageReplacementEffect(UUID cardId) { - super(Duration.EndOfTurn, Outcome.Exile); - this.cardId = cardId; + KessDissidentMageReplacementEffect() { + super(Duration.EndOfGame, Outcome.Exile); staticText = "If a card cast this way would be put into your graveyard, exile it instead"; } KessDissidentMageReplacementEffect(final KessDissidentMageReplacementEffect effect) { super(effect); - this.cardId = effect.cardId; } @Override @@ -173,9 +120,9 @@ class KessDissidentMageReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); - Card card = game.getCard(this.cardId); + Card card = game.getCard(event.getTargetId()); if (controller != null && card != null) { - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.STACK, true); + controller.moveCards(card, Zone.EXILED, source, game); return true; } return false; @@ -189,31 +136,39 @@ class KessDissidentMageReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - return zEvent.getToZone() == Zone.GRAVEYARD - && zEvent.getTargetId().equals(this.cardId); + if (zEvent.getToZone() == Zone.GRAVEYARD) { + KessDissidentMageWatcher watcher = game.getState().getWatcher(KessDissidentMageWatcher.class); + if (watcher != null && source.getSourceId().equals(watcher.spellCastWasAllowedBy(new MageObjectReference(event.getTargetId(), game)))) { + return true; + } + } + return false; } } class KessDissidentMageWatcher extends Watcher { - boolean abilityUsed = false; + // Which kess object did cast which spell from graveyard + private final Set allowingObjects = new HashSet<>(); + private final Map castSpells = new HashMap<>(); KessDissidentMageWatcher() { - super(KessDissidentMageWatcher.class.getSimpleName(), WatcherScope.CARD); + super(KessDissidentMageWatcher.class, WatcherScope.GAME); } KessDissidentMageWatcher(final KessDissidentMageWatcher watcher) { super(watcher); - this.abilityUsed = watcher.abilityUsed; + this.allowingObjects.addAll(watcher.allowingObjects); + this.castSpells.putAll(watcher.castSpells); } @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.GRAVEYARD) { Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell.isInstant() || spell.isSorcery()) { - Optional source = game.getAbility(event.getSourceId(), event.getSourceId()); - abilityUsed = true; + if (null != event.getAdditionalReference() && spell.isInstant() || spell.isSorcery()) { + allowingObjects.add(event.getAdditionalReference()); + castSpells.put(new MageObjectReference(spell.getSourceId(), game), event.getAdditionalReference().getSourceId()); } } } @@ -226,10 +181,15 @@ class KessDissidentMageWatcher extends Watcher { @Override public void reset() { super.reset(); - abilityUsed = false; + allowingObjects.clear(); } - public boolean isAbilityUsed() { - return abilityUsed; + public boolean isAbilityUsed(MageObjectReference mor) { + return allowingObjects.contains(mor); } + + public UUID spellCastWasAllowedBy(MageObjectReference mor) { + return castSpells.getOrDefault(mor, null); + } + } diff --git a/Mage.Sets/src/mage/cards/k/KessigWolfRun.java b/Mage.Sets/src/mage/cards/k/KessigWolfRun.java index 87a7e9e7ddb..3dfb9a59d9f 100644 --- a/Mage.Sets/src/mage/cards/k/KessigWolfRun.java +++ b/Mage.Sets/src/mage/cards/k/KessigWolfRun.java @@ -33,7 +33,7 @@ public final class KessigWolfRun extends CardImpl { // {X}{R}{G}, {T}: Target creature gets +X/+0 and gains trample until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{X}{R}{G}")); ability.addCost(new TapSourceCost()); - ability.addEffect(new BoostTargetEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); + ability.addEffect(new BoostTargetEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java b/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java index 18f4dfcdc3b..ab0b2b932a4 100644 --- a/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java +++ b/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java @@ -33,7 +33,7 @@ public final class KestiaTheCultivator extends CardImpl { static { filter.add(Predicates.or( - new EnchantedPredicate(), + EnchantedPredicate.instance, new CardTypePredicate(CardType.ENCHANTMENT) )); filter.add(new ControllerPredicate(TargetController.YOU)); diff --git a/Mage.Sets/src/mage/cards/k/KhabalGhoul.java b/Mage.Sets/src/mage/cards/k/KhabalGhoul.java index 28fc3288234..06a0fe4e253 100644 --- a/Mage.Sets/src/mage/cards/k/KhabalGhoul.java +++ b/Mage.Sets/src/mage/cards/k/KhabalGhoul.java @@ -28,7 +28,7 @@ public final class KhabalGhoul extends CardImpl { // At the beginning of each end step, put a +1/+1 counter on Khabal Ghoul for each creature that died this turn. this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(), - new CreaturesDiedThisTurnCount(), true), TargetController.ANY, false), new CreaturesDiedWatcher()); + CreaturesDiedThisTurnCount.instance, true), TargetController.ANY, false), new CreaturesDiedWatcher()); } public KhabalGhoul(final KhabalGhoul card) { diff --git a/Mage.Sets/src/mage/cards/k/KheruDreadmaw.java b/Mage.Sets/src/mage/cards/k/KheruDreadmaw.java index 270eaeacf41..2c5328e31ac 100644 --- a/Mage.Sets/src/mage/cards/k/KheruDreadmaw.java +++ b/Mage.Sets/src/mage/cards/k/KheruDreadmaw.java @@ -37,7 +37,7 @@ public final class KheruDreadmaw extends CardImpl { this.addAbility(DefenderAbility.getInstance()); // {1}{G}, Sacrifice another creature: You gain life equal to the sacrificed creature's toughness. - Effect effect = new GainLifeEffect(new SacrificeCostCreaturesToughness()); + Effect effect = new GainLifeEffect(SacrificeCostCreaturesToughness.instance); effect.setText("You gain life equal to the sacrificed creature's toughness"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{1}{G}")); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE))); diff --git a/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java b/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java index 853f920dd6c..075f42fd6ba 100644 --- a/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java +++ b/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java @@ -78,7 +78,7 @@ class KheruSpellsnatcherEffect extends OneShotEffect { StackObject stackObject = game.getStack().getStackObject(objectId); if (stackObject != null && game.getStack().counter(targetPointer.getFirst(game, source), source.getSourceId(), game, Zone.EXILED, false, ZoneDetail.NONE)) { - if (!((Spell) stackObject).isCopy()) { + if (!stackObject.isCopy()) { MageObject card = game.getObject(stackObject.getSourceId()); if (card instanceof Card) { ((Card) card).moveToZone(Zone.EXILED, sourceId, game, true); diff --git a/Mage.Sets/src/mage/cards/k/KiAdiMundi.java b/Mage.Sets/src/mage/cards/k/KiAdiMundi.java index 6640a431129..63d42793a71 100644 --- a/Mage.Sets/src/mage/cards/k/KiAdiMundi.java +++ b/Mage.Sets/src/mage/cards/k/KiAdiMundi.java @@ -27,7 +27,7 @@ public final class KiAdiMundi extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/k/KillSwitch.java b/Mage.Sets/src/mage/cards/k/KillSwitch.java index 928d3f91e74..7c3d8248b81 100644 --- a/Mage.Sets/src/mage/cards/k/KillSwitch.java +++ b/Mage.Sets/src/mage/cards/k/KillSwitch.java @@ -29,7 +29,7 @@ public final class KillSwitch extends CardImpl { //static { - // filter.add(new AnotherPredicate()); + // filter.add(AnotherPredicate.instance); // } public KillSwitch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KillingGlare.java b/Mage.Sets/src/mage/cards/k/KillingGlare.java index 5382bf5557c..16704117adb 100644 --- a/Mage.Sets/src/mage/cards/k/KillingGlare.java +++ b/Mage.Sets/src/mage/cards/k/KillingGlare.java @@ -1,9 +1,7 @@ package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,21 +11,21 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class KillingGlare extends CardImpl { - public KillingGlare (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{B}"); - + public KillingGlare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}"); // Destroy target creature with power X or less. - this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with power X or less"))); - + this.getSpellAbility().addEffect(new DestroyTargetEffect("destroy target creature with power X or less")); + this.getSpellAbility().setTargetAdjuster(KillingGlareAdjuster.instance); } public KillingGlare(final KillingGlare card) { @@ -35,19 +33,20 @@ public final class KillingGlare extends CardImpl { } @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power " + xValue + " or less"); - filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1)); - ability.addTarget(new TargetCreaturePermanent(filter)); - } - } - - - @Override - public KillingGlare copy() { + public KillingGlare copy() { return new KillingGlare(this); } } + +enum KillingGlareAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + ability.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power " + xValue + " or less"); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/k/KillingWave.java b/Mage.Sets/src/mage/cards/k/KillingWave.java index 9027d41357a..0f146aac56d 100644 --- a/Mage.Sets/src/mage/cards/k/KillingWave.java +++ b/Mage.Sets/src/mage/cards/k/KillingWave.java @@ -61,7 +61,7 @@ class KillingWaveEffect extends OneShotEffect { return false; } - int amount = (new ManacostVariableValue()).calculate(game, source, this); + int amount = (ManacostVariableValue.instance).calculate(game, source, this); if (amount > 0) { List sacrifices = new LinkedList<>(); Map lifePaidAmounts = new HashMap<>(); diff --git a/Mage.Sets/src/mage/cards/k/KingsAssassin.java b/Mage.Sets/src/mage/cards/k/KingsAssassin.java index 7651353f168..52dff0cd15c 100644 --- a/Mage.Sets/src/mage/cards/k/KingsAssassin.java +++ b/Mage.Sets/src/mage/cards/k/KingsAssassin.java @@ -26,7 +26,7 @@ public final class KingsAssassin extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public KingsAssassin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KiorasFollower.java b/Mage.Sets/src/mage/cards/k/KiorasFollower.java index 05417a3b96b..d6a0b2eb138 100644 --- a/Mage.Sets/src/mage/cards/k/KiorasFollower.java +++ b/Mage.Sets/src/mage/cards/k/KiorasFollower.java @@ -25,7 +25,7 @@ public final class KiorasFollower extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public KiorasFollower(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{U}"); diff --git a/Mage.Sets/src/mage/cards/k/KiraGreatGlassSpinner.java b/Mage.Sets/src/mage/cards/k/KiraGreatGlassSpinner.java index 97a195a7a91..246e39bfe4b 100644 --- a/Mage.Sets/src/mage/cards/k/KiraGreatGlassSpinner.java +++ b/Mage.Sets/src/mage/cards/k/KiraGreatGlassSpinner.java @@ -82,7 +82,7 @@ class KiraGreatGlassSpinnerAbility extends TriggeredAbilityImpl { if (event.getTargetId().equals(this.getSourceId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature()) { - NumberOfTimesPermanentTargetedATurnWatcher watcher = (NumberOfTimesPermanentTargetedATurnWatcher) game.getState().getWatchers().get(NumberOfTimesPermanentTargetedATurnWatcher.class.getSimpleName()); + NumberOfTimesPermanentTargetedATurnWatcher watcher = game.getState().getWatcher(NumberOfTimesPermanentTargetedATurnWatcher.class); if (watcher != null && watcher.notMoreThanOnceTargetedThisTurn(permanent, game)) { for (Effect effect : getEffects()) { effect.setTargetPointer(new FixedTarget(event.getSourceId())); diff --git a/Mage.Sets/src/mage/cards/k/KitsuneLoreweaver.java b/Mage.Sets/src/mage/cards/k/KitsuneLoreweaver.java index 8724a8582e7..0b71aea401f 100644 --- a/Mage.Sets/src/mage/cards/k/KitsuneLoreweaver.java +++ b/Mage.Sets/src/mage/cards/k/KitsuneLoreweaver.java @@ -30,7 +30,7 @@ public final class KitsuneLoreweaver extends CardImpl { this.toughness = new MageInt(1); // {1}{W}: Kitsune Loreweaver gets +0/+X until end of turn, where X is the number of cards in your hand. - Effect effect = new BoostSourceEffect(new StaticValue(0), new CardsInControllerHandCount(), Duration.EndOfTurn, true); + Effect effect = new BoostSourceEffect(new StaticValue(0), CardsInControllerHandCount.instance, Duration.EndOfTurn, true); effect.setText("{this} gets +0/+X until end of turn, where X is the number of cards in your hand"); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{W}"))); } diff --git a/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java b/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java index f352b996234..0349e3bd190 100644 --- a/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java +++ b/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java @@ -43,7 +43,7 @@ public final class KiyomaroFirstToStand extends CardImpl { this.toughness = new MageInt(0); // Kiyomaro, First to Stand's power and toughness are each equal to the number of cards in your hand. - DynamicValue xValue= new CardsInControllerHandCount(); + DynamicValue xValue= CardsInControllerHandCount.instance; this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame))); // As long as you have four or more cards in hand, Kiyomaro has vigilance. diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranRoyalGuard.java b/Mage.Sets/src/mage/cards/k/KjeldoranRoyalGuard.java index fc7d7bbaa5f..36c340c81c9 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranRoyalGuard.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranRoyalGuard.java @@ -55,7 +55,7 @@ class KjeldoranRoyalGuardEffect extends ReplacementEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked creatures"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } KjeldoranRoyalGuardEffect() { diff --git a/Mage.Sets/src/mage/cards/k/KnightExemplar.java b/Mage.Sets/src/mage/cards/k/KnightExemplar.java index 17b9e9f765e..9c069322b69 100644 --- a/Mage.Sets/src/mage/cards/k/KnightExemplar.java +++ b/Mage.Sets/src/mage/cards/k/KnightExemplar.java @@ -43,7 +43,7 @@ public final class KnightExemplar extends CardImpl { // Other Knight creatures you control get +1/+1 and are indestructible. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); FilterCreaturePermanent indestructibleFilter = filter.copy(); - indestructibleFilter.add(new AnotherPredicate()); + indestructibleFilter.add(AnotherPredicate.instance); indestructibleFilter.add(new ControllerPredicate(TargetController.YOU)); indestructibleFilter.setMessage("Other Knight creatures you control"); Effect effect = new GainAbilityAllEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield, indestructibleFilter, false); diff --git a/Mage.Sets/src/mage/cards/k/KnightOfNewAlara.java b/Mage.Sets/src/mage/cards/k/KnightOfNewAlara.java index 85348bfd94f..09567e76204 100644 --- a/Mage.Sets/src/mage/cards/k/KnightOfNewAlara.java +++ b/Mage.Sets/src/mage/cards/k/KnightOfNewAlara.java @@ -55,7 +55,7 @@ class KnightOfNewAlaraEffect extends ContinuousEffectImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public KnightOfNewAlaraEffect() { diff --git a/Mage.Sets/src/mage/cards/k/KnightOfSorrows.java b/Mage.Sets/src/mage/cards/k/KnightOfSorrows.java new file mode 100644 index 00000000000..7bf0cabd447 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KnightOfSorrows.java @@ -0,0 +1,42 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureEffect; +import mage.abilities.keyword.AfterlifeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KnightOfSorrows extends CardImpl { + + public KnightOfSorrows(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Knight of Sorrows can block an additional creature each combat. + this.addAbility(new SimpleStaticAbility(new CanBlockAdditionalCreatureEffect())); + + // Afterlife 1 + this.addAbility(new AfterlifeAbility(1)); + } + + private KnightOfSorrows(final KnightOfSorrows card) { + super(card); + } + + @Override + public KnightOfSorrows copy() { + return new KnightOfSorrows(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KnightOfTheLastBreath.java b/Mage.Sets/src/mage/cards/k/KnightOfTheLastBreath.java new file mode 100644 index 00000000000..5ac5c3ea80d --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KnightOfTheLastBreath.java @@ -0,0 +1,64 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.AfterlifeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.WhiteBlackSpiritToken; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KnightOfTheLastBreath extends CardImpl { + + private static final FilterControlledPermanent filter + = new FilterControlledCreaturePermanent("another nontoken creature"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); + } + + public KnightOfTheLastBreath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}{B}"); + + this.subtype.add(SubType.GIANT); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // {3}, Sacrifice another nontoken creature: Create a 1/1 white and black spirit creature token with flying. + Ability ability = new SimpleActivatedAbility( + new CreateTokenEffect(new WhiteBlackSpiritToken()), new GenericManaCost(3) + ); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + this.addAbility(ability); + + // Afterlife 3 + this.addAbility(new AfterlifeAbility(3)); + } + + private KnightOfTheLastBreath(final KnightOfTheLastBreath card) { + super(card); + } + + @Override + public KnightOfTheLastBreath copy() { + return new KnightOfTheLastBreath(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java b/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java index 482ed9506d0..289dd51febd 100644 --- a/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java +++ b/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java @@ -85,7 +85,7 @@ class BecomesMonarchTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkInterveningIfClause(Game game) { - MonarchAtTurnStartWatcher watcher = (MonarchAtTurnStartWatcher) game.getState().getWatchers().get(MonarchAtTurnStartWatcher.class.getSimpleName()); + MonarchAtTurnStartWatcher watcher = game.getState().getWatcher(MonarchAtTurnStartWatcher.class); return watcher != null && isControlledBy(watcher.getMonarchIdAtTurnStart()); } @@ -105,7 +105,7 @@ class MonarchAtTurnStartWatcher extends Watcher { private UUID monarchIdAtTurnStart; public MonarchAtTurnStartWatcher() { - super(MonarchAtTurnStartWatcher.class.getSimpleName(), WatcherScope.GAME); + super(MonarchAtTurnStartWatcher.class, WatcherScope.GAME); } public MonarchAtTurnStartWatcher(final MonarchAtTurnStartWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/k/KnollspineDragon.java b/Mage.Sets/src/mage/cards/k/KnollspineDragon.java index b1a35e8e063..10124eefd8d 100644 --- a/Mage.Sets/src/mage/cards/k/KnollspineDragon.java +++ b/Mage.Sets/src/mage/cards/k/KnollspineDragon.java @@ -68,7 +68,7 @@ class KnollspineDragonEffect extends OneShotEffect { if (controller != null) { new DiscardHandControllerEffect().apply(game, source); if (targetOpponent != null) { - AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = (AmountOfDamageAPlayerReceivedThisTurnWatcher) game.getState().getWatchers().get(AmountOfDamageAPlayerReceivedThisTurnWatcher.class.getSimpleName()); + AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = game.getState().getWatcher(AmountOfDamageAPlayerReceivedThisTurnWatcher.class); if (watcher != null) { int drawAmount = watcher.getAmountOfDamageReceivedThisTurn(targetOpponent.getId()); controller.drawCards(drawAmount, game); diff --git a/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java b/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java index 7da7179e698..8b2a45c4c39 100644 --- a/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java +++ b/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java @@ -32,7 +32,7 @@ public final class KnollspineInvocation extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}{R}"); // {X}, Discard a card with converted mana cost X: Knollspine Invocation deals X damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue(), true), new ManaCostsImpl<>("{X}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance, true), new ManaCostsImpl<>("{X}")); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KnotvinePaladin.java b/Mage.Sets/src/mage/cards/k/KnotvinePaladin.java index 7ec1c739e3e..29736510509 100644 --- a/Mage.Sets/src/mage/cards/k/KnotvinePaladin.java +++ b/Mage.Sets/src/mage/cards/k/KnotvinePaladin.java @@ -23,7 +23,7 @@ public final class KnotvinePaladin extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } diff --git a/Mage.Sets/src/mage/cards/k/KorozdaGuildmage.java b/Mage.Sets/src/mage/cards/k/KorozdaGuildmage.java index 4959961c930..872488a84d0 100644 --- a/Mage.Sets/src/mage/cards/k/KorozdaGuildmage.java +++ b/Mage.Sets/src/mage/cards/k/KorozdaGuildmage.java @@ -34,7 +34,7 @@ public final class KorozdaGuildmage extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public KorozdaGuildmage(UUID ownerId, CardSetInfo setInfo) { @@ -53,7 +53,7 @@ public final class KorozdaGuildmage extends CardImpl { this.addAbility(ability); // {2}{B}{G}, Sacrifice a nontoken creature: create X 1/1 green Saproling creature tokens, where X is the sacrificed creature's toughness. - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken(),new SacrificeCostCreaturesToughness()),new ManaCostsImpl("{2}{B}{G}")); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken(),SacrificeCostCreaturesToughness.instance),new ManaCostsImpl("{2}{B}{G}")); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1,filter, true))); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KoskunFalls.java b/Mage.Sets/src/mage/cards/k/KoskunFalls.java index 70d378577a5..d285532a0f1 100644 --- a/Mage.Sets/src/mage/cards/k/KoskunFalls.java +++ b/Mage.Sets/src/mage/cards/k/KoskunFalls.java @@ -29,7 +29,7 @@ public final class KoskunFalls extends CardImpl { private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filterCreature.add(Predicates.not(new TappedPredicate())); + filterCreature.add(Predicates.not(TappedPredicate.instance)); } public KoskunFalls(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KozileksSentinel.java b/Mage.Sets/src/mage/cards/k/KozileksSentinel.java index 4cbaef9e8f5..9399ec74d29 100644 --- a/Mage.Sets/src/mage/cards/k/KozileksSentinel.java +++ b/Mage.Sets/src/mage/cards/k/KozileksSentinel.java @@ -23,7 +23,7 @@ public final class KozileksSentinel extends CardImpl { private static final FilterSpell filterSpell = new FilterSpell("a colorless spell"); static { - filterSpell.add(new ColorlessPredicate()); + filterSpell.add(ColorlessPredicate.instance); } public KozileksSentinel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KrarksThumb.java b/Mage.Sets/src/mage/cards/k/KrarksThumb.java index 3acb3bde5aa..d5698826939 100644 --- a/Mage.Sets/src/mage/cards/k/KrarksThumb.java +++ b/Mage.Sets/src/mage/cards/k/KrarksThumb.java @@ -1,7 +1,6 @@ package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; @@ -9,25 +8,28 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; +import mage.game.events.FlipCoinEvent; import mage.game.events.GameEvent; import mage.players.Player; +import mage.util.CardUtil; import mage.util.RandomUtil; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KrarksThumb extends CardImpl { public KrarksThumb(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); addSuperType(SuperType.LEGENDARY); // If you would flip a coin, instead flip two coins and ignore one. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KrarksThumbEffect())); } - public KrarksThumb(final KrarksThumb card) { + private KrarksThumb(final KrarksThumb card) { super(card); } @@ -44,26 +46,30 @@ class KrarksThumbEffect extends ReplacementEffectImpl { staticText = "If you would flip a coin, instead flip two coins and ignore one"; } - KrarksThumbEffect(final KrarksThumbEffect effect) { + private KrarksThumbEffect(final KrarksThumbEffect effect) { super(effect); } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); - if (player != null) { - // because second flip is ignored it may not be done by the player method - boolean secondCoinFlip = RandomUtil.nextBoolean(); - if (!game.isSimulation()) { - game.informPlayers("[Flip a coin] " + player.getLogName() + (secondCoinFlip ? " won (head)." : " lost (tail).")); - } - if (player.chooseUse(outcome, "Ignore the first coin flip?", source, game)) { - event.setFlag(secondCoinFlip); - game.informPlayers(player.getLogName() + " ignores the first coin flip."); - } else { - game.informPlayers(player.getLogName() + " ignores the second coin flip."); - } + if (player == null || !player.getId().equals(source.getControllerId())) { + return false; } + FlipCoinEvent flipEvent = (FlipCoinEvent) event; + boolean secondFlip = RandomUtil.nextBoolean(); + game.informPlayers(player.getLogName() + " flipped a " + flipEvent.getResultName() + + " and a " + CardUtil.booleanToFlipName(secondFlip) + ); + boolean chosenFlip = player.chooseUse( + Outcome.Benefit, "Choose which coin you want", + (flipEvent.isWinnable() ? "(You chose " + flipEvent.getChosenName() + ")" : null), + flipEvent.getResultName(), CardUtil.booleanToFlipName(secondFlip), source, game + ); + if (!chosenFlip) { + flipEvent.setResult(secondFlip); + } + game.informPlayers(player.getLogName() + " chooses to keep " + flipEvent.getResultName()); return false; } diff --git a/Mage.Sets/src/mage/cards/k/KraumLudevicsOpus.java b/Mage.Sets/src/mage/cards/k/KraumLudevicsOpus.java index bf8957318a5..c02cf364faf 100644 --- a/Mage.Sets/src/mage/cards/k/KraumLudevicsOpus.java +++ b/Mage.Sets/src/mage/cards/k/KraumLudevicsOpus.java @@ -80,7 +80,7 @@ class KraumLudevicsOpusTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(controllerId).contains(event.getPlayerId())) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) { return true; } diff --git a/Mage.Sets/src/mage/cards/k/KravTheUnredeemed.java b/Mage.Sets/src/mage/cards/k/KravTheUnredeemed.java index 8a08d9630de..136033ed407 100644 --- a/Mage.Sets/src/mage/cards/k/KravTheUnredeemed.java +++ b/Mage.Sets/src/mage/cards/k/KravTheUnredeemed.java @@ -76,7 +76,7 @@ class KravTheUnredeemedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int xValue = new GetXValue().calculate(game, source, this); + int xValue = GetXValue.instance.calculate(game, source, this); new DrawCardTargetEffect(xValue).apply(game, source); new GainLifeTargetEffect(xValue).apply(game, source); new AddCountersSourceEffect(CounterType.P1P1.createInstance(xValue)).apply(game, source); diff --git a/Mage.Sets/src/mage/cards/k/KrovikanPlague.java b/Mage.Sets/src/mage/cards/k/KrovikanPlague.java index 8bc9f49f3d2..835ac9ee080 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanPlague.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanPlague.java @@ -46,7 +46,7 @@ public final class KrovikanPlague extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("enchanted creature is untapped"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public KrovikanPlague(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KrovikanVampire.java b/Mage.Sets/src/mage/cards/k/KrovikanVampire.java index c260081ba44..9918b146382 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanVampire.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanVampire.java @@ -112,26 +112,24 @@ enum KrovikanVampireInterveningIfCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - KrovikanVampireCreaturesDiedWatcher watcherDied = (KrovikanVampireCreaturesDiedWatcher) game.getState().getWatchers().get(KrovikanVampireCreaturesDiedWatcher.class.getSimpleName()); - KrovikanVampireCreaturesDamagedWatcher watcherDamaged = (KrovikanVampireCreaturesDamagedWatcher) game.getState().getWatchers().get(KrovikanVampireCreaturesDamagedWatcher.class.getSimpleName()); + KrovikanVampireCreaturesDiedWatcher watcherDied = game.getState().getWatcher(KrovikanVampireCreaturesDiedWatcher.class); + KrovikanVampireCreaturesDamagedWatcher watcherDamaged = game.getState().getWatcher(KrovikanVampireCreaturesDamagedWatcher.class); if (watcherDied != null) { Set creaturesThatDiedThisTurn = watcherDied.diedThisTurn; - if (creaturesThatDiedThisTurn != null) { - for (UUID mor : creaturesThatDiedThisTurn) { - if (watcherDamaged != null) { - for (UUID mor2 : watcherDamaged.getDamagedBySource()) { - if (mor2 != null - && mor == mor2) { - creaturesAffected.add(mor); - } + for (UUID mor : creaturesThatDiedThisTurn) { + if (watcherDamaged != null) { + for (UUID mor2 : watcherDamaged.getDamagedBySource()) { + if (mor2 != null + && mor == mor2) { + creaturesAffected.add(mor); } } } - if (creaturesAffected != null - && creaturesAffected.size() > 0) { - game.getState().setValue(source.getSourceId() + "creatureToGainControl", creaturesAffected); - return true; - } + } + if (creaturesAffected != null + && creaturesAffected.size() > 0) { + game.getState().setValue(source.getSourceId() + "creatureToGainControl", creaturesAffected); + return true; } } return false; @@ -148,7 +146,7 @@ class KrovikanVampireCreaturesDamagedWatcher extends Watcher { public final Set damagedBySource = new HashSet<>(); public KrovikanVampireCreaturesDamagedWatcher() { - super(KrovikanVampireCreaturesDamagedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(KrovikanVampireCreaturesDamagedWatcher.class, WatcherScope.GAME); } public KrovikanVampireCreaturesDamagedWatcher(final KrovikanVampireCreaturesDamagedWatcher watcher) { @@ -184,7 +182,7 @@ class KrovikanVampireCreaturesDiedWatcher extends Watcher { public final Set diedThisTurn = new HashSet<>(); public KrovikanVampireCreaturesDiedWatcher() { - super(KrovikanVampireCreaturesDiedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(KrovikanVampireCreaturesDiedWatcher.class, WatcherScope.GAME); } public KrovikanVampireCreaturesDiedWatcher(final KrovikanVampireCreaturesDiedWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/k/KryShield.java b/Mage.Sets/src/mage/cards/k/KryShield.java index 8fc55fc5dc4..eb321f215e2 100644 --- a/Mage.Sets/src/mage/cards/k/KryShield.java +++ b/Mage.Sets/src/mage/cards/k/KryShield.java @@ -31,7 +31,7 @@ public final class KryShield extends CardImpl { Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn); effect.setText("Prevent all damage that would be dealt this turn by target creature you control"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2)); - ability.addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true) + ability.addEffect(new BoostTargetEffect(new StaticValue(0), TargetConvertedManaCost.instance, Duration.EndOfTurn, true) .setText("That creature gets +0/+X until end of turn, where X is its converted mana cost")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/k/Kudzu.java b/Mage.Sets/src/mage/cards/k/Kudzu.java index 37e3b35540d..0c8f9cb857a 100644 --- a/Mage.Sets/src/mage/cards/k/Kudzu.java +++ b/Mage.Sets/src/mage/cards/k/Kudzu.java @@ -1,7 +1,5 @@ - package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -21,8 +19,9 @@ import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class Kudzu extends CardImpl { @@ -73,7 +72,6 @@ class KudzuEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent kudzu = game.getPermanentOrLKIBattlefield(source.getSourceId()); - Card kudzuCard = game.getCard(source.getSourceId()); if (kudzu != null) { Permanent enchantedLand = game.getPermanentOrLKIBattlefield(kudzu.getAttachedTo()); Player controller = game.getPlayer(source.getControllerId()); @@ -86,8 +84,8 @@ class KudzuEffect extends OneShotEffect { if (!game.getBattlefield().getAllActivePermanents(CardType.LAND).isEmpty()) { //lands are available on the battlefield Target target = new TargetLandPermanent(); target.setNotTarget(true); //not a target, it is chosen - if (kudzuCard != null - && landsController != null) { + Card kudzuCard = game.getCard(source.getSourceId()); + if (kudzuCard != null && landsController != null) { if (landsController.choose(Outcome.Detriment, target, source.getId(), game)) { if (target.getFirstTarget() != null) { Permanent landChosen = game.getPermanent(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/k/KukemssaPirates.java b/Mage.Sets/src/mage/cards/k/KukemssaPirates.java index 5464da339d4..3371ea8a14c 100644 --- a/Mage.Sets/src/mage/cards/k/KukemssaPirates.java +++ b/Mage.Sets/src/mage/cards/k/KukemssaPirates.java @@ -1,29 +1,32 @@ package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.common.FilterArtifactPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; import mage.target.common.TargetArtifactPermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class KukemssaPirates extends CardImpl { - private final UUID originalId; + private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact defending player controls"); + + static { + filter.add(DefendingPlayerControlsPredicate.instance); + } public KukemssaPirates(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -36,26 +39,12 @@ public final class KukemssaPirates extends CardImpl { // Whenever Kukemssa Pirates attacks and isn't blocked, you may gain control of target artifact defending player controls. If you do, Kukemssa Pirates assigns no combat damage this turn. Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(new GainControlTargetEffect(Duration.Custom), true); ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true)); - ability.addTarget(new TargetArtifactPermanent(new FilterArtifactPermanent("artifact defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetArtifactPermanent(filter)); this.addAbility(ability); } public KukemssaPirates(final KukemssaPirates card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetArtifactPermanent target = new TargetArtifactPermanent(filter); - ability.addTarget(target); - } } @Override diff --git a/Mage.Sets/src/mage/cards/k/KulrathKnight.java b/Mage.Sets/src/mage/cards/k/KulrathKnight.java index a4ad1cc07c2..16687c520ce 100644 --- a/Mage.Sets/src/mage/cards/k/KulrathKnight.java +++ b/Mage.Sets/src/mage/cards/k/KulrathKnight.java @@ -61,7 +61,7 @@ class KulrathKnightRestrictionEffect extends RestrictionEffect { static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); - filter.add(new CounterAnyPredicate()); + filter.add(CounterAnyPredicate.instance); } public KulrathKnightRestrictionEffect() { diff --git a/Mage.Sets/src/mage/cards/k/KumanosBlessing.java b/Mage.Sets/src/mage/cards/k/KumanosBlessing.java index c745c6fd9c6..6c0f1f2d18e 100644 --- a/Mage.Sets/src/mage/cards/k/KumanosBlessing.java +++ b/Mage.Sets/src/mage/cards/k/KumanosBlessing.java @@ -94,7 +94,7 @@ class KumanosBlessingEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zce = (ZoneChangeEvent) event; if (zce.isDiesEvent()) { - DamagedByEnchantedWatcher watcher = (DamagedByEnchantedWatcher) game.getState().getWatchers().get(DamagedByEnchantedWatcher.class.getSimpleName(), source.getSourceId()); + DamagedByEnchantedWatcher watcher = game.getState().getWatcher(DamagedByEnchantedWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.wasDamaged(zce.getTarget(), game); } @@ -109,7 +109,7 @@ class DamagedByEnchantedWatcher extends Watcher { private final Set damagedCreatures = new HashSet<>(); public DamagedByEnchantedWatcher() { - super(DamagedByEnchantedWatcher.class.getSimpleName(), WatcherScope.CARD); + super(DamagedByEnchantedWatcher.class, WatcherScope.CARD); } public DamagedByEnchantedWatcher(final DamagedByEnchantedWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java b/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java index 1750aaad300..620c839d28e 100644 --- a/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java +++ b/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java @@ -34,12 +34,12 @@ public final class KumenaTyrantOfOrazca extends CardImpl { private static final FilterControlledPermanent filterAll = new FilterControlledPermanent("Merfolk you control"); static { - filterAnotherNotTapped.add(new AnotherPredicate()); + filterAnotherNotTapped.add(AnotherPredicate.instance); filterAnotherNotTapped.add(new SubtypePredicate(SubType.MERFOLK)); - filterAnotherNotTapped.add(Predicates.not(new TappedPredicate())); + filterAnotherNotTapped.add(Predicates.not(TappedPredicate.instance)); filterNotTapped.add(new SubtypePredicate(SubType.MERFOLK)); - filterNotTapped.add(Predicates.not(new TappedPredicate())); + filterNotTapped.add(Predicates.not(TappedPredicate.instance)); filterAll.add(new SubtypePredicate(SubType.MERFOLK)); } diff --git a/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java b/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java index 90981f90196..58cc2dd7779 100644 --- a/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java +++ b/Mage.Sets/src/mage/cards/k/KumenasSpeaker.java @@ -24,7 +24,7 @@ public final class KumenasSpeaker extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another Merfolk or an Island"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.or( new SubtypePredicate(SubType.ISLAND), new SubtypePredicate(SubType.MERFOLK))); diff --git a/Mage.Sets/src/mage/cards/k/KuonOgreAscendant.java b/Mage.Sets/src/mage/cards/k/KuonOgreAscendant.java index ee72d2a3c9e..cf6d5084365 100644 --- a/Mage.Sets/src/mage/cards/k/KuonOgreAscendant.java +++ b/Mage.Sets/src/mage/cards/k/KuonOgreAscendant.java @@ -89,7 +89,7 @@ enum KuonOgreAscendantCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - CreaturesDiedWatcher watcher = (CreaturesDiedWatcher) game.getState().getWatchers().get(CreaturesDiedWatcher.class.getSimpleName()); + CreaturesDiedWatcher watcher = game.getState().getWatcher(CreaturesDiedWatcher.class); if (watcher != null) { return watcher.getAmountOfCreaturesDiedThisTurn() > 2; } diff --git a/Mage.Sets/src/mage/cards/k/KydeleChosenOfKruphix.java b/Mage.Sets/src/mage/cards/k/KydeleChosenOfKruphix.java index ba654daf775..21e19810cdb 100644 --- a/Mage.Sets/src/mage/cards/k/KydeleChosenOfKruphix.java +++ b/Mage.Sets/src/mage/cards/k/KydeleChosenOfKruphix.java @@ -57,8 +57,11 @@ class CardsDrawnThisTurnDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - KydeleCardsDrawnThisTurnWatcher watcher = (KydeleCardsDrawnThisTurnWatcher) game.getState().getWatchers().get(KydeleCardsDrawnThisTurnWatcher.class.getSimpleName()); - return watcher.getCardsDrawnThisTurn(sourceAbility.getControllerId()); + KydeleCardsDrawnThisTurnWatcher watcher = game.getState().getWatcher(KydeleCardsDrawnThisTurnWatcher.class); + if(watcher != null) { + return watcher.getCardsDrawnThisTurn(sourceAbility.getControllerId()); + } + return 0; } @Override @@ -82,7 +85,7 @@ class KydeleCardsDrawnThisTurnWatcher extends Watcher { private final Map cardsDrawnThisTurn = new HashMap<>(); public KydeleCardsDrawnThisTurnWatcher() { - super(KydeleCardsDrawnThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(KydeleCardsDrawnThisTurnWatcher.class, WatcherScope.GAME); } public KydeleCardsDrawnThisTurnWatcher(final KydeleCardsDrawnThisTurnWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/k/KyloRen.java b/Mage.Sets/src/mage/cards/k/KyloRen.java index 19326d19259..eab9b02ff1d 100644 --- a/Mage.Sets/src/mage/cards/k/KyloRen.java +++ b/Mage.Sets/src/mage/cards/k/KyloRen.java @@ -39,7 +39,7 @@ public final class KyloRen extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public KyloRen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java b/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java index f21e9a828ea..e9af826e1a8 100644 --- a/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java +++ b/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java @@ -24,7 +24,7 @@ public final class KyrenNegotiations extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public KyrenNegotiations(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java index d420ff39a62..4e36e7bd8d7 100644 --- a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java +++ b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java @@ -71,7 +71,7 @@ class KytheonHeroOfAkrosCondition implements Condition { public boolean apply(Game game, Ability source) { Permanent sourceObject = game.getPermanent(source.getSourceId()); if (sourceObject != null) { - AttackedOrBlockedThisCombatWatcher watcher = (AttackedOrBlockedThisCombatWatcher) game.getState().getWatchers().get(AttackedOrBlockedThisCombatWatcher.class.getSimpleName()); + AttackedOrBlockedThisCombatWatcher watcher = game.getState().getWatcher(AttackedOrBlockedThisCombatWatcher.class); if (watcher != null) { boolean sourceFound = false; int number = 0; diff --git a/Mage.Sets/src/mage/cards/l/LadySun.java b/Mage.Sets/src/mage/cards/l/LadySun.java index 8d9ca4863d3..255c43bbd81 100644 --- a/Mage.Sets/src/mage/cards/l/LadySun.java +++ b/Mage.Sets/src/mage/cards/l/LadySun.java @@ -28,7 +28,7 @@ public final class LadySun extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public LadySun(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java b/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java index 20fcc00fcbf..b3930a952c7 100644 --- a/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java +++ b/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java @@ -26,7 +26,7 @@ public final class LamplighterOfSelhoff extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Zombie"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.ZOMBIE)); } diff --git a/Mage.Sets/src/mage/cards/l/Lashknife.java b/Mage.Sets/src/mage/cards/l/Lashknife.java index c0f5db91dad..a99bf8d1173 100644 --- a/Mage.Sets/src/mage/cards/l/Lashknife.java +++ b/Mage.Sets/src/mage/cards/l/Lashknife.java @@ -38,7 +38,7 @@ public final class Lashknife extends CardImpl { static { plainsFilter.add(new SubtypePredicate(SubType.PLAINS)); - creatureFilter.add(Predicates.not(new TappedPredicate())); + creatureFilter.add(Predicates.not(TappedPredicate.instance)); } public Lashknife(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LastLaugh.java b/Mage.Sets/src/mage/cards/l/LastLaugh.java index 1a35b3f9a08..14c712bfa31 100644 --- a/Mage.Sets/src/mage/cards/l/LastLaugh.java +++ b/Mage.Sets/src/mage/cards/l/LastLaugh.java @@ -27,7 +27,7 @@ public final class LastLaugh extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("a permanent other than Last Laugh"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public LastLaugh(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java b/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java index bdb34d6533b..e93fb4b01db 100644 --- a/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java +++ b/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java @@ -34,8 +34,8 @@ public final class LathlissDragonQueen extends CardImpl { static { filter.add(new SubtypePredicate(SubType.DRAGON)); - filter.add(Predicates.not(new TokenPredicate())); - filter.add(new AnotherPredicate()); + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); filter2.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/l/LatullaKeldonOverseer.java b/Mage.Sets/src/mage/cards/l/LatullaKeldonOverseer.java index 7c86ccbe4fd..30171595ff4 100644 --- a/Mage.Sets/src/mage/cards/l/LatullaKeldonOverseer.java +++ b/Mage.Sets/src/mage/cards/l/LatullaKeldonOverseer.java @@ -35,7 +35,7 @@ public final class LatullaKeldonOverseer extends CardImpl { this.toughness = new MageInt(3); // {X}{R}, {tap}, Discard two cards: Latulla, Keldon Overseer deals X damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{R}")); ability.addCost(new TapSourceCost()); ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, 2, new FilterCard("two cards")))); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/l/Launch.java b/Mage.Sets/src/mage/cards/l/Launch.java index 9c3c984cd9d..3e0518ed3d2 100644 --- a/Mage.Sets/src/mage/cards/l/Launch.java +++ b/Mage.Sets/src/mage/cards/l/Launch.java @@ -1,7 +1,5 @@ - package mage.cards.l; -import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; @@ -11,22 +9,18 @@ import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Derpthemeus */ public final class Launch extends CardImpl { public Launch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -34,8 +28,10 @@ public final class Launch extends CardImpl { this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + // Enchanted creature has flying. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield))); + // When Launch is put into a graveyard from the battlefield, return Launch to its owner's hand. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ReturnToHandSourceEffect())); diff --git a/Mage.Sets/src/mage/cards/l/LavaballTrap.java b/Mage.Sets/src/mage/cards/l/LavaballTrap.java index 745a056dc81..df7428ffb67 100644 --- a/Mage.Sets/src/mage/cards/l/LavaballTrap.java +++ b/Mage.Sets/src/mage/cards/l/LavaballTrap.java @@ -57,7 +57,7 @@ enum LavaballTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getSimpleName()); + PermanentsEnteredBattlefieldWatcher watcher = game.getState().getWatcher(PermanentsEnteredBattlefieldWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { List permanents = watcher.getThisTurnEnteringPermanents(opponentId); diff --git a/Mage.Sets/src/mage/cards/l/LavaclawReaches.java b/Mage.Sets/src/mage/cards/l/LavaclawReaches.java index e1c3f7b6fd1..9988c05f7d4 100644 --- a/Mage.Sets/src/mage/cards/l/LavaclawReaches.java +++ b/Mage.Sets/src/mage/cards/l/LavaclawReaches.java @@ -60,7 +60,7 @@ class LavaclawReachesToken extends TokenImpl { color.setBlack(true); power = new MageInt(2); toughness = new MageInt(2); - addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn), new ManaCostsImpl("{X}"))); + addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn), new ManaCostsImpl("{X}"))); } public LavaclawReachesToken(final LavaclawReachesToken token) { super(token); diff --git a/Mage.Sets/src/mage/cards/l/Lavalanche.java b/Mage.Sets/src/mage/cards/l/Lavalanche.java index bbb74ff71da..231134ea215 100644 --- a/Mage.Sets/src/mage/cards/l/Lavalanche.java +++ b/Mage.Sets/src/mage/cards/l/Lavalanche.java @@ -29,7 +29,7 @@ public final class Lavalanche extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{R}{G}"); // Lavalanche deals X damage to target player and each creature he or she controls. - this.getSpellAbility().addEffect(new LavalancheEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new LavalancheEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); } diff --git a/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java b/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java new file mode 100644 index 00000000000..4276ebfd59f --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LaviniaAzoriusRenegade.java @@ -0,0 +1,159 @@ + +package mage.cards.l; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.target.targetpointer.FixedTarget; + +import java.util.List; +import java.util.UUID; + +/** + * + * @author NinthWorld + */ +public final class LaviniaAzoriusRenegade extends CardImpl { + + public LaviniaAzoriusRenegade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{U}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.addSuperType(SuperType.LEGENDARY); + + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Each opponent can't cast noncreature spells with converted mana cost greater than the number of lands that player controls. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LaviniaAzoriusRenegadeReplacementEffect())); + + // Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell. + this.addAbility(new LaviniaAzoriusRenegadeTriggeredAbility()); + } + + public LaviniaAzoriusRenegade(final LaviniaAzoriusRenegade card) { + super(card); + } + + @Override + public LaviniaAzoriusRenegade copy() { + return new LaviniaAzoriusRenegade(this); + } +} + +class LaviniaAzoriusRenegadeReplacementEffect extends ContinuousRuleModifyingEffectImpl { + + LaviniaAzoriusRenegadeReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "Each opponent can't cast noncreature spells with converted mana cost greater than the number of lands that player controls."; + } + + LaviniaAzoriusRenegadeReplacementEffect(final LaviniaAzoriusRenegadeReplacementEffect effect) { + super(effect); + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "You can't cast noncreature spells with converted mana cost greater than " + getLandCount(source, event, game) + " (" + mageObject.getIdName() + ")."; + } + return null; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (game.getPlayer(source.getControllerId()).hasOpponent(event.getPlayerId(), game)) { + FilterCard filter = new FilterCard(); + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + filter.add(new ConvertedManaCostPredicate(ComparisonType.MORE_THAN, getLandCount(source, event, game))); + + Card card = game.getCard(event.getSourceId()); + return card != null && filter.match(card, game); + } + return false; + } + + private int getLandCount(Ability source, GameEvent event, Game game) { + int landCount = 0; + UUID playerId = event.getPlayerId(); + if(playerId != null) { + List permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, playerId, source.getSourceId(), game); + for (Permanent permanent : permanents) { + if (permanent.isControlledBy(playerId)) { + landCount++; + } + } + } + return landCount; + } + + @Override + public LaviniaAzoriusRenegadeReplacementEffect copy() { + return new LaviniaAzoriusRenegadeReplacementEffect(this); + } +} + + +class LaviniaAzoriusRenegadeTriggeredAbility extends TriggeredAbilityImpl { + + public LaviniaAzoriusRenegadeTriggeredAbility() { + super(Zone.BATTLEFIELD, new CounterTargetEffect(), false); + } + + public LaviniaAzoriusRenegadeTriggeredAbility(final LaviniaAzoriusRenegadeTriggeredAbility ability) { + super(ability); + } + + @Override + public LaviniaAzoriusRenegadeTriggeredAbility copy() { + return new LaviniaAzoriusRenegadeTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.getPlayer(this.getControllerId()).hasOpponent(event.getPlayerId(), game)) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getStackAbility().getManaCostsToPay().getPayment().count() == 0) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/l/LawmagesBinding.java b/Mage.Sets/src/mage/cards/l/LawmagesBinding.java new file mode 100644 index 00000000000..f5d89ce8146 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LawmagesBinding.java @@ -0,0 +1,52 @@ +package mage.cards.l; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantBlockAttackActivateAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LawmagesBinding extends CardImpl { + + public LawmagesBinding(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{U}"); + + this.subtype.add(SubType.AURA); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature can't attack or block, and its activate abilities can't be activated. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBlockAttackActivateAttachedEffect())); + } + + private LawmagesBinding(final LawmagesBinding card) { + super(card); + } + + @Override + public LawmagesBinding copy() { + return new LawmagesBinding(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java b/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java index fcb2eca5f22..71cdf748fef 100644 --- a/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java +++ b/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java @@ -80,7 +80,7 @@ class LazavDimirMastermindEffect extends OneShotEffect { && lazavDimirMastermind != null) { Card copyFromCard = game.getCard(((FixedTarget) getTargetPointer()).getTarget()); if (copyFromCard != null) { - newBluePrint = new PermanentCard((Card) copyFromCard, source.getControllerId(), game); + newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); ApplyToPermanent applier = new LazavDimirMastermindApplier(); applier.apply(game, newBluePrint, source, lazavDimirMastermind.getId()); diff --git a/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java b/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java index a8bf016ec6a..5ee5f63379f 100644 --- a/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java +++ b/Mage.Sets/src/mage/cards/l/LazavTheMultifarious.java @@ -110,7 +110,7 @@ class LazavTheMultifariousEffect extends OneShotEffect { && lazavTheMultifarious != null) { Card copyFromCard = game.getCard(source.getFirstTarget()); if (copyFromCard != null) { - newBluePrint = new PermanentCard((Card) copyFromCard, source.getControllerId(), game); + newBluePrint = new PermanentCard(copyFromCard, source.getControllerId(), game); newBluePrint.assignNewId(); ApplyToPermanent applier = new LazavTheMultifariousApplier(); applier.apply(game, newBluePrint, source, lazavTheMultifarious.getId()); diff --git a/Mage.Sets/src/mage/cards/l/Leapfrog.java b/Mage.Sets/src/mage/cards/l/Leapfrog.java index 8e1006f6975..f71d344ce0c 100644 --- a/Mage.Sets/src/mage/cards/l/Leapfrog.java +++ b/Mage.Sets/src/mage/cards/l/Leapfrog.java @@ -62,8 +62,8 @@ enum LeapfrogCondition implements Condition { @Override public boolean apply(Game game, Ability source) { SpellsCastWatcher watcher - = (SpellsCastWatcher) game.getState().getWatchers().get( - SpellsCastWatcher.class.getSimpleName() + = game.getState().getWatcher( + SpellsCastWatcher.class ); if (watcher == null) { return false; diff --git a/Mage.Sets/src/mage/cards/l/LeaveChance.java b/Mage.Sets/src/mage/cards/l/LeaveChance.java index 09d06d1ce12..366f9ea9014 100644 --- a/Mage.Sets/src/mage/cards/l/LeaveChance.java +++ b/Mage.Sets/src/mage/cards/l/LeaveChance.java @@ -42,7 +42,7 @@ public final class LeaveChance extends SplitCard { // Chance // Sorcery // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Discard any number of cards, then draw that many cards. getRightHalfCard().getSpellAbility().addEffect(new ChanceEffect()); diff --git a/Mage.Sets/src/mage/cards/l/LedevChampion.java b/Mage.Sets/src/mage/cards/l/LedevChampion.java index 8c5d59ecaed..babd14a4eb4 100644 --- a/Mage.Sets/src/mage/cards/l/LedevChampion.java +++ b/Mage.Sets/src/mage/cards/l/LedevChampion.java @@ -68,7 +68,7 @@ class LedevChampionEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public LedevChampionEffect() { diff --git a/Mage.Sets/src/mage/cards/l/LegionGuildmage.java b/Mage.Sets/src/mage/cards/l/LegionGuildmage.java index f0ef4685372..93dbb3cad04 100644 --- a/Mage.Sets/src/mage/cards/l/LegionGuildmage.java +++ b/Mage.Sets/src/mage/cards/l/LegionGuildmage.java @@ -27,7 +27,7 @@ public final class LegionGuildmage extends CardImpl { = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public LegionGuildmage(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LegionsInitiative.java b/Mage.Sets/src/mage/cards/l/LegionsInitiative.java index 05038cb183d..8f209d80b3d 100644 --- a/Mage.Sets/src/mage/cards/l/LegionsInitiative.java +++ b/Mage.Sets/src/mage/cards/l/LegionsInitiative.java @@ -1,7 +1,5 @@ - package mage.cards.l; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -17,11 +15,7 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -32,8 +26,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class LegionsInitiative extends CardImpl { @@ -47,7 +42,7 @@ public final class LegionsInitiative extends CardImpl { } public LegionsInitiative(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}{W}"); // Red creatures you control get +1/+0. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield, filterRedCreature))); @@ -136,12 +131,14 @@ class LegionsInitiativeReturnFromExileEffect extends OneShotEffect { exile = exile.copy(); for (UUID cardId : exile) { Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - Permanent returnedCreature = game.getPermanent(cardId); - if (returnedCreature != null) { - ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(returnedCreature.getId())); - game.addEffect(effect, source); + if (card != null) { + card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); + Permanent returnedCreature = game.getPermanent(cardId); + if (returnedCreature != null) { + ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(returnedCreature.getId())); + game.addEffect(effect, source); + } } } game.getExile().getExileZone(source.getSourceId()).clear(); diff --git a/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java b/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java index e86a5719636..b3fbdbf3ec1 100644 --- a/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java +++ b/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java @@ -38,7 +38,7 @@ public final class LenaSelflessChampion extends CardImpl { = new FilterControlledCreaturePermanent("nontoken creature you control"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public LenaSelflessChampion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LensOfClarity.java b/Mage.Sets/src/mage/cards/l/LensOfClarity.java index c958c1d3759..cbf6afb818d 100644 --- a/Mage.Sets/src/mage/cards/l/LensOfClarity.java +++ b/Mage.Sets/src/mage/cards/l/LensOfClarity.java @@ -110,7 +110,7 @@ class LensOfClarityLookFaceDownAbility extends ActivatedAbilityImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature you don't control"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); filter.add(new ControllerPredicate(TargetController.NOT_YOU)); } diff --git a/Mage.Sets/src/mage/cards/l/LeoninBladetrap.java b/Mage.Sets/src/mage/cards/l/LeoninBladetrap.java index 007da60f6ae..0bc2e9ff716 100644 --- a/Mage.Sets/src/mage/cards/l/LeoninBladetrap.java +++ b/Mage.Sets/src/mage/cards/l/LeoninBladetrap.java @@ -26,7 +26,7 @@ public final class LeoninBladetrap extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature without flying"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); } diff --git a/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java b/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java index 270e0500530..675371692d4 100644 --- a/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java +++ b/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java @@ -71,7 +71,7 @@ class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - CardsAmountDrawnThisTurnWatcher watcher = (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.class.getSimpleName()); + CardsAmountDrawnThisTurnWatcher watcher = game.getState().getWatcher(CardsAmountDrawnThisTurnWatcher.class); Player controller = game.getPlayer(source.getControllerId()); return watcher != null && controller != null && watcher.getAmountCardsDrawn(event.getPlayerId()) >= 1 && game.isOpponent(controller, event.getPlayerId()); diff --git a/Mage.Sets/src/mage/cards/l/LesserWerewolf.java b/Mage.Sets/src/mage/cards/l/LesserWerewolf.java new file mode 100644 index 00000000000..84d836b950c --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LesserWerewolf.java @@ -0,0 +1,93 @@ + +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.condition.common.IsStepCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.BoostCounter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.BlockedByIdPredicate; +import mage.filter.predicate.permanent.BlockingAttackerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public final class LesserWerewolf extends CardImpl { + + public LesserWerewolf(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // {B}: If Lesser Werewolf’s power is 1 or more, it gets -1/-0 until end of turn and put a -0/-1 counter on target creature blocking or blocked by Lesser Werewolf. Activate this ability only during the declare blockers step. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new LesserWerewolfEffect(), new ManaCostsImpl("{B}"), new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false)); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature blocking or blocked by Lesser Werewolf"); + filter.add(Predicates.or(new BlockedByIdPredicate(this.getId()), + new BlockingAttackerIdPredicate(this.getId()))); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + + } + + public LesserWerewolf(final LesserWerewolf card) { + super(card); + } + + @Override + public LesserWerewolf copy() { + return new LesserWerewolf(this); + } +} + +class LesserWerewolfEffect extends OneShotEffect { + + public LesserWerewolfEffect() { + super(Outcome.Detriment); + this.staticText = "If {this}’s power is 1 or more, it gets -1/-0 until end of turn and put a -0/-1 counter on target creature blocking or blocked by {this}"; + } + + public LesserWerewolfEffect(final LesserWerewolfEffect effect) { + super(effect); + } + + @Override + public LesserWerewolfEffect copy() { + return new LesserWerewolfEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + Permanent targetPermanent = game.getPermanentOrLKIBattlefield(targetPointer.getFirst(game, source)); + if (controller != null && sourcePermanent != null && targetPermanent != null) { + if (sourcePermanent.getPower().getValue() >= 1) { + game.addEffect(new BoostSourceEffect(-1, 0, Duration.EndOfTurn), source); + new AddCountersTargetEffect(new BoostCounter(0, -1), outcome).apply(game, source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/l/LethargyTrap.java b/Mage.Sets/src/mage/cards/l/LethargyTrap.java index d06efc253cd..ecad4964478 100644 --- a/Mage.Sets/src/mage/cards/l/LethargyTrap.java +++ b/Mage.Sets/src/mage/cards/l/LethargyTrap.java @@ -26,7 +26,7 @@ public final class LethargyTrap extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creatures"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public LethargyTrap(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/Liability.java b/Mage.Sets/src/mage/cards/l/Liability.java index 6973291332c..0c1930b7ede 100644 --- a/Mage.Sets/src/mage/cards/l/Liability.java +++ b/Mage.Sets/src/mage/cards/l/Liability.java @@ -1,11 +1,8 @@ - package mage.cards.l; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,20 +15,21 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** - * * @author L_J */ public final class Liability extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("a nontoken permanent"); - + static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } - + public Liability(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}"); // Whenever a nontoken permanent is put into a player's graveyard from the battlefield, that player loses 1 life. this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new LiabilityEffect(), false, filter, true)); diff --git a/Mage.Sets/src/mage/cards/l/Lich.java b/Mage.Sets/src/mage/cards/l/Lich.java index 523d67acc0a..e77d1031f57 100644 --- a/Mage.Sets/src/mage/cards/l/Lich.java +++ b/Mage.Sets/src/mage/cards/l/Lich.java @@ -41,7 +41,7 @@ public final class Lich extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{B}{B}{B}"); // As Lich enters the battlefield, you lose life equal to your life total. - this.addAbility(new EntersBattlefieldAbility(new LoseLifeSourceControllerEffect(new ControllerLifeCount()), null, "As Lich enters the battlefield, you lose life equal to your life total.", null)); + this.addAbility(new EntersBattlefieldAbility(new LoseLifeSourceControllerEffect(ControllerLifeCount.instance), null, "As Lich enters the battlefield, you lose life equal to your life total.", null)); // You don't lose the game for having 0 or less life. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontLoseByZeroOrLessLifeEffect(Duration.WhileOnBattlefield))); @@ -145,7 +145,7 @@ class LichDamageEffect extends OneShotEffect { private static final FilterControlledPermanent filter = new FilterControlledPermanent("nontoken permanent"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } private int amount = 0; diff --git a/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java b/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java index 05adae41876..599139b73f0 100644 --- a/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java +++ b/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java @@ -112,9 +112,9 @@ class YouGainLifeCount implements DynamicValue { } public int calculate(Game game, UUID controllerId) { - PlayerGainedLifeWatcher watcher = (PlayerGainedLifeWatcher) game.getState().getWatchers().get(PlayerGainedLifeWatcher.class.getSimpleName()); + PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); if (watcher != null) { - return watcher.getLiveGained(controllerId); + return watcher.getLifeGained(controllerId); } return 0; } diff --git a/Mage.Sets/src/mage/cards/l/LiegeOfThePit.java b/Mage.Sets/src/mage/cards/l/LiegeOfThePit.java index e3d9eea26ea..7e63ce8903c 100644 --- a/Mage.Sets/src/mage/cards/l/LiegeOfThePit.java +++ b/Mage.Sets/src/mage/cards/l/LiegeOfThePit.java @@ -86,7 +86,7 @@ class LiegeOfThePitEffect extends OneShotEffect { } FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature other than " + sourcePermanent.getName()); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); if (target.canChoose(source.getSourceId(), player.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/l/LifecraftAwakening.java b/Mage.Sets/src/mage/cards/l/LifecraftAwakening.java index 7aabdf3f900..a6ff60b5017 100644 --- a/Mage.Sets/src/mage/cards/l/LifecraftAwakening.java +++ b/Mage.Sets/src/mage/cards/l/LifecraftAwakening.java @@ -39,7 +39,7 @@ public final class LifecraftAwakening extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{G}"); // Put X +1/+1 counters on target artifact you control. If it isn't a creature or Vehicle, it becomes a 0/0 Construct artifact creature. - ManacostVariableValue manaX = new ManacostVariableValue(); + ManacostVariableValue manaX = ManacostVariableValue.instance; getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(), manaX)); getSpellAbility().addTarget(new TargetArtifactPermanent(filter)); getSpellAbility().addEffect(new LifecraftAwakeningEffect()); diff --git a/Mage.Sets/src/mage/cards/l/LightUpTheStage.java b/Mage.Sets/src/mage/cards/l/LightUpTheStage.java index 2a48c3106cf..21aa8ff2b4a 100644 --- a/Mage.Sets/src/mage/cards/l/LightUpTheStage.java +++ b/Mage.Sets/src/mage/cards/l/LightUpTheStage.java @@ -26,11 +26,11 @@ public final class LightUpTheStage extends CardImpl { public LightUpTheStage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); - // Spectacle {R} - this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{R}"))); - // Exile the top two cards of your library. Until the end of your next turn, you may play those cards. this.getSpellAbility().addEffect(new LightUpTheStageEffect()); + + // Spectacle {R} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{R}"))); } public LightUpTheStage(final LightUpTheStage card) { @@ -45,12 +45,12 @@ public final class LightUpTheStage extends CardImpl { class LightUpTheStageEffect extends OneShotEffect { - public LightUpTheStageEffect() { + LightUpTheStageEffect() { super(Outcome.PlayForFree); this.staticText = "Exile the top two cards of your library. Until the end of your next turn, you may play those cards"; } - public LightUpTheStageEffect(final LightUpTheStageEffect effect) { + private LightUpTheStageEffect(final LightUpTheStageEffect effect) { super(effect); } @@ -62,10 +62,10 @@ class LightUpTheStageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Card sourceCard = game.getCard(source.getSourceId()); if (controller != null) { Set cards = controller.getLibrary().getTopCards(game, 2); - controller.moveCardsToExile(cards, source, game, true, CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName()); + Card sourceCard = game.getCard(source.getSourceId()); + controller.moveCardsToExile(cards, source, game, true, CardUtil.getCardExileZoneId(game, source), sourceCard != null ? sourceCard.getIdName() : ""); for (Card card : cards) { ContinuousEffect effect = new LightUpTheStageMayPlayEffect(); @@ -83,12 +83,12 @@ class LightUpTheStageMayPlayEffect extends AsThoughEffectImpl { private int castOnTurn = 0; - public LightUpTheStageMayPlayEffect() { + LightUpTheStageMayPlayEffect() { super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit); this.staticText = "Until the end of your next turn, you may play that card."; } - public LightUpTheStageMayPlayEffect(final LightUpTheStageMayPlayEffect effect) { + private LightUpTheStageMayPlayEffect(final LightUpTheStageMayPlayEffect effect) { super(effect); castOnTurn = effect.castOnTurn; } @@ -107,9 +107,7 @@ class LightUpTheStageMayPlayEffect extends AsThoughEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (castOnTurn != game.getTurnNum() && game.getPhase().getStep().getType() == PhaseStep.END_TURN) { - if (game.isActivePlayer(source.getControllerId())) { - return true; - } + return game.isActivePlayer(source.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/l/LightkeeperOfEmeria.java b/Mage.Sets/src/mage/cards/l/LightkeeperOfEmeria.java index 05cad39bf7e..2b3be08030a 100644 --- a/Mage.Sets/src/mage/cards/l/LightkeeperOfEmeria.java +++ b/Mage.Sets/src/mage/cards/l/LightkeeperOfEmeria.java @@ -35,7 +35,7 @@ public final class LightkeeperOfEmeria extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Lightkeeper of Emeria enters the battlefield, you gain 2 life for each time it was kicked. - Effect effect = new GainLifeEffect(new MultipliedValue(new MultikickerCount(), 2)); + Effect effect = new GainLifeEffect(new MultipliedValue(MultikickerCount.instance, 2)); effect.setText("you gain 2 life for each time it was kicked"); this.addAbility(new EntersBattlefieldTriggeredAbility(effect, false)); } diff --git a/Mage.Sets/src/mage/cards/l/LightningCoils.java b/Mage.Sets/src/mage/cards/l/LightningCoils.java index 22885e7b29c..9b290065a0f 100644 --- a/Mage.Sets/src/mage/cards/l/LightningCoils.java +++ b/Mage.Sets/src/mage/cards/l/LightningCoils.java @@ -32,7 +32,7 @@ public final class LightningCoils extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a nontoken creature you control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public LightningCoils(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java b/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java index f6a0956905e..f4db5ab2b78 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaDefiantNecromancer.java @@ -1,4 +1,3 @@ - package mage.cards.l; import java.util.UUID; @@ -21,6 +20,7 @@ import mage.filter.predicate.mageobject.SupertypePredicate; import mage.game.Game; import mage.game.command.emblems.LilianaDefiantNecromancerEmblem; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -28,14 +28,12 @@ import mage.target.common.TargetCardInYourGraveyard; */ public final class LilianaDefiantNecromancer extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard("nonlegendary creature with converted mana cost X from your graveyard"); + protected static final FilterCreatureCard filter = new FilterCreatureCard("nonlegendary creature with converted mana cost X from your graveyard"); static { filter.add(Predicates.not(new SupertypePredicate(SuperType.LEGENDARY))); } - UUID ability2Id; - public LilianaDefiantNecromancer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); this.addSuperType(SuperType.LEGENDARY); @@ -49,36 +47,18 @@ public final class LilianaDefiantNecromancer extends CardImpl { // +2: Each player discards a card. this.addAbility(new LoyaltyAbility(new DiscardEachPlayerEffect(1, false), 2)); - //TODO: Make ability properly copiable // -X: Return target nonlegendary creature with converted mana cost X from your graveyard to the battlefield. Ability ability = new LoyaltyAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()); - ability2Id = ability.getOriginalId(); ability.addTarget(new TargetCardInYourGraveyard(filter)); + ability.setTargetAdjuster(LilianaDefiantNecromancerAdjuster.instance); this.addAbility(ability); //-8: You get an emblem with "Whenever a creature dies, return it to the battlefield under your control at the beginning of the next end step."; this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new LilianaDefiantNecromancerEmblem()), -8)); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(ability2Id)) { - int cmc = 0; - for (Cost cost : ability.getCosts()) { - if (cost instanceof PayVariableLoyaltyCost) { - cmc = ((PayVariableLoyaltyCost) cost).getAmount(); - } - } - FilterCard newFilter = filter.copy(); - newFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, cmc)); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInYourGraveyard(newFilter)); - } - } - public LilianaDefiantNecromancer(final LilianaDefiantNecromancer card) { super(card); - this.ability2Id = card.ability2Id; } @Override @@ -86,3 +66,21 @@ public final class LilianaDefiantNecromancer extends CardImpl { return new LilianaDefiantNecromancer(this); } } + +enum LilianaDefiantNecromancerAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int cmc = 0; + for (Cost cost : ability.getCosts()) { + if (cost instanceof PayVariableLoyaltyCost) { + cmc = ((PayVariableLoyaltyCost) cost).getAmount(); + } + } + FilterCard newFilter = LilianaDefiantNecromancer.filter.copy(); + newFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, cmc)); + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard(newFilter)); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java index c0ad532fb88..990e7a7b2e1 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaHereticalHealer.java @@ -32,8 +32,8 @@ public final class LilianaHereticalHealer extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public LilianaHereticalHealer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LingeringPhantom.java b/Mage.Sets/src/mage/cards/l/LingeringPhantom.java index 380cfca8096..1a16edbbbdd 100644 --- a/Mage.Sets/src/mage/cards/l/LingeringPhantom.java +++ b/Mage.Sets/src/mage/cards/l/LingeringPhantom.java @@ -24,7 +24,7 @@ public final class LingeringPhantom extends CardImpl { private static final FilterSpell filter = new FilterSpell("a historic spell"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public LingeringPhantom(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LiquidFire.java b/Mage.Sets/src/mage/cards/l/LiquidFire.java index 04b40d14139..32737ce082b 100644 --- a/Mage.Sets/src/mage/cards/l/LiquidFire.java +++ b/Mage.Sets/src/mage/cards/l/LiquidFire.java @@ -30,7 +30,7 @@ public final class LiquidFire extends CardImpl { // As an additional cost to cast Liquid Fire, choose a number between 0 and 5. this.getSpellAbility().addCost(new LiquidFireCost()); // Liquid Fire deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number. - DynamicValue choiceValue = new GetXValue(); + DynamicValue choiceValue = GetXValue.instance; this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new LiquidFireEffect(choiceValue)); diff --git a/Mage.Sets/src/mage/cards/l/LivingInferno.java b/Mage.Sets/src/mage/cards/l/LivingInferno.java index 5d8992a61e2..50e31e74718 100644 --- a/Mage.Sets/src/mage/cards/l/LivingInferno.java +++ b/Mage.Sets/src/mage/cards/l/LivingInferno.java @@ -1,9 +1,6 @@ package mage.cards.l; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -12,50 +9,38 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetCreaturePermanentAmount; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** - * * @author LevelX2 & L_J */ public final class LivingInferno extends CardImpl { - private final UUID originalId; - public LivingInferno(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{R}{R}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(8); this.toughness = new MageInt(5); // {T}: Living Inferno deals damage equal to its power divided as you choose among any number of target creatures. Each of those creatures deals damage equal to its power to Living Inferno. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LivingInfernoEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanentAmount(1)); + ability.setTargetAdjuster(LivingInfernoAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability.getOriginalId().equals(originalId)) { - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); - if (sourcePermanent != null) { - int xValue = sourcePermanent.getPower().getValue(); - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanentAmount(xValue)); - } - } } public LivingInferno(final LivingInferno card) { super(card); - this.originalId = card.originalId; } @Override @@ -64,11 +49,26 @@ public final class LivingInferno extends CardImpl { } } +enum LivingInfernoAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId()); + if (sourcePermanent != null) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanentAmount(sourcePermanent.getPower().getValue())); + } + } +} + class LivingInfernoEffect extends OneShotEffect { public LivingInfernoEffect() { super(Outcome.Benefit); - this.staticText = "{this} deals damage equal to its power divided as you choose among any number of target creatures. Each of those creatures deals damage equal to its power to {this}"; + this.staticText = "{this} deals damage equal to its power " + + "divided as you choose among any number of target creatures. " + + "Each of those creatures deals damage equal to its power to {this}"; } public LivingInfernoEffect(final LivingInfernoEffect effect) { diff --git a/Mage.Sets/src/mage/cards/l/LivingLore.java b/Mage.Sets/src/mage/cards/l/LivingLore.java index 7438a74bc3b..85b5d1144f9 100644 --- a/Mage.Sets/src/mage/cards/l/LivingLore.java +++ b/Mage.Sets/src/mage/cards/l/LivingLore.java @@ -14,12 +14,7 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.ExileZone; import mage.game.Game; @@ -36,7 +31,7 @@ public final class LivingLore extends CardImpl { public LivingLore(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); - this.subtype.add("Avatar"); + this.subtype.add(SubType.AVATAR); this.power = new MageInt(0); this.toughness = new MageInt(0); diff --git a/Mage.Sets/src/mage/cards/l/LivingTotem.java b/Mage.Sets/src/mage/cards/l/LivingTotem.java index 1f1eb84004a..7c63adb3c53 100644 --- a/Mage.Sets/src/mage/cards/l/LivingTotem.java +++ b/Mage.Sets/src/mage/cards/l/LivingTotem.java @@ -25,7 +25,7 @@ public final class LivingTotem extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public LivingTotem(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java b/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java index f0a02284140..2757f292e63 100644 --- a/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java +++ b/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java @@ -25,7 +25,7 @@ public final class LlanowarBehemoth extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public LlanowarBehemoth(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LoamDryad.java b/Mage.Sets/src/mage/cards/l/LoamDryad.java index d4e1f9d8ebf..b2940609ab7 100644 --- a/Mage.Sets/src/mage/cards/l/LoamDryad.java +++ b/Mage.Sets/src/mage/cards/l/LoamDryad.java @@ -24,7 +24,7 @@ public final class LoamDryad extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public LoamDryad(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LodestoneMyr.java b/Mage.Sets/src/mage/cards/l/LodestoneMyr.java index 274faad42ec..fcbd7bf7e82 100644 --- a/Mage.Sets/src/mage/cards/l/LodestoneMyr.java +++ b/Mage.Sets/src/mage/cards/l/LodestoneMyr.java @@ -26,7 +26,7 @@ public final class LodestoneMyr extends CardImpl { private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("untapped artifact you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public LodestoneMyr(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LogicKnot.java b/Mage.Sets/src/mage/cards/l/LogicKnot.java index 49b6eaff913..daa6d03ee13 100644 --- a/Mage.Sets/src/mage/cards/l/LogicKnot.java +++ b/Mage.Sets/src/mage/cards/l/LogicKnot.java @@ -24,7 +24,7 @@ public final class LogicKnot extends CardImpl { this.addAbility(new DelveAbility()); // Counter target spell unless its controller pays {X}. - this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/l/LordOfThePit.java b/Mage.Sets/src/mage/cards/l/LordOfThePit.java index 53a3a56b398..e957943c5a8 100644 --- a/Mage.Sets/src/mage/cards/l/LordOfThePit.java +++ b/Mage.Sets/src/mage/cards/l/LordOfThePit.java @@ -78,7 +78,7 @@ class LordOfThePitEffect extends OneShotEffect { } FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature other than " + sourcePermanent.getName()); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); if (target.canChoose(source.getSourceId(), player.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/l/LordWindgrace.java b/Mage.Sets/src/mage/cards/l/LordWindgrace.java index a4126678c59..517407e8882 100644 --- a/Mage.Sets/src/mage/cards/l/LordWindgrace.java +++ b/Mage.Sets/src/mage/cards/l/LordWindgrace.java @@ -10,19 +10,20 @@ import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.Card; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.TargetController; +import mage.filter.StaticFilters; import mage.filter.common.FilterLandCard; import mage.filter.predicate.other.OwnerPredicate; import mage.game.Game; import mage.game.permanent.token.CatWarriorToken; import mage.players.Player; -import mage.target.common.TargetCardInASingleGraveyard; +import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetNonlandPermanent; /** @@ -49,9 +50,9 @@ public final class LordWindgrace extends CardImpl { // -3: Return up to two target land cards from your graveyard to the battlefield. Ability ability = new LoyaltyAbility( - new ReturnFromGraveyardToBattlefieldTargetEffect(), -3 + new ReturnFromGraveyardToBattlefieldTargetEffect().setText("return up to two target land cards from your graveyard to the battlefield"), -3 ); - ability.addTarget(new TargetCardInASingleGraveyard(0, 2, filter)); + ability.addTarget(new TargetCardInYourGraveyard(0, 2, filter)); this.addAbility(ability); // -11: Destroy up to six target nonland permanents, then create six 2/2 green Cat Warrior creature tokens with forestwalk. @@ -61,7 +62,7 @@ public final class LordWindgrace extends CardImpl { .setText(", then create six 2/2 green Cat Warrior " + "creature tokens with forestwalk") ); - ability.addTarget(new TargetNonlandPermanent(0, 6, false)); + ability.addTarget(new TargetNonlandPermanent(0, 6, StaticFilters.FILTER_PERMANENTS_NON_LAND, false)); this.addAbility(ability); // Lord Windgrace can be your commander. diff --git a/Mage.Sets/src/mage/cards/l/LoreseekersStone.java b/Mage.Sets/src/mage/cards/l/LoreseekersStone.java index 091e5a49c3d..784b468a7dd 100644 --- a/Mage.Sets/src/mage/cards/l/LoreseekersStone.java +++ b/Mage.Sets/src/mage/cards/l/LoreseekersStone.java @@ -1,28 +1,22 @@ - package mage.cards.l; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.CostModificationType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.players.Player; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class LoreseekersStone extends CardImpl { @@ -31,17 +25,11 @@ public final class LoreseekersStone extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); // {3}, {T}: Draw three cards. This ability costs {1} more to activate for each card in your hand. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(3), new GenericManaCost(3)); - ability.addCost(new TapSourceCost()); - for (Effect effect : ability.getEffects()) { - effect.setText("Draw three cards. This ability costs {1} more to activate for each card in your hand"); - } - this.addAbility(ability); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new LoreseekersStoneCostIncreasingEffect(ability.getOriginalId()))); - + this.addAbility(new LoreseekersStoneActivatedAbility()); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new LoreseekersStoneCostIncreasingEffect())); } - public LoreseekersStone(final LoreseekersStone card) { + private LoreseekersStone(final LoreseekersStone card) { super(card); } @@ -51,18 +39,34 @@ public final class LoreseekersStone extends CardImpl { } } -class LoreseekersStoneCostIncreasingEffect extends CostModificationEffectImpl { +class LoreseekersStoneActivatedAbility extends SimpleActivatedAbility { - private final UUID originalId; - - LoreseekersStoneCostIncreasingEffect(UUID originalId) { - super(Duration.EndOfGame, Outcome.Benefit, CostModificationType.INCREASE_COST); - this.originalId = originalId; + public LoreseekersStoneActivatedAbility() { + super(Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(3) + .setText("Draw three cards. This ability costs {1} more to activate for each card in your hand"), + new GenericManaCost(3)); + this.addCost(new TapSourceCost()); } - LoreseekersStoneCostIncreasingEffect(final LoreseekersStoneCostIncreasingEffect effect) { + private LoreseekersStoneActivatedAbility(final LoreseekersStoneActivatedAbility ability) { + super(ability); + } + + @Override + public LoreseekersStoneActivatedAbility copy() { + return new LoreseekersStoneActivatedAbility(this); + } +} + +class LoreseekersStoneCostIncreasingEffect extends CostModificationEffectImpl { + + LoreseekersStoneCostIncreasingEffect() { + super(Duration.EndOfGame, Outcome.Benefit, CostModificationType.INCREASE_COST); + } + + private LoreseekersStoneCostIncreasingEffect(final LoreseekersStoneCostIncreasingEffect effect) { super(effect); - this.originalId = effect.originalId; } @Override @@ -76,12 +80,11 @@ class LoreseekersStoneCostIncreasingEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify.getOriginalId().equals(originalId); + return (abilityToModify instanceof LoreseekersStoneActivatedAbility) && abilityToModify.getSourceId().equals(source.getSourceId()); } @Override public LoreseekersStoneCostIncreasingEffect copy() { return new LoreseekersStoneCostIncreasingEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/l/LotusVale.java b/Mage.Sets/src/mage/cards/l/LotusVale.java index 1d13d07a893..052c1c11eb9 100644 --- a/Mage.Sets/src/mage/cards/l/LotusVale.java +++ b/Mage.Sets/src/mage/cards/l/LotusVale.java @@ -26,7 +26,7 @@ public final class LotusVale extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("two untapped lands"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public LotusVale(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java b/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java index 9499bda49ec..67b4a4bde5d 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java +++ b/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java @@ -53,7 +53,7 @@ class LudevicNecroAlchemistCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); PlayerList playerList = game.getState().getPlayerList().copy(); Player currentPlayer; UUID sourcePlayerId = source.getControllerId(); @@ -65,7 +65,7 @@ class LudevicNecroAlchemistCondition implements Condition { currentPlayer = playerList.getNext(game); while (watcher != null && currentPlayer != null) { - if (!Objects.equals(currentPlayer.getId(), sourcePlayerId) && watcher.getLiveLost(currentPlayer.getId()) > 0) { + if (!Objects.equals(currentPlayer.getId(), sourcePlayerId) && watcher.getLifeLost(currentPlayer.getId()) > 0) { return true; } if (Objects.equals(currentPlayer, firstPlayer)) { diff --git a/Mage.Sets/src/mage/cards/l/LullmageMentor.java b/Mage.Sets/src/mage/cards/l/LullmageMentor.java index eebcda5ac9b..7262f0752cd 100644 --- a/Mage.Sets/src/mage/cards/l/LullmageMentor.java +++ b/Mage.Sets/src/mage/cards/l/LullmageMentor.java @@ -32,7 +32,7 @@ public final class LullmageMentor extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MERFOLK)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public LullmageMentor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/l/LumberingBattlement.java b/Mage.Sets/src/mage/cards/l/LumberingBattlement.java new file mode 100644 index 00000000000..38f3c1022c5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LumberingBattlement.java @@ -0,0 +1,164 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.util.CardUtil; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import static mage.constants.Outcome.Benefit; + +/** + * @author TheElk801 + */ +public final class LumberingBattlement extends CardImpl { + + public LumberingBattlement(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // When Lumbering Battlement enters the battlefield, exile any number of other nontoken creatures you control until it leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new LumberingBattlementEffect()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); + this.addAbility(ability); + + // Lumbering Battlement gets +2/+2 for each card exiled with it. + this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( + LumberingBattlementValue.instance, + LumberingBattlementValue.instance, + Duration.WhileOnBattlefield + ).setText("{this} gets +2/+2 for each card exiled with it."))); + } + + private LumberingBattlement(final LumberingBattlement card) { + super(card); + } + + @Override + public LumberingBattlement copy() { + return new LumberingBattlement(this); + } +} + +class LumberingBattlementEffect extends OneShotEffect { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("other nontoken creatures"); + + static { + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); + } + + LumberingBattlementEffect() { + super(Benefit); + staticText = "exile any number of other nontoken creatures you control until it leaves the battlefield"; + } + + private LumberingBattlementEffect(final LumberingBattlementEffect effect) { + super(effect); + } + + @Override + public LumberingBattlementEffect copy() { + return new LumberingBattlementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent sourcePerm = source.getSourcePermanentIfItStillExists(game); + if (player == null || sourcePerm == null) { + return false; + } + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + if (!player.choose(Outcome.Neutral, target, source.getSourceId(), game)) { + return false; + } + Set cards = new HashSet(); + for (UUID targetId : target.getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + cards.add(permanent); + } + } + return player.moveCardsToExile( + cards, source, game, true, + CardUtil.getCardExileZoneId(game, source), sourcePerm.getIdName() + ); + } +} + +enum LumberingBattlementValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + if (sourceAbility == null) { + return 0; + } + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId( + game, sourceAbility.getSourceId(), + sourceAbility.getSourceObjectZoneChangeCounter() + )); + if (exileZone == null) { + exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, sourceAbility)); + } + if (exileZone == null) { + return 0; + } + int counter = 0; + for (UUID cardId : exileZone) { + Card card = game.getCard(cardId); + if (card != null) { + counter++; + } + } + return 2 * counter; + } + + @Override + public DynamicValue copy() { + return instance; + } + + @Override + public String getMessage() { + return ""; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/l/LuminarchAscension.java b/Mage.Sets/src/mage/cards/l/LuminarchAscension.java index b2710993d13..e0382cabbbb 100644 --- a/Mage.Sets/src/mage/cards/l/LuminarchAscension.java +++ b/Mage.Sets/src/mage/cards/l/LuminarchAscension.java @@ -29,7 +29,7 @@ import mage.watchers.common.PlayerLostLifeWatcher; */ public final class LuminarchAscension extends CardImpl { - private String rule = "At the beginning of each opponent's end step, if you didn't lose life this turn, you may put a quest counter on {this}. (Damage causes loss of life.)"; + private static final String rule = "At the beginning of each opponent's end step, if you didn't lose life this turn, you may put a quest counter on {this}. (Damage causes loss of life.)"; public LuminarchAscension(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); @@ -119,9 +119,9 @@ enum YouLostNoLifeThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { - return (watcher.getLiveLost(source.getControllerId()) == 0); + return (watcher.getLifeLost(source.getControllerId()) == 0); } return false; } diff --git a/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java b/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java index ce678715e65..e35a5c6b043 100644 --- a/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java +++ b/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java @@ -1,7 +1,6 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -10,8 +9,8 @@ import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; @@ -19,15 +18,17 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class LuminatePrimordial extends CardImpl { public LuminatePrimordial(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}{W}"); this.subtype.add(SubType.AVATAR); this.power = new MageInt(4); @@ -38,23 +39,9 @@ public final class LuminatePrimordial extends CardImpl { // When Luminate Primordial enters the battlefield, for each opponent, exile up to one target creature // that player controls and that player gains life equal to its power. - this.addAbility(new EntersBattlefieldTriggeredAbility(new LuminatePrimordialEffect(),false)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for(UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0,1, filter,false); - ability.addTarget(target); - } - } - } + Ability ability = new EntersBattlefieldTriggeredAbility(new LuminatePrimordialEffect(), false); + ability.setTargetAdjuster(LuminatePrimordialAdjuster.instance); + this.addAbility(ability); } public LuminatePrimordial(final LuminatePrimordial card) { @@ -67,6 +54,24 @@ public final class LuminatePrimordial extends CardImpl { } } +enum LuminatePrimordialAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); + filter.add(new ControllerIdPredicate(opponentId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); + ability.addTarget(target); + } + } + } +} + class LuminatePrimordialEffect extends OneShotEffect { public LuminatePrimordialEffect() { @@ -85,7 +90,7 @@ class LuminatePrimordialEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (Target target: source.getTargets()) { + for (Target target : source.getTargets()) { if (target instanceof TargetCreaturePermanent) { Permanent targetCreature = game.getPermanent(target.getFirstTarget()); if (targetCreature != null && !targetCreature.isControlledBy(source.getControllerId())) { diff --git a/Mage.Sets/src/mage/cards/l/LureOfPrey.java b/Mage.Sets/src/mage/cards/l/LureOfPrey.java index c6b81a46c8e..7189a59a681 100644 --- a/Mage.Sets/src/mage/cards/l/LureOfPrey.java +++ b/Mage.Sets/src/mage/cards/l/LureOfPrey.java @@ -69,7 +69,7 @@ class LureOfPreyRestrictionEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getSourceId().equals(source.getSourceId())) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { for (UUID playerId : game.getOpponents(source.getControllerId())) { if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(playerId) != 0) { diff --git a/Mage.Sets/src/mage/cards/m/MacabreMockery.java b/Mage.Sets/src/mage/cards/m/MacabreMockery.java new file mode 100644 index 00000000000..5b63264a564 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MacabreMockery.java @@ -0,0 +1,92 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MacabreMockery extends CardImpl { + + public MacabreMockery(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}{R}"); + + // Put target creature card from an opponent's graveyard onto the battlefield under your control. It gets +2/+0 and gains haste until end of turn. Sacrifice it at the beginning of the next end step. + this.getSpellAbility().addEffect(new MacabreMockeryEffect()); + this.getSpellAbility().addTarget(new TargetCardInOpponentsGraveyard(StaticFilters.FILTER_CARD_CREATURE)); + } + + private MacabreMockery(final MacabreMockery card) { + super(card); + } + + @Override + public MacabreMockery copy() { + return new MacabreMockery(this); + } +} + +class MacabreMockeryEffect extends OneShotEffect { + + MacabreMockeryEffect() { + super(Outcome.PutCreatureInPlay); + staticText = "Put target creature card from an opponent's graveyard onto the battlefield under your control. " + + "It gets +2/+0 and gains haste until end of turn. Sacrifice it at the beginning of the next end step."; + } + + private MacabreMockeryEffect(final MacabreMockeryEffect effect) { + super(effect); + } + + @Override + public MacabreMockeryEffect copy() { + return new MacabreMockeryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (card == null) { + return false; + } + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || !controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { + return false; + } + Permanent permanent = game.getPermanent(card.getId()); + if (permanent == null) { + return false; + } + ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + effect = new BoostTargetEffect(2, 0, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + Effect sacrificeEffect = new SacrificeTargetEffect("exile " + permanent.getLogName()); + sacrificeEffect.setTargetPointer(new FixedTarget(permanent, game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + sacrificeEffect, TargetController.YOU + ), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MacabreWaltz.java b/Mage.Sets/src/mage/cards/m/MacabreWaltz.java index a37c9811ae1..c1623e6f2b1 100644 --- a/Mage.Sets/src/mage/cards/m/MacabreWaltz.java +++ b/Mage.Sets/src/mage/cards/m/MacabreWaltz.java @@ -2,29 +2,31 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.target.common.TargetCardInYourGraveyard; -/** - * - * @author LoneFox +import java.util.UUID; +/** + * @author LoneFox */ public final class MacabreWaltz extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard("creature cards from your graveyard"); + public MacabreWaltz(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); // Return up to two target creature cards from your graveyard to your hand, then discard a card. this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 2, new FilterCreatureCard("creature cards from your graveyard"))); - this.getSpellAbility().addEffect(new DiscardControllerEffect(1)); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 2, filter)); + this.getSpellAbility().addEffect(new DiscardControllerEffect(1).setText(", then discard a card")); } public MacabreWaltz(final MacabreWaltz card) { diff --git a/Mage.Sets/src/mage/cards/m/MadAuntie.java b/Mage.Sets/src/mage/cards/m/MadAuntie.java index 465facd99c9..8e3f29ce38f 100644 --- a/Mage.Sets/src/mage/cards/m/MadAuntie.java +++ b/Mage.Sets/src/mage/cards/m/MadAuntie.java @@ -31,7 +31,7 @@ public final class MadAuntie extends CardImpl { static { filter1.add(new SubtypePredicate(SubType.GOBLIN)); - filter1.add(new AnotherPredicate()); + filter1.add(AnotherPredicate.instance); } public MadAuntie(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MadDog.java b/Mage.Sets/src/mage/cards/m/MadDog.java index f9206d7ec02..17254366cdf 100644 --- a/Mage.Sets/src/mage/cards/m/MadDog.java +++ b/Mage.Sets/src/mage/cards/m/MadDog.java @@ -58,18 +58,18 @@ enum MadDogCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent madDog = game.getPermanent(source.getSourceId()); - PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getSimpleName()); - AttackedThisTurnWatcher watcher2 = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + PermanentsEnteredBattlefieldWatcher watcher = game.getState().getWatcher(PermanentsEnteredBattlefieldWatcher.class); + AttackedThisTurnWatcher watcher2 = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null && watcher2 != null && madDog != null) { // For some reason, compare did not work when checking the lists. Thus the interation. List permanents = watcher.getThisTurnEnteringPermanents(source.getControllerId()); - if (!permanents.stream().noneMatch((p) -> (p.getId().equals(madDog.getId())))) { + if (permanents.stream().anyMatch((p) -> (p.getId().equals(madDog.getId())))) { return false; } Set mor = watcher2.getAttackedThisTurnCreatures(); - if (!mor.stream().noneMatch((m) -> (m.getPermanent(game).equals(madDog)))) { + if (mor.stream().anyMatch((m) -> (m.getPermanent(game).equals(madDog)))) { return false; } return true; // Mad Dog did not come into play this turn nor did he attack this turn. Sacrifice the hound. diff --git a/Mage.Sets/src/mage/cards/m/MaddeningImp.java b/Mage.Sets/src/mage/cards/m/MaddeningImp.java index 72cda096ce9..e76411ba6a1 100644 --- a/Mage.Sets/src/mage/cards/m/MaddeningImp.java +++ b/Mage.Sets/src/mage/cards/m/MaddeningImp.java @@ -160,7 +160,7 @@ class MaddeningImpDelayedDestroyEffect extends OneShotEffect { continue; } // Creatures that attacked are safe. - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null && watcher.getAttackedThisTurnCreatures().contains(mor)) { continue; } diff --git a/Mage.Sets/src/mage/cards/m/MaelstromNexus.java b/Mage.Sets/src/mage/cards/m/MaelstromNexus.java index c88f8d523ce..e1b2c2bde22 100644 --- a/Mage.Sets/src/mage/cards/m/MaelstromNexus.java +++ b/Mage.Sets/src/mage/cards/m/MaelstromNexus.java @@ -69,7 +69,7 @@ class MaelstromNexusGainCascadeFirstSpellEffect extends ContinuousEffectImpl { // only spells cast, so no copies of spells if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; - FirstSpellCastThisTurnWatcher watcher = (FirstSpellCastThisTurnWatcher) game.getState().getWatchers().get(FirstSpellCastThisTurnWatcher.class.getSimpleName()); + FirstSpellCastThisTurnWatcher watcher = game.getState().getWatcher(FirstSpellCastThisTurnWatcher.class); if (watcher != null && spell.getId().equals(watcher.getIdOfFirstCastSpell(source.getControllerId()))) { game.getState().addOtherAbility(spell.getCard(), cascadeAbility); } diff --git a/Mage.Sets/src/mage/cards/m/MageRingNetwork.java b/Mage.Sets/src/mage/cards/m/MageRingNetwork.java index 3edaf7279c8..21506a8beca 100644 --- a/Mage.Sets/src/mage/cards/m/MageRingNetwork.java +++ b/Mage.Sets/src/mage/cards/m/MageRingNetwork.java @@ -39,7 +39,7 @@ public final class MageRingNetwork extends CardImpl { // {T}, Remove any number of storage counters from Mage-Ring Network: Add {C} for each storage counter removed this way. ability = new DynamicManaAbility( Mana.ColorlessMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {C} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/m/MagetaTheLion.java b/Mage.Sets/src/mage/cards/m/MagetaTheLion.java index 1a665bf335c..ac3636dcf5c 100644 --- a/Mage.Sets/src/mage/cards/m/MagetaTheLion.java +++ b/Mage.Sets/src/mage/cards/m/MagetaTheLion.java @@ -31,7 +31,7 @@ public final class MagetaTheLion extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MagetaTheLion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MagisterOfWorth.java b/Mage.Sets/src/mage/cards/m/MagisterOfWorth.java index 289c1294458..4a0067ac5cf 100644 --- a/Mage.Sets/src/mage/cards/m/MagisterOfWorth.java +++ b/Mage.Sets/src/mage/cards/m/MagisterOfWorth.java @@ -92,7 +92,7 @@ class MagisterOfWorthVoteEffect extends OneShotEffect { new MagisterOfWorthReturnFromGraveyardEffect().apply(game, source); } else { FilterPermanent filter = new FilterCreaturePermanent("creatures other than {this}"); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); new DestroyAllEffect(filter).apply(game, source); } return true; diff --git a/Mage.Sets/src/mage/cards/m/MagmaBurst.java b/Mage.Sets/src/mage/cards/m/MagmaBurst.java index 761e9fd419a..5d81a3b4bda 100644 --- a/Mage.Sets/src/mage/cards/m/MagmaBurst.java +++ b/Mage.Sets/src/mage/cards/m/MagmaBurst.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.KickedCondition; import mage.abilities.costs.common.SacrificeTargetCost; @@ -13,18 +12,17 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; -import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetControlledPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LoneFox - * */ public final class MagmaBurst extends CardImpl { - private final UUID originalId; - public MagmaBurst(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}"); @@ -32,21 +30,13 @@ public final class MagmaBurst extends CardImpl { this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("two lands"), true)))); // Magma Burst deals 3 damage to any target. If Magma Burst was kicked, it deals 3 damage to another any target. Effect effect = new DamageTargetEffect(3); - effect.setText("{this} deals 3 damage to any target. if this spell was kicked, it deals 3 damage to another target."); + effect.setText("{this} deals 3 damage to any target. If this spell was kicked, it deals 3 damage to another target."); this.getSpellAbility().addEffect(effect); - originalId = this.getSpellAbility().getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.addTarget(new TargetAnyTarget(KickedCondition.instance.apply(game, ability) ? 2 : 1)); - } + this.getSpellAbility().setTargetAdjuster(MagmaBurstAdjuster.instance); } public MagmaBurst(final MagmaBurst card) { super(card); - this.originalId = card.originalId; } @Override @@ -54,3 +44,12 @@ public final class MagmaBurst extends CardImpl { return new MagmaBurst(this); } } + +enum MagmaBurstAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.addTarget(new TargetAnyTarget(KickedCondition.instance.apply(game, ability) ? 2 : 1)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/Magmaquake.java b/Mage.Sets/src/mage/cards/m/Magmaquake.java index 98e00ba168f..4522a2d70b7 100644 --- a/Mage.Sets/src/mage/cards/m/Magmaquake.java +++ b/Mage.Sets/src/mage/cards/m/Magmaquake.java @@ -34,7 +34,7 @@ public final class Magmaquake extends CardImpl { // Magmaquake deals X damage to each creature without flying and each planeswalker. - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, filter)); } public Magmaquake(final Magmaquake card) { diff --git a/Mage.Sets/src/mage/cards/m/MagneticMountain.java b/Mage.Sets/src/mage/cards/m/MagneticMountain.java index 5cb79401b80..92f9b301943 100644 --- a/Mage.Sets/src/mage/cards/m/MagneticMountain.java +++ b/Mage.Sets/src/mage/cards/m/MagneticMountain.java @@ -65,7 +65,7 @@ class MagneticMountainEffect extends OneShotEffect { static { filter2.add(new ColorPredicate(ObjectColor.BLUE)); - filter2.add(new TappedPredicate()); + filter2.add(TappedPredicate.instance); } MagneticMountainEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java index 5ee6f042a78..26a6b6e3e2e 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java @@ -78,7 +78,10 @@ class MagusOfTheMindEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); + if(watcher == null){ + return false; + } int stormCount = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() + 1; if (controller != null && sourceObject != null) { controller.shuffleLibrary(source, game); diff --git a/Mage.Sets/src/mage/cards/m/MajesticHeliopterus.java b/Mage.Sets/src/mage/cards/m/MajesticHeliopterus.java index 3ce444d6cf8..a302dcb0e5e 100644 --- a/Mage.Sets/src/mage/cards/m/MajesticHeliopterus.java +++ b/Mage.Sets/src/mage/cards/m/MajesticHeliopterus.java @@ -27,7 +27,7 @@ public final class MajesticHeliopterus extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target Dinosaur you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DINOSAUR)); } public MajesticHeliopterus(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MalakirSoothsayer.java b/Mage.Sets/src/mage/cards/m/MalakirSoothsayer.java index a53374fa6e6..e55d840ec1a 100644 --- a/Mage.Sets/src/mage/cards/m/MalakirSoothsayer.java +++ b/Mage.Sets/src/mage/cards/m/MalakirSoothsayer.java @@ -31,7 +31,7 @@ public final class MalakirSoothsayer extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MalakirSoothsayer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MaliciousAdvice.java b/Mage.Sets/src/mage/cards/m/MaliciousAdvice.java index 610edcb5894..b75bb70a686 100644 --- a/Mage.Sets/src/mage/cards/m/MaliciousAdvice.java +++ b/Mage.Sets/src/mage/cards/m/MaliciousAdvice.java @@ -1,9 +1,7 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; @@ -16,38 +14,24 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LoneFox */ public final class MaliciousAdvice extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("artifacts, creatures, and/or lands"); - - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.ARTIFACT), - new CardTypePredicate(CardType.CREATURE), - new CardTypePredicate(CardType.LAND))); - } - public MaliciousAdvice(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}{B}"); // Tap X target artifacts, creatures, and/or lands. You lose X life. Effect effect = new TapTargetEffect(); - effect.setText("X target artifacts, creatures, and/or lands"); + effect.setText("X target artifacts, creatures, and/or lands."); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(new ManacostVariableValue())); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - ability.addTarget(new TargetPermanent(ability.getManaCostsToPay().getX(), filter)); - } + this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(ManacostVariableValue.instance)); + this.getSpellAbility().setTargetAdjuster(MaliciousAdviceAdjuster.instance); } public MaliciousAdvice(final MaliciousAdvice card) { @@ -59,3 +43,22 @@ public final class MaliciousAdvice extends CardImpl { return new MaliciousAdvice(this); } } + +enum MaliciousAdviceAdjuster implements TargetAdjuster { + instance; + private static final FilterPermanent filter = new FilterPermanent("artifacts, creatures, and/or lands"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND) + )); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetPermanent(ability.getManaCostsToPay().getX(), filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/Malignus.java b/Mage.Sets/src/mage/cards/m/Malignus.java index 7db53127549..156ede533cf 100644 --- a/Mage.Sets/src/mage/cards/m/Malignus.java +++ b/Mage.Sets/src/mage/cards/m/Malignus.java @@ -74,7 +74,7 @@ class HighestLifeTotalAmongOpponentsCount implements DynamicValue { @Override public DynamicValue copy() { - return new CardsInControllerHandCount(); + return CardsInControllerHandCount.instance; } @Override diff --git a/Mage.Sets/src/mage/cards/m/ManaCache.java b/Mage.Sets/src/mage/cards/m/ManaCache.java index 75437573ac8..54cb19a0bac 100644 --- a/Mage.Sets/src/mage/cards/m/ManaCache.java +++ b/Mage.Sets/src/mage/cards/m/ManaCache.java @@ -59,7 +59,7 @@ class ManaCacheEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ManaCacheEffect() { diff --git a/Mage.Sets/src/mage/cards/m/ManaClash.java b/Mage.Sets/src/mage/cards/m/ManaClash.java index 4c8fe0ee5c4..af3dba45bca 100644 --- a/Mage.Sets/src/mage/cards/m/ManaClash.java +++ b/Mage.Sets/src/mage/cards/m/ManaClash.java @@ -62,8 +62,8 @@ class ManaClashEffect extends OneShotEffect { if (!targetOpponent.canRespond() || !controller.canRespond()) { return false; } - boolean controllerFlip = controller.flipCoin(game); - boolean opponentFlip = targetOpponent.flipCoin(game); + boolean controllerFlip = controller.flipCoin(source, game, false); + boolean opponentFlip = targetOpponent.flipCoin(source, game, false); if (controllerFlip && opponentFlip) { bothHeads = true; } diff --git a/Mage.Sets/src/mage/cards/m/ManaCrypt.java b/Mage.Sets/src/mage/cards/m/ManaCrypt.java index 90535e37a6c..51c09adc938 100644 --- a/Mage.Sets/src/mage/cards/m/ManaCrypt.java +++ b/Mage.Sets/src/mage/cards/m/ManaCrypt.java @@ -58,7 +58,7 @@ class ManaCryptEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { player.damage(3, source.getSourceId(), game, false, true); } return true; diff --git a/Mage.Sets/src/mage/cards/m/ManaGeyser.java b/Mage.Sets/src/mage/cards/m/ManaGeyser.java index 7e752d2ee9d..1069b455208 100644 --- a/Mage.Sets/src/mage/cards/m/ManaGeyser.java +++ b/Mage.Sets/src/mage/cards/m/ManaGeyser.java @@ -21,7 +21,7 @@ public final class ManaGeyser extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent("tapped land your opponents control"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerPredicate(TargetController.OPPONENT)); } public ManaGeyser(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/ManaMaze.java b/Mage.Sets/src/mage/cards/m/ManaMaze.java index 29502df744e..2ff6f483348 100644 --- a/Mage.Sets/src/mage/cards/m/ManaMaze.java +++ b/Mage.Sets/src/mage/cards/m/ManaMaze.java @@ -63,7 +63,7 @@ class ManaMazeEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { Card card = game.getCard(event.getSourceId()); if (card != null) { - LastSpellCastWatcher watcher = (LastSpellCastWatcher) game.getState().getWatchers().get(LastSpellCastWatcher.class.getSimpleName()); + LastSpellCastWatcher watcher = game.getState().getWatcher(LastSpellCastWatcher.class); if (watcher != null && watcher.lastSpellCast != null) { return !card.getColor(game).intersection(watcher.lastSpellCast.getColor(game)).isColorless(); } @@ -87,7 +87,7 @@ class LastSpellCastWatcher extends Watcher { Spell lastSpellCast = null; public LastSpellCastWatcher() { - super(LastSpellCastWatcher.class.getSimpleName(), WatcherScope.GAME); + super(LastSpellCastWatcher.class, WatcherScope.GAME); } public LastSpellCastWatcher(final LastSpellCastWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/m/ManaScrew.java b/Mage.Sets/src/mage/cards/m/ManaScrew.java index f2228b428bc..24b3514c9ee 100644 --- a/Mage.Sets/src/mage/cards/m/ManaScrew.java +++ b/Mage.Sets/src/mage/cards/m/ManaScrew.java @@ -88,7 +88,7 @@ class ManaScrewEffect extends BasicManaEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - if (player != null && player.flipCoin(game)) { + if (player != null && player.flipCoin(source, game, true)) { player.getManaPool().addMana(getMana(game, source), game, source); } return true; diff --git a/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java b/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java index 7d5a219f10c..866ab25de72 100644 --- a/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java +++ b/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java @@ -52,12 +52,12 @@ public final class MarathWillOfTheWild extends CardImpl { this.toughness = new MageInt(0); // Marath, Will of the Wild enters the battlefield with a number of +1/+1 counters on it equal to the amount of mana spent to cast it. - Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new ManaSpentToCastCount(), true); + Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), ManaSpentToCastCount.instance, true); effect.setText("with a number of +1/+1 counters on it equal to the amount of mana spent to cast it"); this.addAbility(new EntersBattlefieldAbility(effect)); // {X}, Remove X +1/+1 counters from Marath: Choose one - Put X +1/+1 counters on target creature; - effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), new ManacostVariableValue()); + effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), ManacostVariableValue.instance); effect.setText("Put X +1/+1 counters on target creature"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new MarathWillOfTheWildRemoveCountersCost()); @@ -65,7 +65,7 @@ public final class MarathWillOfTheWild extends CardImpl { // or Marath deals X damage to any target; Mode mode = new Mode(); - mode.addEffect(new DamageTargetEffect(new ManacostVariableValue())); + mode.addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); mode.addTarget(new TargetAnyTarget()); ability.addMode(mode); @@ -132,7 +132,7 @@ class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - int amount = new ManacostVariableValue().calculate(game, source, this); + int amount = ManacostVariableValue.instance.calculate(game, source, this); Token token = new MarathWillOfTheWildElementalToken(); token.getPower().modifyBaseValue(amount); token.getToughness().modifyBaseValue(amount); @@ -165,7 +165,7 @@ class MarathWillOfTheWildRemoveCountersCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - int amount = new ManacostVariableValue().calculate(game, ability, null); + int amount = ManacostVariableValue.instance.calculate(game, ability, null); Permanent permanent = game.getPermanent(sourceId); if (permanent != null && permanent.getCounters(game).getCount(CounterType.P1P1) >= amount) { permanent.removeCounters(CounterType.P1P1.getName(), amount, game); diff --git a/Mage.Sets/src/mage/cards/m/MaraudingBoneslasher.java b/Mage.Sets/src/mage/cards/m/MaraudingBoneslasher.java index dfe8f338075..63ce40b3c2f 100644 --- a/Mage.Sets/src/mage/cards/m/MaraudingBoneslasher.java +++ b/Mage.Sets/src/mage/cards/m/MaraudingBoneslasher.java @@ -24,7 +24,7 @@ public final class MaraudingBoneslasher extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ZOMBIE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MaraudingBoneslasher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MaraxusOfKeld.java b/Mage.Sets/src/mage/cards/m/MaraxusOfKeld.java index 3619d29b3fd..9d560a6bb06 100644 --- a/Mage.Sets/src/mage/cards/m/MaraxusOfKeld.java +++ b/Mage.Sets/src/mage/cards/m/MaraxusOfKeld.java @@ -27,7 +27,7 @@ public final class MaraxusOfKeld extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped artifacts, creatures, and lands you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE), diff --git a/Mage.Sets/src/mage/cards/m/MarchOfSouls.java b/Mage.Sets/src/mage/cards/m/MarchOfSouls.java index e8b392c6f70..afb8a682f0e 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfSouls.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfSouls.java @@ -13,19 +13,16 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.SpiritWhiteToken; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; /** - * * @author LoneFox - */ public final class MarchOfSouls extends CardImpl { public MarchOfSouls(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}"); // Destroy all creatures. They can't be regenerated. For each creature destroyed this way, its controller creates a 1/1 white Spirit creature token with flying. this.getSpellAbility().addEffect(new MarchOfSoulsEffect()); @@ -59,22 +56,18 @@ class MarchOfSoulsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - List creatures = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, - source.getControllerId(), source.getSourceId(), game); Map playersWithCreatures = new HashMap<>(); - for(Permanent p : creatures) { + for (Permanent p : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURES, + source.getControllerId(), source.getSourceId(), game + )) { UUID controllerId = p.getControllerId(); - if(p.destroy(source.getSourceId(), game, true)) { - if(playersWithCreatures.containsKey(controllerId)) { - playersWithCreatures.put(controllerId, playersWithCreatures.get(controllerId) + 1); - } - else { - playersWithCreatures.put(controllerId, 1); - } + if (p.destroy(source.getSourceId(), game, true)) { + playersWithCreatures.put(controllerId, playersWithCreatures.getOrDefault(controllerId, 0) + 1); } } SpiritWhiteToken token = new SpiritWhiteToken(); - for(UUID playerId : playersWithCreatures.keySet()) { + for (UUID playerId : playersWithCreatures.keySet()) { token.putOntoBattlefield(playersWithCreatures.get(playerId), game, source.getSourceId(), playerId); } return true; diff --git a/Mage.Sets/src/mage/cards/m/MarchOfTheMultitudes.java b/Mage.Sets/src/mage/cards/m/MarchOfTheMultitudes.java index b15c38640f8..1f6f9fe5a4d 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfTheMultitudes.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfTheMultitudes.java @@ -24,7 +24,7 @@ public final class MarchOfTheMultitudes extends CardImpl { // Create X 1/1 white Soldier creature tokens with lifelink. this.getSpellAbility().addEffect(new CreateTokenEffect( new SoldierLifelinkToken(), - new ManacostVariableValue() + ManacostVariableValue.instance )); } diff --git a/Mage.Sets/src/mage/cards/m/MarduAscendancy.java b/Mage.Sets/src/mage/cards/m/MarduAscendancy.java index f7e370116ce..d821628d156 100644 --- a/Mage.Sets/src/mage/cards/m/MarduAscendancy.java +++ b/Mage.Sets/src/mage/cards/m/MarduAscendancy.java @@ -30,7 +30,7 @@ public final class MarduAscendancy extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control"); static { - attackFilter.add(Predicates.not(new TokenPredicate())); + attackFilter.add(Predicates.not(TokenPredicate.instance)); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/m/MarkovCrusader.java b/Mage.Sets/src/mage/cards/m/MarkovCrusader.java index 9df87e68fc5..328a6f715fa 100644 --- a/Mage.Sets/src/mage/cards/m/MarkovCrusader.java +++ b/Mage.Sets/src/mage/cards/m/MarkovCrusader.java @@ -29,7 +29,7 @@ public final class MarkovCrusader extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Vampire"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/m/Maro.java b/Mage.Sets/src/mage/cards/m/Maro.java index e611397388c..68bd5c1faf2 100644 --- a/Mage.Sets/src/mage/cards/m/Maro.java +++ b/Mage.Sets/src/mage/cards/m/Maro.java @@ -27,7 +27,7 @@ public final class Maro extends CardImpl { this.toughness = new MageInt(0); // Maro's power and toughness are each equal to the number of cards in your hand. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInControllerHandCount(), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(CardsInControllerHandCount.instance, Duration.EndOfGame))); } public Maro(final Maro card) { diff --git a/Mage.Sets/src/mage/cards/m/MarshalingTheTroops.java b/Mage.Sets/src/mage/cards/m/MarshalingTheTroops.java index 5f4a56391ff..ac37de8471c 100644 --- a/Mage.Sets/src/mage/cards/m/MarshalingTheTroops.java +++ b/Mage.Sets/src/mage/cards/m/MarshalingTheTroops.java @@ -49,7 +49,7 @@ class MarshalingTheTroopsEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MarshalingTheTroopsEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java b/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java index 39c3a3503da..9fc03f6d555 100644 --- a/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java +++ b/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java @@ -1,80 +1,55 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; -import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.MultikickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author jeffwadsworth - * */ public final class MarshalsAnthem extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control"); - private static final FilterCard filterCard = new FilterCard("creature card in your graveyard"); - - static { - filter.add(new ControllerPredicate(TargetController.YOU)); - filterCard.add(new CardTypePredicate(CardType.CREATURE)); - } - - private final UUID originalId; + private static final String rule = "return up to X target creature cards from your graveyard to the battlefield, " + + "where X is the number of times {this} was kicked"; public MarshalsAnthem(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // Multikicker {1}{W} this.addAbility(new MultikickerAbility("{1}{W}")); // Creatures you control get +1/+1. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, false))); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield) + )); // When Marshal's Anthem enters the battlefield, return up to X target creature cards from your graveyard to the battlefield, where X is the number of times Marshal's Anthem was kicked. - //TODO this should always trigger, even if it wasn't kicked - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false), - KickedCondition.instance, - "When {this} enters the battlefield, return up to X target creature cards from your graveyard to the battlefield, where X is the number of times {this} was kicked."); - originalId = ability.getOriginalId(); + Ability ability = new EntersBattlefieldTriggeredAbility( + new ReturnFromGraveyardToBattlefieldTargetEffect().setText(rule), false + ); + ability.setTargetAdjuster(MarshalsAnthemAdjuster.instance); this.addAbility(ability); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - int numbTargets = new MultikickerCount().calculate(game, ability, null); - if (numbTargets > 0) { - ability.addTarget(new TargetCardInYourGraveyard(0, numbTargets, filterCard)); - } - } } public MarshalsAnthem(final MarshalsAnthem card) { super(card); - this.originalId = card.originalId; } @Override @@ -82,3 +57,17 @@ public final class MarshalsAnthem extends CardImpl { return new MarshalsAnthem(this); } } + +enum MarshalsAnthemAdjuster implements TargetAdjuster { + instance; + private static final FilterCard filter = new FilterCreatureCard("creature card in your graveyard"); + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numbTargets = MultikickerCount.instance.calculate(game, ability, null); + if (numbTargets > 0) { + ability.addTarget(new TargetCardInYourGraveyard(0, numbTargets, filter)); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MartonStromgald.java b/Mage.Sets/src/mage/cards/m/MartonStromgald.java index bc3a6cee4e0..1bfecf2a857 100644 --- a/Mage.Sets/src/mage/cards/m/MartonStromgald.java +++ b/Mage.Sets/src/mage/cards/m/MartonStromgald.java @@ -27,8 +27,8 @@ public final class MartonStromgald extends CardImpl { private static final FilterBlockingCreature blockingFilter = new FilterBlockingCreature("blocking creature other than {this}"); static { - attackingFilter.add(new AnotherPredicate()); - blockingFilter.add(new AnotherPredicate()); + attackingFilter.add(AnotherPredicate.instance); + blockingFilter.add(AnotherPredicate.instance); } public MartonStromgald(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfAshes.java b/Mage.Sets/src/mage/cards/m/MartyrOfAshes.java index 9a99586b08a..c43c8a45e2d 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrOfAshes.java +++ b/Mage.Sets/src/mage/cards/m/MartyrOfAshes.java @@ -48,7 +48,7 @@ public final class MartyrOfAshes extends CardImpl { this.toughness = new MageInt(1); // {2}, Reveal X red cards from your hand, Sacrifice Martyr of Ashes: Martyr of Ashes deals X damage to each creature without flying. - Effect effect = new DamageAllEffect(new RevealTargetFromHandCostCount(), filterCreature); + Effect effect = new DamageAllEffect(RevealTargetFromHandCostCount.instance, filterCreature); effect.setText("Martyr of Ashes deals X damage to each creature without flying."); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2)); ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, Integer.MAX_VALUE, filterHand))); diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfBones.java b/Mage.Sets/src/mage/cards/m/MartyrOfBones.java index e280e71f9ed..a90e986f1b8 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrOfBones.java +++ b/Mage.Sets/src/mage/cards/m/MartyrOfBones.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -25,17 +24,17 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInASingleGraveyard; import mage.target.common.TargetCardInHand; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author emerald000 */ public final class MartyrOfBones extends CardImpl { - private final UUID originalId; - public MartyrOfBones(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -49,27 +48,12 @@ public final class MartyrOfBones extends CardImpl { ability.addCost(new RevealVariableBlackCardsFromHandCost()); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCardInASingleGraveyard(0, 1, new FilterCard("cards in a single graveyard"))); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(MartyrOfBonesAdjuster.instance); this.addAbility(ability); } public MartyrOfBones(final MartyrOfBones card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int amount = 0; - for (Cost cost : ability.getCosts()) { - if (cost instanceof RevealVariableBlackCardsFromHandCost) { - amount = ((VariableCost) cost).getAmount(); - } - } - ability.getTargets().clear(); - ability.addTarget(new TargetCardInASingleGraveyard(0, amount, new FilterCard())); - } } @Override @@ -78,6 +62,22 @@ public final class MartyrOfBones extends CardImpl { } } +enum MartyrOfBonesAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int amount = 0; + for (Cost cost : ability.getCosts()) { + if (cost instanceof RevealVariableBlackCardsFromHandCost) { + amount = ((VariableCost) cost).getAmount(); + } + } + ability.getTargets().clear(); + ability.addTarget(new TargetCardInASingleGraveyard(0, amount, new FilterCard())); + } +} + class RevealVariableBlackCardsFromHandCost extends VariableCostImpl { private static final FilterCard filter = new FilterCard("X black cards from your hand"); diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfFrost.java b/Mage.Sets/src/mage/cards/m/MartyrOfFrost.java index 44e48efe62c..5ec56acb5ae 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrOfFrost.java +++ b/Mage.Sets/src/mage/cards/m/MartyrOfFrost.java @@ -42,7 +42,7 @@ public final class MartyrOfFrost extends CardImpl { this.toughness = new MageInt(1); // {2}, Reveal X blue cards from your hand, Sacrifice Martyr of Frost: Counter target spell unless its controller pays {X}. - Effect effect = new CounterUnlessPaysEffect(new RevealTargetFromHandCostCount()); + Effect effect = new CounterUnlessPaysEffect(RevealTargetFromHandCostCount.instance); effect.setText("Counter target spell unless its controller pays {X}."); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2)); ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, Integer.MAX_VALUE, filter))); diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfSands.java b/Mage.Sets/src/mage/cards/m/MartyrOfSands.java index 5076f87b2fb..d6c7baa4635 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrOfSands.java +++ b/Mage.Sets/src/mage/cards/m/MartyrOfSands.java @@ -43,7 +43,7 @@ public final class MartyrOfSands extends CardImpl { this.toughness = new MageInt(1); // {1}, Reveal X white cards from your hand, Sacrifice Martyr of Sands: You gain three times X life. - Effect effect = new GainLifeEffect(new MultipliedValue(new RevealTargetFromHandCostCount(), 3)); + Effect effect = new GainLifeEffect(new MultipliedValue(RevealTargetFromHandCostCount.instance, 3)); effect.setText("You gain three times X life."); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}")); ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, Integer.MAX_VALUE, filter))); diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfSpores.java b/Mage.Sets/src/mage/cards/m/MartyrOfSpores.java index 160441a376f..4bb1335d443 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrOfSpores.java +++ b/Mage.Sets/src/mage/cards/m/MartyrOfSpores.java @@ -43,7 +43,7 @@ public final class MartyrOfSpores extends CardImpl { this.toughness = new MageInt(1); // {1}, Reveal X green cards from your hand, Sacrifice Martyr of Spores: Target creature gets +X/+X until end of turn. - Effect effect = new BoostTargetEffect(new RevealTargetFromHandCostCount(), new RevealTargetFromHandCostCount(), Duration.EndOfTurn, true); + Effect effect = new BoostTargetEffect(RevealTargetFromHandCostCount.instance, RevealTargetFromHandCostCount.instance, Duration.EndOfTurn, true); effect.setText("Target creature gets +X/+X until end of turn."); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(1)); ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, Integer.MAX_VALUE, filter))); diff --git a/Mage.Sets/src/mage/cards/m/Martyrdom.java b/Mage.Sets/src/mage/cards/m/Martyrdom.java index b684ec48b71..067ad072787 100644 --- a/Mage.Sets/src/mage/cards/m/Martyrdom.java +++ b/Mage.Sets/src/mage/cards/m/Martyrdom.java @@ -94,11 +94,6 @@ class MartyrdomActivatedAbility extends ActivatedAbilityImpl { this.caster = ability.caster; } - @Override - public Effects getEffects(Game game, EffectType effectType) { - return super.getEffects(game, effectType); - } - @Override public ActivationStatus canActivate(UUID playerId, Game game) { if (playerId.equals(caster)) { diff --git a/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java b/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java index 8a237ea8793..353450b9829 100644 --- a/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java +++ b/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java @@ -25,7 +25,7 @@ public final class MarwynTheNurturer extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Elf"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.ELF)); } diff --git a/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java b/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java index f13d5931d53..776aa88b33b 100644 --- a/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java +++ b/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java @@ -31,7 +31,7 @@ public final class MaskOfTheMimic extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public MaskOfTheMimic(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MassManipulation.java b/Mage.Sets/src/mage/cards/m/MassManipulation.java new file mode 100644 index 00000000000..61104d45bb0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MassManipulation.java @@ -0,0 +1,50 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.game.Game; +import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MassManipulation extends CardImpl { + + public MassManipulation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{U}{U}{U}{U}"); + + // Gain control of X target creatures and/or planeswalkers. + this.getSpellAbility().addEffect( + new GainControlTargetEffect(Duration.Custom, true) + .setText("Gain control of X target creatures and/or planeswalkers.") + ); + this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker()); + this.getSpellAbility().setTargetAdjuster(MassManipulationAdjuster.instance); + } + + private MassManipulation(final MassManipulation card) { + super(card); + } + + @Override + public MassManipulation copy() { + return new MassManipulation(this); + } +} + +enum MassManipulationAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreatureOrPlaneswalker(ability.getManaCostsToPay().getX())); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MassMutiny.java b/Mage.Sets/src/mage/cards/m/MassMutiny.java index 10a9549d8be..1ca9b18e39c 100644 --- a/Mage.Sets/src/mage/cards/m/MassMutiny.java +++ b/Mage.Sets/src/mage/cards/m/MassMutiny.java @@ -1,9 +1,7 @@ - package mage.cards.m; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; @@ -21,6 +19,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; /** @@ -34,22 +33,7 @@ public final class MassMutiny extends CardImpl { // For each opponent, gain control of up to one target creature that player controls until end of turn. Untap those creatures. They gain haste until end of turn. this.getSpellAbility().addEffect(new MassMutinyEffect()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - } + this.getSpellAbility().setTargetAdjuster(MassMutinyAdjuster.instance); } public MassMutiny(final MassMutiny card) { @@ -62,6 +46,24 @@ public final class MassMutiny extends CardImpl { } } +enum MassMutinyAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getName()); + filter.add(new ControllerIdPredicate(opponentId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); + ability.addTarget(target); + } + } + } +} + class MassMutinyEffect extends OneShotEffect { public MassMutinyEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MasterApothecary.java b/Mage.Sets/src/mage/cards/m/MasterApothecary.java index c7e02a7431c..bb44e92b0dc 100644 --- a/Mage.Sets/src/mage/cards/m/MasterApothecary.java +++ b/Mage.Sets/src/mage/cards/m/MasterApothecary.java @@ -30,7 +30,7 @@ public final class MasterApothecary extends CardImpl { static { filter.add(new SubtypePredicate(SubType.CLERIC)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MasterApothecary(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java b/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java index 00e6affcea9..f54b0f4c509 100644 --- a/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java +++ b/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java @@ -22,7 +22,7 @@ public final class MasterOfDiversion extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public MasterOfDiversion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java b/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java index a4bb0aa626e..ec5f5d5fc50 100644 --- a/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java +++ b/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java @@ -69,7 +69,7 @@ class MasterOfTheWildHuntEffect extends OneShotEffect { static { filter.add(new SubtypePredicate(SubType.WOLF)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MasterOfTheWildHuntEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MasterTheWay.java b/Mage.Sets/src/mage/cards/m/MasterTheWay.java index 9325793aa83..e3fc9243cf4 100644 --- a/Mage.Sets/src/mage/cards/m/MasterTheWay.java +++ b/Mage.Sets/src/mage/cards/m/MasterTheWay.java @@ -23,7 +23,7 @@ public final class MasterTheWay extends CardImpl { // Draw a card. Master the Way deals damage to any target equal to the number of cards in your hand. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); - Effect effect = new DamageTargetEffect(new CardsInControllerHandCount()); + Effect effect = new DamageTargetEffect(CardsInControllerHandCount.instance); effect.setText("{this} deals damage to any target equal to the number of cards in your hand"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java index a5861363c57..ea80d6b2aae 100644 --- a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java +++ b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java @@ -79,7 +79,7 @@ public final class MasterWarcraft extends CardImpl { @Override public boolean apply(Game game, Ability source) { - MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName()); + MasterWarcraftCastWatcher watcher = game.getState().getWatcher(MasterWarcraftCastWatcher.class); if (watcher != null) { watcher.increment(); return true; @@ -105,7 +105,7 @@ public final class MasterWarcraft extends CardImpl { @Override public boolean apply(Game game, Ability source) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); if (watcher != null) { watcher.increment(); return true; @@ -153,7 +153,10 @@ class MasterWarcraftChooseAttackersEffect extends ContinuousRuleModifyingEffectI @Override public boolean applies(GameEvent event, Ability source, Game game) { - MasterWarcraftCastWatcher watcher = (MasterWarcraftCastWatcher) game.getState().getWatchers().get(MasterWarcraftCastWatcher.class.getSimpleName()); + MasterWarcraftCastWatcher watcher = game.getState().getWatcher(MasterWarcraftCastWatcher.class); + if(watcher == null){ + return false; + } watcher.decrement(); if (watcher.copyCountApply > 0) { game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); @@ -226,7 +229,10 @@ class MasterWarcraftChooseBlockersEffect extends ContinuousRuleModifyingEffectIm @Override public boolean applies(GameEvent event, Ability source, Game game) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); + if(watcher == null){ + return false; + } watcher.decrement(); if (watcher.copyCountApply > 0) { game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply"); diff --git a/Mage.Sets/src/mage/cards/m/MasumaroFirstToLive.java b/Mage.Sets/src/mage/cards/m/MasumaroFirstToLive.java index e7721a06a81..3e67265849d 100644 --- a/Mage.Sets/src/mage/cards/m/MasumaroFirstToLive.java +++ b/Mage.Sets/src/mage/cards/m/MasumaroFirstToLive.java @@ -32,7 +32,7 @@ public final class MasumaroFirstToLive extends CardImpl { this.toughness = new MageInt(0); // Masumaro, First to Live's power and toughness are each equal to twice the number of cards in your hand. - DynamicValue xValue= new MultipliedValue(new CardsInControllerHandCount(), 2); + DynamicValue xValue= new MultipliedValue(CardsInControllerHandCount.instance, 2); Effect effect = new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame); effect.setText("{this}'s power and toughness are each equal to twice the number of cards in your hand"); this.addAbility(new SimpleStaticAbility(Zone.ALL, effect)); diff --git a/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java b/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java index 45ab9cb6320..8c17f8b06a9 100644 --- a/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java +++ b/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java @@ -28,7 +28,7 @@ public final class MausoleumHarpy extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/m/MausoleumWanderer.java b/Mage.Sets/src/mage/cards/m/MausoleumWanderer.java index a77aef89b91..b37f3779c8f 100644 --- a/Mage.Sets/src/mage/cards/m/MausoleumWanderer.java +++ b/Mage.Sets/src/mage/cards/m/MausoleumWanderer.java @@ -31,7 +31,7 @@ public final class MausoleumWanderer extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.SPIRIT)); } diff --git a/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java b/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java index a0b101ebcb4..98fe12b17d7 100644 --- a/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java +++ b/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java @@ -57,7 +57,7 @@ class MavrenFeinDuskApostleTriggeredAbility extends TriggeredAbilityImpl { static { filter.add(new SubtypePredicate(SubType.VAMPIRE)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/m/MazeAbomination.java b/Mage.Sets/src/mage/cards/m/MazeAbomination.java index 7168099bec2..751d9ee3fa5 100644 --- a/Mage.Sets/src/mage/cards/m/MazeAbomination.java +++ b/Mage.Sets/src/mage/cards/m/MazeAbomination.java @@ -26,7 +26,7 @@ public final class MazeAbomination extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Multicolored creatures you control"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public MazeAbomination (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MazeBehemoth.java b/Mage.Sets/src/mage/cards/m/MazeBehemoth.java index ddeb6ec6f22..a9b69d81d15 100644 --- a/Mage.Sets/src/mage/cards/m/MazeBehemoth.java +++ b/Mage.Sets/src/mage/cards/m/MazeBehemoth.java @@ -26,7 +26,7 @@ public final class MazeBehemoth extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Multicolored creatures you control"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public MazeBehemoth (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MazeGlider.java b/Mage.Sets/src/mage/cards/m/MazeGlider.java index 1e58b2d741e..b39b8301ba5 100644 --- a/Mage.Sets/src/mage/cards/m/MazeGlider.java +++ b/Mage.Sets/src/mage/cards/m/MazeGlider.java @@ -26,7 +26,7 @@ public final class MazeGlider extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Multicolored creatures you control"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public MazeGlider (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MazeRusher.java b/Mage.Sets/src/mage/cards/m/MazeRusher.java index 995e865c6e6..aed3e120bba 100644 --- a/Mage.Sets/src/mage/cards/m/MazeRusher.java +++ b/Mage.Sets/src/mage/cards/m/MazeRusher.java @@ -26,7 +26,7 @@ public final class MazeRusher extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Multicolored creatures you control"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public MazeRusher (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MazeSentinel.java b/Mage.Sets/src/mage/cards/m/MazeSentinel.java index 11218b098a0..357af8a3988 100644 --- a/Mage.Sets/src/mage/cards/m/MazeSentinel.java +++ b/Mage.Sets/src/mage/cards/m/MazeSentinel.java @@ -26,7 +26,7 @@ public final class MazeSentinel extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Multicolored creatures you control"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public MazeSentinel (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MeishinTheMindCage.java b/Mage.Sets/src/mage/cards/m/MeishinTheMindCage.java index 2d29f4215a1..a88e657705d 100644 --- a/Mage.Sets/src/mage/cards/m/MeishinTheMindCage.java +++ b/Mage.Sets/src/mage/cards/m/MeishinTheMindCage.java @@ -26,7 +26,7 @@ public final class MeishinTheMindCage extends CardImpl { addSuperType(SuperType.LEGENDARY); // All creatures get -X/-0, where X is the number of cards in your hand. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new SignInversionDynamicValue(new CardsInControllerHandCount()), new StaticValue(0), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE, false, "All creatures get -X/-0, where X is the number of cards in your hand"))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new SignInversionDynamicValue(CardsInControllerHandCount.instance), new StaticValue(0), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE, false, "All creatures get -X/-0, where X is the number of cards in your hand"))); } public MeishinTheMindCage(final MeishinTheMindCage card) { diff --git a/Mage.Sets/src/mage/cards/m/Melee.java b/Mage.Sets/src/mage/cards/m/Melee.java index 3031c15e649..4fe220c0276 100644 --- a/Mage.Sets/src/mage/cards/m/Melee.java +++ b/Mage.Sets/src/mage/cards/m/Melee.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; @@ -17,19 +16,21 @@ import mage.abilities.effects.common.RemoveFromCombatTargetEffect; import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TurnPhase; import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; -import mage.watchers.Watcher; import mage.watchers.common.ChooseBlockersRedundancyWatcher; +import java.util.UUID; + /** - * * @author L_J */ public final class Melee extends CardImpl { @@ -61,27 +62,27 @@ public final class Melee extends CardImpl { public Melee copy() { return new Melee(this); } - + private class ChooseBlockersRedundancyWatcherIncrementEffect extends OneShotEffect { - + ChooseBlockersRedundancyWatcherIncrementEffect() { super(Outcome.Neutral); } - + ChooseBlockersRedundancyWatcherIncrementEffect(final ChooseBlockersRedundancyWatcherIncrementEffect effect) { super(effect); } - + @Override public boolean apply(Game game, Ability source) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); if (watcher != null) { watcher.increment(); return true; } return false; } - + @Override public ChooseBlockersRedundancyWatcherIncrementEffect copy() { return new ChooseBlockersRedundancyWatcherIncrementEffect(this); @@ -117,7 +118,10 @@ class MeleeChooseBlockersEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); + if (watcher == null) { + return false; + } watcher.decrement(); watcher.copyCount--; if (watcher.copyCountApply > 0) { diff --git a/Mage.Sets/src/mage/cards/m/MemoryCrystal.java b/Mage.Sets/src/mage/cards/m/MemoryCrystal.java index 2da9818be48..00d1411e834 100644 --- a/Mage.Sets/src/mage/cards/m/MemoryCrystal.java +++ b/Mage.Sets/src/mage/cards/m/MemoryCrystal.java @@ -61,7 +61,7 @@ class MemoryCrystalSpellsCostReductionEffect extends CostModificationEffectImpl if (card != null) { for (Ability ability : card.getAbilities()) { if (ability instanceof BuybackAbility) { - if (((BuybackAbility) ability).isActivated()) { + if (ability.isActivated()) { int amountToReduce = ((BuybackAbility) ability).reduceCost(2); CardUtil.reduceCost(abilityToModify, amountToReduce); } diff --git a/Mage.Sets/src/mage/cards/m/MentorOfTheMeek.java b/Mage.Sets/src/mage/cards/m/MentorOfTheMeek.java index 116cd617b66..7e007dec24e 100644 --- a/Mage.Sets/src/mage/cards/m/MentorOfTheMeek.java +++ b/Mage.Sets/src/mage/cards/m/MentorOfTheMeek.java @@ -28,7 +28,7 @@ public final class MentorOfTheMeek extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another creature with power 2 or less"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); } diff --git a/Mage.Sets/src/mage/cards/m/MercadianAtlas.java b/Mage.Sets/src/mage/cards/m/MercadianAtlas.java index c2d980a6ed3..5fb9e90c5a0 100644 --- a/Mage.Sets/src/mage/cards/m/MercadianAtlas.java +++ b/Mage.Sets/src/mage/cards/m/MercadianAtlas.java @@ -49,7 +49,7 @@ enum MercadianAtlasCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayLandWatcher watcher = (PlayLandWatcher) game.getState().getWatchers().get(PlayLandWatcher.class.getSimpleName()); + PlayLandWatcher watcher = game.getState().getWatcher(PlayLandWatcher.class); if (watcher != null) { return !watcher.landPlayed(source.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/m/MercadianBazaar.java b/Mage.Sets/src/mage/cards/m/MercadianBazaar.java index dc03c83a538..aadd3bbe450 100644 --- a/Mage.Sets/src/mage/cards/m/MercadianBazaar.java +++ b/Mage.Sets/src/mage/cards/m/MercadianBazaar.java @@ -34,7 +34,7 @@ public final class MercadianBazaar extends CardImpl { // {tap}, Remove any number of storage counters from Mercadian Bazaar: Add {R} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.RedMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {R} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/m/MercenaryInformer.java b/Mage.Sets/src/mage/cards/m/MercenaryInformer.java index 44cb9245b47..e50658d5fa6 100644 --- a/Mage.Sets/src/mage/cards/m/MercenaryInformer.java +++ b/Mage.Sets/src/mage/cards/m/MercenaryInformer.java @@ -36,7 +36,7 @@ public final class MercenaryInformer extends CardImpl { static { filterBlack.add(new ColorPredicate(ObjectColor.BLACK)); - filterMercenary.add(Predicates.not(new TokenPredicate())); + filterMercenary.add(Predicates.not(TokenPredicate.instance)); filterMercenary.add(new SubtypePredicate(SubType.MERCENARY)); } diff --git a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java index 2c59d904fc3..d63af5b129c 100644 --- a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java +++ b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java @@ -116,7 +116,7 @@ class TapXTargetCost extends VariableCostImpl { final static FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("untapped artifacts you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public TapXTargetCost() { diff --git a/Mage.Sets/src/mage/cards/m/MercurialChemister.java b/Mage.Sets/src/mage/cards/m/MercurialChemister.java index 9365da620db..b3390f455ec 100644 --- a/Mage.Sets/src/mage/cards/m/MercurialChemister.java +++ b/Mage.Sets/src/mage/cards/m/MercurialChemister.java @@ -39,7 +39,7 @@ public final class MercurialChemister extends CardImpl { this.addAbility(ability); // {R}, {T}, Discard a card: Mercurial Chemister deals damage to target creature equal to the discarded card's converted mana cost. - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new DiscardCostCardConvertedMana()), new ManaCostsImpl("{R}")); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(DiscardCostCardConvertedMana.instance), new ManaCostsImpl("{R}")); ability.addTarget(new TargetCreaturePermanent()); ability.addCost(new TapSourceCost()); ability.addCost(new DiscardCardCost()); diff --git a/Mage.Sets/src/mage/cards/m/MercurialGeists.java b/Mage.Sets/src/mage/cards/m/MercurialGeists.java index 4842ee08274..f0749140073 100644 --- a/Mage.Sets/src/mage/cards/m/MercurialGeists.java +++ b/Mage.Sets/src/mage/cards/m/MercurialGeists.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; @@ -9,18 +7,19 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author fireshoes */ public final class MercurialGeists extends CardImpl { public MercurialGeists(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(1); this.toughness = new MageInt(3); @@ -29,7 +28,7 @@ public final class MercurialGeists extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever you cast an instant or sorcery spell, Mercurial Geists gets +3/+0 until end of turn. - this.addAbility(new SpellCastControllerTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false)); } public MercurialGeists(final MercurialGeists card) { diff --git a/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java b/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java index 9845b838450..0e1dfd36cbb 100644 --- a/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java +++ b/Mage.Sets/src/mage/cards/m/MerenOfClanNelToth.java @@ -32,7 +32,7 @@ public final class MerenOfClanNelToth extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/m/MerrowBonegnawer.java b/Mage.Sets/src/mage/cards/m/MerrowBonegnawer.java index 0b533c9260d..f274496308c 100644 --- a/Mage.Sets/src/mage/cards/m/MerrowBonegnawer.java +++ b/Mage.Sets/src/mage/cards/m/MerrowBonegnawer.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -20,14 +19,13 @@ import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class MerrowBonegnawer extends CardImpl { - private UUID exileId = UUID.randomUUID(); - private static final FilterSpell filter = new FilterSpell("a black spell"); static { @@ -43,7 +41,7 @@ public final class MerrowBonegnawer extends CardImpl { this.toughness = new MageInt(1); // {tap}: Target player exiles a card from their graveyard. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileFromZoneTargetEffect(Zone.GRAVEYARD, exileId, getIdName(), new FilterCard()), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileFromZoneTargetEffect(Zone.GRAVEYARD, null, getIdName(), new FilterCard()), new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/Merseine.java b/Mage.Sets/src/mage/cards/m/Merseine.java index 836365c8502..cec4a052dce 100644 --- a/Mage.Sets/src/mage/cards/m/Merseine.java +++ b/Mage.Sets/src/mage/cards/m/Merseine.java @@ -77,11 +77,6 @@ class MerseineActivatedAbility extends SimpleActivatedAbility { super(ability); } - @Override - public Effects getEffects(Game game, EffectType effectType) { - return super.getEffects(game, effectType); - } - @Override public ActivationStatus canActivate(UUID playerId, Game game) { Permanent sourcePermanent = game.getBattlefield().getPermanent(this.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/m/MesmerizingBenthid.java b/Mage.Sets/src/mage/cards/m/MesmerizingBenthid.java new file mode 100644 index 00000000000..330da204905 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MesmerizingBenthid.java @@ -0,0 +1,56 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.permanent.token.MesmerizingBenthidToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MesmerizingBenthid extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(SubType.ILLUSION); + + public MesmerizingBenthid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); + + this.subtype.add(SubType.OCTOPUS); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // When Mesmerizing Benthid enters the battlefield, create two 0/2 blue Illusion creature tokens with "Whenever this creature blocks a creature, that creature doesn't untap during its controller's next untap step." + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new MesmerizingBenthidToken(), 2) + )); + + // Mesmerizing Benthid has hexproof as long as you control an Illusion. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(HexproofAbility.getInstance()), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} has hexproof as long as you control an Illusion." + ))); + } + + private MesmerizingBenthid(final MesmerizingBenthid card) { + super(card); + } + + @Override + public MesmerizingBenthid copy() { + return new MesmerizingBenthid(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MetalspinnersPuzzleknot.java b/Mage.Sets/src/mage/cards/m/MetalspinnersPuzzleknot.java index 38acc7c2cc2..377521781dd 100644 --- a/Mage.Sets/src/mage/cards/m/MetalspinnersPuzzleknot.java +++ b/Mage.Sets/src/mage/cards/m/MetalspinnersPuzzleknot.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -15,22 +13,21 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author emerald000 */ public final class MetalspinnersPuzzleknot extends CardImpl { public MetalspinnersPuzzleknot(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // When Metalspinner's Puzzleknot enters the battlefield, you draw a card and you lose 1 life. - Effect drawEffect = new DrawCardSourceControllerEffect(1); - drawEffect.setText("you draw a card"); + Effect drawEffect = new DrawCardSourceControllerEffect(1, "you"); Ability ability = new EntersBattlefieldTriggeredAbility(drawEffect); Effect lifeEffect = new LoseLifeSourceControllerEffect(1); - lifeEffect.setText("and you lose 1 life"); - ability.addEffect(lifeEffect); + ability.addEffect(lifeEffect.concatBy("and")); this.addAbility(ability); // {2}{B}, Sacrifice Metalspinner's Puzzleknot: You draw a card and you lose 1 life. diff --git a/Mage.Sets/src/mage/cards/m/MeteorBlast.java b/Mage.Sets/src/mage/cards/m/MeteorBlast.java index fb57f84cce0..9331bce50dc 100644 --- a/Mage.Sets/src/mage/cards/m/MeteorBlast.java +++ b/Mage.Sets/src/mage/cards/m/MeteorBlast.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -13,6 +12,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetAnyTarget; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -21,7 +21,7 @@ import mage.target.common.TargetAnyTarget; public final class MeteorBlast extends CardImpl { public MeteorBlast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}{R}{R}"); // Meteor Blast deals 4 damage to each of X target creatures and/or players. this.getSpellAbility().addEffect(new MeteorBlastEffect()); @@ -31,6 +31,15 @@ public final class MeteorBlast extends CardImpl { super(card); } + @Override + public MeteorBlast copy() { + return new MeteorBlast(this); + } +} + +enum MeteorBlastAdjuster implements TargetAdjuster { + instance; + @Override public void adjustTargets(Ability ability, Game game) { int xValue = ability.getManaCostsToPay().getX(); @@ -39,11 +48,6 @@ public final class MeteorBlast extends CardImpl { ability.addTarget(target); } } - - @Override - public MeteorBlast copy() { - return new MeteorBlast(this); - } } class MeteorBlastEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/cards/m/MeteorShower.java b/Mage.Sets/src/mage/cards/m/MeteorShower.java index 9c8031c50df..2fa2390c042 100644 --- a/Mage.Sets/src/mage/cards/m/MeteorShower.java +++ b/Mage.Sets/src/mage/cards/m/MeteorShower.java @@ -21,7 +21,7 @@ public final class MeteorShower extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{R}"); // Meteor Shower deals X plus 1 damage divided as you choose among any number of target creatures and/or players. - DynamicValue xValue = new IntPlusDynamicValue(1, new ManacostVariableValue()); + DynamicValue xValue = new IntPlusDynamicValue(1, ManacostVariableValue.instance); this.getSpellAbility().addEffect(new DamageMultiEffect(xValue)); this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue)); } diff --git a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java index 0b77db95408..5288f951286 100644 --- a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java +++ b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java @@ -90,7 +90,7 @@ class MetzaliTowerOfTriumphEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Watcher watcher = game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + Watcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher instanceof AttackedThisTurnWatcher) { Set attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures(); List available = new ArrayList<>(); diff --git a/Mage.Sets/src/mage/cards/m/MidnightEntourage.java b/Mage.Sets/src/mage/cards/m/MidnightEntourage.java index 9c0843b6d7f..4fdd87ec210 100644 --- a/Mage.Sets/src/mage/cards/m/MidnightEntourage.java +++ b/Mage.Sets/src/mage/cards/m/MidnightEntourage.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesThisOrAnotherCreatureTriggeredAbility; @@ -17,8 +15,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; +import java.util.UUID; + /** - * * @author Styxo */ public final class MidnightEntourage extends CardImpl { @@ -42,10 +41,9 @@ public final class MidnightEntourage extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); // Whenever Midnight Entourage or another Aetherborn you control dies, you draw a card and you lose 1 life. - Ability ability = new DiesThisOrAnotherCreatureTriggeredAbility(new DrawCardSourceControllerEffect(1), false, filter); + Ability ability = new DiesThisOrAnotherCreatureTriggeredAbility(new DrawCardSourceControllerEffect(1, "you"), false, filter); Effect effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - ability.addEffect(effect); + ability.addEffect(effect.concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MidnightGuard.java b/Mage.Sets/src/mage/cards/m/MidnightGuard.java index b0c76111bcf..3019134b08f 100644 --- a/Mage.Sets/src/mage/cards/m/MidnightGuard.java +++ b/Mage.Sets/src/mage/cards/m/MidnightGuard.java @@ -21,7 +21,7 @@ public final class MidnightGuard extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MidnightGuard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MidnightReaper.java b/Mage.Sets/src/mage/cards/m/MidnightReaper.java index 5af4535203d..cfe9c74eb99 100644 --- a/Mage.Sets/src/mage/cards/m/MidnightReaper.java +++ b/Mage.Sets/src/mage/cards/m/MidnightReaper.java @@ -27,7 +27,7 @@ public final class MidnightReaper extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public MidnightReaper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MidnightRitual.java b/Mage.Sets/src/mage/cards/m/MidnightRitual.java index 23205ab2542..08ccd0518a6 100644 --- a/Mage.Sets/src/mage/cards/m/MidnightRitual.java +++ b/Mage.Sets/src/mage/cards/m/MidnightRitual.java @@ -1,9 +1,7 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,9 +15,11 @@ import mage.game.Game; import mage.game.permanent.token.ZombieToken; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author Skyler Sell */ public final class MidnightRitual extends CardImpl { @@ -31,14 +31,7 @@ public final class MidnightRitual extends CardImpl { // For each creature card exiled this way, create a 2/2 black Zombie creature token. this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); this.getSpellAbility().addEffect(new MidnightRitualEffect()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - ability.addTarget(new TargetCardInYourGraveyard(ability.getManaCostsToPay().getX(), StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); - } + this.getSpellAbility().setTargetAdjuster(MidnightRitualAdjuster.instance); } public MidnightRitual(final MidnightRitual card) { @@ -51,6 +44,16 @@ public final class MidnightRitual extends CardImpl { } } +enum MidnightRitualAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard(ability.getManaCostsToPay().getX(), StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + } +} + class MidnightRitualEffect extends OneShotEffect { public MidnightRitualEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MightOfOldKrosa.java b/Mage.Sets/src/mage/cards/m/MightOfOldKrosa.java index fb603636a0f..ac0fe3ed0f5 100644 --- a/Mage.Sets/src/mage/cards/m/MightOfOldKrosa.java +++ b/Mage.Sets/src/mage/cards/m/MightOfOldKrosa.java @@ -3,7 +3,7 @@ package mage.cards.m; import java.util.UUID; import mage.abilities.condition.LockedInCondition; -import mage.abilities.condition.common.MyMainPhaseCondition; +import mage.abilities.condition.common.AddendumCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; @@ -25,7 +25,7 @@ public final class MightOfOldKrosa extends CardImpl { this.getSpellAbility().addEffect(new ConditionalContinuousEffect( new BoostTargetEffect(4,4, Duration.EndOfTurn), new BoostTargetEffect(2, 2, Duration.EndOfTurn), - new LockedInCondition(MyMainPhaseCondition.instance), + new LockedInCondition(AddendumCondition.instance), "Target creature gets +2/+2 until end of turn. If you cast this spell during your main phase, that creature gets +4/+4 until end of turn instead")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/m/Mightstone.java b/Mage.Sets/src/mage/cards/m/Mightstone.java index f7922170fde..bb36bf9e8de 100644 --- a/Mage.Sets/src/mage/cards/m/Mightstone.java +++ b/Mage.Sets/src/mage/cards/m/Mightstone.java @@ -21,7 +21,7 @@ public final class Mightstone extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creatures"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public Mightstone(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MijaeDjinn.java b/Mage.Sets/src/mage/cards/m/MijaeDjinn.java index 7407d86d66e..6ec0f9b8d1d 100644 --- a/Mage.Sets/src/mage/cards/m/MijaeDjinn.java +++ b/Mage.Sets/src/mage/cards/m/MijaeDjinn.java @@ -57,7 +57,7 @@ class MijaeDjinnEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent creature = game.getPermanent(source.getSourceId()); if (controller != null && creature != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { return true; } else { creature.removeFromCombat(game); diff --git a/Mage.Sets/src/mage/cards/m/MikaeusTheLunarch.java b/Mage.Sets/src/mage/cards/m/MikaeusTheLunarch.java index 5e0a0a04976..7f72fa46f41 100644 --- a/Mage.Sets/src/mage/cards/m/MikaeusTheLunarch.java +++ b/Mage.Sets/src/mage/cards/m/MikaeusTheLunarch.java @@ -30,7 +30,7 @@ public final class MikaeusTheLunarch extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MikaeusTheLunarch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MilitantAngel.java b/Mage.Sets/src/mage/cards/m/MilitantAngel.java index 790f1e62c17..c1ff666a0dd 100644 --- a/Mage.Sets/src/mage/cards/m/MilitantAngel.java +++ b/Mage.Sets/src/mage/cards/m/MilitantAngel.java @@ -33,7 +33,7 @@ public final class MilitantAngel extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // When Militant Angel enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn. - Effect effect = new CreateTokenEffect(new KnightToken(), new AttackedThisTurnOpponentsCount()); + Effect effect = new CreateTokenEffect(new KnightToken(), AttackedThisTurnOpponentsCount.instance); effect.setText("create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn"); this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); } diff --git a/Mage.Sets/src/mage/cards/m/MilitiasPride.java b/Mage.Sets/src/mage/cards/m/MilitiasPride.java index 1f23407eb24..5d413d911c0 100644 --- a/Mage.Sets/src/mage/cards/m/MilitiasPride.java +++ b/Mage.Sets/src/mage/cards/m/MilitiasPride.java @@ -63,8 +63,8 @@ class MilitiasPrideTriggerAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(Predicates.not(new TokenPredicate())); - Permanent permanent = (Permanent) game.getPermanent(event.getSourceId()); + filter.add(Predicates.not(TokenPredicate.instance)); + Permanent permanent = game.getPermanent(event.getSourceId()); return permanent != null && filter.match(permanent, sourceId, controllerId, game); } diff --git a/Mage.Sets/src/mage/cards/m/MindShatter.java b/Mage.Sets/src/mage/cards/m/MindShatter.java index 244b241f933..8e048a27ab7 100644 --- a/Mage.Sets/src/mage/cards/m/MindShatter.java +++ b/Mage.Sets/src/mage/cards/m/MindShatter.java @@ -19,7 +19,7 @@ public final class MindShatter extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}{B}"); // Target player discards X cards at random. - this.getSpellAbility().addEffect(new DiscardTargetEffect(new ManacostVariableValue(), true)); + this.getSpellAbility().addEffect(new DiscardTargetEffect(ManacostVariableValue.instance, true)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/m/MindSpring.java b/Mage.Sets/src/mage/cards/m/MindSpring.java index f327dde9c9e..58b59946328 100644 --- a/Mage.Sets/src/mage/cards/m/MindSpring.java +++ b/Mage.Sets/src/mage/cards/m/MindSpring.java @@ -18,7 +18,7 @@ public final class MindSpring extends CardImpl { public MindSpring(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}{U}"); - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(ManacostVariableValue.instance)); } public MindSpring(final MindSpring card) { diff --git a/Mage.Sets/src/mage/cards/m/MindTwist.java b/Mage.Sets/src/mage/cards/m/MindTwist.java index 1b1b377ffcd..bddc25745ab 100644 --- a/Mage.Sets/src/mage/cards/m/MindTwist.java +++ b/Mage.Sets/src/mage/cards/m/MindTwist.java @@ -20,7 +20,7 @@ public final class MindTwist extends CardImpl { // Target player discards X cards at random. - this.getSpellAbility().addEffect(new DiscardTargetEffect(new ManacostVariableValue(), true)); + this.getSpellAbility().addEffect(new DiscardTargetEffect(ManacostVariableValue.instance, true)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/m/MindWarp.java b/Mage.Sets/src/mage/cards/m/MindWarp.java index c82cf55fb61..3db8935245e 100644 --- a/Mage.Sets/src/mage/cards/m/MindWarp.java +++ b/Mage.Sets/src/mage/cards/m/MindWarp.java @@ -28,7 +28,7 @@ public final class MindWarp extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{3}{B}"); // Look at target player's hand and choose X cards from it. That player discards those cards. - this.getSpellAbility().addEffect(new MindWarpEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new MindWarpEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/m/MindbreakTrap.java b/Mage.Sets/src/mage/cards/m/MindbreakTrap.java index 253fc6ef504..9fc7ea6c507 100644 --- a/Mage.Sets/src/mage/cards/m/MindbreakTrap.java +++ b/Mage.Sets/src/mage/cards/m/MindbreakTrap.java @@ -52,7 +52,7 @@ enum MindbreakTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(opponentId) > 2) { diff --git a/Mage.Sets/src/mage/cards/m/MindsDilation.java b/Mage.Sets/src/mage/cards/m/MindsDilation.java index 941ef597ace..b3a7c6381f2 100644 --- a/Mage.Sets/src/mage/cards/m/MindsDilation.java +++ b/Mage.Sets/src/mage/cards/m/MindsDilation.java @@ -65,7 +65,7 @@ class MindsDilationTriggeredAbility extends SpellCastOpponentTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(event.getPlayerId()); if (spells != null && spells.size() == 1) { diff --git a/Mage.Sets/src/mage/cards/m/MindstormCrown.java b/Mage.Sets/src/mage/cards/m/MindstormCrown.java index c186f02a157..7748a50006c 100644 --- a/Mage.Sets/src/mage/cards/m/MindstormCrown.java +++ b/Mage.Sets/src/mage/cards/m/MindstormCrown.java @@ -63,7 +63,7 @@ class MindstormCrownEffect extends OneShotEffect { if (player == null) { return false; } - MindstormCrownWatcher watcher = (MindstormCrownWatcher) game.getState().getWatchers().get(MindstormCrownWatcher.class.getSimpleName()); + MindstormCrownWatcher watcher = game.getState().getWatcher(MindstormCrownWatcher.class); if (watcher != null && watcher.getCardsInHandCount() == 0) { player.drawCards(1, game); } else { @@ -80,7 +80,7 @@ class MindstormCrownWatcher extends Watcher { private int cardsInHandCount; public MindstormCrownWatcher() { - super(MindstormCrownWatcher.class.getSimpleName(), WatcherScope.GAME); + super(MindstormCrownWatcher.class, WatcherScope.GAME); } public MindstormCrownWatcher(final MindstormCrownWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/m/Mindswipe.java b/Mage.Sets/src/mage/cards/m/Mindswipe.java index fbfa217fd31..1650b14967c 100644 --- a/Mage.Sets/src/mage/cards/m/Mindswipe.java +++ b/Mage.Sets/src/mage/cards/m/Mindswipe.java @@ -29,7 +29,7 @@ public final class Mindswipe extends CardImpl { // Counter target spell unless its controller pays {X}. Mindswipe deals X damage to that spell's controller. - Effect effect = new CounterUnlessPaysEffect(new ManacostVariableValue()); + Effect effect = new CounterUnlessPaysEffect(ManacostVariableValue.instance); effect.setText("Counter target spell unless its controller pays {X}."); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetSpell()); @@ -74,7 +74,7 @@ class MindswipeEffect extends OneShotEffect { Spell spell = (Spell) object; Player spellController = game.getPlayer(spell.getControllerId()); if (spellController != null) { - int damage = new ManacostVariableValue().calculate(game, source, this); + int damage = ManacostVariableValue.instance.calculate(game, source, this); spellController.damage(damage, source.getSourceId(), game, false, true); } return true; diff --git a/Mage.Sets/src/mage/cards/m/MineMineMine.java b/Mage.Sets/src/mage/cards/m/MineMineMine.java index b5c54f0dad2..4d227ec47f8 100644 --- a/Mage.Sets/src/mage/cards/m/MineMineMine.java +++ b/Mage.Sets/src/mage/cards/m/MineMineMine.java @@ -33,7 +33,7 @@ public final class MineMineMine extends CardImpl { public MineMineMine(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); - // When Mine, Mine, Mine enters the battlefield, each player puts his or her library into his or her hand. + // When Mine, Mine, Mine enters the battlefield, each player puts their library into their hand. this.addAbility(new EntersBattlefieldTriggeredAbility(new MineMineMineDrawEffect())); // Players have no maximum hand size and don't lose the game for drawing from an empty library. @@ -45,7 +45,7 @@ public final class MineMineMine extends CardImpl { // Each player can't cast more than one spell each turn. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantCastMoreThanOneSpellEffect(TargetController.ANY))); - // When Mine, Mine, Mine leaves the battlefield, each player shuffles his or her hand and graveyard into his or her library. + // When Mine, Mine, Mine leaves the battlefield, each player shuffles their hand and graveyard into their library. this.addAbility(new LeavesBattlefieldTriggeredAbility(new ShuffleHandGraveyardAllEffect(), false)); } diff --git a/Mage.Sets/src/mage/cards/m/MinionOfLeshrac.java b/Mage.Sets/src/mage/cards/m/MinionOfLeshrac.java index a8dabd9b207..154468baf30 100644 --- a/Mage.Sets/src/mage/cards/m/MinionOfLeshrac.java +++ b/Mage.Sets/src/mage/cards/m/MinionOfLeshrac.java @@ -92,7 +92,7 @@ class MinionLeshracEffect extends OneShotEffect { && minionLeshrac != null) { FilterControlledPermanent filterCreature = new FilterControlledPermanent(); filterCreature.add(new CardTypePredicate(CardType.CREATURE)); - filterCreature.add(new AnotherPredicate()); + filterCreature.add(AnotherPredicate.instance); TargetControlledPermanent target = new TargetControlledPermanent(filterCreature); SacrificeTargetCost cost = new SacrificeTargetCost(target); if (controller.chooseUse(Outcome.AIDontUseIt, "Do you wish to sacrifice another creature to prevent the 5 damage to you?", source, game) diff --git a/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java b/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java index 5b5fce962fe..25ff9a740de 100644 --- a/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java +++ b/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -13,17 +11,13 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author L_J */ public final class MinionOfTheWastes extends CardImpl { @@ -39,7 +33,7 @@ public final class MinionOfTheWastes extends CardImpl { // As Minion of the Wastes enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards. this.addAbility(new AsEntersBattlefieldAbility(new MinionOfTheWastesEffect())); - + // Minion of the Wastes's power and toughness are each equal to the life paid as it entered the battlefield. this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield"))); } @@ -74,10 +68,10 @@ class MinionOfTheWastesEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Card sourceCard = game.getCard(source.getSourceId()); int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of life", game); controller.loseLife(payAmount, game, false); - game.informPlayers(sourceCard.getLogName() + ": " + controller.getLogName() + + Card sourceCard = game.getCard(source.getSourceId()); + game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() + " pays " + payAmount + " life"); game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source); return true; diff --git a/Mage.Sets/src/mage/cards/m/MinionReflector.java b/Mage.Sets/src/mage/cards/m/MinionReflector.java index a4226643089..31da2e28812 100644 --- a/Mage.Sets/src/mage/cards/m/MinionReflector.java +++ b/Mage.Sets/src/mage/cards/m/MinionReflector.java @@ -35,7 +35,7 @@ public final class MinionReflector extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public MinionReflector(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MinistrantOfObligation.java b/Mage.Sets/src/mage/cards/m/MinistrantOfObligation.java new file mode 100644 index 00000000000..48c3fda6035 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MinistrantOfObligation.java @@ -0,0 +1,37 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.keyword.AfterlifeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MinistrantOfObligation extends CardImpl { + + public MinistrantOfObligation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Afterlife 2 + this.addAbility(new AfterlifeAbility(2)); + } + + private MinistrantOfObligation(final MinistrantOfObligation card) { + super(card); + } + + @Override + public MinistrantOfObligation copy() { + return new MinistrantOfObligation(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MirrorEntity.java b/Mage.Sets/src/mage/cards/m/MirrorEntity.java index b5246cc7e3b..9174db87c9e 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorEntity.java +++ b/Mage.Sets/src/mage/cards/m/MirrorEntity.java @@ -40,7 +40,7 @@ public final class MirrorEntity extends CardImpl { // Changeling this.addAbility(ChangelingAbility.getInstance()); // {X}: Until end of turn, creatures you control have base power and toughness X/X and gain all creature types. - DynamicValue variableMana = new ManacostVariableValue(); + DynamicValue variableMana = ManacostVariableValue.instance; Effect effect = new SetPowerToughnessAllEffect(variableMana, variableMana, Duration.EndOfTurn, filter, true); effect.setText("Until end of turn, creatures you control have base power and toughness X/X"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new VariableManaCost()); diff --git a/Mage.Sets/src/mage/cards/m/MirrorMarch.java b/Mage.Sets/src/mage/cards/m/MirrorMarch.java new file mode 100644 index 00000000000..c68bf6b03ad --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MirrorMarch.java @@ -0,0 +1,95 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MirrorMarch extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("nontoken creature"); + + static { + filter.add(Predicates.not(TokenPredicate.instance)); + } + + public MirrorMarch(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{R}"); + + // Whenever a nontoken creature enters the battlefield under your control, flip a coin until you lose a flip. For each flip you won, create a token that's a copy of that creature. Those tokens gain haste. Exile them at the beginning of the next end step. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, new MirrorMarchEffect(), filter, false, SetTargetPointer.PERMANENT, + "Whenever a nontoken creature enters the battlefield under your control, " + + "flip a coin until you lose a flip. For each flip you won, " + + "create a token that's a copy of that creature. Those tokens gain haste. " + + "Exile them at the beginning of the next end step." + )); + } + + private MirrorMarch(final MirrorMarch card) { + super(card); + } + + @Override + public MirrorMarch copy() { + return new MirrorMarch(this); + } +} + +class MirrorMarchEffect extends OneShotEffect { + + MirrorMarchEffect() { + super(Outcome.Benefit); + } + + private MirrorMarchEffect(final MirrorMarchEffect effect) { + super(effect); + } + + @Override + public MirrorMarchEffect copy() { + return new MirrorMarchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + int counter = 0; + boolean wonFlip = false; + do { + wonFlip = player.flipCoin(source, game, true); + if (wonFlip) { + counter++; + } + } while (wonFlip); + if (counter > 0) { + CreateTokenCopyTargetEffect effect + = new CreateTokenCopyTargetEffect(player.getId(), null, true, counter); + effect.setUseLKI(true); + effect.setTargetPointer(targetPointer); + effect.apply(game, source); + effect.exileTokensCreatedAtNextEndStep(game, source); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MirrorStrike.java b/Mage.Sets/src/mage/cards/m/MirrorStrike.java index b76e9ff5693..f6f38df4317 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorStrike.java +++ b/Mage.Sets/src/mage/cards/m/MirrorStrike.java @@ -29,7 +29,7 @@ public final class MirrorStrike extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked creature"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } public MirrorStrike(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/Mirrorworks.java b/Mage.Sets/src/mage/cards/m/Mirrorworks.java index 80d47816576..c96992b9a42 100644 --- a/Mage.Sets/src/mage/cards/m/Mirrorworks.java +++ b/Mage.Sets/src/mage/cards/m/Mirrorworks.java @@ -26,8 +26,8 @@ public final class Mirrorworks extends CardImpl { private final static FilterArtifactPermanent filter = new FilterArtifactPermanent("another nontoken artifact"); static { - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public Mirrorworks(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/Mise.java b/Mage.Sets/src/mage/cards/m/Mise.java index 23cdc07e72c..06074b560f1 100644 --- a/Mage.Sets/src/mage/cards/m/Mise.java +++ b/Mage.Sets/src/mage/cards/m/Mise.java @@ -52,7 +52,7 @@ class MiseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - Object object = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + Object object = game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (player != null && object instanceof String) { Card card = player.getLibrary().getFromTop(game); String namedCard = (String) object; diff --git a/Mage.Sets/src/mage/cards/m/MishrasSelfReplicator.java b/Mage.Sets/src/mage/cards/m/MishrasSelfReplicator.java index 351049efa76..709731b01e4 100644 --- a/Mage.Sets/src/mage/cards/m/MishrasSelfReplicator.java +++ b/Mage.Sets/src/mage/cards/m/MishrasSelfReplicator.java @@ -23,7 +23,7 @@ public final class MishrasSelfReplicator extends CardImpl { private static final FilterSpell filter = new FilterSpell("a historic spell"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public MishrasSelfReplicator(UUID ownerId, CardSetInfo setInfo) { @@ -37,7 +37,7 @@ public final class MishrasSelfReplicator extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid( new CreateTokenCopySourceEffect() .setText("create a token that's a copy of {this}. (Artifacts, legendaries, and Sagas are historic.)"), - new ManaCostsImpl("{1}")), filter, true)); + new ManaCostsImpl("{1}")), filter, false)); } diff --git a/Mage.Sets/src/mage/cards/m/Mistcaller.java b/Mage.Sets/src/mage/cards/m/Mistcaller.java index 88f7d3952ed..e2bef655e5c 100644 --- a/Mage.Sets/src/mage/cards/m/Mistcaller.java +++ b/Mage.Sets/src/mage/cards/m/Mistcaller.java @@ -1,6 +1,5 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -8,21 +7,18 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.players.Player; import mage.watchers.common.CreatureWasCastWatcher; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class Mistcaller extends CardImpl { @@ -96,14 +92,14 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { Card card = game.getCard(event.getTargetId()); - Object entersTransformed = game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId()); - if (entersTransformed instanceof Boolean && (Boolean) entersTransformed && card.getSecondCardFace() != null) { - card = card.getSecondCardFace(); - } - if (card.isCreature()) { // TODO: Bestow Card cast as Enchantment probably not handled correctly - CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get(CreatureWasCastWatcher.class.getSimpleName()); - if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { - return true; + if (card != null) { + Object entersTransformed = game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + event.getTargetId()); + if (entersTransformed instanceof Boolean && (Boolean) entersTransformed && card.getSecondCardFace() != null) { + card = card.getSecondCardFace(); + } + if (card != null && card.isCreature()) { // TODO: Bestow Card cast as Enchantment probably not handled correctly + CreatureWasCastWatcher watcher = game.getState().getWatcher(CreatureWasCastWatcher.class); + return watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId()); } } } diff --git a/Mage.Sets/src/mage/cards/m/MobileGarrison.java b/Mage.Sets/src/mage/cards/m/MobileGarrison.java index 35793906e41..3ebd7811e8f 100644 --- a/Mage.Sets/src/mage/cards/m/MobileGarrison.java +++ b/Mage.Sets/src/mage/cards/m/MobileGarrison.java @@ -27,7 +27,7 @@ public final class MobileGarrison extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another target artifact or creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE) diff --git a/Mage.Sets/src/mage/cards/m/MoggAssassin.java b/Mage.Sets/src/mage/cards/m/MoggAssassin.java index 1051e3a9fd2..8f8f2a93526 100644 --- a/Mage.Sets/src/mage/cards/m/MoggAssassin.java +++ b/Mage.Sets/src/mage/cards/m/MoggAssassin.java @@ -2,7 +2,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -11,8 +10,8 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; @@ -20,59 +19,36 @@ import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponentsCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author L_J */ public final class MoggAssassin extends CardImpl { - private final UUID originalId; - public MoggAssassin(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.ASSASSIN); this.power = new MageInt(2); this.toughness = new MageInt(1); - - //TODO: Make ability properly copiable + // {T}: You choose target creature an opponent controls, and that opponent chooses target creature. Flip a coin. If you win the flip, destroy the creature you chose. If you lose the flip, destroy the creature your opponent chose. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MoggAssassinEffect(), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new MoggAssassinEffect(), + new TapSourceCost() + ); ability.addTarget(new TargetOpponentsCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent()); + ability.setTargetAdjuster(MoggAssassinAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - UUID opponentId = null; - if (game.getOpponents(controller.getId()).size() > 1) { - Target target = ability.getTargets().get(0); - if (controller.chooseTarget(Outcome.DestroyPermanent, target, ability, game)) { - Permanent permanent = game.getPermanent(target.getFirstTarget()); - opponentId = permanent.getControllerId(); - } else { - opponentId = game.getOpponents(controller.getId()).iterator().next(); - } - } else { - opponentId = game.getOpponents(controller.getId()).iterator().next(); - } - - if (opponentId != null) { - ability.getTargets().get(1).setTargetController(opponentId); - } - } - } } public MoggAssassin(final MoggAssassin card) { super(card); - this.originalId = card.originalId; } @Override @@ -82,6 +58,34 @@ public final class MoggAssassin extends CardImpl { } +enum MoggAssassinAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller == null) { + return; + } + UUID opponentId = null; + if (game.getOpponents(controller.getId()).size() > 1) { + Target target = ability.getTargets().get(0); + if (controller.chooseTarget(Outcome.DestroyPermanent, target, ability, game)) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); + opponentId = permanent.getControllerId(); + } else { + opponentId = game.getOpponents(controller.getId()).iterator().next(); + } + } else { + opponentId = game.getOpponents(controller.getId()).iterator().next(); + } + + if (opponentId != null) { + ability.getTargets().get(1).setTargetController(opponentId); + } + } +} + class MoggAssassinEffect extends OneShotEffect { public MoggAssassinEffect() { @@ -100,21 +104,21 @@ class MoggAssassinEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent chosenPermanent = game.getPermanent(source.getTargets().get(0).getFirstTarget()); - Permanent opponentsPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (controller.flipCoin(game)) { - if (chosenPermanent != null) { - chosenPermanent.destroy(source.getSourceId(), game, false); - return true; - } - } else { - if (opponentsPermanent != null) { - opponentsPermanent.destroy(source.getSourceId(), game, false); - return true; - } + if (controller == null) { + return false; + } + Permanent chosenPermanent = game.getPermanent(source.getTargets().get(0).getFirstTarget()); + Permanent opponentsPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + if (controller.flipCoin(source, game, true)) { + if (chosenPermanent != null) { + chosenPermanent.destroy(source.getSourceId(), game, false); + return true; + } + } else { + if (opponentsPermanent != null) { + opponentsPermanent.destroy(source.getSourceId(), game, false); + return true; } } return false; diff --git a/Mage.Sets/src/mage/cards/m/MoggBombers.java b/Mage.Sets/src/mage/cards/m/MoggBombers.java index 65700c1643e..b0635fc2ebd 100644 --- a/Mage.Sets/src/mage/cards/m/MoggBombers.java +++ b/Mage.Sets/src/mage/cards/m/MoggBombers.java @@ -26,7 +26,7 @@ public final class MoggBombers extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MoggBombers(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MoggConscripts.java b/Mage.Sets/src/mage/cards/m/MoggConscripts.java index f70bacbbfd1..9a69e98c7ca 100644 --- a/Mage.Sets/src/mage/cards/m/MoggConscripts.java +++ b/Mage.Sets/src/mage/cards/m/MoggConscripts.java @@ -67,7 +67,7 @@ class MoggConscriptsEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(source.getSourceId())) { - PlayerCastCreatureWatcher watcher = (PlayerCastCreatureWatcher) game.getState().getWatchers().get(PlayerCastCreatureWatcher.class.getSimpleName()); + PlayerCastCreatureWatcher watcher = game.getState().getWatcher(PlayerCastCreatureWatcher.class); if (watcher != null && !watcher.playerDidCastCreatureThisTurn(source.getControllerId())) { return true; } diff --git a/Mage.Sets/src/mage/cards/m/MoggJailer.java b/Mage.Sets/src/mage/cards/m/MoggJailer.java index bce46bb14ab..8b8eb90e0a3 100644 --- a/Mage.Sets/src/mage/cards/m/MoggJailer.java +++ b/Mage.Sets/src/mage/cards/m/MoggJailer.java @@ -25,7 +25,7 @@ public final class MoggJailer extends CardImpl { static final private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature with power 2 or less"); static { - filter.add(Predicates.and(new PowerPredicate(ComparisonType.FEWER_THAN, 2), Predicates.not(new TappedPredicate()))); + filter.add(Predicates.and(new PowerPredicate(ComparisonType.FEWER_THAN, 2), Predicates.not(TappedPredicate.instance))); } public MoggJailer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MoggSquad.java b/Mage.Sets/src/mage/cards/m/MoggSquad.java index c7b2934783e..d41435d187d 100644 --- a/Mage.Sets/src/mage/cards/m/MoggSquad.java +++ b/Mage.Sets/src/mage/cards/m/MoggSquad.java @@ -27,7 +27,7 @@ public final class MoggSquad extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature on the battlefield"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MoggSquad(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MogissMarauder.java b/Mage.Sets/src/mage/cards/m/MogissMarauder.java index b5271f482d7..d797c3fd005 100644 --- a/Mage.Sets/src/mage/cards/m/MogissMarauder.java +++ b/Mage.Sets/src/mage/cards/m/MogissMarauder.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -12,20 +11,22 @@ import mage.abilities.keyword.IntimidateAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ColoredManaSymbol; import mage.constants.Duration; +import mage.constants.SubType; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class MogissMarauder extends CardImpl { public MogissMarauder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.BERSERKER); @@ -35,24 +36,13 @@ public final class MogissMarauder extends CardImpl { // When Mogis's Marauder enters the battlefield, up to X target creatures each gain intimidate and haste, where X is your devotion to black. Ability ability = new EntersBattlefieldTriggeredAbility( new GainAbilityTargetEffect(IntimidateAbility.getInstance(), Duration.EndOfTurn, - "up to X target creatures each gain intimidate"), false); + "up to X target creatures each gain intimidate"), false); ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn, "and haste until end of turn, where X is your devotion to black")); - ability.addTarget(new TargetCreaturePermanent()); + ability.setTargetAdjuster(MogissMarauderAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - int numbTargets = new DevotionCount(ColoredManaSymbol.B).calculate(game, ability, null); - if (numbTargets > 0) { - ability.addTarget(new TargetCreaturePermanent(0,numbTargets)); - } - } - } - public MogissMarauder(final MogissMarauder card) { super(card); } @@ -62,3 +52,16 @@ public final class MogissMarauder extends CardImpl { return new MogissMarauder(this); } } + +enum MogissMarauderAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numbTargets = new DevotionCount(ColoredManaSymbol.B).calculate(game, ability, null); + if (numbTargets > 0) { + ability.addTarget(new TargetCreaturePermanent(0, numbTargets)); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/Molder.java b/Mage.Sets/src/mage/cards/m/Molder.java index 5501bbe9336..cffc75b81a1 100644 --- a/Mage.Sets/src/mage/cards/m/Molder.java +++ b/Mage.Sets/src/mage/cards/m/Molder.java @@ -1,9 +1,7 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -11,13 +9,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterArtifactOrEnchantmentPermanent; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LoneFox */ public final class Molder extends CardImpl { @@ -26,20 +27,9 @@ public final class Molder extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{G}"); // Destroy target artifact or enchantment with converted mana cost X. It can't be regenerated. You gain X life. - this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetPermanent(new FilterArtifactOrEnchantmentPermanent("artifact or enchantment with converted mana cost X"))); - this.getSpellAbility().addEffect(new GainLifeEffect(new ManacostVariableValue())); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterArtifactOrEnchantmentPermanent filter = new FilterArtifactOrEnchantmentPermanent("artifact or enchantment with converted mana cost X"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.addTarget(new TargetPermanent(filter)); - } + this.getSpellAbility().addEffect(new DestroyTargetEffect("Destroy target artifact or enchantment with converted mana cost X.", true)); + this.getSpellAbility().addEffect(new GainLifeEffect(ManacostVariableValue.instance)); + this.getSpellAbility().setTargetAdjuster(MolderAdjuster.instance); } public Molder(final Molder card) { @@ -51,3 +41,16 @@ public final class Molder extends CardImpl { return new Molder(this); } } + +enum MolderAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent("artifact or enchantment with converted mana cost " + xValue); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetPermanent(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MoltenBirth.java b/Mage.Sets/src/mage/cards/m/MoltenBirth.java index 66898ae84db..6fbee1801cb 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenBirth.java +++ b/Mage.Sets/src/mage/cards/m/MoltenBirth.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -14,8 +12,9 @@ import mage.game.Game; import mage.game.permanent.token.MoltenBirthElementalToken; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class MoltenBirth extends CardImpl { @@ -57,13 +56,15 @@ class MoltenBirthEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Card molten = game.getCard(source.getSourceId()); if (controller != null) { MoltenBirthElementalToken token = new MoltenBirthElementalToken(); token.putOntoBattlefield(2, game, source.getSourceId(), source.getControllerId()); - if (controller.flipCoin(game)) { - molten.moveToZone(Zone.HAND, source.getSourceId(), game, true); - game.informPlayers(controller.getLogName() + " won the flip. " + molten.getLogName() + " is returned to " + controller.getLogName() + "'s hand."); + if (controller.flipCoin(source, game, true)) { + Card molten = game.getCard(source.getSourceId()); + if (molten != null) { + molten.moveToZone(Zone.HAND, source.getSourceId(), game, true); + game.informPlayers(controller.getLogName() + " won the flip. " + molten.getLogName() + " is returned to " + controller.getLogName() + "'s hand."); + } } return true; } diff --git a/Mage.Sets/src/mage/cards/m/MoltenNursery.java b/Mage.Sets/src/mage/cards/m/MoltenNursery.java index dcc0dace269..e0280c34cda 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenNursery.java +++ b/Mage.Sets/src/mage/cards/m/MoltenNursery.java @@ -22,7 +22,7 @@ public final class MoltenNursery extends CardImpl { private static final FilterSpell filter = new FilterSpell("a colorless spell"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public MoltenNursery(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java b/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java index 58eaca78306..c557bcccf9b 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java +++ b/Mage.Sets/src/mage/cards/m/MoltenPrimordial.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -13,9 +12,9 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; @@ -23,16 +22,18 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MoltenPrimordial extends CardImpl { public MoltenPrimordial(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); this.subtype.add(SubType.AVATAR); this.power = new MageInt(6); @@ -42,23 +43,9 @@ public final class MoltenPrimordial extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Molten Primordial enters the battlefield, for each opponent, take control of up to one target creature that player controls until end of turn. Untap those creatures. They have haste until end of turn. - this.addAbility(new EntersBattlefieldTriggeredAbility(new MoltenPrimordialEffect(),false)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for(UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0,1, filter,false); - ability.addTarget(target); - } - } - } + Ability ability = new EntersBattlefieldTriggeredAbility(new MoltenPrimordialEffect(), false); + ability.setTargetAdjuster(MoltenPrimordialAdjuster.instance); + this.addAbility(ability); } public MoltenPrimordial(final MoltenPrimordial card) { @@ -71,6 +58,24 @@ public final class MoltenPrimordial extends CardImpl { } } +enum MoltenPrimordialAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); + filter.add(new ControllerIdPredicate(opponentId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); + ability.addTarget(target); + } + } + } +} + class MoltenPrimordialEffect extends OneShotEffect { public MoltenPrimordialEffect() { @@ -90,7 +95,7 @@ class MoltenPrimordialEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { boolean result = false; - for (Target target: source.getTargets()) { + for (Target target : source.getTargets()) { if (target instanceof TargetCreaturePermanent) { Permanent targetCreature = game.getPermanent(target.getFirstTarget()); if (targetCreature != null) { diff --git a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java index bd9f8b6e8de..b2d6e26ee9e 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java +++ b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java @@ -83,11 +83,11 @@ class MoltenPsycheEffect extends OneShotEffect { } } if (MetalcraftCondition.instance.apply(game, source)) { - MoltenPsycheWatcher watcher = (MoltenPsycheWatcher) game.getState().getWatchers().get(MoltenPsycheWatcher.class.getSimpleName()); + MoltenPsycheWatcher watcher = game.getState().getWatcher(MoltenPsycheWatcher.class); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { if (game.isOpponent(controller, playerId)) { Player player = game.getPlayer(playerId); - if (player != null) { + if (player != null && watcher != null) { player.damage(watcher.getDraws(playerId), source.getSourceId(), game, false, true); } } diff --git a/Mage.Sets/src/mage/cards/m/MoltenSentry.java b/Mage.Sets/src/mage/cards/m/MoltenSentry.java index c4640f09dce..d39b4c15517 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenSentry.java +++ b/Mage.Sets/src/mage/cards/m/MoltenSentry.java @@ -64,7 +64,7 @@ class MoltenSentryEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, false)) { game.informPlayers("Heads: " + permanent.getLogName() + " enters the battlefield as a 5/2 creature with haste"); permanent.getPower().modifyBaseValue(5); permanent.getToughness().modifyBaseValue(2); diff --git a/Mage.Sets/src/mage/cards/m/MoltenSlagheap.java b/Mage.Sets/src/mage/cards/m/MoltenSlagheap.java index a6e3ef4dea9..5d339c274aa 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenSlagheap.java +++ b/Mage.Sets/src/mage/cards/m/MoltenSlagheap.java @@ -36,7 +36,7 @@ public final class MoltenSlagheap extends CardImpl { this.addAbility(ability); // {1}, Remove X storage counters from Molten Slagheap: Add X mana in any combination of {B} and/or {R}. ability = new SimpleManaAbility(Zone.BATTLEFIELD, - new AddManaInAnyCombinationEffect(new RemovedCountersForCostValue(), ColoredManaSymbol.B, ColoredManaSymbol.R), + new AddManaInAnyCombinationEffect(RemovedCountersForCostValue.instance, ColoredManaSymbol.B, ColoredManaSymbol.R), new GenericManaCost(1)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance())); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/Monsoon.java b/Mage.Sets/src/mage/cards/m/Monsoon.java index 4b91ad79f8e..24c52740c5c 100644 --- a/Mage.Sets/src/mage/cards/m/Monsoon.java +++ b/Mage.Sets/src/mage/cards/m/Monsoon.java @@ -50,7 +50,7 @@ class MonsoonEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterPermanent(); static { filter.add(new SubtypePredicate(SubType.ISLAND)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MonsoonEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java b/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java index 77087fd6242..28f7226af55 100644 --- a/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java +++ b/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java @@ -21,7 +21,7 @@ public final class MonstrousOnslaught extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); // Monstrous Onslaught deals X damage divided as you choose among any number of target creatures, where X is the greatest power among creatures you control as you cast Monstrous Onslaught. - DynamicValue xValue = new GreatestPowerAmongControlledCreaturesValue(); + DynamicValue xValue = GreatestPowerAmongControlledCreaturesValue.instance; Effect effect = new DamageMultiEffect(xValue); effect.setText("{this} deals X damage divided as you choose among any number of target creatures, where X is the greatest power among creatures you control as you cast {this}"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/m/MorkrutNecropod.java b/Mage.Sets/src/mage/cards/m/MorkrutNecropod.java index 7bffaa9327f..08a609f0edb 100644 --- a/Mage.Sets/src/mage/cards/m/MorkrutNecropod.java +++ b/Mage.Sets/src/mage/cards/m/MorkrutNecropod.java @@ -27,7 +27,7 @@ public final class MorkrutNecropod extends CardImpl { filter.add(Predicates.or( new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.LAND))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MorkrutNecropod(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/Mortuary.java b/Mage.Sets/src/mage/cards/m/Mortuary.java index f1aa17f0801..22797d4d4fa 100644 --- a/Mage.Sets/src/mage/cards/m/Mortuary.java +++ b/Mage.Sets/src/mage/cards/m/Mortuary.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.PutOnLibraryTargetEffect; @@ -10,8 +8,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author HCrescent */ public final class Mortuary extends CardImpl { @@ -19,9 +18,9 @@ public final class Mortuary extends CardImpl { public Mortuary(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); - - Ability ability = new PutIntoGraveFromBattlefieldAllTriggeredAbility(new PutOnLibraryTargetEffect(true, "put that card on top of your library."), false, StaticFilters.FILTER_PERMANENT_CREATURE, true, true); + // Whenever a creature is put into your graveyard from the battlefield, put that card on top of your library. + Ability ability = new PutIntoGraveFromBattlefieldAllTriggeredAbility(new PutOnLibraryTargetEffect(true, "put that card on top of your library."), false, StaticFilters.FILTER_PERMANENT_CREATURE, true, true); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java b/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java index e0c45e08017..2218db67e66 100644 --- a/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java +++ b/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java @@ -36,7 +36,7 @@ public final class MossbridgeTroll extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MossbridgeTroll(UUID ownerId, CardSetInfo setInfo) { @@ -109,8 +109,8 @@ class MossbridgeTrollCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("any number of untapped creatures other than {this} with total power 10 or greater"); static { - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TappedPredicate.instance)); } public MossbridgeTrollCost() { diff --git a/Mage.Sets/src/mage/cards/m/MothdustChangeling.java b/Mage.Sets/src/mage/cards/m/MothdustChangeling.java index 9f645fe8eb7..6f276339b1e 100644 --- a/Mage.Sets/src/mage/cards/m/MothdustChangeling.java +++ b/Mage.Sets/src/mage/cards/m/MothdustChangeling.java @@ -27,7 +27,7 @@ public final class MothdustChangeling extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MothdustChangeling(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MouthFeed.java b/Mage.Sets/src/mage/cards/m/MouthFeed.java index 17fabe507f6..c154c520907 100644 --- a/Mage.Sets/src/mage/cards/m/MouthFeed.java +++ b/Mage.Sets/src/mage/cards/m/MouthFeed.java @@ -38,7 +38,7 @@ public final class MouthFeed extends SplitCard { // to // Feed // Draw a card for each creature you control with power 3 or greater - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); Effect draw = new DrawCardSourceControllerEffect(new PermanentsOnBattlefieldCount(filterCreaturesYouControlPower3orGreater)); getRightHalfCard().getSpellAbility().addEffect(draw); diff --git a/Mage.Sets/src/mage/cards/m/MudbrawlerCohort.java b/Mage.Sets/src/mage/cards/m/MudbrawlerCohort.java index a8ff123ee6e..1d0ddf8e5c5 100644 --- a/Mage.Sets/src/mage/cards/m/MudbrawlerCohort.java +++ b/Mage.Sets/src/mage/cards/m/MudbrawlerCohort.java @@ -34,7 +34,7 @@ public final class MudbrawlerCohort extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.RED)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MudbrawlerCohort(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/Mudslide.java b/Mage.Sets/src/mage/cards/m/Mudslide.java index c63e74715d2..84d3855ead9 100644 --- a/Mage.Sets/src/mage/cards/m/Mudslide.java +++ b/Mage.Sets/src/mage/cards/m/Mudslide.java @@ -65,7 +65,7 @@ class MudslideEffect extends OneShotEffect { static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } MudslideEffect() { diff --git a/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java b/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java index f80bf2ab4d4..dcb9f0f3b22 100644 --- a/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java +++ b/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java @@ -88,7 +88,7 @@ class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl { && source.isControlledBy(game.getOwnerId(objectId)) // only from your graveyard && affectedControllerId.equals(game.getActivePlayerId()) // only during your turns (e.g. prevent flash creatures) && Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) { - MuldrothaTheGravetideWatcher watcher = (MuldrothaTheGravetideWatcher) game.getState().getWatchers().get(MuldrothaTheGravetideWatcher.class.getSimpleName()); + MuldrothaTheGravetideWatcher watcher = game.getState().getWatcher(MuldrothaTheGravetideWatcher.class); MageObject mageObject = game.getObject(objectId); if (mageObject != null && watcher != null) { for (CardType cardType : mageObject.getCardType()) { @@ -121,7 +121,7 @@ class MuldrothaTheGravetideWatcher extends Watcher { private Zone fromZone; public MuldrothaTheGravetideWatcher() { - super(MuldrothaTheGravetideWatcher.class.getSimpleName(), WatcherScope.GAME); + super(MuldrothaTheGravetideWatcher.class, WatcherScope.GAME); } public MuldrothaTheGravetideWatcher(final MuldrothaTheGravetideWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/m/MultaniMaroSorcerer.java b/Mage.Sets/src/mage/cards/m/MultaniMaroSorcerer.java index 63949d9ba94..d2e45d955e9 100644 --- a/Mage.Sets/src/mage/cards/m/MultaniMaroSorcerer.java +++ b/Mage.Sets/src/mage/cards/m/MultaniMaroSorcerer.java @@ -33,7 +33,7 @@ public final class MultaniMaroSorcerer extends CardImpl { this.addAbility(ShroudAbility.getInstance()); // Multani, Maro-Sorcerer's power and toughness are each equal to the total number of cards in all players' hands. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInAllHandsCount(), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(CardsInAllHandsCount.instance, Duration.EndOfGame))); } public MultaniMaroSorcerer(final MultaniMaroSorcerer card) { diff --git a/Mage.Sets/src/mage/cards/m/MultanisPresence.java b/Mage.Sets/src/mage/cards/m/MultanisPresence.java index 2ad766fea5f..01e1214ae82 100644 --- a/Mage.Sets/src/mage/cards/m/MultanisPresence.java +++ b/Mage.Sets/src/mage/cards/m/MultanisPresence.java @@ -62,8 +62,8 @@ class MultanisPresenceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - MultanisPresenceWatcher watcher = (MultanisPresenceWatcher) game.getState().getWatchers().get(MultanisPresenceWatcher.class.getSimpleName()); - return (watcher.getSpellsCastThisTurn(controllerId).contains(event.getTargetId())); + MultanisPresenceWatcher watcher = game.getState().getWatcher(MultanisPresenceWatcher.class); + return watcher != null && watcher.getSpellsCastThisTurn(controllerId).contains(event.getTargetId()); } @Override diff --git a/Mage.Sets/src/mage/cards/m/MummyParamount.java b/Mage.Sets/src/mage/cards/m/MummyParamount.java index e48d48455c2..4555272f37d 100644 --- a/Mage.Sets/src/mage/cards/m/MummyParamount.java +++ b/Mage.Sets/src/mage/cards/m/MummyParamount.java @@ -23,7 +23,7 @@ public final class MummyParamount extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Zombie"); static { filter.add(new SubtypePredicate(SubType.ZOMBIE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MummyParamount(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MundasVanguard.java b/Mage.Sets/src/mage/cards/m/MundasVanguard.java index b2c05c34b7a..52708a49288 100644 --- a/Mage.Sets/src/mage/cards/m/MundasVanguard.java +++ b/Mage.Sets/src/mage/cards/m/MundasVanguard.java @@ -32,7 +32,7 @@ public final class MundasVanguard extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public MundasVanguard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java b/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java index 169a2b55eef..5056353cdca 100644 --- a/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java +++ b/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java @@ -21,7 +21,7 @@ public final class MurderousCompulsion extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public MurderousCompulsion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MurmuringMystic.java b/Mage.Sets/src/mage/cards/m/MurmuringMystic.java index e68836883f6..68ef0c9f873 100644 --- a/Mage.Sets/src/mage/cards/m/MurmuringMystic.java +++ b/Mage.Sets/src/mage/cards/m/MurmuringMystic.java @@ -1,18 +1,18 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.permanent.token.BirdIllusionToken; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class MurmuringMystic extends CardImpl { @@ -28,7 +28,7 @@ public final class MurmuringMystic extends CardImpl { // Whenever you cast an instant or sorcery spell, create a 1/1 blue Bird Illusion creature token with flying. this.addAbility(new SpellCastControllerTriggeredAbility( new CreateTokenEffect(new BirdIllusionToken()), - StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false )); } diff --git a/Mage.Sets/src/mage/cards/m/Musician.java b/Mage.Sets/src/mage/cards/m/Musician.java new file mode 100644 index 00000000000..4b99c7b0042 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Musician.java @@ -0,0 +1,134 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.constants.SubType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DestroySourceEffect; +import mage.abilities.effects.common.DoUnlessControllerPaysEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public final class Musician extends CardImpl { + + public Musician(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Cumulative upkeep {1} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); + + // {tap}: Put a music counter on target creature. If it doesn't have "At the beginning of your upkeep, destroy this creature unless you pay {1} for each music counter on it," it gains that ability. + Effect effect = new DoUnlessControllerPaysEffect( + new DestroySourceEffect(), + new DynamicValueGenericManaCost( + new CountersSourceCount( + CounterType.MUSIC))); + effect.setText("destroy this creature unless you pay {1} for each music counter on it"); + Ability ability = new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, + effect, + TargetController.YOU, + false, + false, + "At the beginning of your upkeep, "); + Effect effect2 = new AddCountersTargetEffect(CounterType.MUSIC.createInstance()); + effect2.setText("Put a music counter on target creature"); + Effect effect3 = new GainAbilityTargetEffect( + ability, + Duration.WhileOnBattlefield); + effect3.setText("If it doesn't have \"At the beginning of your upkeep, destroy this creature unless you pay {1} for each music counter on it,\" it gains that ability"); + Ability ability2 = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + effect2, + new TapSourceCost()); + ability2.addTarget(new TargetCreaturePermanent()); + ability2.addEffect(effect3); + this.addAbility(ability2); + + } + + private Musician(final Musician card) { + super(card); + } + + @Override + public Musician copy() { + return new Musician(this); + } +} + +class DynamicValueGenericManaCost extends CostImpl { + + DynamicValue amount; + + public DynamicValueGenericManaCost(DynamicValue amount) { + this.amount = amount; + setText(); + } + + public DynamicValueGenericManaCost(DynamicValueGenericManaCost cost) { + super(cost); + this.amount = cost.amount; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + Player controller = game.getPlayer(controllerId); + if (controller == null) { + return false; + } + int convertedCost = amount.calculate(game, ability, null); + Cost cost = new GenericManaCost(convertedCost); + return cost.canPay(ability, sourceId, controllerId, game); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Player controller = game.getPlayer(controllerId); + int convertedCost = amount.calculate(game, ability, null); + Cost cost = new GenericManaCost(convertedCost); + if (controller != null) { + paid = cost.pay(ability, game, sourceId, controllerId, noMana); + } + return paid; + } + + @Override + public DynamicValueGenericManaCost copy() { + return new DynamicValueGenericManaCost(this); + } + + private void setText() { + text = ("{1} for each music counter on {this}"); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MycosynthFiend.java b/Mage.Sets/src/mage/cards/m/MycosynthFiend.java index ddeaa5a4785..99d1ecdfb52 100644 --- a/Mage.Sets/src/mage/cards/m/MycosynthFiend.java +++ b/Mage.Sets/src/mage/cards/m/MycosynthFiend.java @@ -27,7 +27,7 @@ public final class MycosynthFiend extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - DynamicValue value = new OpponentsPoisonCountersCount(); + DynamicValue value = OpponentsPoisonCountersCount.instance; this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(value, value, Duration.WhileOnBattlefield))); } diff --git a/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java b/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java index 923b7ab694b..6bad3165ae0 100644 --- a/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java +++ b/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java @@ -34,7 +34,7 @@ public final class MyojinOfCleansingFire extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public MyojinOfCleansingFire(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java index 0302a4c60a6..b43eed17cc8 100644 --- a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java +++ b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java @@ -105,7 +105,7 @@ class MyrBattlesphereEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Myr you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.MYR)); } diff --git a/Mage.Sets/src/mage/cards/m/MythUnbound.java b/Mage.Sets/src/mage/cards/m/MythUnbound.java index 28924a6075f..86e13abb32e 100644 --- a/Mage.Sets/src/mage/cards/m/MythUnbound.java +++ b/Mage.Sets/src/mage/cards/m/MythUnbound.java @@ -32,7 +32,7 @@ public final class MythUnbound extends CardImpl { private static final FilterPermanent filter = new FilterPermanent(); static { - filter.add(new CommanderPredicate()); + filter.add(CommanderPredicate.instance); filter.add(new OwnerPredicate(TargetController.YOU)); } @@ -78,9 +78,9 @@ class MythUnboundCostReductionEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - Ability spellAbility = (SpellAbility) abilityToModify; + Ability spellAbility = abilityToModify; if (spellAbility != null) { - Integer amount = (Integer) game.getState().getValue(abilityToModify.getControllerId() + "_castCount"); + Integer amount = (Integer) game.getState().getValue(abilityToModify.getSourceId() + "_castCount"); if (amount != null && amount > 0) { CardUtil.reduceCost(spellAbility, amount); return true; @@ -99,7 +99,7 @@ class MythUnboundCostReductionEffect extends CostModificationEffectImpl { if (abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { - return player.getCommandersIds().contains(spell.getId()); + return player.getCommandersIds().contains(spell.getSourceId()); } } } diff --git a/Mage.Sets/src/mage/cards/n/N1Starfighter.java b/Mage.Sets/src/mage/cards/n/N1Starfighter.java index 85284b54fc9..bd50c4d84f7 100644 --- a/Mage.Sets/src/mage/cards/n/N1Starfighter.java +++ b/Mage.Sets/src/mage/cards/n/N1Starfighter.java @@ -28,7 +28,7 @@ public final class N1Starfighter extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public N1Starfighter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NahiriTheHarbinger.java b/Mage.Sets/src/mage/cards/n/NahiriTheHarbinger.java index c0dd70f67eb..1ba32622d66 100644 --- a/Mage.Sets/src/mage/cards/n/NahiriTheHarbinger.java +++ b/Mage.Sets/src/mage/cards/n/NahiriTheHarbinger.java @@ -49,9 +49,9 @@ public final class NahiriTheHarbinger extends CardImpl { static { filter.add(Predicates.or(new CardTypePredicate(CardType.ENCHANTMENT), (Predicates.and(new CardTypePredicate(CardType.ARTIFACT), - new TappedPredicate())), + TappedPredicate.instance)), (Predicates.and(new CardTypePredicate(CardType.CREATURE), - new TappedPredicate())))); + TappedPredicate.instance)))); } public NahiriTheHarbinger(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NahirisWrath.java b/Mage.Sets/src/mage/cards/n/NahirisWrath.java index e23c093552a..3777758cfe7 100644 --- a/Mage.Sets/src/mage/cards/n/NahirisWrath.java +++ b/Mage.Sets/src/mage/cards/n/NahirisWrath.java @@ -1,7 +1,6 @@ package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCost; @@ -19,38 +18,26 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class NahirisWrath extends CardImpl { public NahirisWrath(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); // As an additional cost to cast Nahiri's Wrath, discard X cards. this.getSpellAbility().addCost(new NahirisWrathAdditionalCost()); // Nahiri's Wrath deals damage equal to the total converted mana cost of the discarded cards to each of up to X target creatures and/or planeswalkers. - Effect effect = new DamageTargetEffect(new DiscardCostCardConvertedMana()); + Effect effect = new DamageTargetEffect(DiscardCostCardConvertedMana.instance); effect.setText("{this} deals damage equal to the total converted mana cost of the discarded cards to each of up to X target creatures and/or planeswalkers"); this.getSpellAbility().addEffect(effect); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - int numTargets = 0; - for (VariableCost cost : ability.getCosts().getVariableCosts()) { - if (cost instanceof NahirisWrathAdditionalCost) { - numTargets = ((NahirisWrathAdditionalCost) cost).getAmount(); - break; - } - } - if (numTargets > 0) { - ability.addTarget(new TargetCreatureOrPlaneswalker(0, numTargets, new FilterCreatureOrPlaneswalkerPermanent(), false)); - } + this.getSpellAbility().setTargetAdjuster(NahirisWrathAdjuster.instance); } public NahirisWrath(final NahirisWrath card) { @@ -63,6 +50,25 @@ public final class NahirisWrath extends CardImpl { } } +enum NahirisWrathAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numTargets = 0; + for (VariableCost cost : ability.getCosts().getVariableCosts()) { + if (cost instanceof NahirisWrathAdditionalCost) { + numTargets = cost.getAmount(); + break; + } + } + if (numTargets > 0) { + ability.addTarget(new TargetCreatureOrPlaneswalker(0, numTargets, new FilterCreatureOrPlaneswalkerPermanent(), false)); + } + } +} + class NahirisWrathAdditionalCost extends VariableCostImpl { NahirisWrathAdditionalCost() { diff --git a/Mage.Sets/src/mage/cards/n/NamelessRace.java b/Mage.Sets/src/mage/cards/n/NamelessRace.java index e561b069369..73afab8657f 100644 --- a/Mage.Sets/src/mage/cards/n/NamelessRace.java +++ b/Mage.Sets/src/mage/cards/n/NamelessRace.java @@ -1,7 +1,5 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -16,12 +14,7 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; @@ -32,8 +25,9 @@ import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author L_J */ public final class NamelessRace extends CardImpl { @@ -48,7 +42,7 @@ public final class NamelessRace extends CardImpl { // As Nameless Race enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards. this.addAbility(new AsEntersBattlefieldAbility(new NamelessRaceEffect())); - + // Nameless Race's power and toughness are each equal to the life paid as it entered the battlefield. this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield"))); } @@ -64,13 +58,13 @@ public final class NamelessRace extends CardImpl { } class NamelessRaceEffect extends OneShotEffect { - + private static final FilterPermanent filter = new FilterPermanent("white nontoken permanents your opponents control"); private static final FilterCard filter2 = new FilterCard("white cards in their graveyards"); - + static { filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(new ControllerPredicate(TargetController.OPPONENT)); filter2.add(new ColorPredicate(ObjectColor.WHITE)); filter2.add(new OwnerPredicate(TargetController.OPPONENT)); @@ -94,13 +88,13 @@ class NamelessRaceEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Card sourceCard = game.getCard(source.getSourceId()); int permanentsInPlay = new PermanentsOnBattlefieldCount(filter).calculate(game, source, null); int cardsInGraveyards = new CardsInAllGraveyardsCount(filter2).calculate(game, source, null); int maxAmount = Math.min(permanentsInPlay + cardsInGraveyards, controller.getLife()); int payAmount = controller.getAmount(0, maxAmount, "Pay up to " + maxAmount + " life", game); controller.loseLife(payAmount, game, false); - game.informPlayers(sourceCard.getLogName() + ": " + controller.getLogName() + + Card sourceCard = game.getCard(source.getSourceId()); + game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() + " pays " + payAmount + " life"); game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source); return true; diff --git a/Mage.Sets/src/mage/cards/n/NantukoShaman.java b/Mage.Sets/src/mage/cards/n/NantukoShaman.java index b17eaccb4bd..ad62796b096 100644 --- a/Mage.Sets/src/mage/cards/n/NantukoShaman.java +++ b/Mage.Sets/src/mage/cards/n/NantukoShaman.java @@ -26,7 +26,7 @@ public final class NantukoShaman extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent(); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public NantukoShaman(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NaturesChosen.java b/Mage.Sets/src/mage/cards/n/NaturesChosen.java index 9cb96ea8a30..6fb1055bef0 100644 --- a/Mage.Sets/src/mage/cards/n/NaturesChosen.java +++ b/Mage.Sets/src/mage/cards/n/NaturesChosen.java @@ -49,7 +49,7 @@ public final class NaturesChosen extends CardImpl { static { filterWhiteUntappedCreature.add(new ColorPredicate(ObjectColor.WHITE)); - filterWhiteUntappedCreature.add(Predicates.not(new TappedPredicate())); + filterWhiteUntappedCreature.add(Predicates.not(TappedPredicate.instance)); } public NaturesChosen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NayaHushblade.java b/Mage.Sets/src/mage/cards/n/NayaHushblade.java index 45c7ecb36e7..343d71f445d 100644 --- a/Mage.Sets/src/mage/cards/n/NayaHushblade.java +++ b/Mage.Sets/src/mage/cards/n/NayaHushblade.java @@ -29,8 +29,8 @@ public final class NayaHushblade extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another multicolor permanent"); static { - filter.add(new MulticoloredPredicate()); - filter.add(new AnotherPredicate()); + filter.add(MulticoloredPredicate.instance); + filter.add(AnotherPredicate.instance); } public NayaHushblade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java b/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java index 2c3bf2f8f77..bd4511146b4 100644 --- a/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java +++ b/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java @@ -26,11 +26,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import java.util.UUID; /** - * * @author spjspj */ public final class NazahnReveredBladesmith extends CardImpl { @@ -38,7 +38,7 @@ public final class NazahnReveredBladesmith extends CardImpl { private static final FilterControlledCreaturePermanent equippedFilter = new FilterControlledCreaturePermanent("equipped creature you control"); static { - equippedFilter.add(new EquippedPredicate()); + equippedFilter.add(EquippedPredicate.instance); equippedFilter.add(new ControllerPredicate(TargetController.YOU)); } @@ -65,25 +65,10 @@ public final class NazahnReveredBladesmith extends CardImpl { // Whenever an equipped creature you control attacks, you may tap target creature defending player controls. Ability ability = new AttacksCreatureYouControlTriggeredAbility(new NazahnTapEffect(), true, equippedFilter, true); ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + ability.setTargetAdjuster(NazahnReveredBladesmithAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof AttacksCreatureYouControlTriggeredAbility) { - FilterCreaturePermanent filterDefender = new FilterCreaturePermanent("creature defending player controls"); - for (Effect effect : ability.getEffects()) { - if (effect instanceof NazahnTapEffect) { - filterDefender.add(new ControllerIdPredicate(game.getCombat().getDefendingPlayerId(effect.getTargetPointer().getFirst(game, ability), game))); - break; - } - } - ability.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filterDefender); - ability.addTarget(target); - } - } - public NazahnReveredBladesmith(final NazahnReveredBladesmith card) { super(card); } @@ -94,6 +79,24 @@ public final class NazahnReveredBladesmith extends CardImpl { } } +enum NazahnReveredBladesmithAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + FilterCreaturePermanent filterDefender = new FilterCreaturePermanent("creature defending player controls"); + for (Effect effect : ability.getEffects()) { + if (effect instanceof NazahnTapEffect) { + filterDefender.add(new ControllerIdPredicate(game.getCombat().getDefendingPlayerId(effect.getTargetPointer().getFirst(game, ability), game))); + break; + } + } + ability.getTargets().clear(); + TargetCreaturePermanent target = new TargetCreaturePermanent(filterDefender); + ability.addTarget(target); + } +} + class NazahnTapEffect extends TapTargetEffect { NazahnTapEffect() { diff --git a/Mage.Sets/src/mage/cards/n/NebulonBFrigate.java b/Mage.Sets/src/mage/cards/n/NebulonBFrigate.java index 2d318c7129f..ba7c2cf73d8 100644 --- a/Mage.Sets/src/mage/cards/n/NebulonBFrigate.java +++ b/Mage.Sets/src/mage/cards/n/NebulonBFrigate.java @@ -25,7 +25,7 @@ public final class NebulonBFrigate extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public NebulonBFrigate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/Necrologia.java b/Mage.Sets/src/mage/cards/n/Necrologia.java index 1d35c3bebab..d1c3dc8a265 100644 --- a/Mage.Sets/src/mage/cards/n/Necrologia.java +++ b/Mage.Sets/src/mage/cards/n/Necrologia.java @@ -29,7 +29,7 @@ public final class Necrologia extends CardImpl { this.getSpellAbility().addCost(new PayVariableLifeCost(true)); // Draw X cards. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new GetXValue())); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(GetXValue.instance)); } public Necrologia(final Necrologia card) { diff --git a/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java b/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java index 168c633cb71..c80c8ff70a7 100644 --- a/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java +++ b/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java @@ -36,7 +36,7 @@ public final class NecromancersMagemark extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures you control that are enchanted"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/n/NecropolisFiend.java b/Mage.Sets/src/mage/cards/n/NecropolisFiend.java index a4219545b3a..e1b5a829d9b 100644 --- a/Mage.Sets/src/mage/cards/n/NecropolisFiend.java +++ b/Mage.Sets/src/mage/cards/n/NecropolisFiend.java @@ -1,11 +1,11 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.VariableCost; import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.common.TapSourceCost; @@ -21,8 +21,8 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; @@ -30,15 +30,17 @@ import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class NecropolisFiend extends CardImpl { public NecropolisFiend(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{7}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{7}{B}{B}"); this.subtype.add(SubType.DEMON); this.power = new MageInt(4); @@ -46,54 +48,29 @@ public final class NecropolisFiend extends CardImpl { // Delve this.addAbility(new DelveAbility()); + // Flying this.addAbility(FlyingAbility.getInstance()); - //TODO: Make ability properly copiable + // {X}, {T}, Exile X cards from your graveyard: Target creature gets -X/-X until end of turn. - DynamicValue xValue = new SignInversionDynamicValue(new ManacostVariableValue()); - Effect effect = new BoostTargetEffect(xValue,xValue,Duration.EndOfTurn); + DynamicValue xValue = new SignInversionDynamicValue(ManacostVariableValue.instance); + Effect effect = new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn); effect.setText("Target creature gets -X/-X until end of turn"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, effect, + new ManaCostsImpl("{X}") + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); - ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(1,1,new FilterCard("cards from your graveyard")), "Exile X cards from your graveyard")); + ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard( + 1, 1, new FilterCard("cards from your graveyard") + ), "Exile X cards from your graveyard")); + ability.setTargetAdjuster(NecropolisFiendTargetAdjuster.instance); + ability.setCostAdjuster(NecropolisFiendCostAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - for (VariableCost variableCost: ability.getManaCostsToPay().getVariableCosts()) { - if (variableCost instanceof VariableManaCost) { - ((VariableManaCost)variableCost).setMaxX(controller.getGraveyard().size()); - } - } - } - } - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility) { - int xValue = ability.getManaCostsToPay().getX(); - for(Cost cost: ability.getCosts()) { - if (cost instanceof ExileFromGraveCost) { - ExileFromGraveCost exileCost = (ExileFromGraveCost) cost; - for(Target target: exileCost.getTargets()) { - if (target instanceof TargetCardInYourGraveyard) { - target.setMaxNumberOfTargets(xValue); - target.setMinNumberOfTargets(xValue); - } - } - - } - } - } - } - public NecropolisFiend(final NecropolisFiend card) { super(card); } @@ -103,3 +80,41 @@ public final class NecropolisFiend extends CardImpl { return new NecropolisFiend(this); } } + +enum NecropolisFiendCostAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller == null) { + return; + } + for (VariableCost variableCost : ability.getManaCostsToPay().getVariableCosts()) { + if (variableCost instanceof VariableManaCost) { + ((VariableManaCost) variableCost).setMaxX(controller.getGraveyard().size()); + } + } + } +} + +enum NecropolisFiendTargetAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + for (Cost cost : ability.getCosts()) { + if (!(cost instanceof ExileFromGraveCost)) { + continue; + } + ExileFromGraveCost exileCost = (ExileFromGraveCost) cost; + for (Target target : exileCost.getTargets()) { + if (target instanceof TargetCardInYourGraveyard) { + target.setMaxNumberOfTargets(xValue); + target.setMinNumberOfTargets(xValue); + } + } + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NecroticPlague.java b/Mage.Sets/src/mage/cards/n/NecroticPlague.java index 00d17e62134..5bc9c3137a6 100644 --- a/Mage.Sets/src/mage/cards/n/NecroticPlague.java +++ b/Mage.Sets/src/mage/cards/n/NecroticPlague.java @@ -1,7 +1,6 @@ package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DiesAttachedTriggeredAbility; @@ -15,35 +14,24 @@ import mage.abilities.keyword.EnchantAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerPredicate; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class NecroticPlague extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); - - static { - filter.add(new ControllerPredicate(TargetController.OPPONENT)); - } - public NecroticPlague(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); this.subtype.add(SubType.AURA); @@ -53,33 +41,18 @@ public final class NecroticPlague extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Enchanted creature has "At the beginning of your upkeep, sacrifice this creature." // When enchanted creature dies, its controller chooses target creature one of their opponents controls. Return Necrotic Plague from its owner's graveyard to the battlefield attached to that creature. - Ability gainedAbility = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect(), TargetController.YOU, false); - Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield); + ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect(), TargetController.YOU, false); + Effect effect = new GainAbilityAttachedEffect(ability, AttachmentType.AURA, Duration.WhileOnBattlefield); effect.setText("Enchanted creature has \"At the beginning of your upkeep, sacrifice this creature.\""); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); - this.addAbility(new DiesAttachedTriggeredAbility(new NecroticPlagueEffect(), "enchanted creature", false)); - } + ability = new DiesAttachedTriggeredAbility(new NecroticPlagueEffect(), "enchanted creature", false); + ability.setTargetAdjuster(NecroticPlagueAdjuster.instance); + this.addAbility(ability); - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof DiesAttachedTriggeredAbility) { - Permanent attachedTo = null; - for (Effect effect : ability.getEffects()) { - attachedTo = (Permanent) effect.getValue("attachedTo"); - } - if (attachedTo != null) { - Player creatureController = game.getPlayer(attachedTo.getControllerId()); - if (creatureController != null) { - ability.setControllerId(creatureController.getId()); - ability.getTargets().clear(); - TargetPermanent target = new TargetPermanent(filter); - ability.getTargets().add(target); - } - } - } } public NecroticPlague(final NecroticPlague card) { @@ -93,11 +66,35 @@ public final class NecroticPlague extends CardImpl { } +enum NecroticPlagueAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Permanent attachedTo = null; + for (Effect effect : ability.getEffects()) { + attachedTo = (Permanent) effect.getValue("attachedTo"); + } + if (attachedTo == null) { + return; + } + Player creatureController = game.getPlayer(attachedTo.getControllerId()); + if (creatureController == null) { + return; + } + ability.setControllerId(creatureController.getId()); + ability.getTargets().clear(); + TargetPermanent target = new TargetOpponentsCreaturePermanent(); + ability.getTargets().add(target); + } +} + class NecroticPlagueEffect extends OneShotEffect { public NecroticPlagueEffect() { super(Outcome.PutCardInPlay); - staticText = "its controller chooses target creature one of their opponents controls. Return {this} from its owner's graveyard to the battlefield attached to that creature"; + staticText = "its controller chooses target creature one of their opponents controls. " + + "Return {this} from its owner's graveyard to the battlefield attached to that creature"; } public NecroticPlagueEffect(final NecroticPlagueEffect effect) { diff --git a/Mage.Sets/src/mage/cards/n/NeedleDrop.java b/Mage.Sets/src/mage/cards/n/NeedleDrop.java index 2b299e4f35a..63a5b8535d6 100644 --- a/Mage.Sets/src/mage/cards/n/NeedleDrop.java +++ b/Mage.Sets/src/mage/cards/n/NeedleDrop.java @@ -58,7 +58,7 @@ class DamagedThisTurnPredicate implements Predicate { @Override public boolean apply(MageItem input, Game game) { - DamageDoneWatcher watcher = (DamageDoneWatcher) game.getState().getWatchers().get(DamageDoneWatcher.class.getSimpleName()); + DamageDoneWatcher watcher = game.getState().getWatcher(DamageDoneWatcher.class); if (watcher != null) { if (input instanceof MageObject) { return watcher.isDamaged(input.getId(), ((MageObject) input).getZoneChangeCounter(game), game); diff --git a/Mage.Sets/src/mage/cards/n/NeedlebiteTrap.java b/Mage.Sets/src/mage/cards/n/NeedlebiteTrap.java index bfa69afdc8c..5a07ec5668b 100644 --- a/Mage.Sets/src/mage/cards/n/NeedlebiteTrap.java +++ b/Mage.Sets/src/mage/cards/n/NeedlebiteTrap.java @@ -51,10 +51,10 @@ enum NeedlebiteTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerGainedLifeWatcher watcher = (PlayerGainedLifeWatcher) game.getState().getWatchers().get(PlayerGainedLifeWatcher.class.getSimpleName()); + PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { - if (watcher.getLiveGained(opponentId) > 0) { + if (watcher.getLifeGained(opponentId) > 0) { return true; } } diff --git a/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java b/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java index ef22b710b6f..0cab56e3fe8 100644 --- a/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java +++ b/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java @@ -1,7 +1,6 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -11,19 +10,16 @@ import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGravey import mage.abilities.keyword.MonstrosityAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.CostModificationType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.players.Player; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class NemesisOfMortals extends CardImpl { @@ -41,6 +37,7 @@ public final class NemesisOfMortals extends CardImpl { this.addAbility(ability); // {7}{G}{G}: Monstrosity 5. This ability costs {1} less to activate for each creature card in your graveyard. + // TODO: Make ability properly copiable ability = new MonstrosityAbility("{7}{G}{G}", 5); for (Effect effect : ability.getEffects()) { effect.setText("Monstrosity 5. This ability costs {1} less to activate for each creature card in your graveyard"); @@ -49,7 +46,7 @@ public final class NemesisOfMortals extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.ALL, new NemesisOfMortalsCostReducingEffect(ability.getOriginalId()))); } - public NemesisOfMortals(final NemesisOfMortals card) { + private NemesisOfMortals(final NemesisOfMortals card) { super(card); } @@ -68,7 +65,7 @@ class NemesisOfMortalsCostReducingEffect extends CostModificationEffectImpl { this.originalId = originalId; } - NemesisOfMortalsCostReducingEffect(final NemesisOfMortalsCostReducingEffect effect) { + private NemesisOfMortalsCostReducingEffect(final NemesisOfMortalsCostReducingEffect effect) { super(effect); this.originalId = effect.originalId; } @@ -77,7 +74,7 @@ class NemesisOfMortalsCostReducingEffect extends CostModificationEffectImpl { public boolean apply(Game game, Ability source, Ability abilityToModify) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - CardUtil.reduceCost(abilityToModify, controller.getGraveyard().getCards(new FilterCreatureCard(), game).size()); + CardUtil.reduceCost(abilityToModify, controller.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/n/NemesisTrap.java b/Mage.Sets/src/mage/cards/n/NemesisTrap.java index 003fa1cb475..39512496787 100644 --- a/Mage.Sets/src/mage/cards/n/NemesisTrap.java +++ b/Mage.Sets/src/mage/cards/n/NemesisTrap.java @@ -36,7 +36,7 @@ public final class NemesisTrap extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.WHITE)); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public NemesisTrap(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java b/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java index 5a69454d633..04135db5baf 100644 --- a/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java +++ b/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java @@ -25,7 +25,7 @@ public final class NephaliaSmuggler extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public NephaliaSmuggler(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java b/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java index 3cb5b250f23..1d5e7026cb2 100644 --- a/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java +++ b/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java @@ -25,7 +25,7 @@ public final class NessianWildsRavager extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public NessianWildsRavager(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NettleDrone.java b/Mage.Sets/src/mage/cards/n/NettleDrone.java index da8ddeef7c8..e565226ee20 100644 --- a/Mage.Sets/src/mage/cards/n/NettleDrone.java +++ b/Mage.Sets/src/mage/cards/n/NettleDrone.java @@ -27,7 +27,7 @@ public final class NettleDrone extends CardImpl { private static final FilterSpell filterSpell = new FilterSpell("a colorless spell"); static { - filterSpell.add(new ColorlessPredicate()); + filterSpell.add(ColorlessPredicate.instance); } public NettleDrone(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NeutralizingBlast.java b/Mage.Sets/src/mage/cards/n/NeutralizingBlast.java index 39a9864fc7e..f4eeb349855 100644 --- a/Mage.Sets/src/mage/cards/n/NeutralizingBlast.java +++ b/Mage.Sets/src/mage/cards/n/NeutralizingBlast.java @@ -18,7 +18,7 @@ public final class NeutralizingBlast extends CardImpl { private static final FilterSpell filter = new FilterSpell("multicolored spell"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public NeutralizingBlast(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NeverReturn.java b/Mage.Sets/src/mage/cards/n/NeverReturn.java index 8318ab0b607..60500ee835f 100644 --- a/Mage.Sets/src/mage/cards/n/NeverReturn.java +++ b/Mage.Sets/src/mage/cards/n/NeverReturn.java @@ -31,7 +31,7 @@ public final class NeverReturn extends SplitCard { // Return // Exile target card from a graveyard. Create a 2/2 black Zombie creature token. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addEffect(new ExileTargetEffect()); getRightHalfCard().getSpellAbility().addTarget(new TargetCardInGraveyard()); getRightHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken())); diff --git a/Mage.Sets/src/mage/cards/n/NewBlood.java b/Mage.Sets/src/mage/cards/n/NewBlood.java index b4b1ee8437a..4361a19ef0d 100644 --- a/Mage.Sets/src/mage/cards/n/NewBlood.java +++ b/Mage.Sets/src/mage/cards/n/NewBlood.java @@ -39,7 +39,7 @@ public final class NewBlood extends CardImpl { TextPartSubType textPartVampire = (TextPartSubType) addTextPart(new TextPartSubType(SubType.VAMPIRE)); FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped Vampire you control"); filter.add(new TextPartSubtypePredicate(textPartVampire)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); // As an additional cost to cast New Blood, tap an untapped Vampire you control. this.getSpellAbility().addCost(new TapTargetCost( new TargetControlledCreaturePermanent(1, 1, filter, true))); diff --git a/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java b/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java index aafd4aeadf1..a0d0d6b82d8 100644 --- a/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java +++ b/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java @@ -1,7 +1,5 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -19,8 +17,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class NiblisOfFrost extends CardImpl { @@ -31,7 +30,7 @@ public final class NiblisOfFrost extends CardImpl { } public NiblisOfFrost(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(3); this.toughness = new MageInt(3); @@ -43,7 +42,7 @@ public final class NiblisOfFrost extends CardImpl { this.addAbility(new ProwessAbility()); // Whenever you cast an instant or sorcery spell, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step. - Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); + Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false); ability.addTarget(new TargetCreaturePermanent(filterCreature)); ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That creature")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/n/Nightcreep.java b/Mage.Sets/src/mage/cards/n/Nightcreep.java index 13e51cd7b0a..45cde1263cb 100644 --- a/Mage.Sets/src/mage/cards/n/Nightcreep.java +++ b/Mage.Sets/src/mage/cards/n/Nightcreep.java @@ -59,11 +59,6 @@ class NightcreepLandEffect extends BecomesBasicLandTargetEffect { this.setTargetPointer(new FixedTargets(targets, game)); } - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - return super.apply(layer, sublayer, source, game); - } - @Override public NightcreepLandEffect copy() { return new NightcreepLandEffect(this); @@ -88,11 +83,6 @@ class NightcreepCreatureEffect extends BecomesColorTargetEffect { this.setTargetPointer(new FixedTargets(targets, game)); } - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - return super.apply(layer, sublayer, source, game); - } - @Override public NightcreepCreatureEffect copy() { return new NightcreepCreatureEffect(this); diff --git a/Mage.Sets/src/mage/cards/n/NightmarishEnd.java b/Mage.Sets/src/mage/cards/n/NightmarishEnd.java index ccf1c13d351..c597bc8f7a2 100644 --- a/Mage.Sets/src/mage/cards/n/NightmarishEnd.java +++ b/Mage.Sets/src/mage/cards/n/NightmarishEnd.java @@ -24,7 +24,7 @@ public final class NightmarishEnd extends CardImpl { // Target creature gets -X/-X until end of turn, where X is the number of cards in your hand. - DynamicValue xValue = new SignInversionDynamicValue(new CardsInControllerHandCount()); + DynamicValue xValue = new SignInversionDynamicValue(CardsInControllerHandCount.instance); Effect effect = new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn, true); effect.setText("Target creature gets -X/-X until end of turn, where X is the number of cards in your hand"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/n/Nightsnare.java b/Mage.Sets/src/mage/cards/n/Nightsnare.java index 7a4517db4ae..c189b8eedc1 100644 --- a/Mage.Sets/src/mage/cards/n/Nightsnare.java +++ b/Mage.Sets/src/mage/cards/n/Nightsnare.java @@ -1,14 +1,8 @@ - package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -18,14 +12,15 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Nightsnare extends CardImpl { public Nightsnare(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); // Target opponent reveals their hand. You may choose a nonland card from it. If you do, that player discards that card. If you don't, that player discards two cards. this.getSpellAbility().addTarget(new TargetOpponent()); @@ -57,11 +52,11 @@ class NightsnareDiscardEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - Card sourceCard = game.getCard(source.getSourceId()); if (player != null && controller != null) { if (!player.getHand().isEmpty()) { Cards revealedCards = new CardsImpl(); revealedCards.addAll(player.getHand()); + Card sourceCard = game.getCard(source.getSourceId()); player.revealCards(sourceCard != null ? sourceCard.getIdName() : "Discard", revealedCards, game); // You may choose a nonland card from it. if (controller.chooseUse(outcome, "Choose a a card to discard? (Otherwise " + player.getLogName() + " has to discard 2 cards).", source, game)) { diff --git a/Mage.Sets/src/mage/cards/n/NikyaOfTheOldWays.java b/Mage.Sets/src/mage/cards/n/NikyaOfTheOldWays.java new file mode 100644 index 00000000000..cdb990392d6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NikyaOfTheOldWays.java @@ -0,0 +1,88 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.TapForManaAllTriggeredManaAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.mana.AddManaOfAnyTypeProducedEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NikyaOfTheOldWays extends CardImpl { + + public NikyaOfTheOldWays(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.CENTAUR); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // You can't cast noncreature spells. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, new NikyaOfTheOldWaysCantCastEffect() + )); + + // Whenever you tap a land for mana, add one mana of any type that land produced. + AddManaOfAnyTypeProducedEffect effect = new AddManaOfAnyTypeProducedEffect(); + effect.setText("add one mana of any type that land produced"); + this.addAbility(new TapForManaAllTriggeredManaAbility( + effect, + new FilterControlledLandPermanent("you tap a land"), + SetTargetPointer.PERMANENT) + ); + } + + private NikyaOfTheOldWays(final NikyaOfTheOldWays card) { + super(card); + } + + @Override + public NikyaOfTheOldWays copy() { + return new NikyaOfTheOldWays(this); + } +} + +class NikyaOfTheOldWaysCantCastEffect extends ContinuousRuleModifyingEffectImpl { + + NikyaOfTheOldWaysCantCastEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "You can't cast noncreature spells"; + } + + private NikyaOfTheOldWaysCantCastEffect(final NikyaOfTheOldWaysCantCastEffect effect) { + super(effect); + } + + @Override + public NikyaOfTheOldWaysCantCastEffect copy() { + return new NikyaOfTheOldWaysCantCastEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getPlayerId().equals(source.getControllerId())) { + Card card = game.getCard(event.getSourceId()); + return card != null && !card.isCreature(); + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NinthBridgePatrol.java b/Mage.Sets/src/mage/cards/n/NinthBridgePatrol.java index ebbcfc3ca77..1ba7fd421b9 100644 --- a/Mage.Sets/src/mage/cards/n/NinthBridgePatrol.java +++ b/Mage.Sets/src/mage/cards/n/NinthBridgePatrol.java @@ -26,7 +26,7 @@ public final class NinthBridgePatrol extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public NinthBridgePatrol(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NoContest.java b/Mage.Sets/src/mage/cards/n/NoContest.java index 1298ece8083..5a2f1421277 100644 --- a/Mage.Sets/src/mage/cards/n/NoContest.java +++ b/Mage.Sets/src/mage/cards/n/NoContest.java @@ -1,8 +1,5 @@ - package mage.cards.n; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.common.FightTargetsEffect; import mage.cards.Card; @@ -19,6 +16,9 @@ import mage.game.stack.Spell; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.Set; +import java.util.UUID; + /** * @author Styxo */ @@ -56,8 +56,11 @@ class TargetCreatureWithLessPowerPermanent extends TargetPermanent { @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - int maxPower = Integer.MIN_VALUE; // get the most poerful controlled creature that can be targeted + int maxPower = Integer.MIN_VALUE; // get the most powerful controlled creature that can be targeted Card sourceCard = game.getCard(sourceId); + if (sourceCard == null) { + return false; + } for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, sourceControllerId, game)) { if (permanent.getPower().getValue() > maxPower && permanent.canBeTargetedBy(sourceCard, sourceControllerId, game)) { maxPower = permanent.getPower().getValue(); diff --git a/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java b/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java index 063f4958cbd..b07ceb984fc 100644 --- a/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java +++ b/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java @@ -58,7 +58,7 @@ class NoRestForTheWickedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - NoRestForTheWickedWatcher watcher = (NoRestForTheWickedWatcher) game.getState().getWatchers().get(NoRestForTheWickedWatcher.class.getSimpleName()); + NoRestForTheWickedWatcher watcher = game.getState().getWatcher(NoRestForTheWickedWatcher.class); Player controller = game.getPlayer(source.getControllerId()); if (watcher != null && controller != null) { Cards cardsToHand = new CardsImpl(); @@ -90,7 +90,7 @@ class NoRestForTheWickedWatcher extends Watcher { List cards; public NoRestForTheWickedWatcher() { - super(NoRestForTheWickedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(NoRestForTheWickedWatcher.class, WatcherScope.GAME); this.cards = new ArrayList<>(); } diff --git a/Mage.Sets/src/mage/cards/n/NobleStand.java b/Mage.Sets/src/mage/cards/n/NobleStand.java index ed5d96b2024..5d490b14578 100644 --- a/Mage.Sets/src/mage/cards/n/NobleStand.java +++ b/Mage.Sets/src/mage/cards/n/NobleStand.java @@ -56,8 +56,8 @@ class NobleStandAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(Predicates.not(new TokenPredicate())); - Permanent permanent = (Permanent) game.getPermanent(event.getSourceId()); + filter.add(Predicates.not(TokenPredicate.instance)); + Permanent permanent = game.getPermanent(event.getSourceId()); return permanent != null && filter.match(permanent, sourceId, controllerId, game); } diff --git a/Mage.Sets/src/mage/cards/n/NogginWhack.java b/Mage.Sets/src/mage/cards/n/NogginWhack.java index 3d5311a9510..5aa88225c42 100644 --- a/Mage.Sets/src/mage/cards/n/NogginWhack.java +++ b/Mage.Sets/src/mage/cards/n/NogginWhack.java @@ -96,7 +96,7 @@ class NogginWhackEffect extends OneShotEffect { if (!revealedCards.isEmpty()) { targetPlayer.revealCards("Noggin Whack", revealedCards, game); controller.chooseTarget(Outcome.Exile, revealedCards, targetInHand, source, game); - for (UUID cardId : (List) targetInHand.getTargets()) { + for (UUID cardId : targetInHand.getTargets()) { Card card = game.getCard(cardId); if (card != null) { controller.discard(card, source, game); diff --git a/Mage.Sets/src/mage/cards/n/NostalgicDreams.java b/Mage.Sets/src/mage/cards/n/NostalgicDreams.java index b0de519a184..a9d8eec1aef 100644 --- a/Mage.Sets/src/mage/cards/n/NostalgicDreams.java +++ b/Mage.Sets/src/mage/cards/n/NostalgicDreams.java @@ -1,9 +1,7 @@ package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.costs.common.DiscardXTargetCost; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.Effect; @@ -15,11 +13,12 @@ import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.game.Game; -import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class NostalgicDreams extends CardImpl { @@ -33,27 +32,31 @@ public final class NostalgicDreams extends CardImpl { Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return X target cards from your graveyard to your hand"); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().setTargetAdjuster(NostalgicDreamsAdjuster.instance); + // Exile Nostalgic Dreams. this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); - } public NostalgicDreams(final NostalgicDreams card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = new GetXValue().calculate(game, ability, null); - Target target = new TargetCardInYourGraveyard(xValue, StaticFilters.FILTER_CARD_FROM_YOUR_GRAVEYARD); - ability.addTarget(target); - } - - } - @Override public NostalgicDreams copy() { return new NostalgicDreams(this); } } + +enum NostalgicDreamsAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard( + GetXValue.instance.calculate(game, ability, null), + StaticFilters.FILTER_CARD_FROM_YOUR_GRAVEYARD + )); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NosyGoblin.java b/Mage.Sets/src/mage/cards/n/NosyGoblin.java index d0bf2f67eb9..369af08b43e 100644 --- a/Mage.Sets/src/mage/cards/n/NosyGoblin.java +++ b/Mage.Sets/src/mage/cards/n/NosyGoblin.java @@ -26,7 +26,7 @@ public final class NosyGoblin extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public NosyGoblin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NotionThief.java b/Mage.Sets/src/mage/cards/n/NotionThief.java index 9ff6a3977a7..75626aeb1ac 100644 --- a/Mage.Sets/src/mage/cards/n/NotionThief.java +++ b/Mage.Sets/src/mage/cards/n/NotionThief.java @@ -90,7 +90,7 @@ class NotionThiefReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { if (game.isActivePlayer(event.getPlayerId()) && game.getStep().getType() == PhaseStep.DRAW) { - CardsDrawnDuringDrawStepWatcher watcher = (CardsDrawnDuringDrawStepWatcher) game.getState().getWatchers().get(CardsDrawnDuringDrawStepWatcher.class.getSimpleName()); + CardsDrawnDuringDrawStepWatcher watcher = game.getState().getWatcher(CardsDrawnDuringDrawStepWatcher.class); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) { return true; } diff --git a/Mage.Sets/src/mage/cards/n/NotoriousThrong.java b/Mage.Sets/src/mage/cards/n/NotoriousThrong.java index 8663f38d83c..cb553b3b774 100644 --- a/Mage.Sets/src/mage/cards/n/NotoriousThrong.java +++ b/Mage.Sets/src/mage/cards/n/NotoriousThrong.java @@ -70,7 +70,7 @@ class NotoriousThrongEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = (AmountOfDamageAPlayerReceivedThisTurnWatcher) game.getState().getWatchers().get(AmountOfDamageAPlayerReceivedThisTurnWatcher.class.getSimpleName()); + AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = game.getState().getWatcher(AmountOfDamageAPlayerReceivedThisTurnWatcher.class); if(controller != null && watcher != null) { int numTokens = 0; for(UUID opponentId: game.getOpponents(controller.getId())) { diff --git a/Mage.Sets/src/mage/cards/n/NourishingShoal.java b/Mage.Sets/src/mage/cards/n/NourishingShoal.java index f6459c10858..aa39d1d90fa 100644 --- a/Mage.Sets/src/mage/cards/n/NourishingShoal.java +++ b/Mage.Sets/src/mage/cards/n/NourishingShoal.java @@ -36,7 +36,7 @@ public final class NourishingShoal extends CardImpl { this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter), true))); // You gain X life. - this.getSpellAbility().addEffect(new GainLifeEffect(new ExileFromHandCostCardConvertedMana())); + this.getSpellAbility().addEffect(new GainLifeEffect(ExileFromHandCostCardConvertedMana.instance)); } diff --git a/Mage.Sets/src/mage/cards/n/NovablastWurm.java b/Mage.Sets/src/mage/cards/n/NovablastWurm.java index b61d7f32c3d..e8c8fc9e02e 100644 --- a/Mage.Sets/src/mage/cards/n/NovablastWurm.java +++ b/Mage.Sets/src/mage/cards/n/NovablastWurm.java @@ -22,7 +22,7 @@ public final class NovablastWurm extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new CardTypePredicate(CardType.CREATURE)); } diff --git a/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java b/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java index 9314df3c4a0..c41310dc4dd 100644 --- a/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java +++ b/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java @@ -28,7 +28,7 @@ public final class NoxiousGearhulk extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public NoxiousGearhulk(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java b/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java index 6f7d1807571..a7892984442 100644 --- a/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java +++ b/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java @@ -1,7 +1,6 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.continuous.BoostAllEffect; @@ -10,42 +9,45 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class NoxiousGhoul extends CardImpl { - final FilterPermanent filter = new FilterPermanent("Noxious Ghoul or another Zombie"); - final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("non-Zombie"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterPermanent(); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(Predicates.not(new SubtypePredicate(SubType.ZOMBIE))); + filter2.add(NoxiousGhoulPredicate.instance); + } public NoxiousGhoul(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.ZOMBIE); this.power = new MageInt(3); this.toughness = new MageInt(3); - filter.add(Predicates.or( - new CardIdPredicate(this.getId()), - new SubtypePredicate(SubType.ZOMBIE))); - - filter2.add(new CardTypePredicate(CardType.CREATURE)); - filter2.add(Predicates.not( - new SubtypePredicate(SubType.ZOMBIE))); - - final String rule = "Whenever {this} or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn."; - // Whenever Noxious Ghoul or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn. - this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new BoostAllEffect(-1, -1, Duration.EndOfTurn, filter2, false), filter, false, rule)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new BoostAllEffect(-1, -1, Duration.EndOfTurn, filter, false), + filter2, "Whenever {this} or another Zombie enters the battlefield, " + + "all non-Zombie creatures get -1/-1 until end of turn." + )); } public NoxiousGhoul(final NoxiousGhoul card) { @@ -57,3 +59,13 @@ public final class NoxiousGhoul extends CardImpl { return new NoxiousGhoul(this); } } + +enum NoxiousGhoulPredicate implements ObjectSourcePlayerPredicate> { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().hasSubtype(SubType.ZOMBIE, game) + || input.getObject().getId().equals(input.getSourceId()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NoxiousGroodion.java b/Mage.Sets/src/mage/cards/n/NoxiousGroodion.java new file mode 100644 index 00000000000..f9af47f5b8d --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NoxiousGroodion.java @@ -0,0 +1,36 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NoxiousGroodion extends CardImpl { + + public NoxiousGroodion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + } + + private NoxiousGroodion(final NoxiousGroodion card) { + super(card); + } + + @Override + public NoxiousGroodion copy() { + return new NoxiousGroodion(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NullmageShepherd.java b/Mage.Sets/src/mage/cards/n/NullmageShepherd.java index 0373a0c16e4..38ed9f9b56d 100644 --- a/Mage.Sets/src/mage/cards/n/NullmageShepherd.java +++ b/Mage.Sets/src/mage/cards/n/NullmageShepherd.java @@ -28,7 +28,7 @@ public final class NullmageShepherd extends CardImpl { private static final FilterControlledCreaturePermanent filterCost = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filterCost.add(Predicates.not(new TappedPredicate())); + filterCost.add(Predicates.not(TappedPredicate.instance)); } public NullmageShepherd(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/n/NullstoneGargoyle.java b/Mage.Sets/src/mage/cards/n/NullstoneGargoyle.java index 35cbeedc1d2..54997e89b69 100644 --- a/Mage.Sets/src/mage/cards/n/NullstoneGargoyle.java +++ b/Mage.Sets/src/mage/cards/n/NullstoneGargoyle.java @@ -74,7 +74,7 @@ class NullstoneGargoyleTriggeredAbility extends TriggeredAbilityImpl { if (spell.isCreature()) { return false; } - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null && watcher.getNumberOfNonCreatureSpells() == 1) { for (Effect effect : getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage.Sets/src/mage/cards/n/NuteGunray.java b/Mage.Sets/src/mage/cards/n/NuteGunray.java index aad1a83e17a..bffe968bd27 100644 --- a/Mage.Sets/src/mage/cards/n/NuteGunray.java +++ b/Mage.Sets/src/mage/cards/n/NuteGunray.java @@ -34,7 +34,7 @@ public final class NuteGunray extends CardImpl { private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("non-token artifact"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public NuteGunray(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java b/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java index b494987c9ea..6333d5a3f35 100644 --- a/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java +++ b/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java @@ -99,7 +99,7 @@ class OKagachiVengefulKamiTriggeredAbility extends TriggeredAbilityImpl { UUID you = this.getControllerId(); Permanent p = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage() && p != null && p.getId().equals(this.getSourceId())) { - PlayersAttackedLastTurnWatcher watcher = (PlayersAttackedLastTurnWatcher) game.getState().getWatchers().get(PlayersAttackedLastTurnWatcher.class.getSimpleName()); + PlayersAttackedLastTurnWatcher watcher = game.getState().getWatcher(PlayersAttackedLastTurnWatcher.class); if (watcher != null && watcher.attackedLastTurn(damagedPlayerId, you)) { FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent defending player controls"); filter.add(new ControllerIdPredicate(damagedPlayerId)); diff --git a/Mage.Sets/src/mage/cards/o/OakStreetInnkeeper.java b/Mage.Sets/src/mage/cards/o/OakStreetInnkeeper.java index bd5dbb0a8b9..a25c0b16166 100644 --- a/Mage.Sets/src/mage/cards/o/OakStreetInnkeeper.java +++ b/Mage.Sets/src/mage/cards/o/OakStreetInnkeeper.java @@ -26,7 +26,7 @@ public final class OakStreetInnkeeper extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("tapped creatures you control"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public OakStreetInnkeeper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OathOfChandra.java b/Mage.Sets/src/mage/cards/o/OathOfChandra.java index 4610ca8f5c8..a2a574a5e3d 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfChandra.java +++ b/Mage.Sets/src/mage/cards/o/OathOfChandra.java @@ -69,7 +69,7 @@ enum OathOfChandraCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - OathOfChandraWatcher watcher = (OathOfChandraWatcher) game.getState().getWatchers().get(OathOfChandraWatcher.class.getSimpleName()); + OathOfChandraWatcher watcher = game.getState().getWatcher(OathOfChandraWatcher.class); return watcher != null && watcher.enteredPlaneswalkerForPlayer(source.getControllerId()); } @@ -85,7 +85,7 @@ class OathOfChandraWatcher extends Watcher { private final Set players = new HashSet<>(); public OathOfChandraWatcher() { - super(OathOfChandraWatcher.class.getSimpleName(), WatcherScope.GAME); + super(OathOfChandraWatcher.class, WatcherScope.GAME); } public OathOfChandraWatcher(final OathOfChandraWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/o/OathOfDruids.java b/Mage.Sets/src/mage/cards/o/OathOfDruids.java index c8bb0d56eb7..652548ad6f1 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfDruids.java +++ b/Mage.Sets/src/mage/cards/o/OathOfDruids.java @@ -1,15 +1,10 @@ package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.TargetController; @@ -21,20 +16,15 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author Plopman */ public final class OathOfDruids extends CardImpl { - private final UUID originalId; - private static final FilterPlayer filter = new FilterPlayer(); - - static { - filter.add(new OathOfDruidsPredicate()); - } - public OathOfDruids(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); @@ -42,27 +32,12 @@ public final class OathOfDruids extends CardImpl { // The first player may reveal cards from the top of their library until he or she reveals a creature card. // If he or she does, that player puts that card onto the battlefield and all other cards revealed this way into their graveyard. Ability ability = new BeginningOfUpkeepTriggeredAbility(new OathOfDruidsEffect(), TargetController.ANY, false); - ability.addTarget(new TargetPlayer(1, 1, false, filter)); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(OathOfDruidsAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - ability.getTargets().clear(); - TargetPlayer target = new TargetPlayer(1, 1, false, filter); - target.setTargetController(activePlayer.getId()); - ability.getTargets().add(target); - } - } - } - public OathOfDruids(final OathOfDruids card) { super(card); - this.originalId = card.originalId; } @Override @@ -71,6 +46,26 @@ public final class OathOfDruids extends CardImpl { } } +enum OathOfDruidsAdjuster implements TargetAdjuster { + instance; + private static final FilterPlayer filter = new FilterPlayer(); + + static { + filter.add(new OathOfDruidsPredicate()); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer != null) { + ability.getTargets().clear(); + TargetPlayer target = new TargetPlayer(1, 1, false, filter); + target.setTargetController(activePlayer.getId()); + ability.getTargets().add(target); + } + } +} + class OathOfDruidsPredicate implements ObjectSourcePlayerPredicate> { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); diff --git a/Mage.Sets/src/mage/cards/o/OathOfGhouls.java b/Mage.Sets/src/mage/cards/o/OathOfGhouls.java index 310ab0a52a9..73b5eb4677b 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfGhouls.java +++ b/Mage.Sets/src/mage/cards/o/OathOfGhouls.java @@ -1,7 +1,6 @@ package mage.cards.o; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -15,57 +14,36 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.FilterPlayer; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; -import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.TargetPlayer; import mage.target.common.TargetCardInGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class OathOfGhouls extends CardImpl { - private final UUID originalId; - private static final FilterPlayer filter = new FilterPlayer(); - - static { - filter.add(new OathOfGhoulsPredicate()); - } - public OathOfGhouls(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); // At the beginning of each player's upkeep, that player chooses target player whose graveyard has fewer creature cards in it than their graveyard does and is their opponent. The first player may return a creature card from their graveyard to their hand. Ability ability = new BeginningOfUpkeepTriggeredAbility(new OathOfGhoulsEffect(), TargetController.ANY, false); - ability.addTarget(new TargetPlayer(1, 1, false, filter)); + ability.setTargetAdjuster(OathOfGhoulsAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - ability.getTargets().clear(); - TargetPlayer target = new TargetPlayer(1, 1, false, filter); - target.setTargetController(activePlayer.getId()); - ability.getTargets().add(target); - } - } } public OathOfGhouls(final OathOfGhouls card) { super(card); - this.originalId = card.originalId; } @Override @@ -74,14 +52,28 @@ public final class OathOfGhouls extends CardImpl { } } -class OathOfGhoulsPredicate implements ObjectSourcePlayerPredicate> { - - private static final FilterCard filter = new FilterCard("creature cards"); +enum OathOfGhoulsAdjuster implements TargetAdjuster { + instance; + private static final FilterPlayer filter = new FilterPlayer(); static { - filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new OathOfGhoulsPredicate()); } + @Override + public void adjustTargets(Ability ability, Game game) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer != null) { + ability.getTargets().clear(); + TargetPlayer target = new TargetPlayer(1, 1, false, filter); + target.setTargetController(activePlayer.getId()); + ability.getTargets().add(target); + } + } +} + +class OathOfGhoulsPredicate implements ObjectSourcePlayerPredicate> { + @Override public boolean apply(ObjectSourcePlayer input, Game game) { Player targetPlayer = input.getObject(); @@ -91,8 +83,8 @@ class OathOfGhoulsPredicate implements ObjectSourcePlayerPredicate> { - private static final FilterLandPermanent FILTER = new FilterLandPermanent(); - @Override public boolean apply(ObjectSourcePlayer input, Game game) { - // input.getPlayerId() -- source controller id - // input.getObject() -- checking player - Player targetPlayer = input.getObject(); //Get active input.playerId because adjust target is used after canTarget function - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - - if (targetPlayer == null || activePlayer == null) { + UUID activePlayerId = game.getActivePlayerId(); + if (targetPlayer == null || activePlayerId == null) { return false; } - - // must be opponent - if (!activePlayer.hasOpponent(targetPlayer.getId(), game)) { + if (!targetPlayer.hasOpponent(activePlayerId, game)) { return false; } + int countTargetPlayer = game.getBattlefield().countAll(StaticFilters.FILTER_LAND, targetPlayer.getId(), game); + int countActivePlayer = game.getBattlefield().countAll(StaticFilters.FILTER_LAND, activePlayerId, game); - // must have more lands than active player - int countTargetPlayer = game.getBattlefield().countAll(FILTER, targetPlayer.getId(), game); - int countActivePlayer = game.getBattlefield().countAll(FILTER, activePlayer.getId(), game); return countTargetPlayer > countActivePlayer; } diff --git a/Mage.Sets/src/mage/cards/o/OathOfLiliana.java b/Mage.Sets/src/mage/cards/o/OathOfLiliana.java index 5e45a1e6bef..b8f46913640 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfLiliana.java +++ b/Mage.Sets/src/mage/cards/o/OathOfLiliana.java @@ -57,7 +57,7 @@ enum OathOfLilianaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - OathOfLilianaWatcher watcher = (OathOfLilianaWatcher) game.getState().getWatchers().get(OathOfLilianaWatcher.class.getSimpleName()); + OathOfLilianaWatcher watcher = game.getState().getWatcher(OathOfLilianaWatcher.class); return watcher != null && watcher.enteredPlaneswalkerForPlayer(source.getControllerId()); } @@ -73,7 +73,7 @@ class OathOfLilianaWatcher extends Watcher { private final Set players = new HashSet<>(); public OathOfLilianaWatcher() { - super(OathOfLilianaWatcher.class.getSimpleName(), WatcherScope.GAME); + super(OathOfLilianaWatcher.class, WatcherScope.GAME); } public OathOfLilianaWatcher(final OathOfLilianaWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/o/OathOfLimDul.java b/Mage.Sets/src/mage/cards/o/OathOfLimDul.java new file mode 100644 index 00000000000..2d3aa09c5a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OathOfLimDul.java @@ -0,0 +1,139 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author jeffwadsworth + */ +public final class OathOfLimDul extends CardImpl { + + public OathOfLimDul(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); + + // Whenever you lose life, for each 1 life you lost, sacrifice a permanent other than Oath of Lim-Dul unless you discard a card. + this.addAbility(new OathOfLimDulTriggeredAbility()); + + // {B}{B}: Draw a card. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{B}{B}"))); + + } + + private OathOfLimDul(final OathOfLimDul card) { + super(card); + } + + @Override + public OathOfLimDul copy() { + return new OathOfLimDul(this); + } +} + +class OathOfLimDulTriggeredAbility extends TriggeredAbilityImpl { + + public OathOfLimDulTriggeredAbility() { + super(Zone.BATTLEFIELD, new OathOfLimDulEffect()); + } + + public OathOfLimDulTriggeredAbility(final OathOfLimDulTriggeredAbility ability) { + super(ability); + } + + @Override + public OathOfLimDulTriggeredAbility copy() { + return new OathOfLimDulTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.LOST_LIFE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(controllerId)) { + game.getState().setValue(sourceId.toString() + "oathOfLimDul", event.getAmount()); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever you lose life, for each 1 life you lost, sacrifice a permanent other than {this} unless you discard a card."; + } +} + +class OathOfLimDulEffect extends OneShotEffect { + + private final static FilterControlledPermanent filter = new FilterControlledPermanent("controlled permanent other than Oath of Lim-Dul"); + + static { + filter.add(AnotherPredicate.instance); + } + + public OathOfLimDulEffect() { + super(Outcome.Neutral); + } + + public OathOfLimDulEffect(final OathOfLimDulEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + int amount = (int) game.getState().getValue(source.getSourceId().toString() + "oathOfLimDul"); + if (amount > 0 + && controller != null) { + for (int i = 0; i < amount; i++) { + TargetControlledPermanent target = new TargetControlledPermanent(filter); + target.setNotTarget(true); + if (target.canChoose(controller.getId(), game) + && controller.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) { + Cost cost = new DiscardTargetCost(new TargetCardInHand()); + if (cost.canPay(source, source.getSourceId(), controller.getId(), game) + && controller.chooseUse(Outcome.Benefit, + "Do you wish to discard a card rather than sacrifice the target permanent?", source, game)) { + cost.pay(source, game, source.getSourceId(), controller.getId(), true); + } else { + Permanent targetPermanent = game.getPermanent(target.getFirstTarget()); + if (targetPermanent != null) { + targetPermanent.sacrifice(source.getSourceId(), game); + } + } + } + } + return true; + } + return false; + } + + @Override + public OathOfLimDulEffect copy() { + return new OathOfLimDulEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/o/OathOfMages.java b/Mage.Sets/src/mage/cards/o/OathOfMages.java index 4f43c746653..9621fcb8a77 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfMages.java +++ b/Mage.Sets/src/mage/cards/o/OathOfMages.java @@ -1,7 +1,6 @@ package mage.cards.o; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -17,46 +16,26 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class OathOfMages extends CardImpl { - private final UUID originalId; - private static final FilterPlayer filter = new FilterPlayer(); - - static { - filter.add(new OathOfMagesPredicate()); - } - public OathOfMages(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); // At the beginning of each player's upkeep, that player chooses target player who has more life than he or she does and is their opponent. The first player may have Oath of Mages deal 1 damage to the second player. Ability ability = new BeginningOfUpkeepTriggeredAbility(new OathOfMagesEffect(), TargetController.ANY, false); - ability.addTarget(new TargetPlayer(1, 1, false, filter)); + ability.setTargetAdjuster(OathOfMagesAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - ability.getTargets().clear(); - TargetPlayer target = new TargetPlayer(1, 1, false, filter); - target.setTargetController(activePlayer.getId()); - ability.getTargets().add(target); - } - } } public OathOfMages(final OathOfMages card) { super(card); - this.originalId = card.originalId; } @Override @@ -65,6 +44,26 @@ public final class OathOfMages extends CardImpl { } } +enum OathOfMagesAdjuster implements TargetAdjuster { + instance; + private static final FilterPlayer filter = new FilterPlayer(); + + static { + filter.add(new OathOfMagesPredicate()); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer != null) { + ability.getTargets().clear(); + TargetPlayer target = new TargetPlayer(1, 1, false, filter); + target.setTargetController(activePlayer.getId()); + ability.getTargets().add(target); + } + } +} + class OathOfMagesPredicate implements ObjectSourcePlayerPredicate> { @Override diff --git a/Mage.Sets/src/mage/cards/o/OathOfScholars.java b/Mage.Sets/src/mage/cards/o/OathOfScholars.java index 9a61ce6de8f..75d206ce16d 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfScholars.java +++ b/Mage.Sets/src/mage/cards/o/OathOfScholars.java @@ -1,7 +1,6 @@ package mage.cards.o; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -17,47 +16,26 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class OathOfScholars extends CardImpl { - private final UUID originalId; - private static final FilterPlayer filter = new FilterPlayer(); - - static { - filter.add(new OathOfScholarsPredicate()); - } - public OathOfScholars(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); // At the beginning of each player's upkeep, that player chooses target player who has more cards in hand than he or she does and is their opponent. The first player may discard their hand and draw three cards. Ability ability = new BeginningOfUpkeepTriggeredAbility(new OathOfScholarsEffect(), TargetController.ANY, false); - ability.addTarget(new TargetPlayer(1, 1, false, filter)); + ability.setTargetAdjuster(OathOfScholarsAdjuster.instance); this.addAbility(ability); - originalId = ability.getOriginalId(); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - ability.getTargets().clear(); - TargetPlayer target = new TargetPlayer(1, 1, false, filter); - target.setTargetController(activePlayer.getId()); - ability.getTargets().add(target); - } - } } public OathOfScholars(final OathOfScholars card) { super(card); - this.originalId = card.originalId; } @Override @@ -66,6 +44,26 @@ public final class OathOfScholars extends CardImpl { } } +enum OathOfScholarsAdjuster implements TargetAdjuster { + instance; + private static final FilterPlayer filter = new FilterPlayer(); + + static { + filter.add(new OathOfScholarsPredicate()); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer != null) { + ability.getTargets().clear(); + TargetPlayer target = new TargetPlayer(1, 1, false, filter); + target.setTargetController(activePlayer.getId()); + ability.getTargets().add(target); + } + } +} + class OathOfScholarsPredicate implements ObjectSourcePlayerPredicate> { @Override diff --git a/Mage.Sets/src/mage/cards/o/OathOfTeferi.java b/Mage.Sets/src/mage/cards/o/OathOfTeferi.java index 047d9447689..db292a88a07 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfTeferi.java +++ b/Mage.Sets/src/mage/cards/o/OathOfTeferi.java @@ -36,7 +36,7 @@ public final class OathOfTeferi extends CardImpl { private final static FilterControlledPermanent filter = new FilterControlledPermanent("another target permanent you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public OathOfTeferi(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java b/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java index c73958f38d0..d5718d8eaba 100644 --- a/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java +++ b/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java @@ -1,7 +1,5 @@ - package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; @@ -22,33 +20,38 @@ import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class OathkeeperTakenosDaisho extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("it's a Samurai card"); + static { filter.add(new SubtypePredicate(SubType.SAMURAI)); } public OathkeeperTakenosDaisho(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +3/+1. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3,1, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 1, Duration.WhileOnBattlefield))); + // Whenever equipped creature dies, return that card to the battlefield under your control if it's a Samurai card. this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesAttachedTriggeredAbility(new ReturnToBattlefieldUnderYourControlAttachedEffect(),"equipped creature", false), + new DiesAttachedTriggeredAbility(new ReturnToBattlefieldUnderYourControlAttachedEffect(), "equipped creature", false), new OathkeeperEquippedMatchesFilterCondition(filter), "")); + // When Oathkeeper, Takeno's Daisho is put into a graveyard from the battlefield, exile equipped creature. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ExileEquippedEffect())); + // Equip {2} - this.addAbility(new EquipAbility( Outcome.BoostCreature, new ManaCostsImpl("{2}"))); + this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{2}"))); } public OathkeeperTakenosDaisho(final OathkeeperTakenosDaisho card) { @@ -114,14 +117,12 @@ class OathkeeperEquippedMatchesFilterCondition implements Condition { } } if (attachedTo == null) { - for (Effect effect :source.getEffects()) { + for (Effect effect : source.getEffects()) { attachedTo = (Permanent) effect.getValue("attachedTo"); } } if (attachedTo != null) { - if (filter.match(attachedTo, attachedTo.getId(),attachedTo.getControllerId(), game)) { - return true; - } + return filter.match(attachedTo, attachedTo.getId(), attachedTo.getControllerId(), game); } } diff --git a/Mage.Sets/src/mage/cards/o/ObNixilisReignited.java b/Mage.Sets/src/mage/cards/o/ObNixilisReignited.java index 5bea48f7f8a..3a1003695b4 100644 --- a/Mage.Sets/src/mage/cards/o/ObNixilisReignited.java +++ b/Mage.Sets/src/mage/cards/o/ObNixilisReignited.java @@ -1,7 +1,5 @@ - package mage.cards.o; -import java.util.UUID; import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.effects.Effect; @@ -18,8 +16,9 @@ import mage.game.command.emblems.ObNixilisReignitedEmblem; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ObNixilisReignited extends CardImpl { @@ -32,12 +31,10 @@ public final class ObNixilisReignited extends CardImpl { this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); // +1: You draw a card and you lose 1 life. - Effect effect = new DrawCardSourceControllerEffect(1); - effect.setText("You draw a card"); + Effect effect = new DrawCardSourceControllerEffect(1, "you"); LoyaltyAbility ability1 = new LoyaltyAbility(effect, 1); effect = new LoseLifeSourceControllerEffect(1); - effect.setText("and you lose 1 life"); - ability1.addEffect(effect); + ability1.addEffect(effect.concatBy("and")); this.addAbility(ability1); // -3: Destroy target creature. @@ -47,7 +44,6 @@ public final class ObNixilisReignited extends CardImpl { // -8: Target opponent gets an emblem with "Whenever a player draws a card, you lose 2 life." effect = new GetEmblemTargetPlayerEffect(new ObNixilisReignitedEmblem()); - effect.setText("Target opponent gets an emblem with \"Whenever a player draws a card, you lose 2 life.\""); LoyaltyAbility ability3 = new LoyaltyAbility(effect, -8); ability3.addTarget(new TargetOpponent()); this.addAbility(ability3); diff --git a/Mage.Sets/src/mage/cards/o/OblivionRing.java b/Mage.Sets/src/mage/cards/o/OblivionRing.java index 8b5f3372239..8c4700b069f 100644 --- a/Mage.Sets/src/mage/cards/o/OblivionRing.java +++ b/Mage.Sets/src/mage/cards/o/OblivionRing.java @@ -27,7 +27,7 @@ public final class OblivionRing extends CardImpl { private static final FilterNonlandPermanent anotherNonlandPermanent = new FilterNonlandPermanent("another target nonland permanent"); static { - anotherNonlandPermanent.add(new AnotherPredicate()); + anotherNonlandPermanent.add(AnotherPredicate.instance); } public OblivionRing(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OblivionSower.java b/Mage.Sets/src/mage/cards/o/OblivionSower.java index 8742de4f54a..f3c8a5272d6 100644 --- a/Mage.Sets/src/mage/cards/o/OblivionSower.java +++ b/Mage.Sets/src/mage/cards/o/OblivionSower.java @@ -81,7 +81,7 @@ class OblivionSowerEffect extends OneShotEffect { if (controller != null && targetPlayer != null) { FilterLandCard filter = new FilterLandCard(); filter.add(new OwnerIdPredicate(targetPlayer.getId())); - filter.add(Predicates.not(new FaceDownPredicate())); + filter.add(Predicates.not(FaceDownPredicate.instance)); Cards exiledCards = new CardsImpl(); exiledCards.addAll(game.getExile().getAllCards(game)); Cards exiledLands = new CardsImpl(); diff --git a/Mage.Sets/src/mage/cards/o/OboroEnvoy.java b/Mage.Sets/src/mage/cards/o/OboroEnvoy.java index c4990fe881e..fa6d5891b0c 100644 --- a/Mage.Sets/src/mage/cards/o/OboroEnvoy.java +++ b/Mage.Sets/src/mage/cards/o/OboroEnvoy.java @@ -39,7 +39,7 @@ public final class OboroEnvoy extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // {2}, Return a land you control to its owner's hand: Target creature gets -X/-0 until end of turn, where X is the number of cards in your hand. - Effect effect = new BoostTargetEffect(new SignInversionDynamicValue(new CardsInControllerHandCount()), new StaticValue(-0), Duration.EndOfTurn, true); + Effect effect = new BoostTargetEffect(new SignInversionDynamicValue(CardsInControllerHandCount.instance), new StaticValue(-0), Duration.EndOfTurn, true); effect.setText("Target creature gets -X/-0 until end of turn, where X is the number of cards in your hand"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2)); ability.addCost(new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land")))); diff --git a/Mage.Sets/src/mage/cards/o/ObscuringAether.java b/Mage.Sets/src/mage/cards/o/ObscuringAether.java index 0f4aa3723c7..1b4e559253f 100644 --- a/Mage.Sets/src/mage/cards/o/ObscuringAether.java +++ b/Mage.Sets/src/mage/cards/o/ObscuringAether.java @@ -25,7 +25,7 @@ public final class ObscuringAether extends CardImpl { private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public ObscuringAether(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OddsEnds.java b/Mage.Sets/src/mage/cards/o/OddsEnds.java index e83b5f5258e..efdd05d6e13 100644 --- a/Mage.Sets/src/mage/cards/o/OddsEnds.java +++ b/Mage.Sets/src/mage/cards/o/OddsEnds.java @@ -65,7 +65,7 @@ class OddsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, false)) { game.informPlayers("Odds: Spell countered"); return game.getStack().counter(getTargetPointer().getFirst(game, source), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java b/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java index 70498e24c58..51541f2daa0 100644 --- a/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java +++ b/Mage.Sets/src/mage/cards/o/OdricMasterTactician.java @@ -87,7 +87,7 @@ class OdricMasterTacticianTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean apply(Game game, Ability source) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); if (watcher != null) { watcher.increment(); return true; @@ -130,7 +130,10 @@ class OdricMasterTacticianChooseBlockersEffect extends ContinuousRuleModifyingEf @Override public boolean applies(GameEvent event, Ability source, Game game) { - ChooseBlockersRedundancyWatcher watcher = (ChooseBlockersRedundancyWatcher) game.getState().getWatchers().get(ChooseBlockersRedundancyWatcher.class.getSimpleName()); + ChooseBlockersRedundancyWatcher watcher = game.getState().getWatcher(ChooseBlockersRedundancyWatcher.class); + if(watcher == null){ + return false; + } watcher.decrement(); watcher.copyCount--; if (watcher.copyCountApply > 0) { diff --git a/Mage.Sets/src/mage/cards/o/Offalsnout.java b/Mage.Sets/src/mage/cards/o/Offalsnout.java index 042e3ec854d..3bc244c8c93 100644 --- a/Mage.Sets/src/mage/cards/o/Offalsnout.java +++ b/Mage.Sets/src/mage/cards/o/Offalsnout.java @@ -1,10 +1,9 @@ package mage.cards.o; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.EvokeAbility; import mage.abilities.keyword.FlashAbility; @@ -15,14 +14,15 @@ import mage.constants.SubType; import mage.target.Target; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Offalsnout extends CardImpl { public Offalsnout(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(2); @@ -31,7 +31,7 @@ public final class Offalsnout extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); // When Offalsnout leaves the battlefield, exile target card from a graveyard. - Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect(),false); + Ability ability = new LeavesBattlefieldTriggeredAbility(new ExileTargetEffect(), false); Target target = new TargetCardInGraveyard(); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/o/OgreBattledriver.java b/Mage.Sets/src/mage/cards/o/OgreBattledriver.java index 59f1085d22f..4986765662d 100644 --- a/Mage.Sets/src/mage/cards/o/OgreBattledriver.java +++ b/Mage.Sets/src/mage/cards/o/OgreBattledriver.java @@ -30,7 +30,7 @@ public final class OgreBattledriver extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private static final String rule = "Whenever another creature enters the battlefield under your control, that creature gets +2/+0 and gains haste until end of turn."; diff --git a/Mage.Sets/src/mage/cards/o/OgreSlumlord.java b/Mage.Sets/src/mage/cards/o/OgreSlumlord.java index 475c981d675..9c63fbc4835 100644 --- a/Mage.Sets/src/mage/cards/o/OgreSlumlord.java +++ b/Mage.Sets/src/mage/cards/o/OgreSlumlord.java @@ -31,8 +31,8 @@ public final class OgreSlumlord extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another nontoken creature"); private static final FilterControlledPermanent filter2 = new FilterControlledPermanent("Rats you control"); static { - filter.add(Predicates.not(new TokenPredicate())); - filter.add(new AnotherPredicate()); + filter.add(Predicates.not(TokenPredicate.instance)); + filter.add(AnotherPredicate.instance); filter2.add(new SubtypePredicate(SubType.RAT)); } diff --git a/Mage.Sets/src/mage/cards/o/OkaunEyeOfChaos.java b/Mage.Sets/src/mage/cards/o/OkaunEyeOfChaos.java index f22d1ea5c57..884c23d1254 100644 --- a/Mage.Sets/src/mage/cards/o/OkaunEyeOfChaos.java +++ b/Mage.Sets/src/mage/cards/o/OkaunEyeOfChaos.java @@ -1,7 +1,6 @@ package mage.cards.o; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.common.WinsCoinFlipTriggeredAbility; @@ -13,18 +12,18 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.PartnerWithAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.TargetController; +import mage.constants.*; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class OkaunEyeOfChaos extends CardImpl { + private static final DynamicValue sourcePower = new SourcePermanentPowerCount(); + private static final DynamicValue sourceToughness = new SourcePermanentToughnessValue(); + public OkaunEyeOfChaos(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); @@ -41,8 +40,6 @@ public final class OkaunEyeOfChaos extends CardImpl { this.addAbility(new BeginningOfCombatTriggeredAbility(new FlipUntilLoseEffect(), TargetController.YOU, false)); // Whenever a player wins a coin flip, double Okaun's power and toughness until end of turn. - DynamicValue sourcePower = new SourcePermanentPowerCount(); - DynamicValue sourceToughness = new SourcePermanentToughnessValue(); this.addAbility(new WinsCoinFlipTriggeredAbility( new BoostSourceEffect( sourcePower, diff --git a/Mage.Sets/src/mage/cards/o/OldFogey.java b/Mage.Sets/src/mage/cards/o/OldFogey.java index 4dd4ed481a2..dabcf1537f4 100644 --- a/Mage.Sets/src/mage/cards/o/OldFogey.java +++ b/Mage.Sets/src/mage/cards/o/OldFogey.java @@ -1,4 +1,3 @@ - package mage.cards.o; import java.util.UUID; @@ -39,7 +38,7 @@ public final class OldFogey extends CardImpl { } public OldFogey(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); this.subtype.add(SubType.DINOSAUR); this.power = new MageInt(7); this.toughness = new MageInt(7); @@ -51,7 +50,7 @@ public final class OldFogey extends CardImpl { // Echo {G}{G} this.addAbility(new EchoAbility("{G}{G}")); // Fading 3 - this.addAbility(new FadingAbility(3, this)); + this.addAbility(new FadingAbility(3, this, true)); // Bands with other Dinosaurs this.addAbility(new BandsWithOtherAbility(SubType.DINOSAUR)); // Protection from Homarids @@ -61,7 +60,7 @@ public final class OldFogey extends CardImpl { // Flanking this.addAbility(new FlankingAbility()); // Rampage 2 - this.addAbility(new RampageAbility(2)); + this.addAbility(new RampageAbility(2, true)); } public OldFogey(final OldFogey card) { diff --git a/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java b/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java index 6e5a6763ed6..c221c91dc24 100644 --- a/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java +++ b/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java @@ -36,7 +36,7 @@ public final class OliviaVoldaren extends CardImpl { private static final FilterCreaturePermanent vampireFilter = new FilterCreaturePermanent("Vampire"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); vampireFilter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java b/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java index a5e986680f4..797552378e2 100644 --- a/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java +++ b/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java @@ -28,7 +28,7 @@ public final class OnceMoreWithFeeling extends CardImpl { public OnceMoreWithFeeling(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}{W}{W}{W}"); - // Exile all permanents and all cards from all graveyards. Each player shuffles his or her hand into his or her library, then draws seven cards. Each player's life total becomes 10. Exile Once More with Feeling. + // Exile all permanents and all cards from all graveyards. Each player shuffles their hand into their library, then draws seven cards. Each player's life total becomes 10. Exile Once More with Feeling. this.getSpellAbility().addEffect(new OnceMoreWithFeelingEffect()); Effect effect = new DrawCardAllEffect(7); effect.setText(", then draws seven cards"); diff --git a/Mage.Sets/src/mage/cards/o/OnduWarCleric.java b/Mage.Sets/src/mage/cards/o/OnduWarCleric.java index 4a70adcb89b..8ca40e0e6ce 100644 --- a/Mage.Sets/src/mage/cards/o/OnduWarCleric.java +++ b/Mage.Sets/src/mage/cards/o/OnduWarCleric.java @@ -30,7 +30,7 @@ public final class OnduWarCleric extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public OnduWarCleric(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OnwardVictory.java b/Mage.Sets/src/mage/cards/o/OnwardVictory.java index b70f7bd4aeb..e5d5aa698d1 100644 --- a/Mage.Sets/src/mage/cards/o/OnwardVictory.java +++ b/Mage.Sets/src/mage/cards/o/OnwardVictory.java @@ -25,12 +25,12 @@ public final class OnwardVictory extends SplitCard { // Onward // Target creature gets +X/+0 until end of turn where X is its power. getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); - getLeftHalfCard().getSpellAbility().addEffect(new BoostTargetEffect(new TargetPermanentPowerCount(), new StaticValue(0), Duration.EndOfTurn, true)); + getLeftHalfCard().getSpellAbility().addEffect(new BoostTargetEffect(TargetPermanentPowerCount.instance, new StaticValue(0), Duration.EndOfTurn, true)); // to // Victory // Target creature gains double strike until end of turn. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); Effect effect = new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn); getRightHalfCard().getSpellAbility().addEffect(effect); getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/o/OpalPalace.java b/Mage.Sets/src/mage/cards/o/OpalPalace.java index 345496aa2d6..bfc47e573fb 100644 --- a/Mage.Sets/src/mage/cards/o/OpalPalace.java +++ b/Mage.Sets/src/mage/cards/o/OpalPalace.java @@ -67,7 +67,7 @@ class OpalPalaceWatcher extends Watcher { private final String originalId; public OpalPalaceWatcher(String originalId) { - super(OpalPalaceWatcher.class.getSimpleName(), WatcherScope.CARD); + super(OpalPalaceWatcher.class, WatcherScope.CARD); this.originalId = originalId; } @@ -130,7 +130,7 @@ class OpalPalaceEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - OpalPalaceWatcher watcher = (OpalPalaceWatcher) game.getState().getWatchers().get(OpalPalaceWatcher.class.getSimpleName(), source.getSourceId()); + OpalPalaceWatcher watcher = game.getState().getWatcher(OpalPalaceWatcher.class, source.getSourceId()); return watcher != null && watcher.commanderId.contains(event.getTargetId()); } diff --git a/Mage.Sets/src/mage/cards/o/OpalTitan.java b/Mage.Sets/src/mage/cards/o/OpalTitan.java index 1f215472b72..d75f1cd1e67 100644 --- a/Mage.Sets/src/mage/cards/o/OpalTitan.java +++ b/Mage.Sets/src/mage/cards/o/OpalTitan.java @@ -107,7 +107,7 @@ class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl implements Sou break; case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - if (((ObjectColor) game.getState().getValue("opalTitanColor" + source.getSourceId())) != null) { + if (game.getState().getValue("opalTitanColor" + source.getSourceId()) != null) { for (ObjectColor color : ((ObjectColor) game.getState().getValue("opalTitanColor" + source.getSourceId())).getColors()) { if (!permanent.getAbilities().contains(ProtectionAbility.from(color))) { permanent.addAbility(ProtectionAbility.from(color)); diff --git a/Mage.Sets/src/mage/cards/o/Opalescence.java b/Mage.Sets/src/mage/cards/o/Opalescence.java index 8037d645d00..40319bcfcdb 100644 --- a/Mage.Sets/src/mage/cards/o/Opalescence.java +++ b/Mage.Sets/src/mage/cards/o/Opalescence.java @@ -52,7 +52,7 @@ class OpalescenceEffect extends ContinuousEffectImpl { static { filter.add(Predicates.not(new SubtypePredicate(SubType.AURA))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); checkDependencyTypes = EnumSet.of(DependencyType.AuraAddingRemoving, DependencyType.EnchantmentAddingRemoving); } diff --git a/Mage.Sets/src/mage/cards/o/OpenIntoWonder.java b/Mage.Sets/src/mage/cards/o/OpenIntoWonder.java index 41ef18e9eb5..e92b99a2b50 100644 --- a/Mage.Sets/src/mage/cards/o/OpenIntoWonder.java +++ b/Mage.Sets/src/mage/cards/o/OpenIntoWonder.java @@ -1,9 +1,7 @@ package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -13,12 +11,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.StaticFilters; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class OpenIntoWonder extends CardImpl { @@ -30,28 +29,28 @@ public final class OpenIntoWonder extends CardImpl { Effect effect = new CantBeBlockedTargetEffect(Duration.EndOfTurn); effect.setText("X target creatures can't be blocked this turn"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false)); Ability abilityToGain = new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), false); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(abilityToGain, Duration.EndOfTurn, "Until end of turn, those creatures gain \"Whenever this creature deals combat damage to a player, draw a card.\"")); + this.getSpellAbility().setTargetAdjuster(OpenIntoWonderAdjuster.instance); } public OpenIntoWonder(final OpenIntoWonder card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numberOfTargets = ability.getManaCostsToPay().getX(); - numberOfTargets = Math.min(game.getBattlefield().count(StaticFilters.FILTER_PERMANENT_CREATURE, ability.getSourceId(), ability.getControllerId(), game), numberOfTargets); - ability.addTarget(new TargetCreaturePermanent(numberOfTargets)); - } - } - @Override public OpenIntoWonder copy() { return new OpenIntoWonder(this); } } + +enum OpenIntoWonderAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/o/OpenSeason.java b/Mage.Sets/src/mage/cards/o/OpenSeason.java index 74377fe7226..c871340981a 100644 --- a/Mage.Sets/src/mage/cards/o/OpenSeason.java +++ b/Mage.Sets/src/mage/cards/o/OpenSeason.java @@ -1,7 +1,6 @@ package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -22,10 +21,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author Styxo */ public final class OpenSeason extends CardImpl { @@ -37,7 +37,7 @@ public final class OpenSeason extends CardImpl { Effect effect = new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()); effect.setText("for each opponent, put a bounty counter on target creature that player controls"); Ability ability = new EntersBattlefieldTriggeredAbility(effect); - ability.addTarget(new TargetCreaturePermanent()); + ability.setTargetAdjuster(OpenSeasonAdjuster.instance); this.addAbility(ability); // Creatures your opponent control with bounty counters on them can't activate abilities @@ -48,19 +48,6 @@ public final class OpenSeason extends CardImpl { } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()))); - } - } - } - } - public OpenSeason(final OpenSeason card) { super(card); } @@ -71,6 +58,21 @@ public final class OpenSeason extends CardImpl { } } +enum OpenSeasonAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()))); + } + } + } +} + class OpenSeasonRestrictionEffect extends RestrictionEffect { public OpenSeasonRestrictionEffect() { diff --git a/Mage.Sets/src/mage/cards/o/OpenTheGates.java b/Mage.Sets/src/mage/cards/o/OpenTheGates.java new file mode 100644 index 00000000000..673655a8213 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OpenTheGates.java @@ -0,0 +1,49 @@ +package mage.cards.o; + +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OpenTheGates extends CardImpl { + + private static final FilterCard filter = new FilterCard("basic land card or a Gate card"); + + static { + filter.add(Predicates.or( + Predicates.and( + new SupertypePredicate(SuperType.BASIC), + new CardTypePredicate(CardType.LAND) + ), new SubtypePredicate(SubType.GATE) + )); + } + + public OpenTheGates(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); + + // Search your library for a basic land card or a Gate card, reveal it, put it into your hand, then shuffled your library. + this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true)); + } + + private OpenTheGates(final OpenTheGates card) { + super(card); + } + + @Override + public OpenTheGates copy() { + return new OpenTheGates(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OpenTheGraves.java b/Mage.Sets/src/mage/cards/o/OpenTheGraves.java index b76f2b1047a..aeb45f4a0eb 100644 --- a/Mage.Sets/src/mage/cards/o/OpenTheGraves.java +++ b/Mage.Sets/src/mage/cards/o/OpenTheGraves.java @@ -23,7 +23,7 @@ public final class OpenTheGraves extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public OpenTheGraves(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/Opposition.java b/Mage.Sets/src/mage/cards/o/Opposition.java index 9f140a7c0cd..30112bc8ee0 100644 --- a/Mage.Sets/src/mage/cards/o/Opposition.java +++ b/Mage.Sets/src/mage/cards/o/Opposition.java @@ -36,7 +36,7 @@ public final class Opposition extends CardImpl { private static final FilterControlledCreaturePermanent untappedcreatureyoucontrol = new FilterControlledCreaturePermanent("untapped creature you control"); static { - untappedcreatureyoucontrol.add(Predicates.not(new TappedPredicate())); + untappedcreatureyoucontrol.add(Predicates.not(TappedPredicate.instance)); } public Opposition(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OracleEnVec.java b/Mage.Sets/src/mage/cards/o/OracleEnVec.java index 118fd61524d..46450454ba6 100644 --- a/Mage.Sets/src/mage/cards/o/OracleEnVec.java +++ b/Mage.Sets/src/mage/cards/o/OracleEnVec.java @@ -243,7 +243,7 @@ class OracleEnVecDestroyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null) { for (UUID targetId : chosenCreatures) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage.Sets/src/mage/cards/o/OracleOfNectars.java b/Mage.Sets/src/mage/cards/o/OracleOfNectars.java index 0c8bd66cd1b..94f72f3ee72 100644 --- a/Mage.Sets/src/mage/cards/o/OracleOfNectars.java +++ b/Mage.Sets/src/mage/cards/o/OracleOfNectars.java @@ -30,7 +30,7 @@ public final class OracleOfNectars extends CardImpl { this.toughness = new MageInt(2); // {X}, {tap}: You gain X life. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java b/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java index 2d698b0f094..ddddb169719 100644 --- a/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java +++ b/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java @@ -95,7 +95,7 @@ class OratorOfOjutaiTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { //Intervening if must be checked Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId()); - DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = (DragonOnTheBattlefieldWhileSpellWasCastWatcher) game.getState().getWatchers().get(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class.getSimpleName()); + DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); return event.getTargetId().equals(getSourceId()) && watcher != null && watcher.castWithConditionTrue(sourcePermanent.getSpellAbility().getId()); @@ -135,7 +135,7 @@ class OratorOfOjutaiEffect extends OneShotEffect { if (controller != null) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (sourcePermanent != null) { - DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = (DragonOnTheBattlefieldWhileSpellWasCastWatcher) game.getState().getWatchers().get(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class.getSimpleName()); + DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); if (watcher != null && watcher.castWithConditionTrue(sourcePermanent.getSpellAbility().getId())) { controller.drawCards(1, game); return true; diff --git a/Mage.Sets/src/mage/cards/o/OrcGeneral.java b/Mage.Sets/src/mage/cards/o/OrcGeneral.java index b2d290e3e53..792b222f8a5 100644 --- a/Mage.Sets/src/mage/cards/o/OrcGeneral.java +++ b/Mage.Sets/src/mage/cards/o/OrcGeneral.java @@ -33,7 +33,7 @@ public final class OrcGeneral extends CardImpl { static { filterOrcOrGoblin.add(Predicates.or(new SubtypePredicate(SubType.ORC), new SubtypePredicate(SubType.GOBLIN))); - filterOrcOrGoblin.add(new AnotherPredicate()); + filterOrcOrGoblin.add(AnotherPredicate.instance); filterOrc.add(new SubtypePredicate(SubType.ORC)); } diff --git a/Mage.Sets/src/mage/cards/o/OrcSureshot.java b/Mage.Sets/src/mage/cards/o/OrcSureshot.java index 80c5d978b37..f499838e56c 100644 --- a/Mage.Sets/src/mage/cards/o/OrcSureshot.java +++ b/Mage.Sets/src/mage/cards/o/OrcSureshot.java @@ -29,7 +29,7 @@ public final class OrcSureshot extends CardImpl { private static final FilterCreaturePermanent filterOpponentCreature = new FilterCreaturePermanent("creature an opponent controls"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filterOpponentCreature.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/o/OrchardWarden.java b/Mage.Sets/src/mage/cards/o/OrchardWarden.java index da5336125e2..cd77dd9b47b 100644 --- a/Mage.Sets/src/mage/cards/o/OrchardWarden.java +++ b/Mage.Sets/src/mage/cards/o/OrchardWarden.java @@ -26,7 +26,7 @@ public final class OrchardWarden extends CardImpl { static { filter.add(new SubtypePredicate(SubType.TREEFOLK)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public OrchardWarden(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OrcishCaptain.java b/Mage.Sets/src/mage/cards/o/OrcishCaptain.java index 998fe8e7e8d..adb37723559 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishCaptain.java +++ b/Mage.Sets/src/mage/cards/o/OrcishCaptain.java @@ -69,7 +69,7 @@ class OrcishCaptainEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { game.informPlayers("Orcish Captain: Won flip. Target Orc creature gets +2/+0 until end of turn."); game.addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn), source); return true; diff --git a/Mage.Sets/src/mage/cards/o/OrcishSquatters.java b/Mage.Sets/src/mage/cards/o/OrcishSquatters.java index 33489a79f7c..fd20a8044bc 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishSquatters.java +++ b/Mage.Sets/src/mage/cards/o/OrcishSquatters.java @@ -27,7 +27,7 @@ public final class OrcishSquatters extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent("land defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public OrcishSquatters(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/Orgg.java b/Mage.Sets/src/mage/cards/o/Orgg.java index 60d0bc29d06..2112818ed02 100644 --- a/Mage.Sets/src/mage/cards/o/Orgg.java +++ b/Mage.Sets/src/mage/cards/o/Orgg.java @@ -29,7 +29,7 @@ public final class Orgg extends CardImpl { static final private FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creatures with power 3 or greater"); static { - filter.add(Predicates.and(new PowerPredicate(ComparisonType.MORE_THAN, 2), Predicates.not(new TappedPredicate()))); + filter.add(Predicates.and(new PowerPredicate(ComparisonType.MORE_THAN, 2), Predicates.not(TappedPredicate.instance))); filter2.add(new PowerPredicate(ComparisonType.MORE_THAN, 2)); } public Orgg(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OrimsCure.java b/Mage.Sets/src/mage/cards/o/OrimsCure.java index d80a0cbe503..d7b56148962 100644 --- a/Mage.Sets/src/mage/cards/o/OrimsCure.java +++ b/Mage.Sets/src/mage/cards/o/OrimsCure.java @@ -31,7 +31,7 @@ public final class OrimsCure extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PLAINS)); - filterCreature.add(Predicates.not(new TappedPredicate())); + filterCreature.add(Predicates.not(TappedPredicate.instance)); } public OrimsCure(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/OrimsThunder.java b/Mage.Sets/src/mage/cards/o/OrimsThunder.java index ca705f089db..b1f8a47c077 100644 --- a/Mage.Sets/src/mage/cards/o/OrimsThunder.java +++ b/Mage.Sets/src/mage/cards/o/OrimsThunder.java @@ -3,7 +3,6 @@ package mage.cards.o; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.OneShotEffect; @@ -18,17 +17,17 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import java.util.UUID; /** - * * @author jeffwadsworth */ public final class OrimsThunder extends CardImpl { public OrimsThunder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); // Kicker {R} this.addAbility(new KickerAbility("{R}")); @@ -39,16 +38,9 @@ public final class OrimsThunder extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new OrimsThunderEffect2(), KickedCondition.instance, - "If Orim's Thunder was kicked, it deals damage equal to that permanent's converted mana cost to target creature")); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - if (KickedCondition.instance.apply(game, ability)) { - ability.addTarget(new TargetCreaturePermanent()); - } - } + "If Orim's Thunder was kicked, it deals damage equal to that permanent's converted mana cost to target creature") + ); + this.getSpellAbility().setTargetAdjuster(OrimsThunderAdjuster.instance); } public OrimsThunder(final OrimsThunder card) { @@ -61,6 +53,18 @@ public final class OrimsThunder extends CardImpl { } } +enum OrimsThunderAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + if (KickedCondition.instance.apply(game, ability)) { + ability.addTarget(new TargetCreaturePermanent()); + } + } + +} + class OrimsThunderEffect2 extends OneShotEffect { OrimsThunderEffect2() { diff --git a/Mage.Sets/src/mage/cards/o/OrzhovEnforcer.java b/Mage.Sets/src/mage/cards/o/OrzhovEnforcer.java new file mode 100644 index 00000000000..e944b3e15f5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OrzhovEnforcer.java @@ -0,0 +1,41 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.abilities.keyword.AfterlifeAbility; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OrzhovEnforcer extends CardImpl { + + public OrzhovEnforcer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Afterlife 1 + this.addAbility(new AfterlifeAbility(1)); + } + + private OrzhovEnforcer(final OrzhovEnforcer card) { + super(card); + } + + @Override + public OrzhovEnforcer copy() { + return new OrzhovEnforcer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OrzhovLocket.java b/Mage.Sets/src/mage/cards/o/OrzhovLocket.java new file mode 100644 index 00000000000..a660da2dd03 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OrzhovLocket.java @@ -0,0 +1,46 @@ +package mage.cards.o; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class OrzhovLocket extends CardImpl { + + public OrzhovLocket(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {T}: Add {W} or {B}. + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlackManaAbility()); + + // {W/B}{W/B}{W/B}{W/B}, {T}, Sacrifice Orzhov Locket: Draw two cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), new ManaCostsImpl<>("{W/B}{W/B}{W/B}{W/B}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public OrzhovLocket(final OrzhovLocket card) { + super(card); + } + + @Override + public OrzhovLocket copy() { + return new OrzhovLocket(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OrzhovRacketeers.java b/Mage.Sets/src/mage/cards/o/OrzhovRacketeers.java new file mode 100644 index 00000000000..5c96b03a862 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OrzhovRacketeers.java @@ -0,0 +1,45 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.keyword.AfterlifeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OrzhovRacketeers extends CardImpl { + + public OrzhovRacketeers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever Orzhov Racketeers deals combat damage to a player, that player discards a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new DiscardTargetEffect(1), false, true + )); + + // Afterlife 2 + this.addAbility(new AfterlifeAbility(2)); + + } + + private OrzhovRacketeers(final OrzhovRacketeers card) { + super(card); + } + + @Override + public OrzhovRacketeers copy() { + return new OrzhovRacketeers(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/Outmaneuver.java b/Mage.Sets/src/mage/cards/o/Outmaneuver.java index 3a604f97782..7e005e5bb7e 100644 --- a/Mage.Sets/src/mage/cards/o/Outmaneuver.java +++ b/Mage.Sets/src/mage/cards/o/Outmaneuver.java @@ -26,7 +26,7 @@ public final class Outmaneuver extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new BlockedPredicate()); + filter.add(BlockedPredicate.instance); } public Outmaneuver(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/Outwit.java b/Mage.Sets/src/mage/cards/o/Outwit.java index 8ab33f01c90..5eeafbf2554 100644 --- a/Mage.Sets/src/mage/cards/o/Outwit.java +++ b/Mage.Sets/src/mage/cards/o/Outwit.java @@ -101,7 +101,7 @@ public final class Outwit extends CardImpl { public boolean canChoose(UUID sourceControllerId, Game game) { int count = 0; for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell && filter.match((Spell) stackObject, game)) { + if (stackObject instanceof Spell && filter.match(stackObject, game)) { if (targetsPlayer(stackObject.getId(), game)) { count++; if (count >= this.minNumberOfTargets) { @@ -117,7 +117,7 @@ public final class Outwit extends CardImpl { public Set possibleTargets(UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell && filter.match((Spell) stackObject, game)) { + if (stackObject instanceof Spell && filter.match(stackObject, game)) { if (targetsPlayer(stackObject.getId(), game)) { possibleTargets.add(stackObject.getId()); } diff --git a/Mage.Sets/src/mage/cards/o/OverbeingOfMyth.java b/Mage.Sets/src/mage/cards/o/OverbeingOfMyth.java index c2b78462c69..6484e923032 100644 --- a/Mage.Sets/src/mage/cards/o/OverbeingOfMyth.java +++ b/Mage.Sets/src/mage/cards/o/OverbeingOfMyth.java @@ -33,7 +33,7 @@ public final class OverbeingOfMyth extends CardImpl { this.toughness = new MageInt(0); // Overbeing of Myth's power and toughness are each equal to the number of cards in your hand. - DynamicValue number = new CardsInControllerHandCount(); + DynamicValue number = CardsInControllerHandCount.instance; this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(number, Duration.EndOfGame))); // At the beginning of your draw step, draw an additional card. diff --git a/Mage.Sets/src/mage/cards/o/Overburden.java b/Mage.Sets/src/mage/cards/o/Overburden.java index c41fad613f8..fb145c23318 100644 --- a/Mage.Sets/src/mage/cards/o/Overburden.java +++ b/Mage.Sets/src/mage/cards/o/Overburden.java @@ -25,7 +25,7 @@ public final class Overburden extends CardImpl { private static final FilterControlledLandPermanent RETURN_FILTER = new FilterControlledLandPermanent("a land"); static { - ENTERS_BATTLEFIELD_FILTER.add(Predicates.not(new TokenPredicate())); + ENTERS_BATTLEFIELD_FILTER.add(Predicates.not(TokenPredicate.instance)); } public Overburden(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/o/Overmaster.java b/Mage.Sets/src/mage/cards/o/Overmaster.java index b5c7fdb07b7..fdad1f76eda 100644 --- a/Mage.Sets/src/mage/cards/o/Overmaster.java +++ b/Mage.Sets/src/mage/cards/o/Overmaster.java @@ -67,7 +67,7 @@ class OvermasterEffect extends ContinuousRuleModifyingEffectImpl { @Override public void init(Ability source, Game game) { super.init(source, game); - OvermasterWatcher watcher = (OvermasterWatcher) game.getState().getWatchers().get(OvermasterWatcher.class.getSimpleName(), source.getControllerId()); + OvermasterWatcher watcher = game.getState().getWatcher(OvermasterWatcher.class, source.getControllerId()); if (watcher != null) { watcher.setReady(); } @@ -95,7 +95,7 @@ class OvermasterEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - OvermasterWatcher watcher = (OvermasterWatcher) game.getState().getWatchers().get(OvermasterWatcher.class.getSimpleName(), source.getControllerId()); + OvermasterWatcher watcher = game.getState().getWatcher(OvermasterWatcher.class, source.getControllerId()); return spell != null && watcher != null && watcher.isUncounterable(spell.getId()); } } @@ -106,7 +106,7 @@ class OvermasterWatcher extends Watcher { protected UUID uncounterableSpell; OvermasterWatcher() { - super(OvermasterWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(OvermasterWatcher.class, WatcherScope.PLAYER); } OvermasterWatcher(final OvermasterWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/o/Overrule.java b/Mage.Sets/src/mage/cards/o/Overrule.java index 19b922b8467..5f92d8fd352 100644 --- a/Mage.Sets/src/mage/cards/o/Overrule.java +++ b/Mage.Sets/src/mage/cards/o/Overrule.java @@ -20,11 +20,11 @@ public final class Overrule extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{W}{U}"); // Counter target spell unless its controller pays {X}. - this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetSpell()); // You gain X life. - this.getSpellAbility().addEffect(new GainLifeEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new GainLifeEffect(ManacostVariableValue.instance)); } public Overrule(final Overrule card) { diff --git a/Mage.Sets/src/mage/cards/o/OverseerOfTheDamned.java b/Mage.Sets/src/mage/cards/o/OverseerOfTheDamned.java index 9877dac2df8..a828ea6ca83 100644 --- a/Mage.Sets/src/mage/cards/o/OverseerOfTheDamned.java +++ b/Mage.Sets/src/mage/cards/o/OverseerOfTheDamned.java @@ -33,7 +33,7 @@ public final class OverseerOfTheDamned extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public OverseerOfTheDamned(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PainKami.java b/Mage.Sets/src/mage/cards/p/PainKami.java index f682910a9b7..68c11d11539 100644 --- a/Mage.Sets/src/mage/cards/p/PainKami.java +++ b/Mage.Sets/src/mage/cards/p/PainKami.java @@ -28,7 +28,7 @@ public final class PainKami extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{R}")); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/Painbringer.java b/Mage.Sets/src/mage/cards/p/Painbringer.java index 02af94d9bc2..bc415a2ba1a 100644 --- a/Mage.Sets/src/mage/cards/p/Painbringer.java +++ b/Mage.Sets/src/mage/cards/p/Painbringer.java @@ -35,7 +35,7 @@ public final class Painbringer extends CardImpl { this.toughness = new MageInt(1); // {tap}, Exile any number of cards from your graveyard: Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way. - DynamicValue X = new SignInversionDynamicValue(new GetXValue()); + DynamicValue X = new SignInversionDynamicValue(GetXValue.instance); Effect effect = new BoostTargetEffect(X, X, Duration.EndOfTurn); effect.setText("Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way"); Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/p/Paleoloth.java b/Mage.Sets/src/mage/cards/p/Paleoloth.java index 2a702d824ec..a7650a5bbeb 100644 --- a/Mage.Sets/src/mage/cards/p/Paleoloth.java +++ b/Mage.Sets/src/mage/cards/p/Paleoloth.java @@ -28,7 +28,7 @@ public final class Paleoloth extends CardImpl { static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 4)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private static final String rule = "Whenever another creature with power 5 or greater enters the battlefield under your control, you may return target creature card from your graveyard to your hand."; diff --git a/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java b/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java index 0ce811c3ee0..6289cd9a4cb 100644 --- a/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java +++ b/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java @@ -78,7 +78,7 @@ enum PalladiaMorsTheRuinerCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); - PalladiaMorsTheRuinerWatcher watcher = (PalladiaMorsTheRuinerWatcher) game.getState().getWatchers().get(PalladiaMorsTheRuinerWatcher.class.getSimpleName()); + PalladiaMorsTheRuinerWatcher watcher = game.getState().getWatcher(PalladiaMorsTheRuinerWatcher.class); return permanent != null && !watcher.getDamagers().contains(new MageObjectReference(permanent, game)); } @@ -94,7 +94,7 @@ class PalladiaMorsTheRuinerWatcher extends Watcher { private final Set damagers = new HashSet(); public PalladiaMorsTheRuinerWatcher() { - super(PalladiaMorsTheRuinerWatcher.class.getSimpleName(), WatcherScope.GAME); + super(PalladiaMorsTheRuinerWatcher.class, WatcherScope.GAME); } public PalladiaMorsTheRuinerWatcher(final PalladiaMorsTheRuinerWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/p/Pallimud.java b/Mage.Sets/src/mage/cards/p/Pallimud.java index 780b62129b7..92603a715fb 100644 --- a/Mage.Sets/src/mage/cards/p/Pallimud.java +++ b/Mage.Sets/src/mage/cards/p/Pallimud.java @@ -61,7 +61,7 @@ class AnathemancerCount implements DynamicValue { Player chosenPlayer = game.getPlayer(playerId); if (chosenPlayer != null) { FilterLandPermanent filter = new FilterLandPermanent("tapped lands the chosen player controls"); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerIdPredicate(playerId)); return game.getBattlefield().count(filter, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game); } diff --git a/Mage.Sets/src/mage/cards/p/Panacea.java b/Mage.Sets/src/mage/cards/p/Panacea.java index 70de0178e61..099c2d61c00 100644 --- a/Mage.Sets/src/mage/cards/p/Panacea.java +++ b/Mage.Sets/src/mage/cards/p/Panacea.java @@ -25,7 +25,7 @@ public final class Panacea extends CardImpl { // {X}{X}, {tap}: Prevent the next X damage that would be dealt to any target this turn. Ability ability = new SimpleActivatedAbility( - new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue()), + new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, ManacostVariableValue.instance), new ManaCostsImpl("{X}{X}") ); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/p/Pandemonium.java b/Mage.Sets/src/mage/cards/p/Pandemonium.java index 82d3bfefe32..581cb03e134 100644 --- a/Mage.Sets/src/mage/cards/p/Pandemonium.java +++ b/Mage.Sets/src/mage/cards/p/Pandemonium.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -16,39 +15,31 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class Pandemonium extends CardImpl { - private final UUID originalId; - public Pandemonium(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); // Whenever a creature enters the battlefield, that creature's controller may have it deal damage equal to its power to any target of their choice. - Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PandemoniumEffect(), StaticFilters.FILTER_PERMANENT_CREATURE, false, SetTargetPointer.PERMANENT, ""); + Ability ability = new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new PandemoniumEffect(), + StaticFilters.FILTER_PERMANENT_CREATURE, + false, SetTargetPointer.PERMANENT, "" + ); ability.addTarget(new TargetAnyTarget()); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(PandemoniumAdjuster.instance); this.addAbility(ability); } public Pandemonium(final Pandemonium card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - UUID creatureId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); - Permanent creature = game.getPermanent(creatureId); - if (creature != null) { - ability.getTargets().get(0).setTargetController(creature.getControllerId()); - } - } } @Override @@ -57,6 +48,19 @@ public final class Pandemonium extends CardImpl { } } +enum PandemoniumAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + UUID creatureId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + Permanent creature = game.getPermanent(creatureId); + if (creature != null) { + ability.getTargets().get(0).setTargetController(creature.getControllerId()); + } + } +} + class PandemoniumEffect extends OneShotEffect { public PandemoniumEffect() { diff --git a/Mage.Sets/src/mage/cards/p/PanicSpellbomb.java b/Mage.Sets/src/mage/cards/p/PanicSpellbomb.java index 1b44b323f97..f6fbf675d4a 100644 --- a/Mage.Sets/src/mage/cards/p/PanicSpellbomb.java +++ b/Mage.Sets/src/mage/cards/p/PanicSpellbomb.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -18,14 +16,15 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author North */ public final class PanicSpellbomb extends CardImpl { public PanicSpellbomb(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // Tap, Sacrifice Panic Spellbomb: Target creature can't block this turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBlockTargetEffect(Duration.EndOfTurn), new TapSourceCost()); @@ -34,7 +33,7 @@ public final class PanicSpellbomb extends CardImpl { this.addAbility(ability); // When Panic Spellbomb is put into a graveyard from the battlefield, you may pay Red. If you do, draw a card. - this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{R}")), false)); + this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{R}")), false, false)); } public PanicSpellbomb(final PanicSpellbomb card) { diff --git a/Mage.Sets/src/mage/cards/p/ParadoxHaze.java b/Mage.Sets/src/mage/cards/p/ParadoxHaze.java index eb98a98e32b..6262d3d2589 100644 --- a/Mage.Sets/src/mage/cards/p/ParadoxHaze.java +++ b/Mage.Sets/src/mage/cards/p/ParadoxHaze.java @@ -80,7 +80,7 @@ class ParadoxHazeTriggeredAbility extends TriggeredAbilityImpl { if (permanent != null) { Player player = game.getPlayer(permanent.getAttachedTo()); if (player != null && game.isActivePlayer(player.getId())) { - FirstTimeStepWatcher watcher = (FirstTimeStepWatcher) game.getState().getWatchers().get(EventType.UPKEEP_STEP_POST.toString() + FirstTimeStepWatcher.class.getSimpleName()); + FirstTimeStepWatcher watcher = game.getState().getWatcher(FirstTimeStepWatcher.class, EventType.UPKEEP_STEP_POST.toString()); if (watcher != null && !watcher.conditionMet()) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); return true; diff --git a/Mage.Sets/src/mage/cards/p/ParadoxicalOutcome.java b/Mage.Sets/src/mage/cards/p/ParadoxicalOutcome.java index daa98056f01..5580ac75a1d 100644 --- a/Mage.Sets/src/mage/cards/p/ParadoxicalOutcome.java +++ b/Mage.Sets/src/mage/cards/p/ParadoxicalOutcome.java @@ -34,7 +34,7 @@ public final class ParadoxicalOutcome extends CardImpl { static { filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public ParadoxicalOutcome(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java b/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java index 572ffc20ec4..c470aa6daec 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java @@ -39,7 +39,7 @@ public final class ParagonOfEternalWilds extends CardImpl { filterGreen.add(new ColorPredicate(ObjectColor.GREEN)); filterGreen.add(new ControllerPredicate(TargetController.YOU)); filterGreen2.add(new ColorPredicate(ObjectColor.GREEN)); - filterGreen2.add(new AnotherPredicate()); + filterGreen2.add(AnotherPredicate.instance); } public ParagonOfEternalWilds(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java b/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java index c1fb7a9296a..d88970bc0b5 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java @@ -35,7 +35,7 @@ public final class ParagonOfFierceDefiance extends CardImpl { static { filterCreatures.add(new ColorPredicate(ObjectColor.RED)); - filterCreature.add(new AnotherPredicate()); + filterCreature.add(AnotherPredicate.instance); filterCreature.add(new ColorPredicate(ObjectColor.RED)); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java b/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java index 17c8b02393c..c25d4921ded 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java @@ -39,7 +39,7 @@ public final class ParagonOfGatheringMists extends CardImpl { filterBlue.add(new ColorPredicate(ObjectColor.BLUE)); filterBlue.add(new ControllerPredicate(TargetController.YOU)); filterBlue2.add(new ColorPredicate(ObjectColor.BLUE)); - filterBlue2.add(new AnotherPredicate()); + filterBlue2.add(AnotherPredicate.instance); } public ParagonOfGatheringMists(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java b/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java index 7ae03275b0f..a186d548cb0 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java @@ -37,7 +37,7 @@ public final class ParagonOfNewDawns extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.WHITE)); filter.add(new ControllerPredicate(TargetController.YOU)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); filter2.add(new ColorPredicate(ObjectColor.WHITE)); filter2.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java b/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java index d8a89099933..a23b31ee287 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java @@ -35,7 +35,7 @@ public final class ParagonOfOpenGraves extends CardImpl { static { filterCreatures.add(new ColorPredicate(ObjectColor.BLACK)); - filterCreature.add(new AnotherPredicate()); + filterCreature.add(AnotherPredicate.instance); filterCreature.add(new ColorPredicate(ObjectColor.BLACK)); } diff --git a/Mage.Sets/src/mage/cards/p/ParallelEvolution.java b/Mage.Sets/src/mage/cards/p/ParallelEvolution.java index 9fbccfd9754..84af3037c4e 100644 --- a/Mage.Sets/src/mage/cards/p/ParallelEvolution.java +++ b/Mage.Sets/src/mage/cards/p/ParallelEvolution.java @@ -51,7 +51,7 @@ class ParallelEvolutionEffect extends OneShotEffect { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public ParallelEvolutionEffect() { diff --git a/Mage.Sets/src/mage/cards/p/Paroxysm.java b/Mage.Sets/src/mage/cards/p/Paroxysm.java index 753951b5c18..d24b2e9b276 100644 --- a/Mage.Sets/src/mage/cards/p/Paroxysm.java +++ b/Mage.Sets/src/mage/cards/p/Paroxysm.java @@ -1,111 +1,111 @@ -package mage.cards.p; - -import java.util.UUID; -import mage.constants.SubType; -import mage.target.common.TargetCreaturePermanent; -import mage.abilities.Ability; -import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.constants.Outcome; -import mage.target.TargetPermanent; -import mage.abilities.keyword.EnchantAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.targetpointer.FixedTarget; - -/** - * - * @author jeffwadsworth - */ -public final class Paroxysm extends CardImpl { - - public Paroxysm(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); - - this.subtype.add(SubType.AURA); - - // Enchant creature - TargetPermanent auraTarget = new TargetCreaturePermanent(); - this.getSpellAbility().addTarget(auraTarget); - this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget.getTargetName()); - this.addAbility(ability); - - // At the beginning of the upkeep of enchanted creature's controller, that player reveals the top card of his or her library. - // If that card is a land card, destroy that creature. Otherwise, it gets +3/+3 until end of turn. - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - Zone.BATTLEFIELD, - new ParoxysmEffect(), - TargetController.CONTROLLER_ATTACHED_TO, - false, false, "At the beginning of the upkeep of enchanted creature's controller, ")); - } - - public Paroxysm(final Paroxysm card) { - super(card); - } - - @Override - public Paroxysm copy() { - return new Paroxysm(this); - } -} - -class ParoxysmEffect extends OneShotEffect { - - ParoxysmEffect() { - super(Outcome.BoostCreature); - this.staticText = "that player reveals the top card of his or her library. \n" - + "If that card is a land card, destroy that creature. \n" - + "Otherwise, it gets +3/+3 until end of turn."; - } - - ParoxysmEffect(final ParoxysmEffect effect) { - super(effect); - } - - @Override - public ParoxysmEffect copy() { - return new ParoxysmEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent aura = game.getPermanent(source.getSourceId()); - if (aura != null) { - Permanent creatureAttachedTo = game.getPermanent(aura.getAttachedTo()); - if (creatureAttachedTo != null) { - Player controllerOfCreature = game.getPlayer(creatureAttachedTo.getControllerId()); - if (controllerOfCreature != null) { - Card revealCardFromTop = controllerOfCreature.getLibrary().getFromTop(game); - if (revealCardFromTop != null) { - Cards cards = new CardsImpl(); - cards.add(revealCardFromTop); - controllerOfCreature.revealCards(source, cards, game); - if (revealCardFromTop.isLand()) { - creatureAttachedTo.destroy(source.getSourceId(), game, false); - } else { - ContinuousEffect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(creatureAttachedTo.getId())); - game.addEffect(effect, source); - } - return true; - } - } - } - } - return false; - } -} +package mage.cards.p; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth + */ +public final class Paroxysm extends CardImpl { + + public Paroxysm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of the upkeep of enchanted creature's controller, that player reveals the top card of their library. + // If that card is a land card, destroy that creature. Otherwise, it gets +3/+3 until end of turn. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, + new ParoxysmEffect(), + TargetController.CONTROLLER_ATTACHED_TO, + false, false, "At the beginning of the upkeep of enchanted creature's controller, ")); + } + + public Paroxysm(final Paroxysm card) { + super(card); + } + + @Override + public Paroxysm copy() { + return new Paroxysm(this); + } +} + +class ParoxysmEffect extends OneShotEffect { + + ParoxysmEffect() { + super(Outcome.BoostCreature); + this.staticText = "that player reveals the top card of their library. \n" + + "If that card is a land card, destroy that creature. \n" + + "Otherwise, it gets +3/+3 until end of turn."; + } + + ParoxysmEffect(final ParoxysmEffect effect) { + super(effect); + } + + @Override + public ParoxysmEffect copy() { + return new ParoxysmEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent aura = game.getPermanent(source.getSourceId()); + if (aura != null) { + Permanent creatureAttachedTo = game.getPermanent(aura.getAttachedTo()); + if (creatureAttachedTo != null) { + Player controllerOfCreature = game.getPlayer(creatureAttachedTo.getControllerId()); + if (controllerOfCreature != null) { + Card revealCardFromTop = controllerOfCreature.getLibrary().getFromTop(game); + if (revealCardFromTop != null) { + Cards cards = new CardsImpl(); + cards.add(revealCardFromTop); + controllerOfCreature.revealCards(source, cards, game); + if (revealCardFromTop.isLand()) { + creatureAttachedTo.destroy(source.getSourceId(), game, false); + } else { + ContinuousEffect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(creatureAttachedTo.getId())); + game.addEffect(effect, source); + } + return true; + } + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PartWater.java b/Mage.Sets/src/mage/cards/p/PartWater.java index 0e7c6c11b1e..47afdfb31e1 100644 --- a/Mage.Sets/src/mage/cards/p/PartWater.java +++ b/Mage.Sets/src/mage/cards/p/PartWater.java @@ -1,9 +1,7 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.IslandwalkAbility; @@ -11,34 +9,26 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class PartWater extends CardImpl { public PartWater(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{X}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{U}"); // X target creatures gain islandwalk until end of turn. Effect effect = new GainAbilityTargetEffect(new IslandwalkAbility(false), Duration.EndOfTurn); effect.setText("X target creatures gain islandwalk until end of turn"); this.getSpellAbility().getEffects().add(effect); - this.getSpellAbility().getTargets().add(new TargetCreaturePermanent(1,1)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures gain islandwalk until end of turn"); - ability.getTargets().add(new TargetCreaturePermanent(0, xValue, filter, false)); - } + this.getSpellAbility().getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().setTargetAdjuster(PartWaterAdjuster.instance); } public PartWater(final PartWater card) { @@ -50,3 +40,13 @@ public final class PartWater extends CardImpl { return new PartWater(this); } } + +enum PartWaterAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.getTargets().add(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PastInFlames.java b/Mage.Sets/src/mage/cards/p/PastInFlames.java index 77ac3bb1d26..627aa8791b6 100644 --- a/Mage.Sets/src/mage/cards/p/PastInFlames.java +++ b/Mage.Sets/src/mage/cards/p/PastInFlames.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCostsImpl; @@ -10,23 +8,19 @@ import mage.abilities.keyword.FlashbackAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.TimingRule; +import mage.constants.*; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class PastInFlames extends CardImpl { public PastInFlames(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Each instant and sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. @@ -72,7 +66,7 @@ class PastInFlamesEffect extends ContinuousEffectImpl { player.getGraveyard().stream().map((cardId) -> game.getCard(cardId)).filter((card) -> (card.isInstant() || card.isSorcery())).forEachOrdered((card) -> { affectedObjectList.add(new MageObjectReference(card, game)); }); - } + } } } @@ -82,17 +76,18 @@ class PastInFlamesEffect extends ContinuousEffectImpl { if (player != null) { player.getGraveyard().stream().filter((cardId) -> (affectedObjectList.contains(new MageObjectReference(cardId, game)))).forEachOrdered((cardId) -> { Card card = game.getCard(cardId); - FlashbackAbility ability = null; - if (card.isInstant()) { - ability = new FlashbackAbility(card.getManaCost(), TimingRule.INSTANT); - } - else if (card.isSorcery()) { - ability = new FlashbackAbility(card.getManaCost(), TimingRule.SORCERY); - } - if (ability != null) { - ability.setSourceId(cardId); - ability.setControllerId(card.getOwnerId()); - game.getState().addOtherAbility(card, ability); + if (card != null) { + FlashbackAbility ability = null; + if (card.isInstant()) { + ability = new FlashbackAbility(card.getManaCost(), TimingRule.INSTANT); + } else if (card.isSorcery()) { + ability = new FlashbackAbility(card.getManaCost(), TimingRule.SORCERY); + } + if (ability != null) { + ability.setSourceId(cardId); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } } }); return true; diff --git a/Mage.Sets/src/mage/cards/p/PatriciansScorn.java b/Mage.Sets/src/mage/cards/p/PatriciansScorn.java index 0aed2b41deb..12cecad6c17 100644 --- a/Mage.Sets/src/mage/cards/p/PatriciansScorn.java +++ b/Mage.Sets/src/mage/cards/p/PatriciansScorn.java @@ -52,7 +52,7 @@ class CastWhiteSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PatriciansScornWatcher watcher = (PatriciansScornWatcher) game.getState().getWatchers().get(PatriciansScornWatcher.class.getSimpleName(), source.getSourceId()); + PatriciansScornWatcher watcher = game.getState().getWatcher(PatriciansScornWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.conditionMet(); } @@ -73,7 +73,7 @@ class PatriciansScornWatcher extends Watcher { } public PatriciansScornWatcher() { - super(PatriciansScornWatcher.class.getSimpleName(), WatcherScope.CARD); + super(PatriciansScornWatcher.class, WatcherScope.CARD); } public PatriciansScornWatcher(final PatriciansScornWatcher watcher) { @@ -98,8 +98,4 @@ class PatriciansScornWatcher extends Watcher { } } - @Override - public void reset() { - super.reset(); - } } diff --git a/Mage.Sets/src/mage/cards/p/PatronWizard.java b/Mage.Sets/src/mage/cards/p/PatronWizard.java index 04b436b596f..2e447eb0941 100644 --- a/Mage.Sets/src/mage/cards/p/PatronWizard.java +++ b/Mage.Sets/src/mage/cards/p/PatronWizard.java @@ -30,7 +30,7 @@ public final class PatronWizard extends CardImpl { static { filter.add(new SubtypePredicate(SubType.WIZARD)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public PatronWizard(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PeacewalkerColossus.java b/Mage.Sets/src/mage/cards/p/PeacewalkerColossus.java index 7ce316dfdd6..6792fca6dad 100644 --- a/Mage.Sets/src/mage/cards/p/PeacewalkerColossus.java +++ b/Mage.Sets/src/mage/cards/p/PeacewalkerColossus.java @@ -29,7 +29,7 @@ public final class PeacewalkerColossus extends CardImpl { private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("another target vehicle"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.VEHICLE)); } diff --git a/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java b/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java index 4d87ffe9848..84b1f2598e8 100644 --- a/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java +++ b/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java @@ -34,7 +34,7 @@ public final class PeemaAetherSeer extends CardImpl { this.toughness = new MageInt(2); // When Peema Aether-Seer enters the battlefield, you get an amount of {E} equal to the greatest power among creatures you control. - Effect effect = new GetEnergyCountersControllerEffect(new GreatestPowerAmongControlledCreaturesValue()); + Effect effect = new GetEnergyCountersControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance); effect.setText("you get an amount of {E} equal to the greatest power among creatures you control"); this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); diff --git a/Mage.Sets/src/mage/cards/p/PegasusCourser.java b/Mage.Sets/src/mage/cards/p/PegasusCourser.java index 0388865a9c0..6dbfdc659f7 100644 --- a/Mage.Sets/src/mage/cards/p/PegasusCourser.java +++ b/Mage.Sets/src/mage/cards/p/PegasusCourser.java @@ -25,7 +25,7 @@ public final class PegasusCourser extends CardImpl { static final FilterAttackingCreature filter = new FilterAttackingCreature("another target attacking creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public PegasusCourser(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PermafrostTrap.java b/Mage.Sets/src/mage/cards/p/PermafrostTrap.java index 0d6462c7fd1..f336a14f5eb 100644 --- a/Mage.Sets/src/mage/cards/p/PermafrostTrap.java +++ b/Mage.Sets/src/mage/cards/p/PermafrostTrap.java @@ -54,7 +54,7 @@ enum PermafrostTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getSimpleName()); + PermanentsEnteredBattlefieldWatcher watcher = game.getState().getWatcher(PermanentsEnteredBattlefieldWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { List permanents = watcher.getThisTurnEnteringPermanents(opponentId); diff --git a/Mage.Sets/src/mage/cards/p/PersistentPetitioners.java b/Mage.Sets/src/mage/cards/p/PersistentPetitioners.java new file mode 100644 index 00000000000..d3548d6bee9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PersistentPetitioners.java @@ -0,0 +1,75 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PersistentPetitioners extends CardImpl { + + private static final FilterControlledPermanent filter + = new FilterControlledPermanent("untapped Advisors you control"); + + static { + filter.add(Predicates.not(TappedPredicate.instance)); + filter.add(new SubtypePredicate(SubType.ADVISOR)); + } + + public PersistentPetitioners(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // {1}, {T}: Target player puts the top card of their library into their graveyard. + Ability ability = new SimpleActivatedAbility( + new PutLibraryIntoGraveTargetEffect(1), new GenericManaCost(1) + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + + // Tap four untapped Advisors you control: Target player puts the top twelve cards of their library into their graveyard. + ability = new SimpleActivatedAbility( + new PutLibraryIntoGraveTargetEffect(12), + new TapTargetCost(new TargetControlledPermanent( + 4, 4, filter, true + )) + ); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + + // A deck can have any number of cards named Persistent Petitioners. + this.getSpellAbility().addEffect(new InfoEffect("A deck can have any number of cards named Persistent Petitioners.")); + } + + private PersistentPetitioners(final PersistentPetitioners card) { + super(card); + } + + @Override + public PersistentPetitioners copy() { + return new PersistentPetitioners(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PestilentSpirit.java b/Mage.Sets/src/mage/cards/p/PestilentSpirit.java new file mode 100644 index 00000000000..56f1611be3b --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PestilentSpirit.java @@ -0,0 +1,63 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.GainAbilitySpellsEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterObject; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PestilentSpirit extends CardImpl { + + private static final FilterObject filter = new FilterObject("instant and sorcery spells you control"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY) + )); + } + + public PestilentSpirit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Menace + this.addAbility(new MenaceAbility()); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Instant and sorcery spells you control have deathtouch. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilitySpellsEffect( + DeathtouchAbility.getInstance(), filter + ).setText("Instant and sorcery spells you control have deathtouch") + )); + } + + private PestilentSpirit(final PestilentSpirit card) { + super(card); + } + + @Override + public PestilentSpirit copy() { + return new PestilentSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PetalmaneBaku.java b/Mage.Sets/src/mage/cards/p/PetalmaneBaku.java index 85812a645e7..167b6d2ba11 100644 --- a/Mage.Sets/src/mage/cards/p/PetalmaneBaku.java +++ b/Mage.Sets/src/mage/cards/p/PetalmaneBaku.java @@ -37,7 +37,7 @@ public final class PetalmaneBaku extends CardImpl { // {1}, Remove X ki counters from Petalmane Baku: Add X mana of any one color. Ability ability = new DynamicManaAbility( new Mana(0, 0, 0, 0, 0, 0, 1, 0), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new ManaCostsImpl<>("{1}"), "Add X mana of any one color", true, new CountersSourceCount(CounterType.KI)); diff --git a/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java b/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java index cd47ad163c9..7894efcd3f1 100644 --- a/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java +++ b/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java @@ -82,7 +82,7 @@ class PetrifiedWoodKinEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - DamageDoneWatcher watcher = (DamageDoneWatcher) game.getState().getWatchers().get(DamageDoneWatcher.class.getSimpleName()); + DamageDoneWatcher watcher = game.getState().getWatcher(DamageDoneWatcher.class); Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (player == null || watcher == null || permanent == null) { return false; diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java index 003ff68f888..9c0b2db68f8 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java @@ -21,14 +21,13 @@ import mage.util.functions.ApplyToPermanent; import java.util.UUID; /** - * * @author North */ public final class PhantasmalImage extends CardImpl { private static final String effectText = "a copy of any creature on the battlefield, except it's an Illusion in addition to its other types and it has \"When this creature becomes the target of a spell or ability, sacrifice it.\""; - ApplyToPermanent phantasmalImageApplier = new ApplyToPermanent() { + private static final ApplyToPermanent phantasmalImageApplier = new ApplyToPermanent() { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { if (!permanent.hasSubtype(SubType.ILLUSION, game)) { diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalMount.java b/Mage.Sets/src/mage/cards/p/PhantasmalMount.java new file mode 100644 index 00000000000..549941c397c --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PhantasmalMount.java @@ -0,0 +1,156 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth + */ +public final class PhantasmalMount extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("with toughness 2 or less"); + + static { + filter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public PhantasmalMount(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.ILLUSION); + this.subtype.add(SubType.HORSE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {tap}: Target creature you control with toughness 2 or less gets +1/+1 and gains flying until end of turn. When Phantasmal Mount leaves the battlefield this turn, sacrifice that creature. When the creature leaves the battlefield this turn, sacrifice Phantasmal Mount. + Ability activatedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhantasmalMountEffect(), new TapSourceCost()); + activatedAbility.addTarget(new TargetControlledCreaturePermanent(filter)); + this.addAbility(activatedAbility); + + } + + private PhantasmalMount(final PhantasmalMount card) { + super(card); + } + + @Override + public PhantasmalMount copy() { + return new PhantasmalMount(this); + } +} + +class PhantasmalMountEffect extends OneShotEffect { + + PhantasmalMountEffect() { + super(Outcome.Neutral); + staticText = "Target creature you control with toughness 2 or less gets +1/+1 " + + "and gains flying until end of turn. When {this} leaves the battlefield this turn, " + + "sacrifice that creature. When the creature leaves the battlefield this turn, sacrifice {this}"; + } + + PhantasmalMountEffect(PhantasmalMountEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature != null) { + ContinuousEffect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget())); + game.addEffect(effect, source); + Effect sacrificeCreatureEffect = new SacrificeTargetEffect(); + Effect sacrificePhantasmalMountEffect = new SacrificeTargetEffect(); + ContinuousEffect gainAbility = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); + gainAbility.setTargetPointer(new FixedTarget(source.getFirstTarget())); + game.addEffect(gainAbility, source); + sacrificeCreatureEffect.setTargetPointer(new FixedTarget(source.getFirstTarget())); + sacrificePhantasmalMountEffect.setTargetPointer(new FixedTarget(source.getSourceId())); + DelayedTriggeredAbility dTA = new PhantasmalMountDelayedTriggeredAbility( + sacrificeCreatureEffect, + source.getSourceId()); + DelayedTriggeredAbility dTA2 = new PhantasmalMountDelayedTriggeredAbility( + sacrificePhantasmalMountEffect, + source.getFirstTarget()); + game.addDelayedTriggeredAbility(dTA, source); + game.addDelayedTriggeredAbility(dTA2, source); + return true; + } + return false; + } + + @Override + public PhantasmalMountEffect copy() { + return new PhantasmalMountEffect(this); + } +} + +class PhantasmalMountDelayedTriggeredAbility extends DelayedTriggeredAbility { + + UUID creatureId; + + PhantasmalMountDelayedTriggeredAbility(Effect effect, UUID creatureId) { + super(effect, Duration.EndOfTurn, true); + this.creatureId = creatureId; + } + + PhantasmalMountDelayedTriggeredAbility(PhantasmalMountDelayedTriggeredAbility ability) { + super(ability); + this.creatureId = ability.creatureId; + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.ZONE_CHANGE + && event.getTargetId().equals(creatureId)) { + return true; + } + return false; + } + + @Override + public PhantasmalMountDelayedTriggeredAbility copy() { + return new PhantasmalMountDelayedTriggeredAbility(this); + } + + @Override + public String getRule() { + return "this left the battlefield"; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java b/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java index f5bb97875ca..cb425f1d88e 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalTerrain.java @@ -125,7 +125,8 @@ class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { @Override public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + return layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.TypeChangingEffects_4; } } diff --git a/Mage.Sets/src/mage/cards/p/PhantomGeneral.java b/Mage.Sets/src/mage/cards/p/PhantomGeneral.java index a5e802e5d40..4f2ac31139f 100644 --- a/Mage.Sets/src/mage/cards/p/PhantomGeneral.java +++ b/Mage.Sets/src/mage/cards/p/PhantomGeneral.java @@ -24,7 +24,7 @@ public final class PhantomGeneral extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creature tokens you control"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java b/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java index afb9c707089..41900f0ee1f 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java @@ -56,7 +56,7 @@ class PhyrexianDreadnoughtSacrificeCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("any number of creatures with total power 12 or greater"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public PhyrexianDreadnoughtSacrificeCost() { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianIngester.java b/Mage.Sets/src/mage/cards/p/PhyrexianIngester.java index 0904b81ba8a..0b035db1bd1 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianIngester.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianIngester.java @@ -36,7 +36,7 @@ public final class PhyrexianIngester extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public PhyrexianIngester(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java b/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java index dc33388f9a5..20b78322d07 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianProcessor.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -19,14 +17,15 @@ import mage.game.permanent.token.MinionToken; import mage.players.Player; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author FenrisulfrX */ public final class PhyrexianProcessor extends CardImpl { public PhyrexianProcessor(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // As {this} enters the battlefield, pay any amount of life. this.addAbility(new EntersBattlefieldTriggeredAbility(new PhyrexianProcessorEffect())); @@ -65,11 +64,11 @@ class PhyrexianProcessorEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if(controller != null) { - Card sourceCard = game.getCard(source.getSourceId()); + if (controller != null) { int payAmount = controller.getAmount(0, controller.getLife(), staticText, game); controller.loseLife(payAmount, game, false); - game.informPlayers(sourceCard.getName() + ": " + controller.getLogName() + + Card sourceCard = game.getCard(source.getSourceId()); + game.informPlayers((sourceCard != null ? sourceCard.getName() : "") + ": " + controller.getLogName() + " pays " + payAmount + " life."); String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game); game.getState().setValue(key, payAmount); @@ -80,7 +79,7 @@ class PhyrexianProcessorEffect extends OneShotEffect { } class PhyrexianProcessorCreateTokenEffect extends OneShotEffect { - + public PhyrexianProcessorCreateTokenEffect() { super(Outcome.PutCreatureInPlay); staticText = "Create an X/X black Minion creature token"; @@ -89,7 +88,7 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect { public PhyrexianProcessorCreateTokenEffect(PhyrexianProcessorCreateTokenEffect ability) { super(ability); } - + @Override public PhyrexianProcessorCreateTokenEffect copy() { return new PhyrexianProcessorCreateTokenEffect(this); @@ -99,7 +98,7 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game); Object object = game.getState().getValue(key); - if(object instanceof Integer) { + if (object instanceof Integer) { int lifePaid = (int) object; MinionToken token = new MinionToken(); token.getPower().modifyBaseValue(lifePaid); diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java b/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java index da92e7b58a4..526c986b5bd 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianPurge.java @@ -1,9 +1,8 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.effects.common.DestroyMultiTargetEffect; import mage.abilities.effects.common.InfoEffect; @@ -13,9 +12,11 @@ import mage.constants.CardType; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author escplan9 - Derek Monturo */ public final class PhyrexianPurge extends CardImpl { @@ -28,26 +29,8 @@ public final class PhyrexianPurge extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); this.getSpellAbility().addEffect(new DestroyMultiTargetEffect()); this.getSpellAbility().addEffect(new InfoEffect("

{this} costs 3 life more to cast for each target")); - } - - @Override - public void adjustCosts(Ability ability, Game game) { - int numTargets = ability.getTargets().get(0).getTargets().size(); - if (numTargets > 0) { - ability.getCosts().add(new PayLifeCost(numTargets * 3)); - } - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - Player you = game.getPlayer(ownerId); - if(you != null) { - int maxTargets = you.getLife() / 3; - ability.addTarget(new TargetCreaturePermanent(0, maxTargets)); - } - } + this.getSpellAbility().setTargetAdjuster(PhyrexianPurgeTargetAdjuster.instance); + this.getSpellAbility().setCostAdjuster(PhyrexianPurgeCostAdjuster.instance); } public PhyrexianPurge(final PhyrexianPurge card) { @@ -59,3 +42,27 @@ public final class PhyrexianPurge extends CardImpl { return new PhyrexianPurge(this); } } + +enum PhyrexianPurgeCostAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + int numTargets = ability.getTargets().get(0).getTargets().size(); + if (numTargets > 0) { + ability.getCosts().add(new PayLifeCost(numTargets * 3)); + } + } +} + +enum PhyrexianPurgeTargetAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + Player you = game.getPlayer(ability.getControllerId()); + int maxTargets = you.getLife() / 3; + ability.addTarget(new TargetCreaturePermanent(0, maxTargets)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java b/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java index 4f2f1f4e2dc..3dd4288d02e 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java @@ -30,7 +30,7 @@ public final class PhyrexianSwarmlord extends CardImpl { this.addAbility(InfectAbility.getInstance()); this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", - new CreateTokenEffect(new InsectInfectToken(), new OpponentsPoisonCountersCount()))); + new CreateTokenEffect(new InsectInfectToken(), OpponentsPoisonCountersCount.instance))); } public PhyrexianSwarmlord(final PhyrexianSwarmlord card) { diff --git a/Mage.Sets/src/mage/cards/p/PiannaNomadCaptain.java b/Mage.Sets/src/mage/cards/p/PiannaNomadCaptain.java index 15e7870f00d..72a9ca81f1d 100644 --- a/Mage.Sets/src/mage/cards/p/PiannaNomadCaptain.java +++ b/Mage.Sets/src/mage/cards/p/PiannaNomadCaptain.java @@ -23,7 +23,7 @@ public final class PiannaNomadCaptain extends CardImpl { static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creatures"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public PiannaNomadCaptain(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PiasRevolution.java b/Mage.Sets/src/mage/cards/p/PiasRevolution.java index bba23c5fc61..edaea70c981 100644 --- a/Mage.Sets/src/mage/cards/p/PiasRevolution.java +++ b/Mage.Sets/src/mage/cards/p/PiasRevolution.java @@ -93,7 +93,7 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl { private static final FilterArtifactPermanent filter = new FilterArtifactPermanent(); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(new OwnerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/p/PiousEvangel.java b/Mage.Sets/src/mage/cards/p/PiousEvangel.java index 3cf2046a8a3..917a03a500e 100644 --- a/Mage.Sets/src/mage/cards/p/PiousEvangel.java +++ b/Mage.Sets/src/mage/cards/p/PiousEvangel.java @@ -33,7 +33,7 @@ public final class PiousEvangel extends CardImpl { private static final FilterControlledPermanent filter2 = new FilterControlledPermanent("another permanent"); static { - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public PiousEvangel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PistonFistCyclops.java b/Mage.Sets/src/mage/cards/p/PistonFistCyclops.java index e362ad9416c..e17e51ab881 100644 --- a/Mage.Sets/src/mage/cards/p/PistonFistCyclops.java +++ b/Mage.Sets/src/mage/cards/p/PistonFistCyclops.java @@ -64,8 +64,8 @@ enum PistonFistCyclopsCondition implements Condition { @Override public boolean apply(Game game, Ability source) { SpellsCastWatcher watcher - = (SpellsCastWatcher) game.getState().getWatchers().get( - SpellsCastWatcher.class.getSimpleName() + = game.getState().getWatcher( + SpellsCastWatcher.class ); if (watcher == null) { return false; diff --git a/Mage.Sets/src/mage/cards/p/PitilessPlunderer.java b/Mage.Sets/src/mage/cards/p/PitilessPlunderer.java index fa3228ce6a4..b4667a3b49b 100644 --- a/Mage.Sets/src/mage/cards/p/PitilessPlunderer.java +++ b/Mage.Sets/src/mage/cards/p/PitilessPlunderer.java @@ -24,7 +24,7 @@ public final class PitilessPlunderer extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/p/PitilessPontiff.java b/Mage.Sets/src/mage/cards/p/PitilessPontiff.java new file mode 100644 index 00000000000..4b342f2c18e --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PitilessPontiff.java @@ -0,0 +1,55 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PitilessPontiff extends CardImpl { + + public PitilessPontiff(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {1}, Sacrifice another creature: Pitiless Pontiff gains deathtouch and indestructible until end of turn. + Ability ability = new SimpleActivatedAbility(new GainAbilitySourceEffect( + DeathtouchAbility.getInstance(), Duration.EndOfTurn + ).setText("{this} gains deathtouch"), new GenericManaCost(1)); + ability.addEffect(new GainAbilitySourceEffect( + IndestructibleAbility.getInstance(), Duration.EndOfTurn + ).setText("and indestructible until end of turn")); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent( + StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE + ))); + this.addAbility(ability); + } + + private PitilessPontiff(final PitilessPontiff card) { + super(card); + } + + @Override + public PitilessPontiff copy() { + return new PitilessPontiff(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PlagueBelcher.java b/Mage.Sets/src/mage/cards/p/PlagueBelcher.java index e042dcf7eb6..65ef7f718d6 100644 --- a/Mage.Sets/src/mage/cards/p/PlagueBelcher.java +++ b/Mage.Sets/src/mage/cards/p/PlagueBelcher.java @@ -32,7 +32,7 @@ public final class PlagueBelcher extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new SubtypePredicate(SubType.ZOMBIE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public PlagueBelcher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java b/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java index 05652917b59..0a5dd16f1ee 100644 --- a/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java +++ b/Mage.Sets/src/mage/cards/p/PlagueOfVermin.java @@ -1,9 +1,5 @@ - package mage.cards.p; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -16,14 +12,17 @@ import mage.game.permanent.token.RatToken; import mage.players.Player; import mage.players.PlayerList; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class PlagueOfVermin extends CardImpl { public PlagueOfVermin(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{6}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{B}"); // Starting with you, each player may pay any amount of life. Repeat this process until no one pays life. Each player creates a 1/1 black Rat creature token for each 1 life he or she paid this way. @@ -60,7 +59,6 @@ class PlagueOfVerminEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Card sourceCard = game.getCard(source.getSourceId()); Map payLife = new HashMap<>(); int currentLifePaid; int totalPaidLife; @@ -90,15 +88,16 @@ class PlagueOfVerminEffect extends OneShotEffect { payLife.put(currentPlayer.getId(), currentLifePaid + totalPaidLife); } } - game.informPlayers(sourceCard.getName() + ": " + currentPlayer.getLogName() + " pays " + payLife.get(currentPlayer.getId()) + " life"); + Card sourceCard = game.getCard(source.getSourceId()); + game.informPlayers((sourceCard != null ? sourceCard.getName() : "") + ": " + currentPlayer.getLogName() + " pays " + payLife.get(currentPlayer.getId()) + " life"); firstInactivePlayer = null; } } - + // get next player playerList.getNext(); currentPlayer = game.getPlayer(playerList.get()); - + // if all player since this player didn't put permanent in play finish the process if (currentPlayer.getId().equals(firstInactivePlayer)) { break; diff --git a/Mage.Sets/src/mage/cards/p/PlagueWight.java b/Mage.Sets/src/mage/cards/p/PlagueWight.java new file mode 100644 index 00000000000..433b85b01d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PlagueWight.java @@ -0,0 +1,75 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.BlockedByIdPredicate; +import mage.filter.predicate.permanent.BlockingAttackerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PlagueWight extends CardImpl { + + public PlagueWight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Whenever Plague Wight becomes blocked, each creature blocking it gets -1/-1 until end of turn. + this.addAbility(new BecomesBlockedTriggeredAbility(new PlagueWightEffect(), false)); + } + + private PlagueWight(final PlagueWight card) { + super(card); + } + + @Override + public PlagueWight copy() { + return new PlagueWight(this); + } +} + +class PlagueWightEffect extends OneShotEffect { + + PlagueWightEffect() { + super(Outcome.Benefit); + staticText = "each creature blocking it gets -1/-1 until end of turn."; + } + + private PlagueWightEffect(final PlagueWightEffect effect) { + super(effect); + } + + @Override + public PlagueWightEffect copy() { + return new PlagueWightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new BlockingAttackerIdPredicate(source.getSourceId())); + game.addEffect(new BoostAllEffect(-1, -1, Duration.EndOfTurn, filter, false), source); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/Plaguecrafter.java b/Mage.Sets/src/mage/cards/p/Plaguecrafter.java index 39eaf6eb382..19830b5503a 100644 --- a/Mage.Sets/src/mage/cards/p/Plaguecrafter.java +++ b/Mage.Sets/src/mage/cards/p/Plaguecrafter.java @@ -1,8 +1,5 @@ package mage.cards.p; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -23,8 +20,11 @@ import mage.players.Player; import mage.target.common.TargetControlledPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author themogwi */ public final class Plaguecrafter extends CardImpl { @@ -43,7 +43,7 @@ public final class Plaguecrafter extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new PlaguecrafterEffect())); } - public Plaguecrafter(final Plaguecrafter card) { + private Plaguecrafter(final Plaguecrafter card) { super(card); } @@ -55,13 +55,13 @@ public final class Plaguecrafter extends CardImpl { class PlaguecrafterEffect extends OneShotEffect { - public PlaguecrafterEffect() { + PlaguecrafterEffect() { super(Outcome.Benefit); this.staticText = "each player sacrifices a creature or planeswalker. " + "Each player who can't discards a card."; } - public PlaguecrafterEffect(final PlaguecrafterEffect effect) { + private PlaguecrafterEffect(final PlaguecrafterEffect effect) { super(effect); } @@ -82,20 +82,22 @@ class PlaguecrafterEffect extends OneShotEffect { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - if (player != null) { - FilterControlledPermanent filter = new FilterControlledPermanent(); - filter.add(Predicates.or( - new CardTypePredicate(CardType.CREATURE), - new CardTypePredicate(CardType.PLANESWALKER))); - TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); - if (target.canChoose(player.getId(), game)) { - while (!target.isChosen() && player.canRespond()) { - player.choose(Outcome.Sacrifice, target, source.getSourceId(), game); - } - perms.addAll(target.getTargets()); - } else { - cantSac.add(playerId); + if (player == null) { + continue; + } + FilterControlledPermanent filter = new FilterControlledPermanent("creature or planeswalker"); + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.PLANESWALKER) + )); + TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); + if (target.canChoose(player.getId(), game)) { + while (!target.isChosen() && player.canRespond()) { + player.choose(Outcome.Sacrifice, target, source.getSourceId(), game); } + perms.addAll(target.getTargets()); + } else { + cantSac.add(playerId); } } diff --git a/Mage.Sets/src/mage/cards/p/PlanarChaos.java b/Mage.Sets/src/mage/cards/p/PlanarChaos.java index 4f4dc4c6a7a..863a0d0d4a0 100644 --- a/Mage.Sets/src/mage/cards/p/PlanarChaos.java +++ b/Mage.Sets/src/mage/cards/p/PlanarChaos.java @@ -61,7 +61,7 @@ class PlanarChaosUpkeepEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { Permanent perm = game.getPermanent(source.getSourceId()); if (perm != null) { perm.sacrifice(source.getSourceId(), game); @@ -104,7 +104,7 @@ class PlanarChaosCastAllEffect extends OneShotEffect { if (sourceObject != null && spell != null) { Player caster = game.getPlayer(spell.getControllerId()); if (caster != null) { - if (!caster.flipCoin(game)) { + if (!caster.flipCoin(source, game, true)) { game.informPlayers(sourceObject.getLogName() + ": " + spell.getLogName() + " countered"); game.getStack().counter(getTargetPointer().getFirst(game, source), source.getSourceId(), game); } diff --git a/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java b/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java index 875e2f697ec..01493437e3c 100644 --- a/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java +++ b/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java @@ -155,7 +155,7 @@ class PlaneswalkersMischiefCondition implements Condition { if (!game.getExile().getExileZone(exileId).contains(cardId)) { return false; } - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName(), source.getSourceId()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class, source.getSourceId()); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(source.getControllerId()); if (spells != null) { diff --git a/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java b/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java new file mode 100644 index 00000000000..d88d7c09816 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java @@ -0,0 +1,62 @@ +package mage.cards.p; + +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.mana.AnyColorLandsProduceManaAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PlazaOfHarmony extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter2 = new FilterPermanent(SubType.GATE, "Gate"); + + static { + filter.add(new SubtypePredicate(SubType.GATE)); + } + + private static final Condition condition + = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + + public PlazaOfHarmony(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // When Plaza of Harmony enters the battlefield, if you control two or more Gates, you gain 3 life. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)), + condition, "When {this} enters the battlefield, " + + "if you control two or more Gates, you gain 3 life." + )); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {T}: Add one mana of any type a Gate you control could produce. + this.addAbility(new AnyColorLandsProduceManaAbility(TargetController.YOU, false, filter2)); + } + + private PlazaOfHarmony(final PlazaOfHarmony card) { + super(card); + } + + @Override + public PlazaOfHarmony copy() { + return new PlazaOfHarmony(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PoeDameron.java b/Mage.Sets/src/mage/cards/p/PoeDameron.java index f0e7d9c6a8a..a85a74dd105 100644 --- a/Mage.Sets/src/mage/cards/p/PoeDameron.java +++ b/Mage.Sets/src/mage/cards/p/PoeDameron.java @@ -25,7 +25,7 @@ public final class PoeDameron extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filterStarship.add(new ControllerPredicate(TargetController.YOU)); filterStarship.add(new SubtypePredicate(SubType.STARSHIP)); } diff --git a/Mage.Sets/src/mage/cards/p/PoisonbellyOgre.java b/Mage.Sets/src/mage/cards/p/PoisonbellyOgre.java index 866517b846a..23b359686f8 100644 --- a/Mage.Sets/src/mage/cards/p/PoisonbellyOgre.java +++ b/Mage.Sets/src/mage/cards/p/PoisonbellyOgre.java @@ -22,7 +22,7 @@ public final class PoisonbellyOgre extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private final static String RULE = "Whenever another creature enters the battlefield, its controller loses 1 life."; diff --git a/Mage.Sets/src/mage/cards/p/PollenRemedy.java b/Mage.Sets/src/mage/cards/p/PollenRemedy.java index 65d52569733..b13dadd098c 100644 --- a/Mage.Sets/src/mage/cards/p/PollenRemedy.java +++ b/Mage.Sets/src/mage/cards/p/PollenRemedy.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.UUID; @@ -17,39 +16,30 @@ import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetAnyTargetAmount; +import mage.target.targetadjustment.TargetAdjuster; /** * * @author LoneFox - + * */ public final class PollenRemedy extends CardImpl { - private final UUID originalId; - public PollenRemedy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); // Kicker-Sacrifice a land. this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, new FilterControlledLandPermanent("a land"), true)))); // Prevent the next 3 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose. If Pollen Remedy was kicked, prevent the next 6 damage this way instead. Effect effect = new ConditionalReplacementEffect(new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 6), - KickedCondition.instance, new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 3)); + KickedCondition.instance, new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 3)); effect.setText("Prevent the next 3 damage that would be dealt this turn to any number of targets, divided as you choose. if this spell was kicked, prevent the next 6 damage this way instead."); this.getSpellAbility().addEffect(effect); - originalId = this.getSpellAbility().getOriginalId(); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if(ability.getOriginalId().equals(originalId)) { - ability.addTarget(new TargetAnyTargetAmount(KickedCondition.instance.apply(game, ability) ? 6 : 3)); - } + this.getSpellAbility().setTargetAdjuster(PollenRemedyAdjuster.instance); } public PollenRemedy(final PollenRemedy card) { super(card); - this.originalId = card.originalId; } @Override @@ -57,3 +47,12 @@ public final class PollenRemedy extends CardImpl { return new PollenRemedy(this); } } + +enum PollenRemedyAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.addTarget(new TargetAnyTargetAmount(KickedCondition.instance.apply(game, ability) ? 6 : 3)); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java b/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java index 6f6b1ca6b6b..0fa30f941f0 100644 --- a/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java +++ b/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java @@ -1,9 +1,6 @@ package mage.cards.p; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility; @@ -12,47 +9,44 @@ import mage.abilities.keyword.MonstrosityAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.TargetController; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetCreaturePermanentAmount; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** - * * * The value of X in Polukranos's last ability is equal to the value chosen - * for X when its activated ability was activated. - * + * for X when its activated ability was activated. + *

* * The number of targets chosen for the triggered ability must be at least one - * (if X wasn't 0) and at most X. You choose the division of damage as you put - * the ability on the stack, not as it resolves. Each target must be assigned - * at least 1 damage. In multiplayer games, you may choose creatures controlled - * by different opponents. - * + * (if X wasn't 0) and at most X. You choose the division of damage as you put + * the ability on the stack, not as it resolves. Each target must be assigned + * at least 1 damage. In multiplayer games, you may choose creatures controlled + * by different opponents. + *

* * If some, but not all, of the ability's targets become illegal, you can't change - * the division of damage. Damage that would've been dealt to illegal targets - * simply isn't dealt. - * + * the division of damage. Damage that would've been dealt to illegal targets + * simply isn't dealt. + *

* * As Polukranos's triggered ability resolves, Polukranos deals damage first, then - * the target creatures do. Although no creature will die until after the ability - * finishes resolving, the order could matter if Polukranos has wither or infect. + * the target creatures do. Although no creature will die until after the ability + * finishes resolving, the order could matter if Polukranos has wither or infect. * * @author LevelX2 */ public final class PolukranosWorldEater extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - static { - filter.add(new ControllerPredicate(TargetController.OPPONENT)); - } - public PolukranosWorldEater(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HYDRA); @@ -61,20 +55,11 @@ public final class PolukranosWorldEater extends CardImpl { // {X}{X}{G}: Monstrosity X. this.addAbility(new MonstrosityAbility("{X}{X}{G}", Integer.MAX_VALUE)); + // When Polukranos, World Eater becomes monstrous, it deals X damage divided as you choose among any number of target creatures your opponents control. Each of those creatures deals damage equal to its power to Polukranos. Ability ability = new BecomesMonstrousSourceTriggeredAbility(new PolukranosWorldEaterEffect()); - ability.addTarget(new TargetCreaturePermanentAmount(1, filter)); + ability.setTargetAdjuster(PolukranosWorldEaterAdjuster.instance); this.addAbility(ability); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof BecomesMonstrousSourceTriggeredAbility) { - int xValue = ((BecomesMonstrousSourceTriggeredAbility) ability).getMonstrosityValue(); - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanentAmount(xValue, filter)); - } } public PolukranosWorldEater(final PolukranosWorldEater card) { @@ -87,6 +72,17 @@ public final class PolukranosWorldEater extends CardImpl { } } +enum PolukranosWorldEaterAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue = ((BecomesMonstrousSourceTriggeredAbility) ability).getMonstrosityValue(); + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanentAmount(xValue, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + } +} + class PolukranosWorldEaterEffect extends OneShotEffect { public PolukranosWorldEaterEffect() { @@ -108,7 +104,7 @@ class PolukranosWorldEaterEffect extends OneShotEffect { if (!source.getTargets().isEmpty()) { Target multiTarget = source.getTargets().get(0); Set permanents = new HashSet<>(); - for (UUID target: multiTarget.getTargets()) { + for (UUID target : multiTarget.getTargets()) { Permanent permanent = game.getPermanent(target); if (permanent != null) { permanents.add(permanent); @@ -118,7 +114,7 @@ class PolukranosWorldEaterEffect extends OneShotEffect { // Each of those creatures deals damage equal to its power to Polukranos Permanent sourceCreature = game.getPermanent(source.getSourceId()); if (sourceCreature != null) { - for (Permanent permanent :permanents) { + for (Permanent permanent : permanents) { sourceCreature.damage(permanent.getPower().getValue(), permanent.getId(), game, false, true); } } diff --git a/Mage.Sets/src/mage/cards/p/PontiffOfBlight.java b/Mage.Sets/src/mage/cards/p/PontiffOfBlight.java index 19a3aa1248a..d7f18675a4a 100644 --- a/Mage.Sets/src/mage/cards/p/PontiffOfBlight.java +++ b/Mage.Sets/src/mage/cards/p/PontiffOfBlight.java @@ -28,7 +28,7 @@ public final class PontiffOfBlight extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Other creatures you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/p/PostmortemLunge.java b/Mage.Sets/src/mage/cards/p/PostmortemLunge.java index 65a32494f10..75f35c769a0 100644 --- a/Mage.Sets/src/mage/cards/p/PostmortemLunge.java +++ b/Mage.Sets/src/mage/cards/p/PostmortemLunge.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.ContinuousEffect; @@ -21,8 +19,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** * @author North */ @@ -34,6 +35,7 @@ public final class PostmortemLunge extends CardImpl { // Return target creature card with converted mana cost X from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step. this.getSpellAbility().addEffect(new PostmortemLungeEffect()); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + this.getSpellAbility().setTargetAdjuster(PostmortemLungeAdjuster.instance); } public PostmortemLunge(final PostmortemLunge card) { @@ -44,16 +46,18 @@ public final class PostmortemLunge extends CardImpl { public PostmortemLunge copy() { return new PostmortemLunge(this); } +} + +enum PostmortemLungeAdjuster implements TargetAdjuster { + instance; @Override public void adjustTargets(Ability ability, Game game) { - if (ability.getAbilityType() == AbilityType.SPELL) { // otherwise the target is also added to the delayed triggered ability - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCard filter = new FilterCreatureCard("creature card with converted mana cost " + xValue + " or less from your graveyard"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); - ability.getTargets().add(new TargetCardInYourGraveyard(filter)); - } + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterCard filter = new FilterCreatureCard("creature card with converted mana cost " + xValue + " or less from your graveyard"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + ability.getTargets().add(new TargetCardInYourGraveyard(filter)); } } @@ -76,13 +80,11 @@ class PostmortemLungeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Card card = game.getCard(source.getFirstTarget()); - if (card != null) { Player cardOwner = game.getPlayer(card.getOwnerId()); if (cardOwner == null) { return false; } - if (cardOwner.moveCards(card, Zone.BATTLEFIELD, source, game)) { Permanent permanent = game.getPermanent(card.getId()); if (permanent != null) { @@ -96,7 +98,6 @@ class PostmortemLungeEffect extends OneShotEffect { } return true; } - return false; } } diff --git a/Mage.Sets/src/mage/cards/p/PowerSurge.java b/Mage.Sets/src/mage/cards/p/PowerSurge.java index 186e7039ba6..7b788da9efd 100644 --- a/Mage.Sets/src/mage/cards/p/PowerSurge.java +++ b/Mage.Sets/src/mage/cards/p/PowerSurge.java @@ -64,10 +64,12 @@ class PowerSurgeDamageEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); if (player != null) { - PowerSurgeWatcher watcher = (PowerSurgeWatcher) game.getState().getWatchers().get(PowerSurgeWatcher.class.getSimpleName()); - int damage = watcher.getUntappedLandCount(); - player.damage(damage, source.getSourceId(), game, false, true); - return true; + PowerSurgeWatcher watcher = game.getState().getWatcher(PowerSurgeWatcher.class); + if(watcher != null) { + int damage = watcher.getUntappedLandCount(); + player.damage(damage, source.getSourceId(), game, false, true); + return true; + } } return false; } @@ -83,13 +85,13 @@ class PowerSurgeWatcher extends Watcher { private static final FilterPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } private int untappedLandCount; public PowerSurgeWatcher() { - super(PowerSurgeWatcher.class.getSimpleName(), WatcherScope.GAME); + super(PowerSurgeWatcher.class, WatcherScope.GAME); } public PowerSurgeWatcher(final PowerSurgeWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/p/PrecognitivePerception.java b/Mage.Sets/src/mage/cards/p/PrecognitivePerception.java new file mode 100644 index 00000000000..32f2d035519 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PrecognitivePerception.java @@ -0,0 +1,68 @@ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PrecognitivePerception extends CardImpl { + + public PrecognitivePerception(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}"); + + // Draw three cards. + // Addendum — If you cast this spell during your main phase, instead scry 3, then draw three cards. + this.getSpellAbility().addEffect(new PrecognitivePerceptionEffect()); + } + + private PrecognitivePerception(final PrecognitivePerception card) { + super(card); + } + + @Override + public PrecognitivePerception copy() { + return new PrecognitivePerception(this); + } +} + +class PrecognitivePerceptionEffect extends OneShotEffect { + + PrecognitivePerceptionEffect() { + super(Outcome.Benefit); + staticText = "Draw three cards.
Addendum — " + + "If you cast this spell during your main phase, " + + "instead scry 3, then draw three cards."; + } + + private PrecognitivePerceptionEffect(final PrecognitivePerceptionEffect effect) { + super(effect); + } + + @Override + public PrecognitivePerceptionEffect copy() { + return new PrecognitivePerceptionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + if (AddendumCondition.instance.apply(game, source)) { + controller.scry(3, source, game); + } + controller.drawCards(3, game); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java b/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java index 01c526c4085..57906d28fd0 100644 --- a/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java +++ b/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java @@ -48,7 +48,7 @@ class DidNotCastCreatureCondition implements Condition { public boolean apply(Game game, Ability source) { Permanent p = game.getPermanent(source.getSourceId()); if (p != null) { - Watcher watcher = game.getState().getWatchers().get(CastCreatureWatcher.class.getSimpleName(), source.getSourceId()); + Watcher watcher = game.getState().getWatcher(CastCreatureWatcher.class, source.getSourceId()); if (watcher != null && !watcher.conditionMet()) { return true; } @@ -65,7 +65,7 @@ class DidNotCastCreatureCondition implements Condition { class CastCreatureWatcher extends Watcher { public CastCreatureWatcher() { - super(CastCreatureWatcher.class.getSimpleName(), WatcherScope.CARD); + super(CastCreatureWatcher.class, WatcherScope.CARD); } public CastCreatureWatcher(final CastCreatureWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/p/PrematureBurial.java b/Mage.Sets/src/mage/cards/p/PrematureBurial.java index 3f8ac248ae3..b3ebd0759a8 100644 --- a/Mage.Sets/src/mage/cards/p/PrematureBurial.java +++ b/Mage.Sets/src/mage/cards/p/PrematureBurial.java @@ -66,7 +66,7 @@ class ETBSinceYourLastTurnTarget extends TargetCreaturePermanent { @Override public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { System.out.println("canTarget called"); - ETBSinceYourLastTurnWatcher watcher = (ETBSinceYourLastTurnWatcher) game.getState().getWatchers().get(ETBSinceYourLastTurnWatcher.class.getSimpleName()); + ETBSinceYourLastTurnWatcher watcher = game.getState().getWatcher(ETBSinceYourLastTurnWatcher.class); if (watcher != null){ if (watcher.enteredSinceLastTurn(controllerId, new MageObjectReference(id, game))){ System.out.println(game.getPermanent(id).getIdName()+" entered since the last turn."); @@ -79,11 +79,11 @@ class ETBSinceYourLastTurnTarget extends TargetCreaturePermanent { @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { MageObject targetSource = game.getObject(sourceId); - ETBSinceYourLastTurnWatcher watcher = (ETBSinceYourLastTurnWatcher) game.getState().getWatchers().get(ETBSinceYourLastTurnWatcher.class.getSimpleName()); + ETBSinceYourLastTurnWatcher watcher = game.getState().getWatcher(ETBSinceYourLastTurnWatcher.class); if(targetSource != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { - if (watcher.enteredSinceLastTurn(sourceControllerId, new MageObjectReference(permanent.getId(), game))) { + if (watcher != null && watcher.enteredSinceLastTurn(sourceControllerId, new MageObjectReference(permanent.getId(), game))) { return true; } } @@ -103,7 +103,7 @@ class ETBSinceYourLastTurnWatcher extends Watcher { private final Map> playerToETBMap; public ETBSinceYourLastTurnWatcher() { - super(ETBSinceYourLastTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(ETBSinceYourLastTurnWatcher.class, WatcherScope.GAME); this.playerToETBMap = new HashMap<>(); } diff --git a/Mage.Sets/src/mage/cards/p/PrepareFight.java b/Mage.Sets/src/mage/cards/p/PrepareFight.java index daa30221acc..366411f7ab5 100644 --- a/Mage.Sets/src/mage/cards/p/PrepareFight.java +++ b/Mage.Sets/src/mage/cards/p/PrepareFight.java @@ -49,7 +49,7 @@ public final class PrepareFight extends SplitCard { // to // Fight // Target creature you control fights target creature you don't control. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addEffect(new FightTargetsEffect()); getRightHalfCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); Target target = new TargetCreaturePermanent(filter); diff --git a/Mage.Sets/src/mage/cards/p/PrescientChimera.java b/Mage.Sets/src/mage/cards/p/PrescientChimera.java index 124a222a486..ad0c59673ff 100644 --- a/Mage.Sets/src/mage/cards/p/PrescientChimera.java +++ b/Mage.Sets/src/mage/cards/p/PrescientChimera.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.keyword.ScryEffect; @@ -12,14 +10,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PrescientChimera extends CardImpl { public PrescientChimera(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.CHIMERA); this.power = new MageInt(3); @@ -28,7 +27,7 @@ public final class PrescientChimera extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever you cast an instant or sorcery spell, scry 1. - this.addAbility(new SpellCastControllerTriggeredAbility(new ScryEffect(1), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new ScryEffect(1), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false)); } public PrescientChimera(final PrescientChimera card) { diff --git a/Mage.Sets/src/mage/cards/p/PresenceOfTheWise.java b/Mage.Sets/src/mage/cards/p/PresenceOfTheWise.java index 0129a82eb5f..7c7037e939f 100644 --- a/Mage.Sets/src/mage/cards/p/PresenceOfTheWise.java +++ b/Mage.Sets/src/mage/cards/p/PresenceOfTheWise.java @@ -20,7 +20,7 @@ public final class PresenceOfTheWise extends CardImpl { // You gain 2 life for each card in your hand. this.getSpellAbility().addEffect(new GainLifeEffect( - new MultipliedValue(new CardsInControllerHandCount(), 2),"You gain 2 life for each card in your hand")); + new MultipliedValue(CardsInControllerHandCount.instance, 2),"You gain 2 life for each card in your hand")); } public PresenceOfTheWise(final PresenceOfTheWise card) { diff --git a/Mage.Sets/src/mage/cards/p/PriceOfFame.java b/Mage.Sets/src/mage/cards/p/PriceOfFame.java index 79f7737b9e6..194d35fe996 100644 --- a/Mage.Sets/src/mage/cards/p/PriceOfFame.java +++ b/Mage.Sets/src/mage/cards/p/PriceOfFame.java @@ -1,36 +1,44 @@ package mage.cards.p; -import java.util.Iterator; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceTargetsPermanentCondition; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; import mage.abilities.effects.keyword.SurveilEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SuperType; import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; -import mage.target.Target; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class PriceOfFame extends CardImpl { + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("a legendary creature"); + + static { + filter.add(new SupertypePredicate(SuperType.LEGENDARY)); + } + + private static final Condition condition = new SourceTargetsPermanentCondition(filter); + public PriceOfFame(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}"); // This spell costs {2} less to cast if it targets a legendary creature. - this.addAbility(new SimpleStaticAbility(Zone.STACK, - new SpellCostReductionSourceEffect(2, PriceOfFameCondition.instance)) - .setRuleAtTheTop(true)); + this.addAbility(new SimpleStaticAbility( + Zone.STACK, new SpellCostReductionSourceEffect(2, condition) + ).setRuleAtTheTop(true)); // Destroy target creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); @@ -49,28 +57,3 @@ public final class PriceOfFame extends CardImpl { return new PriceOfFame(this); } } - -enum PriceOfFameCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - StackObject sourceSpell = game.getStack().getStackObject(source.getSourceId()); - if (sourceSpell != null) { - Iterator targets = sourceSpell.getStackAbility().getTargets().iterator(); - while (targets.hasNext()) { - Permanent permanent = game.getPermanentOrLKIBattlefield(targets.next().getFirstTarget()); - if (permanent != null && permanent.isCreature() && permanent.isLegendary()) { - return true; - } - } - } - return false; - } - - @Override - public String toString() { - return "it targets a legendary creature"; - } - -} diff --git a/Mage.Sets/src/mage/cards/p/PrideOfTheClouds.java b/Mage.Sets/src/mage/cards/p/PrideOfTheClouds.java index ab9ce5f0c48..9ac6fc59b9f 100644 --- a/Mage.Sets/src/mage/cards/p/PrideOfTheClouds.java +++ b/Mage.Sets/src/mage/cards/p/PrideOfTheClouds.java @@ -31,7 +31,7 @@ public final class PrideOfTheClouds extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature with flying on the battlefield"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new AbilityPredicate(FlyingAbility.class)); } diff --git a/Mage.Sets/src/mage/cards/p/PrideSovereign.java b/Mage.Sets/src/mage/cards/p/PrideSovereign.java index 42f476571a0..929c2d2b731 100644 --- a/Mage.Sets/src/mage/cards/p/PrideSovereign.java +++ b/Mage.Sets/src/mage/cards/p/PrideSovereign.java @@ -38,7 +38,7 @@ public final class PrideSovereign extends CardImpl { // Pride Sovereign gets +1/+1 for each other Cat you control. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.CAT, "other Cat you control"); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); DynamicValue otherCats = new PermanentsOnBattlefieldCount(filter); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(otherCats, otherCats, Duration.WhileOnBattlefield))); // {W}, {t}, Exert Pride Sovereign: Create two 1/1 white Cat creature tokens with lifelink. diff --git a/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java b/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java new file mode 100644 index 00000000000..801350a032c --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PriestOfForgottenGods.java @@ -0,0 +1,71 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.SacrificeEffect; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PriestOfForgottenGods extends CardImpl { + + private static final FilterControlledPermanent filter + = new FilterControlledCreaturePermanent("other creatures"); + + static { + filter.add(AnotherPredicate.instance); + } + + public PriestOfForgottenGods(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {T}, Sacrifice two other creatures: Any number of target players each lose 2 life and sacrifice a creature. You add {B}{B} and draw a card. + Ability ability = new SimpleActivatedAbility( + new LoseLifeTargetEffect(2) + .setText("Any number of target players each lose 2 life"), + new TapSourceCost() + ); + ability.addEffect( + new SacrificeEffect(StaticFilters.FILTER_PERMANENT_CREATURE, 1, "") + .setText("and sacrifice a creature") + ); + ability.addEffect(new BasicManaEffect(Mana.BlackMana(2)).setText("You add {B}{B}")); + ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and draw a card")); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, filter, true))); + ability.addTarget(new TargetPlayer(0, Integer.MAX_VALUE, false)); + this.addAbility(ability); + } + + private PriestOfForgottenGods(final PriestOfForgottenGods card) { + super(card); + } + + @Override + public PriestOfForgottenGods copy() { + return new PriestOfForgottenGods(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PrimalForcemage.java b/Mage.Sets/src/mage/cards/p/PrimalForcemage.java index 2a17cceae86..c1e50b811e9 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalForcemage.java +++ b/Mage.Sets/src/mage/cards/p/PrimalForcemage.java @@ -27,7 +27,7 @@ public final class PrimalForcemage extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private static final String rule = "Whenever another creature enters the battlefield under your control, that creature gets +3/+3 until end of turn."; diff --git a/Mage.Sets/src/mage/cards/p/PrimalWhisperer.java b/Mage.Sets/src/mage/cards/p/PrimalWhisperer.java index 3ea6fbad59f..61901b4b918 100644 --- a/Mage.Sets/src/mage/cards/p/PrimalWhisperer.java +++ b/Mage.Sets/src/mage/cards/p/PrimalWhisperer.java @@ -26,7 +26,7 @@ public final class PrimalWhisperer extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face-down creature"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public PrimalWhisperer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PrimeSpeakerVannifar.java b/Mage.Sets/src/mage/cards/p/PrimeSpeakerVannifar.java new file mode 100644 index 00000000000..3554ba25ade --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PrimeSpeakerVannifar.java @@ -0,0 +1,107 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 and Loki + */ +public final class PrimeSpeakerVannifar extends CardImpl { + + public PrimeSpeakerVannifar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.OOZE); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // {T}, Sacrifice another creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost, put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, new PrimeSpeakerVannifarEffect(), new TapSourceCost() + ); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent( + StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE + ))); + this.addAbility(ability); + } + + private PrimeSpeakerVannifar(final PrimeSpeakerVannifar card) { + super(card); + } + + @Override + public PrimeSpeakerVannifar copy() { + return new PrimeSpeakerVannifar(this); + } +} + +class PrimeSpeakerVannifarEffect extends OneShotEffect { + + PrimeSpeakerVannifarEffect() { + super(Outcome.Benefit); + staticText = "Search your library for a creature card with converted mana cost equal to 1 " + + "plus the sacrificed creature's converted mana cost, put that card " + + "onto the battlefield, then shuffle your library"; + } + + private PrimeSpeakerVannifarEffect(final PrimeSpeakerVannifarEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sacrificedPermanent = null; + for (Cost cost : source.getCosts()) { + if (cost instanceof SacrificeTargetCost) { + SacrificeTargetCost sacrificeCost = (SacrificeTargetCost) cost; + if (!sacrificeCost.getPermanents().isEmpty()) { + sacrificedPermanent = sacrificeCost.getPermanents().get(0); + } + break; + } + } + Player controller = game.getPlayer(source.getControllerId()); + if (sacrificedPermanent == null || controller == null) { + return false; + } + int newConvertedCost = sacrificedPermanent.getConvertedManaCost() + 1; + FilterCard filter = new FilterCard("creature card with converted mana cost " + newConvertedCost); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, newConvertedCost)); + filter.add(new CardTypePredicate(CardType.CREATURE)); + TargetCardInLibrary target = new TargetCardInLibrary(filter); + if (controller.searchLibrary(target, game)) { + Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + controller.shuffleLibrary(source, game); + return true; + } + + @Override + public PrimeSpeakerVannifarEffect copy() { + return new PrimeSpeakerVannifarEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PrimevalProtector.java b/Mage.Sets/src/mage/cards/p/PrimevalProtector.java index c68fabb66ad..7a09b0723b9 100644 --- a/Mage.Sets/src/mage/cards/p/PrimevalProtector.java +++ b/Mage.Sets/src/mage/cards/p/PrimevalProtector.java @@ -36,7 +36,7 @@ public final class PrimevalProtector extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public PrimevalProtector(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PrimordialMist.java b/Mage.Sets/src/mage/cards/p/PrimordialMist.java index 364db608db3..891466a29b3 100644 --- a/Mage.Sets/src/mage/cards/p/PrimordialMist.java +++ b/Mage.Sets/src/mage/cards/p/PrimordialMist.java @@ -35,7 +35,7 @@ public final class PrimordialMist extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("face down permanent"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public PrimordialMist(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PrincessLeia.java b/Mage.Sets/src/mage/cards/p/PrincessLeia.java index 3a47d9e3ea4..9bcae9ff497 100644 --- a/Mage.Sets/src/mage/cards/p/PrincessLeia.java +++ b/Mage.Sets/src/mage/cards/p/PrincessLeia.java @@ -30,7 +30,7 @@ public final class PrincessLeia extends CardImpl { static { SubtypePredicate rebel = new SubtypePredicate(SubType.REBEL); - filter1.add(new AnotherPredicate()); + filter1.add(AnotherPredicate.instance); filter1.add(rebel); filter2.add(rebel); } diff --git a/Mage.Sets/src/mage/cards/p/PrismaticStrands.java b/Mage.Sets/src/mage/cards/p/PrismaticStrands.java index e5fb668061d..06a50fb4d29 100644 --- a/Mage.Sets/src/mage/cards/p/PrismaticStrands.java +++ b/Mage.Sets/src/mage/cards/p/PrismaticStrands.java @@ -34,7 +34,7 @@ public final class PrismaticStrands extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new ColorPredicate(ObjectColor.WHITE)); } diff --git a/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java b/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java index 77d939f26f8..e8c4babc360 100644 --- a/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java +++ b/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java @@ -89,7 +89,7 @@ class PrizedAmalgamTriggerdAbility extends EntersBattlefieldAllTriggeredAbility if (entersEvent.getFromZone() == Zone.GRAVEYARD) { result = true; } else if (entersEvent.getFromZone() == Zone.STACK && entersEvent.getTarget().isControlledBy(getControllerId())) { - CastFromGraveyardWatcher watcher = (CastFromGraveyardWatcher) game.getState().getWatchers().get(CastFromGraveyardWatcher.class.getSimpleName()); + CastFromGraveyardWatcher watcher = game.getState().getWatcher(CastFromGraveyardWatcher.class); if (watcher != null) { int zcc = game.getState().getZoneChangeCounter(event.getSourceId()); result = watcher.spellWasCastFromGraveyard(event.getSourceId(), zcc - 1); diff --git a/Mage.Sets/src/mage/cards/p/Probe.java b/Mage.Sets/src/mage/cards/p/Probe.java index e8e4e7a6890..6c98d48e93e 100644 --- a/Mage.Sets/src/mage/cards/p/Probe.java +++ b/Mage.Sets/src/mage/cards/p/Probe.java @@ -1,9 +1,7 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawDiscardControllerEffect; @@ -14,9 +12,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.game.Game; import mage.target.TargetPlayer; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class Probe extends CardImpl { @@ -33,16 +33,7 @@ public final class Probe extends CardImpl { new DiscardTargetEffect(2), KickedCondition.instance, "

if this spell was kicked, target player discards two cards")); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - if (KickedCondition.instance.apply(game, ability)) { - ability.addTarget(new TargetPlayer()); - } - } + this.getSpellAbility().setTargetAdjuster(ProbeAdjuster.instance); } public Probe(final Probe card) { @@ -54,3 +45,15 @@ public final class Probe extends CardImpl { return new Probe(this); } } + +enum ProbeAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + if (KickedCondition.instance.apply(game, ability)) { + ability.addTarget(new TargetPlayer()); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/ProfaneCommand.java b/Mage.Sets/src/mage/cards/p/ProfaneCommand.java index 6f32b271f72..9e9b5172f90 100644 --- a/Mage.Sets/src/mage/cards/p/ProfaneCommand.java +++ b/Mage.Sets/src/mage/cards/p/ProfaneCommand.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; @@ -26,6 +25,9 @@ import mage.game.Game; import mage.target.TargetPlayer; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** * @author LevelX2 @@ -36,7 +38,7 @@ public final class ProfaneCommand extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; // Choose two - this.getSpellAbility().getModes().setMinModes(2); this.getSpellAbility().getModes().setMaxModes(2); @@ -64,27 +66,8 @@ public final class ProfaneCommand extends CardImpl { mode.addEffect(effect); mode.addTarget(new TargetCreaturePermanent(0, 1)); this.getSpellAbility().addMode(mode); - } - @Override - public void adjustTargets(Ability ability, Game game) { - // adjust targets is called for every selected mode - Mode mode = ability.getModes().getMode(); - for (Effect effect : mode.getEffects()) { - if (effect instanceof ReturnFromGraveyardToBattlefieldTargetEffect) { - mode.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCard filter = new FilterCreatureCard("creature card with converted mana cost " + xValue + " or less from your graveyard"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); - mode.addTarget(new TargetCardInYourGraveyard(filter)); - } - if (effect instanceof GainAbilityTargetEffect) { - mode.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures gain fear until end of turn"); - mode.addTarget(new TargetCreaturePermanent(0, xValue, filter, false)); - } - } + this.getSpellAbility().setTargetAdjuster(ProfaneCommandAdjuster.instance); } public ProfaneCommand(final ProfaneCommand card) { @@ -96,3 +79,27 @@ public final class ProfaneCommand extends CardImpl { return new ProfaneCommand(this); } } + +enum ProfaneCommandAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + // adjust targets is called for every selected mode + Mode mode = ability.getModes().getMode(); + int xValue = ability.getManaCostsToPay().getX(); + for (Effect effect : mode.getEffects()) { + if (effect instanceof ReturnFromGraveyardToBattlefieldTargetEffect) { + mode.getTargets().clear(); + FilterCard filter = new FilterCreatureCard("creature card with converted mana cost " + xValue + " or less from your graveyard"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + mode.addTarget(new TargetCardInYourGraveyard(filter)); + } + if (effect instanceof GainAbilityTargetEffect) { + mode.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures gain fear until end of turn"); + mode.addTarget(new TargetCreaturePermanent(0, xValue, filter, false)); + } + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java index 156ae583dc9..2de51e27b9d 100644 --- a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java +++ b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java @@ -29,7 +29,7 @@ public final class ProgenitorMimic extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("no Token"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public ProgenitorMimic(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/Prosperity.java b/Mage.Sets/src/mage/cards/p/Prosperity.java index edb928d7bc5..17d84d0b325 100644 --- a/Mage.Sets/src/mage/cards/p/Prosperity.java +++ b/Mage.Sets/src/mage/cards/p/Prosperity.java @@ -19,7 +19,7 @@ public final class Prosperity extends CardImpl { // Each player draws X cards. - this.getSpellAbility().addEffect(new DrawCardAllEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardAllEffect(ManacostVariableValue.instance)); } public Prosperity(final Prosperity card) { diff --git a/Mage.Sets/src/mage/cards/p/ProsshSkyraiderOfKher.java b/Mage.Sets/src/mage/cards/p/ProsshSkyraiderOfKher.java index 3b3e48838b3..bc9badb09fe 100644 --- a/Mage.Sets/src/mage/cards/p/ProsshSkyraiderOfKher.java +++ b/Mage.Sets/src/mage/cards/p/ProsshSkyraiderOfKher.java @@ -38,7 +38,7 @@ public final class ProsshSkyraiderOfKher extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // When you cast Prossh, Skyraider of Kher, create X 0/1 red Kobold creature tokens named Kobolds of Kher Keep, where X is the amount of mana spent to cast Prossh. - this.addAbility(new CastSourceTriggeredAbility(new CreateTokenEffect(new ProsshKoboldToken(), new ManaSpentToCastCount()), false)); + this.addAbility(new CastSourceTriggeredAbility(new CreateTokenEffect(new ProsshKoboldToken(), ManaSpentToCastCount.instance), false)); // Sacrifice another creature: Prossh gets +1/+0 until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, true)))); diff --git a/Mage.Sets/src/mage/cards/p/ProwessOfTheFair.java b/Mage.Sets/src/mage/cards/p/ProwessOfTheFair.java index f642c2b466e..990e3e7b7ec 100644 --- a/Mage.Sets/src/mage/cards/p/ProwessOfTheFair.java +++ b/Mage.Sets/src/mage/cards/p/ProwessOfTheFair.java @@ -25,8 +25,8 @@ public final class ProwessOfTheFair extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ELF)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public ProwessOfTheFair(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/ProwlingCaracal.java b/Mage.Sets/src/mage/cards/p/ProwlingCaracal.java new file mode 100644 index 00000000000..06efcb4f4b6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/ProwlingCaracal.java @@ -0,0 +1,32 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ProwlingCaracal extends CardImpl { + + public ProwlingCaracal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.CAT); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + } + + private ProwlingCaracal(final ProwlingCaracal card) { + super(card); + } + + @Override + public ProwlingCaracal copy() { + return new ProwlingCaracal(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PryingEyes.java b/Mage.Sets/src/mage/cards/p/PryingEyes.java new file mode 100644 index 00000000000..0718b39ff29 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PryingEyes.java @@ -0,0 +1,33 @@ +package mage.cards.p; + +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PryingEyes extends CardImpl { + + public PryingEyes(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}"); + + + // Draw four cards, then discard two cards. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4)); + this.getSpellAbility().addEffect(new DiscardControllerEffect(2).concatBy(", then")); + } + + private PryingEyes(final PryingEyes card) { + super(card); + } + + @Override + public PryingEyes copy() { + return new PryingEyes(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PsychicAllergy.java b/Mage.Sets/src/mage/cards/p/PsychicAllergy.java index c7c5c4cfeb2..17af2bbb36b 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicAllergy.java +++ b/Mage.Sets/src/mage/cards/p/PsychicAllergy.java @@ -84,7 +84,7 @@ class PsychicAllergyEffect extends OneShotEffect { if (player != null) { FilterPermanent filter = new FilterPermanent(); filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(source.getSourceId() + "_color"))); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); int damage = game.getBattlefield().countAll(filter, player.getId(), game); player.damage(damage, source.getSourceId(), game, false, true); return true; diff --git a/Mage.Sets/src/mage/cards/p/PsychicBattle.java b/Mage.Sets/src/mage/cards/p/PsychicBattle.java index f4f3eb91b9a..6c77281e1a5 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicBattle.java +++ b/Mage.Sets/src/mage/cards/p/PsychicBattle.java @@ -31,7 +31,7 @@ public final class PsychicBattle extends CardImpl { public PsychicBattle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}"); - // Whenever a player chooses one or more targets, each player reveals the top card of his or her library. The player who reveals the card with the highest converted mana cost may change the target or targets. If two or more cards are tied for highest cost, the target or targets remain unchanged. Changing targets this way doesn't trigger abilities of permanents named Psychic Battle. + // Whenever a player chooses one or more targets, each player reveals the top card of their library. The player who reveals the card with the highest converted mana cost may change the target or targets. If two or more cards are tied for highest cost, the target or targets remain unchanged. Changing targets this way doesn't trigger abilities of permanents named Psychic Battle. this.addAbility(new PsychicBattleTriggeredAbility()); } diff --git a/Mage.Sets/src/mage/cards/p/PsychicDrain.java b/Mage.Sets/src/mage/cards/p/PsychicDrain.java index 6deb03654bf..8008a2e7fb3 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicDrain.java +++ b/Mage.Sets/src/mage/cards/p/PsychicDrain.java @@ -21,9 +21,9 @@ public final class PsychicDrain extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}{B}"); // Target player puts the top X cards of their library into their graveyard and you gain X life. - this.getSpellAbility().addEffect(new PutLibraryIntoGraveTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new PutLibraryIntoGraveTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); - Effect effect = new GainLifeEffect(new ManacostVariableValue()); + Effect effect = new GainLifeEffect(ManacostVariableValue.instance); effect.setText("and you gain X life"); this.getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/p/PsychicSurgery.java b/Mage.Sets/src/mage/cards/p/PsychicSurgery.java index a3c04aa3268..b50c23af476 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicSurgery.java +++ b/Mage.Sets/src/mage/cards/p/PsychicSurgery.java @@ -29,7 +29,7 @@ public final class PsychicSurgery extends CardImpl { public PsychicSurgery(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); - // Whenever an opponent shuffles his or her library, you may look at the top two cards of that library. + // Whenever an opponent shuffles their library, you may look at the top two cards of that library. // You may exile one of those cards. Then put the rest on top of that library in any order. this.addAbility(new PsychicSurgeryTriggeredAbility()); } diff --git a/Mage.Sets/src/mage/cards/p/PsychicTheft.java b/Mage.Sets/src/mage/cards/p/PsychicTheft.java index b017003c210..1d2d9482687 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicTheft.java +++ b/Mage.Sets/src/mage/cards/p/PsychicTheft.java @@ -162,7 +162,7 @@ class PsychicTheftCondition implements Condition { if (!game.getExile().getExileZone(exileId).contains(cardId)) { return false; } - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName(), source.getSourceId()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class, source.getSourceId()); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(source.getControllerId()); if (spells != null) { diff --git a/Mage.Sets/src/mage/cards/p/PsychosisCrawler.java b/Mage.Sets/src/mage/cards/p/PsychosisCrawler.java index 9df5371fa95..74128f25f30 100644 --- a/Mage.Sets/src/mage/cards/p/PsychosisCrawler.java +++ b/Mage.Sets/src/mage/cards/p/PsychosisCrawler.java @@ -28,7 +28,7 @@ public final class PsychosisCrawler extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInControllerHandCount(), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(CardsInControllerHandCount.instance, Duration.EndOfGame))); this.addAbility(new DrawCardControllerTriggeredAbility(new LoseLifeOpponentsEffect(1), false)); } diff --git a/Mage.Sets/src/mage/cards/p/PsychoticFury.java b/Mage.Sets/src/mage/cards/p/PsychoticFury.java index 89a2e8bb195..c8ebd40196f 100644 --- a/Mage.Sets/src/mage/cards/p/PsychoticFury.java +++ b/Mage.Sets/src/mage/cards/p/PsychoticFury.java @@ -22,7 +22,7 @@ public final class PsychoticFury extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("multicolored creature"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public PsychoticFury(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/Pteramander.java b/Mage.Sets/src/mage/cards/p/Pteramander.java new file mode 100644 index 00000000000..0c5777a0d4d --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/Pteramander.java @@ -0,0 +1,87 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.effects.keyword.AdaptEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Pteramander extends CardImpl { + + public Pteramander(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + + this.subtype.add(SubType.SALAMANDER); + this.subtype.add(SubType.DRAKE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {7}{U}: Adapt 4. This ability costs {1} less to activate for each instant and sorcery card in your graveyard. + // TODO: Make ability properly copiable + Ability ability = new SimpleActivatedAbility(new AdaptEffect(4).setText("Adapt 4. This ability costs {1} less to activate for each instant and sorcery card in your graveyard."), new ManaCostsImpl("{7}{U}")); + this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new PteramanderCostIncreasingEffect(ability.getOriginalId()))); + } + + private Pteramander(final Pteramander card) { + super(card); + } + + @Override + public Pteramander copy() { + return new Pteramander(this); + } +} + +class PteramanderCostIncreasingEffect extends CostModificationEffectImpl { + + private final UUID originalId; + + PteramanderCostIncreasingEffect(UUID originalId) { + super(Duration.EndOfGame, Outcome.Benefit, CostModificationType.REDUCE_COST); + this.originalId = originalId; + } + + private PteramanderCostIncreasingEffect(final PteramanderCostIncreasingEffect effect) { + super(effect); + this.originalId = effect.originalId; + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + CardUtil.reduceCost(abilityToModify, controller.getGraveyard().count(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, game)); + } + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + return abilityToModify.getOriginalId().equals(originalId); + } + + @Override + public PteramanderCostIncreasingEffect copy() { + return new PteramanderCostIncreasingEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/p/PucasMischief.java b/Mage.Sets/src/mage/cards/p/PucasMischief.java index cb5f3d419e3..dcf0628b1b4 100644 --- a/Mage.Sets/src/mage/cards/p/PucasMischief.java +++ b/Mage.Sets/src/mage/cards/p/PucasMischief.java @@ -64,11 +64,6 @@ class TargetControlledPermanentWithCMCGreaterOrLessThanOpponentPermanent extends super(target); } - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - return super.canTarget(controllerId, id, source, game); - } - @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); diff --git a/Mage.Sets/src/mage/cards/p/PullFromEternity.java b/Mage.Sets/src/mage/cards/p/PullFromEternity.java index 46fe77e642c..5a7aecf42da 100644 --- a/Mage.Sets/src/mage/cards/p/PullFromEternity.java +++ b/Mage.Sets/src/mage/cards/p/PullFromEternity.java @@ -26,7 +26,7 @@ public final class PullFromEternity extends CardImpl { private static final FilterCard filter = new FilterCard("face-up exiled card"); static { - filter.add(Predicates.not(new FaceDownPredicate())); + filter.add(Predicates.not(FaceDownPredicate.instance)); } public PullFromEternity(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PullFromTomorrow.java b/Mage.Sets/src/mage/cards/p/PullFromTomorrow.java index 2a2760fdebb..bc190746707 100644 --- a/Mage.Sets/src/mage/cards/p/PullFromTomorrow.java +++ b/Mage.Sets/src/mage/cards/p/PullFromTomorrow.java @@ -20,7 +20,7 @@ public final class PullFromTomorrow extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}{U}"); // Draw X cards, then discard a card. - getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new ManacostVariableValue())); + getSpellAbility().addEffect(new DrawCardSourceControllerEffect(ManacostVariableValue.instance)); Effect effect = new DiscardControllerEffect(1); effect.setText(", then discard a card"); getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/p/PuppetMaster.java b/Mage.Sets/src/mage/cards/p/PuppetMaster.java new file mode 100644 index 00000000000..7b4a6f874bc --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PuppetMaster.java @@ -0,0 +1,95 @@ + +package mage.cards.p; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DiesAttachedTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public final class PuppetMaster extends CardImpl { + + public PuppetMaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}{U}"); + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // When enchanted creature dies, return that card to its owner's hand. If that card is returned to its owner’s hand this way, you may pay {U}{U}{U}. If you do, return Puppet Master to its owner’s hand. + this.addAbility(new DiesAttachedTriggeredAbility(new PuppetMasterEffect(), "enchanted creature")); + } + + public PuppetMaster(final PuppetMaster card) { + super(card); + } + + @Override + public PuppetMaster copy() { + return new PuppetMaster(this); + } +} + +class PuppetMasterEffect extends OneShotEffect { + + public PuppetMasterEffect() { + super(Outcome.ReturnToHand); + staticText = "return that card to its owner's hand. If that card is returned to its owner’s hand this way, you may pay {U}{U}{U}. If you do, return {this} to its owner’s hand"; + } + + public PuppetMasterEffect(final PuppetMasterEffect effect) { + super(effect); + } + + @Override + public PuppetMasterEffect copy() { + return new PuppetMasterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Object object = getValue("attachedTo"); + if (object instanceof Permanent) { + Card card = game.getCard(((Permanent)object).getId()); + if (card != null) { + if (card.moveToZone(Zone.HAND, source.getSourceId(), game, false)) { + Cost cost = new ManaCostsImpl("{U}{U}{U}"); + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + if (controller.chooseUse(Outcome.Neutral, "Pay " + cost.getText() + " to return " + sourcePermanent.getLogName() + " to its owner's hand?", source, game) + && cost.pay(source, game, source.getSourceId(), controller.getId(), false, null)) { + sourcePermanent.moveToZone(Zone.HAND, source.getSourceId(), game, false); + } + } + return true; + } + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/cards/p/PuppeteerClique.java b/Mage.Sets/src/mage/cards/p/PuppeteerClique.java index 774fa5d6a56..6e874521b63 100644 --- a/Mage.Sets/src/mage/cards/p/PuppeteerClique.java +++ b/Mage.Sets/src/mage/cards/p/PuppeteerClique.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -17,12 +16,7 @@ import mage.abilities.keyword.PersistAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.game.permanent.Permanent; @@ -31,15 +25,15 @@ import mage.target.Target; import mage.target.common.TargetCardInOpponentsGraveyard; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class PuppeteerClique extends CardImpl { public PuppeteerClique(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.FAERIE); this.subtype.add(SubType.WIZARD); @@ -59,7 +53,7 @@ public final class PuppeteerClique extends CardImpl { this.addAbility(new PersistAbility()); } - public PuppeteerClique(final PuppeteerClique card) { + private PuppeteerClique(final PuppeteerClique card) { super(card); } @@ -71,12 +65,12 @@ public final class PuppeteerClique extends CardImpl { class PuppeteerCliqueEffect extends OneShotEffect { - public PuppeteerCliqueEffect() { + PuppeteerCliqueEffect() { super(Outcome.PutCreatureInPlay); staticText = "put target creature card from an opponent's graveyard onto the battlefield under your control. It gains haste. At the beginning of your next end step, exile it"; } - public PuppeteerCliqueEffect(final PuppeteerCliqueEffect effect) { + private PuppeteerCliqueEffect(final PuppeteerCliqueEffect effect) { super(effect); } @@ -87,26 +81,25 @@ class PuppeteerCliqueEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - boolean result = false; Card card = game.getCard(getTargetPointer().getFirst(game, source)); - if (card != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { - Permanent permanent = game.getPermanent(card.getId()); - if (permanent != null) { - ContinuousEffect hasteEffect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); - hasteEffect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(hasteEffect, source); - ExileTargetEffect exileEffect = new ExileTargetEffect("exile " + permanent.getLogName()); - exileEffect.setTargetPointer(new FixedTarget(permanent, game)); - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect, TargetController.YOU); - game.addDelayedTriggeredAbility(delayedAbility, source); - result = true; - } - } - } + if (card == null) { + return false; } - return result; + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || !controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { + return false; + } + Permanent permanent = game.getPermanent(card.getId()); + if (permanent == null) { + return false; + } + ContinuousEffect hasteEffect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); + hasteEffect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(hasteEffect, source); + ExileTargetEffect exileEffect = new ExileTargetEffect("exile " + permanent.getLogName()); + exileEffect.setTargetPointer(new FixedTarget(permanent, game)); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect, TargetController.YOU); + game.addDelayedTriggeredAbility(delayedAbility, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PuppetsVerdict.java b/Mage.Sets/src/mage/cards/p/PuppetsVerdict.java index ab3f3183fbb..080d25a75cf 100644 --- a/Mage.Sets/src/mage/cards/p/PuppetsVerdict.java +++ b/Mage.Sets/src/mage/cards/p/PuppetsVerdict.java @@ -54,7 +54,7 @@ class PuppetsVerdictEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { FilterCreaturePermanent filterPower2OrLess = new FilterCreaturePermanent("all creatures power 2 or less"); filterPower2OrLess.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); diff --git a/Mage.Sets/src/mage/cards/p/PureSimple.java b/Mage.Sets/src/mage/cards/p/PureSimple.java index b73bf79b0ce..e14378e1c52 100644 --- a/Mage.Sets/src/mage/cards/p/PureSimple.java +++ b/Mage.Sets/src/mage/cards/p/PureSimple.java @@ -27,7 +27,7 @@ public final class PureSimple extends SplitCard { static { filterDestroy.add(Predicates.or(new SubtypePredicate(SubType.AURA), new SubtypePredicate(SubType.EQUIPMENT))); - filterMulticolor.add(new MulticoloredPredicate()); + filterMulticolor.add(MulticoloredPredicate.instance); } public PureSimple(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PurphorosGodOfTheForge.java b/Mage.Sets/src/mage/cards/p/PurphorosGodOfTheForge.java index ad1bc787fa0..31c7ecc8676 100644 --- a/Mage.Sets/src/mage/cards/p/PurphorosGodOfTheForge.java +++ b/Mage.Sets/src/mage/cards/p/PurphorosGodOfTheForge.java @@ -27,7 +27,7 @@ public final class PurphorosGodOfTheForge extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public PurphorosGodOfTheForge(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/p/PutAway.java b/Mage.Sets/src/mage/cards/p/PutAway.java index b67ccad8ac7..0f4c6da129f 100644 --- a/Mage.Sets/src/mage/cards/p/PutAway.java +++ b/Mage.Sets/src/mage/cards/p/PutAway.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -17,15 +15,15 @@ import mage.players.Player; import mage.target.TargetSpell; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class PutAway extends CardImpl { public PutAway(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); // Counter target spell. You may shuffle up to one target card from your graveyard into your library. @@ -46,7 +44,7 @@ public final class PutAway extends CardImpl { } class PutAwayEffect extends OneShotEffect { - + boolean countered = false; public PutAwayEffect() { @@ -66,15 +64,14 @@ class PutAwayEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Spell spell = game.getStack().getSpell(source.getFirstTarget()); - Card card = game.getCard(source.getTargets().get(1).getFirstTarget()); - Player you = game.getPlayer(source.getControllerId()); - if (spell != null - && game.getStack().counter(spell.getId(), source.getSourceId(), game)) { + if (spell != null && game.getStack().counter(spell.getId(), source.getSourceId(), game)) { countered = true; } - if (you != null) { - if (card != null - && you.chooseUse(Outcome.Benefit, "Do you wish to shuffle up to one target card from your graveyard into your library?", source, game) + + Card card = game.getCard(source.getTargets().get(1).getFirstTarget()); + Player you = game.getPlayer(source.getControllerId()); + if (you != null && card != null) { + if (you.chooseUse(Outcome.Benefit, "Do you wish to shuffle up to one target card from your graveyard into your library?", source, game) && game.getState().getZone(card.getId()).match(Zone.GRAVEYARD)) { card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); you.shuffleLibrary(source, game); diff --git a/Mage.Sets/src/mage/cards/p/PyromancersAssault.java b/Mage.Sets/src/mage/cards/p/PyromancersAssault.java index 8bc1f2d92f0..f51ade62545 100644 --- a/Mage.Sets/src/mage/cards/p/PyromancersAssault.java +++ b/Mage.Sets/src/mage/cards/p/PyromancersAssault.java @@ -63,7 +63,7 @@ class PyromancersAssaultTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(controllerId)) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) { return true; } diff --git a/Mage.Sets/src/mage/cards/p/Pyromancy.java b/Mage.Sets/src/mage/cards/p/Pyromancy.java index b1d4d0a3cfb..4cc770be5a9 100644 --- a/Mage.Sets/src/mage/cards/p/Pyromancy.java +++ b/Mage.Sets/src/mage/cards/p/Pyromancy.java @@ -25,7 +25,7 @@ public final class Pyromancy extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}{R}"); // {3}, Discard a card at random: Pyromancy deals damage to any target equal to the converted mana cost of the discarded card. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new DiscardCostCardConvertedMana()), new ManaCostsImpl("{3}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(DiscardCostCardConvertedMana.instance), new ManaCostsImpl("{3}")); ability.addTarget(new TargetAnyTarget()); ability.addCost(new DiscardCardCost(true)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/q/QuagVampires.java b/Mage.Sets/src/mage/cards/q/QuagVampires.java index 4cd03cf178e..ebea1544997 100644 --- a/Mage.Sets/src/mage/cards/q/QuagVampires.java +++ b/Mage.Sets/src/mage/cards/q/QuagVampires.java @@ -36,7 +36,7 @@ public final class QuagVampires extends CardImpl { // Quag Vampires enters the battlefield with a +1/+1 counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true), + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true), "with a +1/+1 counter on it for each time it was kicked")); } diff --git a/Mage.Sets/src/mage/cards/q/QuarantineField.java b/Mage.Sets/src/mage/cards/q/QuarantineField.java index ee87bc53b4e..591e3c8d549 100644 --- a/Mage.Sets/src/mage/cards/q/QuarantineField.java +++ b/Mage.Sets/src/mage/cards/q/QuarantineField.java @@ -1,7 +1,6 @@ package mage.cards.q; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -21,10 +20,12 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class QuarantineField extends CardImpl { @@ -35,42 +36,43 @@ public final class QuarantineField extends CardImpl { // Quarantine Field enters the battlefield with X isolation counters on it. this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.ISOLATION.createInstance()))); - // When Quarantine Field enters the battlefield, for each isolation counter on it, exile up to one target nonland permanent an opponenet controls until Quarantine Field leaves the battlefield. + // When Quarantine Field enters the battlefield, for each isolation counter on it, exile up to one target nonland permanent an opponent controls until Quarantine Field leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new QuarantineFieldEffect(), false); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); + ability.setTargetAdjuster(QuarantineFieldAdjuster.instance); this.addAbility(ability); - } public QuarantineField(final QuarantineField card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - Permanent sourceObject = game.getPermanent(ability.getSourceId()); - if (sourceObject != null) { - int isolationCounters = sourceObject.getCounters(game).getCount(CounterType.ISOLATION); - FilterNonlandPermanent filter = new FilterNonlandPermanent("up to " + isolationCounters + " nonland permanents controlled by any opponents"); - filter.add(new ControllerPredicate(TargetController.OPPONENT)); - ability.addTarget(new TargetPermanent(0, isolationCounters, filter, false)); - } - - } - } - @Override public QuarantineField copy() { return new QuarantineField(this); } } +enum QuarantineFieldAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Permanent sourceObject = game.getPermanent(ability.getSourceId()); + if (sourceObject != null) { + int isolationCounters = sourceObject.getCounters(game).getCount(CounterType.ISOLATION); + FilterNonlandPermanent filter = new FilterNonlandPermanent("up to " + isolationCounters + " nonland permanents controlled by an opponent"); + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + ability.addTarget(new TargetPermanent(0, isolationCounters, filter, false)); + } + } +} + class QuarantineFieldEffect extends OneShotEffect { public QuarantineFieldEffect() { super(Outcome.Exile); - this.staticText = "for each isolation counter on it, exile up to one target nonland permanent an opponenet controls until {this} leaves the battlefield"; + this.staticText = "for each isolation counter on it, exile up to one target nonland permanent an opponent controls until {this} leaves the battlefield"; } public QuarantineFieldEffect(final QuarantineFieldEffect effect) { diff --git a/Mage.Sets/src/mage/cards/q/Quench.java b/Mage.Sets/src/mage/cards/q/Quench.java new file mode 100644 index 00000000000..e1ca7a659fd --- /dev/null +++ b/Mage.Sets/src/mage/cards/q/Quench.java @@ -0,0 +1,33 @@ +package mage.cards.q; + +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.TargetSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Quench extends CardImpl { + + public Quench(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + // Counter target spell unless its controller pays {2}. + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(2))); + this.getSpellAbility().addTarget(new TargetSpell()); + } + + private Quench(final Quench card) { + super(card); + } + + @Override + public Quench copy() { + return new Quench(this); + } +} diff --git a/Mage.Sets/src/mage/cards/q/Quicken.java b/Mage.Sets/src/mage/cards/q/Quicken.java index e34973989e3..5025cb4e9da 100644 --- a/Mage.Sets/src/mage/cards/q/Quicken.java +++ b/Mage.Sets/src/mage/cards/q/Quicken.java @@ -64,7 +64,7 @@ class QuickenAsThoughEffect extends AsThoughEffectImpl { @Override public void init(Ability source, Game game) { - quickenWatcher = (QuickenWatcher) game.getState().getWatchers().get(QuickenWatcher.class.getSimpleName()); + quickenWatcher = game.getState().getWatcher(QuickenWatcher.class); Card card = game.getCard(source.getSourceId()); if (quickenWatcher != null && card != null) { zoneChangeCounter = card.getZoneChangeCounter(game); @@ -100,7 +100,7 @@ class QuickenWatcher extends Watcher { public List activeQuickenSpells = new ArrayList<>(); public QuickenWatcher() { - super(QuickenWatcher.class.getSimpleName(), WatcherScope.GAME); + super(QuickenWatcher.class, WatcherScope.GAME); } public QuickenWatcher(final QuickenWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/q/Quickling.java b/Mage.Sets/src/mage/cards/q/Quickling.java index abc6ffa7e7b..4f409074ec3 100644 --- a/Mage.Sets/src/mage/cards/q/Quickling.java +++ b/Mage.Sets/src/mage/cards/q/Quickling.java @@ -60,7 +60,7 @@ class QuicklingEffect extends OneShotEffect { private static final String effectText = "sacrifice it unless you return another creature you control to its owner's hand"; static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } QuicklingEffect() { diff --git a/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java b/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java index 418f839664b..5782524f16e 100644 --- a/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java +++ b/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java @@ -1,6 +1,6 @@ - package mage.cards.q; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -12,19 +12,24 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.DependencyType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; - -import java.util.UUID; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.common.TargetLandPermanent; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FixedTarget; /** * @@ -32,42 +37,22 @@ import mage.target.common.TargetLandPermanent; */ public final class QuicksilverFountain extends CardImpl { - public final UUID originalId; - public QuicksilverFountain(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // At the beginning of each player's upkeep, that player puts a flood counter on target non-Island land he or she controls of their choice. That land is an Island for as long as it has a flood counter on it. Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new QuicksilverFountainEffect(), TargetController.ANY, false, true); ability.addTarget(new TargetLandPermanent()); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(QuicksilverFountainAdjuster.instance); this.addAbility(ability); // At the beginning of each end step, if all lands on the battlefield are Islands, remove all flood counters from them. Condition condition = new AllLandsAreSubtypeCondition(SubType.ISLAND); this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new QuicksilverFountainEffect2(), TargetController.ANY, condition, false)); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - ability.getTargets().clear(); - FilterLandPermanent filter = new FilterLandPermanent(); - filter.add(Predicates.not(new SubtypePredicate(SubType.ISLAND))); - filter.add(new ControllerPredicate(TargetController.ACTIVE)); - TargetLandPermanent target = new TargetLandPermanent(1, 1, filter, false); - target.setTargetController(activePlayer.getId()); - ability.getTargets().add(target); - } - } } public QuicksilverFountain(final QuicksilverFountain card) { super(card); - this.originalId = card.originalId; } @Override @@ -76,11 +61,29 @@ public final class QuicksilverFountain extends CardImpl { } } +enum QuicksilverFountainAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer != null) { + ability.getTargets().clear(); + FilterLandPermanent filter = new FilterLandPermanent(); + filter.add(Predicates.not(new SubtypePredicate(SubType.ISLAND))); + filter.add(new ControllerPredicate(TargetController.ACTIVE)); + TargetLandPermanent target = new TargetLandPermanent(1, 1, filter, false); + target.setTargetController(activePlayer.getId()); + ability.getTargets().add(target); + } + } +} + class QuicksilverFountainEffect extends OneShotEffect { public QuicksilverFountainEffect() { super(Outcome.Neutral); - staticText = "that player puts a flood counter on target non-Island land he or she controls of their choice. That land is an Island for as long as it has a flood counter on it"; + staticText = "that player puts a flood counter on target non-Island land they control of their choice. That land is an Island for as long as it has a flood counter on it"; } public QuicksilverFountainEffect(final QuicksilverFountainEffect effect) { diff --git a/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java b/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java index e98d72f8038..5aa3ab80996 100644 --- a/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java +++ b/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java @@ -1,4 +1,3 @@ - package mage.cards.q; import java.util.UUID; @@ -27,16 +26,15 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @author LevelX2 */ public final class QuillmaneBaku extends CardImpl { - private final UUID originalId; - public QuillmaneBaku(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(3); @@ -45,70 +43,70 @@ public final class QuillmaneBaku extends CardImpl { // Whenever you cast a Spirit or Arcane spell, you may put a ki counter on Skullmane Baku. this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.KI.createInstance()), StaticFilters.SPIRIT_OR_ARCANE_CARD, true)); - //TODO: Make ability properly copiable // {1}, Tap, Remove X ki counters from Quillmane Baku: Return target creature with converted mana cost X or less to its owner's hand. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new QuillmaneBakuReturnEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.KI.createInstance(1))); ability.addTarget(new TargetCreaturePermanent()); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(QuillmaneBakuAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - int maxConvManaCost = 0; - for (Cost cost : ability.getCosts()) { - if (cost instanceof RemoveVariableCountersSourceCost) { - maxConvManaCost = ((RemoveVariableCountersSourceCost) cost).getAmount(); - } - } - ability.getTargets().clear(); - FilterCreaturePermanent newFilter = new FilterCreaturePermanent("creature with converted mana cost " + maxConvManaCost + " or less"); - newFilter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, maxConvManaCost + 1)); - TargetCreaturePermanent target = new TargetCreaturePermanent(newFilter); - ability.getTargets().add(target); - } - } - public QuillmaneBaku(final QuillmaneBaku card) { super(card); - this.originalId = card.originalId; } @Override public QuillmaneBaku copy() { return new QuillmaneBaku(this); } +} - static class QuillmaneBakuReturnEffect extends OneShotEffect { +enum QuillmaneBakuAdjuster implements TargetAdjuster { + instance; - public QuillmaneBakuReturnEffect() { - super(Outcome.ReturnToHand); - this.staticText = "Return target creature with converted mana cost X or less to its owner's hand"; - } - - public QuillmaneBakuReturnEffect(final QuillmaneBakuReturnEffect effect) { - super(effect); - } - - @Override - public QuillmaneBakuReturnEffect copy() { - return new QuillmaneBakuReturnEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; + @Override + public void adjustTargets(Ability ability, Game game) { + int maxConvManaCost = 0; + for (Cost cost : ability.getCosts()) { + if (cost instanceof RemoveVariableCountersSourceCost) { + maxConvManaCost = ((RemoveVariableCountersSourceCost) cost).getAmount(); } - Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (permanent != null) { - controller.moveCards(permanent, Zone.HAND, source, game); - } - return true; } + ability.getTargets().clear(); + FilterCreaturePermanent newFilter = new FilterCreaturePermanent("creature with converted mana cost " + maxConvManaCost + " or less"); + newFilter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, maxConvManaCost + 1)); + TargetCreaturePermanent target = new TargetCreaturePermanent(newFilter); + ability.getTargets().add(target); + } +} + +class QuillmaneBakuReturnEffect extends OneShotEffect { + + public QuillmaneBakuReturnEffect() { + super(Outcome.ReturnToHand); + this.staticText = "Return target creature with converted mana cost X or less to its owner's hand"; + } + + public QuillmaneBakuReturnEffect(final QuillmaneBakuReturnEffect effect) { + super(effect); + } + + @Override + public QuillmaneBakuReturnEffect copy() { + return new QuillmaneBakuReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + controller.moveCards(permanent, Zone.HAND, source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/r/RadiantArchangel.java b/Mage.Sets/src/mage/cards/r/RadiantArchangel.java index e75d2d19a8a..263c3f97797 100644 --- a/Mage.Sets/src/mage/cards/r/RadiantArchangel.java +++ b/Mage.Sets/src/mage/cards/r/RadiantArchangel.java @@ -29,7 +29,7 @@ public final class RadiantArchangel extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature with flying on the battlefield"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new AbilityPredicate(FlyingAbility.class)); } diff --git a/Mage.Sets/src/mage/cards/r/RadiantPurge.java b/Mage.Sets/src/mage/cards/r/RadiantPurge.java index 538c50c9ecc..f4a393fd22c 100644 --- a/Mage.Sets/src/mage/cards/r/RadiantPurge.java +++ b/Mage.Sets/src/mage/cards/r/RadiantPurge.java @@ -21,8 +21,8 @@ public final class RadiantPurge extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("multicolored creature or multicolored enchantment"); static { filter.add(Predicates.or( - Predicates.and(new CardTypePredicate(CardType.CREATURE), new MulticoloredPredicate()), - Predicates.and(new CardTypePredicate(CardType.ENCHANTMENT), new MulticoloredPredicate()))); + Predicates.and(new CardTypePredicate(CardType.CREATURE), MulticoloredPredicate.instance), + Predicates.and(new CardTypePredicate(CardType.ENCHANTMENT), MulticoloredPredicate.instance))); } public RadiantPurge(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RaffCapashenShipsMage.java b/Mage.Sets/src/mage/cards/r/RaffCapashenShipsMage.java index 599a30b642c..1a399e4d416 100644 --- a/Mage.Sets/src/mage/cards/r/RaffCapashenShipsMage.java +++ b/Mage.Sets/src/mage/cards/r/RaffCapashenShipsMage.java @@ -26,7 +26,7 @@ public final class RaffCapashenShipsMage extends CardImpl { private static final FilterCard filter = new FilterCard("historic spells"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public RaffCapashenShipsMage(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RageForger.java b/Mage.Sets/src/mage/cards/r/RageForger.java index b840f2e7fe4..fb10108d1d3 100644 --- a/Mage.Sets/src/mage/cards/r/RageForger.java +++ b/Mage.Sets/src/mage/cards/r/RageForger.java @@ -38,7 +38,7 @@ public final class RageForger extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SHAMAN)); filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filterAttack.add(new CounterPredicate(CounterType.P1P1)); } diff --git a/Mage.Sets/src/mage/cards/r/Ragefire.java b/Mage.Sets/src/mage/cards/r/Ragefire.java new file mode 100644 index 00000000000..4dbe92e7040 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Ragefire.java @@ -0,0 +1,32 @@ +package mage.cards.r; + +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Ragefire extends CardImpl { + + public Ragefire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}"); + + // Ragefire deals 3 damage to target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(3)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private Ragefire(final Ragefire card) { + super(card); + } + + @Override + public Ragefire copy() { + return new Ragefire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RagingSwordtooth.java b/Mage.Sets/src/mage/cards/r/RagingSwordtooth.java index 4b5253d56a0..5856a612a88 100644 --- a/Mage.Sets/src/mage/cards/r/RagingSwordtooth.java +++ b/Mage.Sets/src/mage/cards/r/RagingSwordtooth.java @@ -22,7 +22,7 @@ public final class RagingSwordtooth extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RagingSwordtooth(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RagsRiches.java b/Mage.Sets/src/mage/cards/r/RagsRiches.java index 29033770e5f..d8004b70a7c 100644 --- a/Mage.Sets/src/mage/cards/r/RagsRiches.java +++ b/Mage.Sets/src/mage/cards/r/RagsRiches.java @@ -32,7 +32,7 @@ public final class RagsRiches extends SplitCard { // to // Riches // Each opponent chooses a creature he or she controls. You gain control of each of those creatures. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addEffect(new RichesEffect()); } diff --git a/Mage.Sets/src/mage/cards/r/RaidingParty.java b/Mage.Sets/src/mage/cards/r/RaidingParty.java index 4ea934955a3..9449c53670c 100644 --- a/Mage.Sets/src/mage/cards/r/RaidingParty.java +++ b/Mage.Sets/src/mage/cards/r/RaidingParty.java @@ -73,7 +73,7 @@ class RaidingPartyEffect extends OneShotEffect { private static final FilterPermanent filter2 = new FilterPermanent("Plains"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new ColorPredicate(ObjectColor.WHITE)); filter2.add(new SubtypePredicate(SubType.PLAINS)); } diff --git a/Mage.Sets/src/mage/cards/r/RakdosAugermage.java b/Mage.Sets/src/mage/cards/r/RakdosAugermage.java index 422d4c32918..3fa747f9f58 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosAugermage.java +++ b/Mage.Sets/src/mage/cards/r/RakdosAugermage.java @@ -5,8 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.RevealHandSourceControllerEffect; -import mage.abilities.effects.common.RevealHandTargetEffect; import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.*; @@ -23,14 +21,13 @@ import mage.target.common.TargetOpponent; import java.util.UUID; /** - * * @author noahg */ public final class RakdosAugermage extends CardImpl { public RakdosAugermage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{R}"); - + this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(3); @@ -71,16 +68,16 @@ class RakdosAugermageEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - Card sourceCard = game.getCard(source.getSourceId()); if (player != null && controller != null) { Cards revealedCards = new CardsImpl(); revealedCards.addAll(controller.getHand()); - player.revealCards((sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ") (" : "Discard (")+controller.getName()+")", revealedCards, game); + Card sourceCard = game.getCard(source.getSourceId()); + player.revealCards((sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ") (" : "Discard (") + controller.getName() + ")", revealedCards, game); TargetCard target = new TargetCard(Zone.HAND, new FilterCard()); if (player.choose(Outcome.Benefit, revealedCards, target, game)) { Card card = revealedCards.get(target.getFirstTarget(), game); if (card != null) { - return player.discard(card, source, game); + return player.discard(card, source, game); } } } diff --git a/Mage.Sets/src/mage/cards/r/RakdosLocket.java b/Mage.Sets/src/mage/cards/r/RakdosLocket.java new file mode 100644 index 00000000000..1af6807bde1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RakdosLocket.java @@ -0,0 +1,46 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class RakdosLocket extends CardImpl { + + public RakdosLocket(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {T}: Add {B} or {R}. + this.addAbility(new BlackManaAbility()); + this.addAbility(new RedManaAbility()); + + // {B/R}{B/R}{B/R}{B/R}, {T}, Sacrifice Rakdos Locket: Draw two cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), new ManaCostsImpl<>("{B/R}{B/R}{B/R}{B/R}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public RakdosLocket(final RakdosLocket card) { + super(card); + } + + @Override + public RakdosLocket copy() { + return new RakdosLocket(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java b/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java index 31d5b44e3d4..7ada8448d2b 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java +++ b/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java @@ -105,7 +105,7 @@ class RakdosLordOfRiotsCostReductionEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - Ability spellAbility = (SpellAbility) abilityToModify; + Ability spellAbility = abilityToModify; if (spellAbility != null) { OpponentsLostLifeCount dynamicValue = new OpponentsLostLifeCount(); int amount = dynamicValue.calculate(game, source, this); diff --git a/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java b/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java new file mode 100644 index 00000000000..301aed4e1dd --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java @@ -0,0 +1,79 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RakdosRoustabout extends CardImpl { + + public RakdosRoustabout(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever Rakdos Roustabout becomes blocked, it deals 1 damage to the player or planeswalker its attacking. + this.addAbility(new RakdosRoustaboutAbility()); + } + + private RakdosRoustabout(final RakdosRoustabout card) { + super(card); + } + + @Override + public RakdosRoustabout copy() { + return new RakdosRoustabout(this); + } +} + +class RakdosRoustaboutAbility extends TriggeredAbilityImpl { + + RakdosRoustaboutAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(1)); + } + + private RakdosRoustaboutAbility(final RakdosRoustaboutAbility ability) { + super(ability); + } + + @Override + public RakdosRoustaboutAbility copy() { + return new RakdosRoustaboutAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CREATURE_BLOCKED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (sourceId.equals(event.getTargetId())) { + this.getEffects().get(0).setTargetPointer( + new FixedTarget(game.getCombat().getDefenderId(event.getTargetId()), game) + ); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} becomes blocked, it deals 1 damage to the player or planeswalker it’s attacking"; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RakdosTheShowstopper.java b/Mage.Sets/src/mage/cards/r/RakdosTheShowstopper.java new file mode 100644 index 00000000000..be9118e141c --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RakdosTheShowstopper.java @@ -0,0 +1,89 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RakdosTheShowstopper extends CardImpl { + + public RakdosTheShowstopper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DEMON); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Rakdos, the Showstopper enters the battlefield, flip a coin for each creature that isn't a Demon, Devil, or Imp. Destroy each creature whose coin comes up tails. + this.addAbility(new EntersBattlefieldTriggeredAbility(new RakdosTheShowstopperEffect(), false)); + } + + private RakdosTheShowstopper(final RakdosTheShowstopper card) { + super(card); + } + + @Override + public RakdosTheShowstopper copy() { + return new RakdosTheShowstopper(this); + } +} + +class RakdosTheShowstopperEffect extends OneShotEffect { + + RakdosTheShowstopperEffect() { + super(Outcome.Benefit); + staticText = "flip a coin for each creature that isn't a Demon, Devil, or Imp." + + " Destroy each creature whose coin comes up tails."; + } + + private RakdosTheShowstopperEffect(final RakdosTheShowstopperEffect effect) { + super(effect); + } + + @Override + public RakdosTheShowstopperEffect copy() { + return new RakdosTheShowstopperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { + if (permanent != null + && permanent.isCreature() + && !permanent.hasSubtype(SubType.DEMON, game) + && !permanent.hasSubtype(SubType.DEVIL, game) + && !permanent.hasSubtype(SubType.IMP, game) + && !player.flipCoin(source, game, false)) { + permanent.destroy(source.getSourceId(), game, false); + } + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RakdosTrumpeter.java b/Mage.Sets/src/mage/cards/r/RakdosTrumpeter.java new file mode 100644 index 00000000000..a72d29d3255 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RakdosTrumpeter.java @@ -0,0 +1,46 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RakdosTrumpeter extends CardImpl { + + public RakdosTrumpeter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Menace + this.addAbility(new MenaceAbility()); + + // {3}{R}: Rakdos Trumpeter gets +2/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(2, 0, Duration.EndOfTurn), new ManaCostsImpl("{3}{R}") + )); + } + + private RakdosTrumpeter(final RakdosTrumpeter card) { + super(card); + } + + @Override + public RakdosTrumpeter copy() { + return new RakdosTrumpeter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RakdossReturn.java b/Mage.Sets/src/mage/cards/r/RakdossReturn.java index 5d9276caf36..a24d77837ed 100644 --- a/Mage.Sets/src/mage/cards/r/RakdossReturn.java +++ b/Mage.Sets/src/mage/cards/r/RakdossReturn.java @@ -28,7 +28,7 @@ public final class RakdossReturn extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{R}"); // Rakdos's Return deals X damage to target opponent or planeswalker. That player or that planeswalker’s controller discards X cards. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addEffect(new RakdossReturnEffect()); this.getSpellAbility().addTarget(new TargetOpponentOrPlaneswalker()); } @@ -65,7 +65,7 @@ class RakdossReturnEffect extends OneShotEffect { if (player == null) { return false; } - Effect effect = new DiscardTargetEffect(new ManacostVariableValue()); + Effect effect = new DiscardTargetEffect(ManacostVariableValue.instance); effect.setTargetPointer(new FixedTarget(player.getId(), game)); return effect.apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/r/RakkaMar.java b/Mage.Sets/src/mage/cards/r/RakkaMar.java index 4e6f41225a8..30db7aafabc 100644 --- a/Mage.Sets/src/mage/cards/r/RakkaMar.java +++ b/Mage.Sets/src/mage/cards/r/RakkaMar.java @@ -1,7 +1,6 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -17,14 +16,13 @@ import mage.constants.SuperType; import mage.constants.Zone; import mage.game.permanent.token.RakkaMarElementalToken; +import java.util.UUID; + /** - * * @author Loki */ public final class RakkaMar extends CardImpl { - private RakkaMarElementalToken token = new RakkaMarElementalToken(); - public RakkaMar(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); addSuperType(SuperType.LEGENDARY); @@ -34,7 +32,12 @@ public final class RakkaMar extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); this.addAbility(HasteAbility.getInstance()); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(token), new ManaCostsImpl("{R}")); + + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new CreateTokenEffect(new RakkaMarElementalToken()), + new ManaCostsImpl("{R}") + ); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RalZarek.java b/Mage.Sets/src/mage/cards/r/RalZarek.java index 2dfe8cf9b6d..23073717b20 100644 --- a/Mage.Sets/src/mage/cards/r/RalZarek.java +++ b/Mage.Sets/src/mage/cards/r/RalZarek.java @@ -99,7 +99,7 @@ class RalZarekExtraTurnsEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { for (int i = 0; i < 5; i++) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, false)) { game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), false)); } } diff --git a/Mage.Sets/src/mage/cards/r/RallyToBattle.java b/Mage.Sets/src/mage/cards/r/RallyToBattle.java new file mode 100644 index 00000000000..6fce2ef6735 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RallyToBattle.java @@ -0,0 +1,39 @@ +package mage.cards.r; + +import mage.abilities.effects.common.UntapAllControllerEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RallyToBattle extends CardImpl { + + public RallyToBattle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}"); + + + // Creatures you control get +1/+3 until end of turn. Untap them. + this.getSpellAbility().addEffect( + new BoostControlledEffect(1, 3, Duration.EndOfTurn) + ); + this.getSpellAbility().addEffect(new UntapAllControllerEffect( + StaticFilters.FILTER_PERMANENT_CREATURE + ).setText("Untap them")); + } + + private RallyToBattle(final RallyToBattle card) { + super(card); + } + + @Override + public RallyToBattle copy() { + return new RallyToBattle(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RalsStaticaster.java b/Mage.Sets/src/mage/cards/r/RalsStaticaster.java index d5b83f25404..87de152208a 100644 --- a/Mage.Sets/src/mage/cards/r/RalsStaticaster.java +++ b/Mage.Sets/src/mage/cards/r/RalsStaticaster.java @@ -48,7 +48,7 @@ public final class RalsStaticaster extends CardImpl { // Whenever Ral's Staticaster attacks, if you control a Ral planeswalker, Ral's Staticaster gets +1/+0 for each card in your hand until end of turn. this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new BoostSourceEffect( - new CardsInControllerHandCount(), new StaticValue(0), + CardsInControllerHandCount.instance, new StaticValue(0), Duration.EndOfTurn, true), false), new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks, if you control a Ral planeswalker, " diff --git a/Mage.Sets/src/mage/cards/r/RamosianRally.java b/Mage.Sets/src/mage/cards/r/RamosianRally.java index ccd2a9213da..6f9b2d78da2 100644 --- a/Mage.Sets/src/mage/cards/r/RamosianRally.java +++ b/Mage.Sets/src/mage/cards/r/RamosianRally.java @@ -29,7 +29,7 @@ public final class RamosianRally extends CardImpl { static { plainsFilter.add(new SubtypePredicate(SubType.PLAINS)); - creatureFilter.add(Predicates.not(new TappedPredicate())); + creatureFilter.add(Predicates.not(TappedPredicate.instance)); } public RamosianRally(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RampageOfTheClans.java b/Mage.Sets/src/mage/cards/r/RampageOfTheClans.java new file mode 100644 index 00000000000..887a1786e20 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RampageOfTheClans.java @@ -0,0 +1,77 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.CentaurToken; +import mage.game.permanent.token.Token; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RampageOfTheClans extends CardImpl { + + public RampageOfTheClans(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}"); + + // Destroy all artifacts and enchantments. For each permanent destroyed this way, its controller creates a 3/3 green Centaur creature token. + this.getSpellAbility().addEffect(new RampageOfTheClansEffect()); + } + + private RampageOfTheClans(final RampageOfTheClans card) { + super(card); + } + + @Override + public RampageOfTheClans copy() { + return new RampageOfTheClans(this); + } +} + +class RampageOfTheClansEffect extends OneShotEffect { + + RampageOfTheClansEffect() { + super(Outcome.Benefit); + staticText = "Destroy all artifacts and enchantments. " + + "For each permanent destroyed this way, " + + "its controller creates a 3/3 green Centaur creature token."; + } + + private RampageOfTheClansEffect(final RampageOfTheClansEffect effect) { + super(effect); + } + + @Override + public RampageOfTheClansEffect copy() { + return new RampageOfTheClansEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Map playersWithPermanents = new HashMap<>(); + for (Permanent p : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT, + source.getControllerId(), source.getSourceId(), game + )) { + UUID controllerId = p.getControllerId(); + if (p.destroy(source.getSourceId(), game, false)) { + playersWithPermanents.put(controllerId, playersWithPermanents.getOrDefault(controllerId, 0) + 1); + } + } + Token token = new CentaurToken(); + for (UUID playerId : playersWithPermanents.keySet()) { + token.putOntoBattlefield(playersWithPermanents.get(playerId), game, source.getSourceId(), playerId); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RampagingFerocidon.java b/Mage.Sets/src/mage/cards/r/RampagingFerocidon.java index f0403fa0109..939e7eea412 100644 --- a/Mage.Sets/src/mage/cards/r/RampagingFerocidon.java +++ b/Mage.Sets/src/mage/cards/r/RampagingFerocidon.java @@ -34,7 +34,7 @@ public final class RampagingFerocidon extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RampagingFerocidon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RampagingRendhorn.java b/Mage.Sets/src/mage/cards/r/RampagingRendhorn.java new file mode 100644 index 00000000000..eac81672fd0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RampagingRendhorn.java @@ -0,0 +1,36 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RampagingRendhorn extends CardImpl { + + public RampagingRendhorn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Riot + this.addAbility(new RiotAbility()); + } + + private RampagingRendhorn(final RampagingRendhorn card) { + super(card); + } + + @Override + public RampagingRendhorn copy() { + return new RampagingRendhorn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/Ramroller.java b/Mage.Sets/src/mage/cards/r/Ramroller.java index f2574f04848..297bd6a6150 100644 --- a/Mage.Sets/src/mage/cards/r/Ramroller.java +++ b/Mage.Sets/src/mage/cards/r/Ramroller.java @@ -27,7 +27,7 @@ public final class Ramroller extends CardImpl { private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Ramroller(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RamsesOverdark.java b/Mage.Sets/src/mage/cards/r/RamsesOverdark.java index 2ed9c824f45..43475b29cb7 100644 --- a/Mage.Sets/src/mage/cards/r/RamsesOverdark.java +++ b/Mage.Sets/src/mage/cards/r/RamsesOverdark.java @@ -26,7 +26,7 @@ public final class RamsesOverdark extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("enchanted creature"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); } public RamsesOverdark(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RapidFire.java b/Mage.Sets/src/mage/cards/r/RapidFire.java new file mode 100644 index 00000000000..a57b9181edb --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RapidFire.java @@ -0,0 +1,82 @@ + +package mage.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.RampageAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public final class RapidFire extends CardImpl { + + public RapidFire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}"); + + // Cast this spell only before blockers are declared. + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeBlockersAreDeclaredCondition.instance, "Cast this spell only before blockers are declared")); + + // Target creature gains first strike until end of turn. If it doesn’t have rampage, that creature gains rampage 2 until end of turn. + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new RapidFireEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + } + + public RapidFire(final RapidFire card) { + super(card); + } + + @Override + public RapidFire copy() { + return new RapidFire(this); + } + +} + +class RapidFireEffect extends OneShotEffect { + + public RapidFireEffect() { + super(Outcome.AddAbility); + this.staticText = "If it doesn’t have rampage, that creature gains rampage 2 until end of turn"; + } + + public RapidFireEffect(final RapidFireEffect effect) { + super(effect); + } + + @Override + public RapidFireEffect copy() { + return new RapidFireEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + if (!permanent.getAbilities().containsClass(RampageAbility.class)) { + ContinuousEffect effect = new GainAbilityTargetEffect(new RampageAbility(2), Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RashidaScalebane.java b/Mage.Sets/src/mage/cards/r/RashidaScalebane.java index 8e2de6b48a1..af3c5daf3d0 100644 --- a/Mage.Sets/src/mage/cards/r/RashidaScalebane.java +++ b/Mage.Sets/src/mage/cards/r/RashidaScalebane.java @@ -32,7 +32,7 @@ public final class RashidaScalebane extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking or blocking Dragon"); static { - filter.add(Predicates.or(new AttackingPredicate(), new BlockingPredicate())); + filter.add(Predicates.or(AttackingPredicate.instance, BlockingPredicate.instance)); filter.add(new SubtypePredicate(SubType.DRAGON)); } @@ -46,7 +46,7 @@ public final class RashidaScalebane extends CardImpl { // {tap}: Destroy target attacking or blocking Dragon. It can't be regenerated. You gain life equal to its power. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(true), new TapSourceCost()); - Effect effect = new GainLifeEffect(new TargetPermanentPowerCount()); + Effect effect = new GainLifeEffect(TargetPermanentPowerCount.instance); effect.setText("You gain life equal to its power"); ability.addEffect(effect); ability.addTarget(new TargetCreaturePermanent(filter)); diff --git a/Mage.Sets/src/mage/cards/r/RashmiEternitiesCrafter.java b/Mage.Sets/src/mage/cards/r/RashmiEternitiesCrafter.java index d55cf3b4579..6a09ed49408 100644 --- a/Mage.Sets/src/mage/cards/r/RashmiEternitiesCrafter.java +++ b/Mage.Sets/src/mage/cards/r/RashmiEternitiesCrafter.java @@ -70,7 +70,7 @@ class RashmiEternitiesCrafterTriggeredAbility extends SpellCastControllerTrigger @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(event.getPlayerId()); if (spells != null && spells.size() == 1) { diff --git a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java index 36a1b7cc433..bfc57f62a75 100644 --- a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java +++ b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java @@ -80,7 +80,7 @@ enum RasputinDreamweaverStartedUntappedCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - RasputinDreamweaverStartedUntappedWatcher watcher = (RasputinDreamweaverStartedUntappedWatcher) game.getState().getWatchers().get(RasputinDreamweaverStartedUntappedWatcher.class.getSimpleName()); + RasputinDreamweaverStartedUntappedWatcher watcher = game.getState().getWatcher(RasputinDreamweaverStartedUntappedWatcher.class); if (watcher != null) { return watcher.startedUntapped(source.getSourceId()); } @@ -98,13 +98,13 @@ class RasputinDreamweaverStartedUntappedWatcher extends Watcher { private static final FilterPermanent filter = new FilterPermanent("Untapped permanents"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } private final Set startedUntapped = new HashSet<>(0); RasputinDreamweaverStartedUntappedWatcher() { - super(RasputinDreamweaverStartedUntappedWatcher.class.getSimpleName(), WatcherScope.GAME); + super(RasputinDreamweaverStartedUntappedWatcher.class, WatcherScope.GAME); } RasputinDreamweaverStartedUntappedWatcher(final RasputinDreamweaverStartedUntappedWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/r/RatColony.java b/Mage.Sets/src/mage/cards/r/RatColony.java index fefee4c8146..86b6a1d5c24 100644 --- a/Mage.Sets/src/mage/cards/r/RatColony.java +++ b/Mage.Sets/src/mage/cards/r/RatColony.java @@ -28,7 +28,7 @@ public final class RatColony extends CardImpl { static { filter.add(new SubtypePredicate(SubType.RAT)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RatColony(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RathiAssassin.java b/Mage.Sets/src/mage/cards/r/RathiAssassin.java index cb3f0770596..07655c77784 100644 --- a/Mage.Sets/src/mage/cards/r/RathiAssassin.java +++ b/Mage.Sets/src/mage/cards/r/RathiAssassin.java @@ -39,7 +39,7 @@ public final class RathiAssassin extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MERCENARY)); filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4)); - destroyFilter.add(new TappedPredicate()); + destroyFilter.add(TappedPredicate.instance); destroyFilter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); } diff --git a/Mage.Sets/src/mage/cards/r/RavagerWurm.java b/Mage.Sets/src/mage/cards/r/RavagerWurm.java new file mode 100644 index 00000000000..f8af6558fc4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RavagerWurm.java @@ -0,0 +1,92 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.FightTargetSourceEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityType; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RavagerWurm extends CardImpl { + + private static final FilterPermanent filter + = new FilterCreaturePermanent("creature you don't control"); + private static final FilterPermanent filter2 + = new FilterPermanent("land with an activated ability that isn't a mana ability"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + filter2.add(RavagerWurmPredicate.instance); + } + + public RavagerWurm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}{G}"); + + this.subtype.add(SubType.WURM); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // Riot + this.addAbility(new RiotAbility()); + + // When Ravager Wurm enters the battlefield, choose up to one — + // • Ravager Wurm fights target creature you don't control. + Ability ability = new EntersBattlefieldTriggeredAbility( + new FightTargetSourceEffect().setText("{this} fights target creature you don't control"), false + ); + ability.addTarget(new TargetPermanent(filter)); + ability.getModes().setMinModes(0); + ability.getModes().setMaxModes(1); + + // • Destroy target land with an activated ability that isn't a mana ability. + Mode mode = new Mode(new DestroyTargetEffect()); + mode.addTarget(new TargetPermanent(filter2)); + ability.addMode(mode); + this.addAbility(ability); + } + + private RavagerWurm(final RavagerWurm card) { + super(card); + } + + @Override + public RavagerWurm copy() { + return new RavagerWurm(this); + } +} + +enum RavagerWurmPredicate implements Predicate { + instance; + + @Override + public boolean apply(Permanent input, Game game) { + if (input == null || !input.isLand()) { + return false; + } + for (Ability ability : input.getAbilities()) { + if (ability.getAbilityType() == AbilityType.ACTIVATED) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RavagingBlaze.java b/Mage.Sets/src/mage/cards/r/RavagingBlaze.java index 6a85da01800..4b8f4e7f45d 100644 --- a/Mage.Sets/src/mage/cards/r/RavagingBlaze.java +++ b/Mage.Sets/src/mage/cards/r/RavagingBlaze.java @@ -22,10 +22,10 @@ public final class RavagingBlaze extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}{R}"); // Ravaging Blaze deals X damage to target creature. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, Ravaging Blaze also deals X damage to that creature's controller. - this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DamageTargetControllerEffect(new ManacostVariableValue()), + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DamageTargetControllerEffect(ManacostVariableValue.instance), SpellMasteryCondition.instance, "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, Ravaging Blaze also deals X damage to that creature's controller.")); } diff --git a/Mage.Sets/src/mage/cards/r/RavenousTrap.java b/Mage.Sets/src/mage/cards/r/RavenousTrap.java index c1f31a0fdaf..6ae2a950f7d 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousTrap.java +++ b/Mage.Sets/src/mage/cards/r/RavenousTrap.java @@ -50,7 +50,7 @@ enum RavenousTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = (CardsPutIntoGraveyardWatcher) game.getState().getWatchers().get(CardsPutIntoGraveyardWatcher.class.getSimpleName()); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { if (watcher.getAmountCardsPutToGraveyard(opponentId) > 2) { diff --git a/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java b/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java index d4384fe277b..e1bc066563b 100644 --- a/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java +++ b/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java @@ -27,7 +27,7 @@ public final class RazorfinAbolisher extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with a counter on it"); static { - filter.add(new CounterAnyPredicate()); + filter.add(CounterAnyPredicate.instance); } public RazorfinAbolisher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/ReachOfShadows.java b/Mage.Sets/src/mage/cards/r/ReachOfShadows.java index 60c5d7b24a8..0f697be957e 100644 --- a/Mage.Sets/src/mage/cards/r/ReachOfShadows.java +++ b/Mage.Sets/src/mage/cards/r/ReachOfShadows.java @@ -20,7 +20,7 @@ public final class ReachOfShadows extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that's one or more colors"); static { - filter.add(Predicates.not(new ColorlessPredicate())); + filter.add(Predicates.not(ColorlessPredicate.instance)); } public ReachOfShadows(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RealmSeekers.java b/Mage.Sets/src/mage/cards/r/RealmSeekers.java index 283fff9287d..5ac43f2142f 100644 --- a/Mage.Sets/src/mage/cards/r/RealmSeekers.java +++ b/Mage.Sets/src/mage/cards/r/RealmSeekers.java @@ -37,7 +37,7 @@ public final class RealmSeekers extends CardImpl { this.addAbility(new EntersBattlefieldAbility( new AddCountersSourceEffect( CounterType.P1P1.createInstance(), - new CardsInAllHandsCount(), + CardsInAllHandsCount.instance, false), "with X +1/+1 counters on it, where X is the total number of cards in all players' hands")); diff --git a/Mage.Sets/src/mage/cards/r/Reanimate.java b/Mage.Sets/src/mage/cards/r/Reanimate.java index 3a70eaa36e0..d91e2ad3e44 100644 --- a/Mage.Sets/src/mage/cards/r/Reanimate.java +++ b/Mage.Sets/src/mage/cards/r/Reanimate.java @@ -25,7 +25,7 @@ public final class Reanimate extends CardImpl { // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - Effect effect = new LoseLifeSourceControllerEffect(new TargetConvertedManaCost()); + Effect effect = new LoseLifeSourceControllerEffect(TargetConvertedManaCost.instance); effect.setText("You lose life equal to its converted mana cost"); getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/r/Reap.java b/Mage.Sets/src/mage/cards/r/Reap.java index 36d4d1baf6a..f3db1b97ecd 100644 --- a/Mage.Sets/src/mage/cards/r/Reap.java +++ b/Mage.Sets/src/mage/cards/r/Reap.java @@ -1,63 +1,40 @@ package mage.cards.r; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.game.Game; import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetOpponent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author L_J */ public final class Reap extends CardImpl { - - private static final FilterPermanent filter = new FilterPermanent("black permanents"); - - static { - filter.add(new ColorPredicate(ObjectColor.BLACK)); - } public Reap(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Return up to X target cards from your graveyard to your hand, where X is the number of black permanents target opponent controls as you cast Reap. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect().setText("Return up to X target cards from your graveyard to your hand, where X is the number of black permanents target opponent controls as you cast Reap.")); this.getSpellAbility().addTarget(new TargetOpponent()); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 0, new FilterCard("cards from your graveyard"))); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 0)); + this.getSpellAbility().setTargetAdjuster(ReapAdjuster.instance); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null) { - ability.getTargets().clear(); - UUID opponentId = null; - Target target = new TargetOpponent(); - if (controller.chooseTarget(Outcome.ReturnToHand, target, ability, game)) { - opponentId = target.getFirstTarget(); - } - int numbTargets = game.getBattlefield().getAllActivePermanents(filter, opponentId, game).size(); - ability.addTarget(new TargetCardInYourGraveyard(0, numbTargets, new FilterCard("card" + (numbTargets == 1 ? "" : "s") + " from your graveyard"))); - } - } - } - - public Reap(final Reap card) { super(card); } @@ -67,3 +44,27 @@ public final class Reap extends CardImpl { return new Reap(this); } } + +enum ReapAdjuster implements TargetAdjuster { + instance; + private static final FilterPermanent filter = new FilterPermanent("black permanents"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller != null) { + ability.getTargets().clear(); + UUID opponentId = null; + Target target = new TargetOpponent(); + if (controller.chooseTarget(Outcome.ReturnToHand, target, ability, game)) { + opponentId = target.getFirstTarget(); + } + int numbTargets = game.getBattlefield().getAllActivePermanents(filter, opponentId, game).size(); + ability.addTarget(new TargetCardInYourGraveyard(0, numbTargets, new FilterCard("card" + (numbTargets == 1 ? "" : "s") + " from your graveyard"))); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java b/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java index c9a9bf3f10d..519ff15bcc1 100644 --- a/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java +++ b/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java @@ -81,8 +81,8 @@ class ReaperFromTheAbyssAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - Watcher watcher = game.getState().getWatchers().get(MorbidWatcher.class.getSimpleName()); - return watcher.conditionMet(); + Watcher watcher = game.getState().getWatcher(MorbidWatcher.class); + return watcher != null && watcher.conditionMet(); } @Override diff --git a/Mage.Sets/src/mage/cards/r/ReaperKing.java b/Mage.Sets/src/mage/cards/r/ReaperKing.java index ee8a6ef8b86..e3d65bef519 100644 --- a/Mage.Sets/src/mage/cards/r/ReaperKing.java +++ b/Mage.Sets/src/mage/cards/r/ReaperKing.java @@ -27,7 +27,7 @@ public final class ReaperKing extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SCARECROW)); - filterTrigger.add(new AnotherPredicate()); + filterTrigger.add(AnotherPredicate.instance); filterTrigger.add(new SubtypePredicate(SubType.SCARECROW)); } diff --git a/Mage.Sets/src/mage/cards/r/ReasonBelieve.java b/Mage.Sets/src/mage/cards/r/ReasonBelieve.java index 0758c54389d..a0d04ccc9e3 100644 --- a/Mage.Sets/src/mage/cards/r/ReasonBelieve.java +++ b/Mage.Sets/src/mage/cards/r/ReasonBelieve.java @@ -32,7 +32,7 @@ public final class ReasonBelieve extends SplitCard { // Believe // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Look at the top card of your library. You may put it onto the battlefield if it's a creature card. If you don't, put it into your hand. getRightHalfCard().getSpellAbility().addEffect(new BelieveEffect()); diff --git a/Mage.Sets/src/mage/cards/r/ReaverDrone.java b/Mage.Sets/src/mage/cards/r/ReaverDrone.java index 0a373538548..441d903afff 100644 --- a/Mage.Sets/src/mage/cards/r/ReaverDrone.java +++ b/Mage.Sets/src/mage/cards/r/ReaverDrone.java @@ -28,8 +28,8 @@ public final class ReaverDrone extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another colorless creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public ReaverDrone(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RebelInformer.java b/Mage.Sets/src/mage/cards/r/RebelInformer.java index d5328fc4a3e..1bfcbcae639 100644 --- a/Mage.Sets/src/mage/cards/r/RebelInformer.java +++ b/Mage.Sets/src/mage/cards/r/RebelInformer.java @@ -36,7 +36,7 @@ public final class RebelInformer extends CardImpl { static { filterWhite.add(new ColorPredicate(ObjectColor.WHITE)); - filterRebel.add(Predicates.not(new TokenPredicate())); + filterRebel.add(Predicates.not(TokenPredicate.instance)); filterRebel.add(new SubtypePredicate(SubType.REBEL)); } diff --git a/Mage.Sets/src/mage/cards/r/RebornHope.java b/Mage.Sets/src/mage/cards/r/RebornHope.java index 0006834a88d..47f878e8858 100644 --- a/Mage.Sets/src/mage/cards/r/RebornHope.java +++ b/Mage.Sets/src/mage/cards/r/RebornHope.java @@ -19,7 +19,7 @@ public final class RebornHope extends CardImpl { private static final FilterCard filter = new FilterCard("multicolored card from your graveyard"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public RebornHope(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/Reciprocate.java b/Mage.Sets/src/mage/cards/r/Reciprocate.java index 90bcb754d0c..4b20b3759c8 100644 --- a/Mage.Sets/src/mage/cards/r/Reciprocate.java +++ b/Mage.Sets/src/mage/cards/r/Reciprocate.java @@ -53,7 +53,7 @@ class ReciprocateTarget extends TargetPermanent { @Override public boolean canTarget(UUID id, Ability source, Game game) { - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), source.getControllerId()); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, source.getControllerId()); if (watcher != null && watcher.hasSourceDoneDamage(id, game)) { return super.canTarget(id, source, game); } @@ -64,7 +64,7 @@ class ReciprocateTarget extends TargetPermanent { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); Set possibleTargets = new HashSet<>(); - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), sourceControllerId); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId); for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); if (permanent != null && watcher != null && watcher.hasSourceDoneDamage(targetId, game)) { @@ -83,7 +83,7 @@ class ReciprocateTarget extends TargetPermanent { int count = 0; MageObject targetSource = game.getObject(sourceId); if(targetSource != null) { - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), sourceControllerId); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java b/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java index 0e83f3b7fcd..d19cf75607c 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java +++ b/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java @@ -27,7 +27,7 @@ public final class RecklessBushwhacker extends CardImpl { private final static FilterControlledCreaturePermanent FILTER = new FilterControlledCreaturePermanent("other creatures you control"); static { - FILTER.add(new AnotherPredicate()); + FILTER.add(AnotherPredicate.instance); } public RecklessBushwhacker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RecklessCohort.java b/Mage.Sets/src/mage/cards/r/RecklessCohort.java index ec4d153313c..4962f5b3ce8 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessCohort.java +++ b/Mage.Sets/src/mage/cards/r/RecklessCohort.java @@ -24,7 +24,7 @@ public final class RecklessCohort extends CardImpl { private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Ally"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.ALLY)); } diff --git a/Mage.Sets/src/mage/cards/r/ReclusiveWight.java b/Mage.Sets/src/mage/cards/r/ReclusiveWight.java index 01995437b14..936f3a340a9 100644 --- a/Mage.Sets/src/mage/cards/r/ReclusiveWight.java +++ b/Mage.Sets/src/mage/cards/r/ReclusiveWight.java @@ -27,7 +27,7 @@ public final class ReclusiveWight extends CardImpl { static { filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ReclusiveWight(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/Reconnaissance.java b/Mage.Sets/src/mage/cards/r/Reconnaissance.java index fbd93e6ceb6..84fe89dcc41 100644 --- a/Mage.Sets/src/mage/cards/r/Reconnaissance.java +++ b/Mage.Sets/src/mage/cards/r/Reconnaissance.java @@ -27,7 +27,7 @@ public final class Reconnaissance extends CardImpl { private static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature controlled by you"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public Reconnaissance(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RedManaBattery.java b/Mage.Sets/src/mage/cards/r/RedManaBattery.java index 461a4664e3e..1281c0d257b 100644 --- a/Mage.Sets/src/mage/cards/r/RedManaBattery.java +++ b/Mage.Sets/src/mage/cards/r/RedManaBattery.java @@ -36,7 +36,7 @@ public final class RedManaBattery extends CardImpl { // {tap}, Remove any number of charge counters from Red Mana Battery: Add {R}, then add an additional {R} for each charge counter removed this way. ability = new DynamicManaAbility( Mana.RedMana(1), - new IntPlusDynamicValue(1, new RemovedCountersForCostValue()), + new IntPlusDynamicValue(1, RemovedCountersForCostValue.instance), new TapSourceCost(), "Add {R}, then add {R} for each charge counter removed this way", true, new CountersSourceCount(CounterType.CHARGE)); diff --git a/Mage.Sets/src/mage/cards/r/RedSunsZenith.java b/Mage.Sets/src/mage/cards/r/RedSunsZenith.java index a95deffc582..9d39917e0ce 100644 --- a/Mage.Sets/src/mage/cards/r/RedSunsZenith.java +++ b/Mage.Sets/src/mage/cards/r/RedSunsZenith.java @@ -26,7 +26,7 @@ public final class RedSunsZenith extends CardImpl { // If a creature dealt damage this way would die this turn, exile it instead. // Shuffle Red Sun's Zenith into its owner's library. this.getSpellAbility().addTarget(new TargetAnyTarget()); - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn)); this.getSpellAbility().addEffect(ShuffleSpellEffect.getInstance()); this.getSpellAbility().addWatcher(new DamagedByWatcher()); diff --git a/Mage.Sets/src/mage/cards/r/ReduceRubble.java b/Mage.Sets/src/mage/cards/r/ReduceRubble.java index 792cfdb894d..7c3cb39665d 100644 --- a/Mage.Sets/src/mage/cards/r/ReduceRubble.java +++ b/Mage.Sets/src/mage/cards/r/ReduceRubble.java @@ -32,7 +32,7 @@ public final class ReduceRubble extends SplitCard { // Rubble // Up to three target lands don't untap during their controller's next untap step. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); Effect effect = new DontUntapInControllersNextUntapStepTargetEffect(); effect.setText("Up to three target lands don't untap during their controller's next untap step"); getRightHalfCard().getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/r/RefractionTrap.java b/Mage.Sets/src/mage/cards/r/RefractionTrap.java index 84d3bc36722..bea2ff1c967 100644 --- a/Mage.Sets/src/mage/cards/r/RefractionTrap.java +++ b/Mage.Sets/src/mage/cards/r/RefractionTrap.java @@ -59,7 +59,7 @@ enum RefractionTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { List spells = watcher.getSpellsCastThisTurn(opponentId); diff --git a/Mage.Sets/src/mage/cards/r/RefuseCooperate.java b/Mage.Sets/src/mage/cards/r/RefuseCooperate.java index 2ee051d9635..431cf7745cf 100644 --- a/Mage.Sets/src/mage/cards/r/RefuseCooperate.java +++ b/Mage.Sets/src/mage/cards/r/RefuseCooperate.java @@ -34,7 +34,7 @@ public final class RefuseCooperate extends SplitCard { // Cooperate // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Copy target instant or sorcery spell. You may choose new targets for the copy. getRightHalfCard().getSpellAbility().addEffect(new CopyTargetSpellEffect()); getRightHalfCard().getSpellAbility().addTarget(new TargetSpell(new FilterInstantOrSorcerySpell())); diff --git a/Mage.Sets/src/mage/cards/r/Regenesis.java b/Mage.Sets/src/mage/cards/r/Regenesis.java new file mode 100644 index 00000000000..9743d9c073c --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Regenesis.java @@ -0,0 +1,36 @@ +package mage.cards.r; + +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.common.FilterPermanentCard; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Regenesis extends CardImpl { + + private static final FilterCard filter = new FilterPermanentCard("permanent cards from your graveyard"); + + public Regenesis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}{G}"); + + // Return up to two target permanent cards from your graveyard to your hand. + this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 2, filter)); + } + + private Regenesis(final Regenesis card) { + super(card); + } + + @Override + public Regenesis copy() { + return new Regenesis(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java b/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java index adcf7f0b302..4ed64236516 100644 --- a/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java +++ b/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java @@ -75,12 +75,12 @@ class RegnaTheRedeemerCondition extends IntCompareCondition { @Override protected int getInputValue(Game game, Ability source) { int gainedLife = 0; - PlayerGainedLifeWatcher watcher = (PlayerGainedLifeWatcher) game.getState().getWatchers().get(PlayerGainedLifeWatcher.class.getSimpleName()); + PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); if (watcher != null) { for (UUID playerId : game.getPlayerList()) { Player player = game.getPlayer(playerId); if (player != null && !player.hasOpponent(source.getControllerId(), game)) { - gainedLife = watcher.getLiveGained(playerId); + gainedLife = watcher.getLifeGained(playerId); if (gainedLife > 0) { break; } diff --git a/Mage.Sets/src/mage/cards/r/RegnasSanction.java b/Mage.Sets/src/mage/cards/r/RegnasSanction.java index 3ea9507512b..776fdaa6c8a 100644 --- a/Mage.Sets/src/mage/cards/r/RegnasSanction.java +++ b/Mage.Sets/src/mage/cards/r/RegnasSanction.java @@ -70,7 +70,7 @@ class RegnasSanctionEffect extends OneShotEffect { FilterCreaturePermanent filterToTap = new FilterCreaturePermanent(); for (Player player : choice.getFoes()) { FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature you control"); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new ControllerIdPredicate(player.getId())); TargetPermanent target = new TargetPermanent(1, 1, filter, true); if (player.choose(Outcome.Benefit, target, source.getSourceId(), game)) { diff --git a/Mage.Sets/src/mage/cards/r/Reincarnation.java b/Mage.Sets/src/mage/cards/r/Reincarnation.java index ecd453ac2b4..a44d5b3b98e 100644 --- a/Mage.Sets/src/mage/cards/r/Reincarnation.java +++ b/Mage.Sets/src/mage/cards/r/Reincarnation.java @@ -143,6 +143,7 @@ class ReincarnationDelayedEffect extends OneShotEffect { FilterCreatureCard filter = new FilterCreatureCard("a creature card from " + player.getName() + "'s graveyard"); filter.add(new OwnerIdPredicate(player.getId())); Target targetCreature = new TargetCardInGraveyard(filter); + targetCreature.setNotTarget(true); if (targetCreature.canChoose(source.getSourceId(), controller.getId(), game) && controller.chooseTarget(outcome, targetCreature, source, game)) { Card card = game.getCard(targetCreature.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/r/ReleaseTheGremlins.java b/Mage.Sets/src/mage/cards/r/ReleaseTheGremlins.java index d0bc76ed940..eee1db14278 100644 --- a/Mage.Sets/src/mage/cards/r/ReleaseTheGremlins.java +++ b/Mage.Sets/src/mage/cards/r/ReleaseTheGremlins.java @@ -1,9 +1,7 @@ package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DestroyTargetEffect; @@ -13,9 +11,11 @@ import mage.constants.CardType; import mage.game.Game; import mage.game.permanent.token.GremlinToken; import mage.target.common.TargetArtifactPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author Styxo */ public final class ReleaseTheGremlins extends CardImpl { @@ -28,17 +28,9 @@ public final class ReleaseTheGremlins extends CardImpl { this.getSpellAbility().addTarget(new TargetArtifactPermanent()); // Create X 2/2 red Gremlin creature tokens. - this.getSpellAbility().addEffect(new CreateTokenEffect(new GremlinToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new GremlinToken(), ManacostVariableValue.instance)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetArtifactPermanent(xValue, xValue)); - } + this.getSpellAbility().setTargetAdjuster(ReleaseTheGremlinsAdjuster.instance); } public ReleaseTheGremlins(final ReleaseTheGremlins card) { @@ -50,3 +42,13 @@ public final class ReleaseTheGremlins extends CardImpl { return new ReleaseTheGremlins(this); } } + +enum ReleaseTheGremlinsAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetArtifactPermanent(ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RelentlessRats.java b/Mage.Sets/src/mage/cards/r/RelentlessRats.java index 8042cfcee19..02cb98cdd44 100644 --- a/Mage.Sets/src/mage/cards/r/RelentlessRats.java +++ b/Mage.Sets/src/mage/cards/r/RelentlessRats.java @@ -71,7 +71,7 @@ public final class RelentlessRats extends CardImpl { public boolean apply(Game game, Ability source) { int count = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) - 1; if (count > 0) { - Permanent target = (Permanent) game.getPermanent(source.getSourceId()); + Permanent target = game.getPermanent(source.getSourceId()); if (target != null) { target.addPower(count); target.addToughness(count); diff --git a/Mage.Sets/src/mage/cards/r/RelicRunner.java b/Mage.Sets/src/mage/cards/r/RelicRunner.java index 23e3aee8ec5..034c428df0b 100644 --- a/Mage.Sets/src/mage/cards/r/RelicRunner.java +++ b/Mage.Sets/src/mage/cards/r/RelicRunner.java @@ -58,7 +58,7 @@ class CastHistoricSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(source.getControllerId()); if (spells != null) { diff --git a/Mage.Sets/src/mage/cards/r/Remembrance.java b/Mage.Sets/src/mage/cards/r/Remembrance.java index 135d49484ce..3ab60a2647f 100644 --- a/Mage.Sets/src/mage/cards/r/Remembrance.java +++ b/Mage.Sets/src/mage/cards/r/Remembrance.java @@ -55,7 +55,7 @@ class RemembranceTriggeredAbility extends TriggeredAbilityImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public RemembranceTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/r/RenderSilent.java b/Mage.Sets/src/mage/cards/r/RenderSilent.java index b7cdf3c89d2..41c441d74b6 100644 --- a/Mage.Sets/src/mage/cards/r/RenderSilent.java +++ b/Mage.Sets/src/mage/cards/r/RenderSilent.java @@ -30,7 +30,7 @@ public final class RenderSilent extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("multicolored permanent"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public RenderSilent(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RenegadeKrasis.java b/Mage.Sets/src/mage/cards/r/RenegadeKrasis.java index 95a9aceeef3..e692bdb62c7 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeKrasis.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeKrasis.java @@ -52,7 +52,7 @@ class RenegadeKrasisTriggeredAbility extends TriggeredAbilityImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new CounterPredicate(CounterType.P1P1)); } diff --git a/Mage.Sets/src/mage/cards/r/RenounceTheGuilds.java b/Mage.Sets/src/mage/cards/r/RenounceTheGuilds.java index e19fdae0ad3..3bd1e884dc8 100644 --- a/Mage.Sets/src/mage/cards/r/RenounceTheGuilds.java +++ b/Mage.Sets/src/mage/cards/r/RenounceTheGuilds.java @@ -20,7 +20,7 @@ public final class RenounceTheGuilds extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("multicolored permanent"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public RenounceTheGuilds(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java b/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java index ed31ed8cc0a..88983794009 100644 --- a/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java +++ b/Mage.Sets/src/mage/cards/r/RenownedWeaponsmith.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.ConditionalMana; import mage.MageInt; import mage.MageObject; @@ -14,14 +12,10 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.mana.ConditionalColorlessManaAbility; import mage.abilities.mana.builder.ConditionalManaBuilder; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; @@ -30,14 +24,15 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class RenownedWeaponsmith extends CardImpl { public RenownedWeaponsmith(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ARTIFICER); this.power = new MageInt(1); @@ -120,11 +115,14 @@ class RenownedWeaponsmithEffect extends OneShotEffect { TargetCardInLibrary target = new TargetCardInLibrary(filter); if (controller.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { - Card card = game.getCard(target.getFirstTarget()); Cards revealed = new CardsImpl(); - revealed.add(card); - controller.revealCards(sourceObject.getIdName(), revealed, game); - controller.moveCards(revealed, Zone.HAND, source, game); + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + revealed.add(card); + controller.revealCards(sourceObject.getIdName(), revealed, game); + controller.moveCards(revealed, Zone.HAND, source, game); + } + } } controller.shuffleLibrary(source, game); diff --git a/Mage.Sets/src/mage/cards/r/Repeal.java b/Mage.Sets/src/mage/cards/r/Repeal.java index b03390c18d9..34851fedcad 100644 --- a/Mage.Sets/src/mage/cards/r/Repeal.java +++ b/Mage.Sets/src/mage/cards/r/Repeal.java @@ -1,9 +1,7 @@ - package mage.cards.r; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; @@ -15,6 +13,7 @@ import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.TargetPermanent; import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -23,29 +22,17 @@ import mage.target.common.TargetNonlandPermanent; public final class Repeal extends CardImpl { public Repeal(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); // Return target nonland permanent with converted mana cost X to its owner's hand. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addTarget(new TargetPermanent(new FilterNonlandPermanent("nonland permanent with converted mana cost X"))); - + this.getSpellAbility().setTargetAdjuster(RepealAdjuster.instance); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent with converted mana cost " + xValue); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - ability.addTarget(new TargetNonlandPermanent(filter)); - } - } - public Repeal(final Repeal card) { super(card); } @@ -55,3 +42,16 @@ public final class Repeal extends CardImpl { return new Repeal(this); } } + +enum RepealAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent with converted mana cost " + xValue); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetNonlandPermanent(filter)); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RepudiateReplicate.java b/Mage.Sets/src/mage/cards/r/RepudiateReplicate.java new file mode 100644 index 00000000000..b8257fe6332 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RepudiateReplicate.java @@ -0,0 +1,41 @@ +package mage.cards.r; + +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.SpellAbilityType; +import mage.target.common.TargetActivatedOrTriggeredAbility; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RepudiateReplicate extends SplitCard { + + public RepudiateReplicate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{G/U}{G/U}", "{1}{G}{U}", SpellAbilityType.SPLIT); + + // Repudiate + // Counter target activated ability or triggered ability. + this.getLeftHalfCard().getSpellAbility().addEffect(new CounterTargetEffect()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetActivatedOrTriggeredAbility()); + + // Replicate + // Create a token that’s a copy of target creature you control. + this.getRightHalfCard().getSpellAbility().addEffect(new CreateTokenCopyTargetEffect()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + private RepudiateReplicate(final RepudiateReplicate card) { + super(card); + } + + @Override + public RepudiateReplicate copy() { + return new RepudiateReplicate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RequiemAngel.java b/Mage.Sets/src/mage/cards/r/RequiemAngel.java index 7e7efb10e2c..178164eab77 100644 --- a/Mage.Sets/src/mage/cards/r/RequiemAngel.java +++ b/Mage.Sets/src/mage/cards/r/RequiemAngel.java @@ -27,7 +27,7 @@ public final class RequiemAngel extends CardImpl { static { filter.add(Predicates.not(new SubtypePredicate(SubType.SPIRIT))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java b/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java index 4c975ab58c8..1a8f126c8dc 100644 --- a/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java +++ b/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java @@ -122,7 +122,7 @@ class RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect extends OneShot @Override public boolean apply(Game game, Ability source) { - DelayedTriggeredAbility delayedAbility = (DelayedTriggeredAbility) ability.copy(); + DelayedTriggeredAbility delayedAbility = ability.copy(); delayedAbility.getTargets().addAll(source.getTargets()); for (Effect effect : delayedAbility.getEffects()) { effect.getTargetPointer().init(game, source); diff --git a/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java b/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java new file mode 100644 index 00000000000..80f127f7006 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java @@ -0,0 +1,55 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ResoluteWatchdog extends CardImpl { + + public ResoluteWatchdog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.HOUND); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // {1}, Sacrifice Resolute Watchdog: Target creature you control gains indestructible until end of turn. + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect( + IndestructibleAbility.getInstance(), + Duration.EndOfTurn + ), new GenericManaCost(1) + ); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + private ResoluteWatchdog(final ResoluteWatchdog card) { + super(card); + } + + @Override + public ResoluteWatchdog copy() { + return new ResoluteWatchdog(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RestlessDreams.java b/Mage.Sets/src/mage/cards/r/RestlessDreams.java index 9bc906e22a3..d20f30be5e0 100644 --- a/Mage.Sets/src/mage/cards/r/RestlessDreams.java +++ b/Mage.Sets/src/mage/cards/r/RestlessDreams.java @@ -1,23 +1,21 @@ package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.common.DiscardXTargetCost; -import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.game.Game; -import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class RestlessDreams extends CardImpl { @@ -26,7 +24,7 @@ public final class RestlessDreams extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); // As an additional cost to cast Restless Dreams, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); + this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true)); // Return X target creature cards from your graveyard to your hand. Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return X target creature cards from your graveyard to your hand"); @@ -37,15 +35,21 @@ public final class RestlessDreams extends CardImpl { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - int xValue = new GetXValue().calculate(game, ability, null); - Target target = new TargetCardInYourGraveyard(xValue, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD); - ability.addTarget(target); - } - @Override public RestlessDreams copy() { return new RestlessDreams(this); } } + +enum RestlessDreamsAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard( + ability.getManaCostsToPay().getX(), + StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD + )); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RestoreThePeace.java b/Mage.Sets/src/mage/cards/r/RestoreThePeace.java index 48d3e16fb26..ff0bd8cc49d 100644 --- a/Mage.Sets/src/mage/cards/r/RestoreThePeace.java +++ b/Mage.Sets/src/mage/cards/r/RestoreThePeace.java @@ -56,7 +56,7 @@ class RestoreThePeaceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - SourceDidDamageWatcher watcher = (SourceDidDamageWatcher) game.getState().getWatchers().get(SourceDidDamageWatcher.class.getSimpleName()); + SourceDidDamageWatcher watcher = game.getState().getWatcher(SourceDidDamageWatcher.class); if (watcher != null) { for (UUID permId : watcher.damageSources) { Permanent perm = game.getPermanent(permId); diff --git a/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java b/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java index ce921ada409..42aab39e6f4 100644 --- a/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java +++ b/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java @@ -36,7 +36,7 @@ public final class RetributionOfTheAncients extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}"); - DynamicValue xValue = new SignInversionDynamicValue(new GetXValue()); + DynamicValue xValue = new SignInversionDynamicValue(GetXValue.instance); // {B}, Remove X +1/+1 counters from among creatures you control: Target creature gets -X/-X until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(xValue,xValue,Duration.EndOfTurn, true), new ManaCostsImpl("{B}")); ability.addCost(new RemoveVariableCountersTargetCost(filter, CounterType.P1P1, "X", 0)); diff --git a/Mage.Sets/src/mage/cards/r/ReturnToDust.java b/Mage.Sets/src/mage/cards/r/ReturnToDust.java index c57d35ac043..2e25ab591f6 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnToDust.java +++ b/Mage.Sets/src/mage/cards/r/ReturnToDust.java @@ -2,52 +2,87 @@ package mage.cards.r; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author emerald000 */ public final class ReturnToDust extends CardImpl { public ReturnToDust(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}{W}"); // Exile target artifact or enchantment. If you cast this spell during your main phase, you may exile up to one other target artifact or enchantment. - Effect effect = new ExileTargetEffect(); - effect.setText("Exile target artifact or enchantment. If you cast this spell during your main phase, you may exile up to one other target artifact or enchantment"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new ReturnToDustEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(1, 2, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT, false)); } public ReturnToDust(final ReturnToDust card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - if (game.isActivePlayer(ability.getControllerId()) && game.isMainPhase()) { - ability.addTarget(new TargetPermanent(1, 2, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT, false)); - } - else { - ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); - } - } - } - @Override public ReturnToDust copy() { return new ReturnToDust(this); } } + +class ReturnToDustEffect extends OneShotEffect { + + ReturnToDustEffect() { + super(Outcome.DestroyPermanent); + staticText = "Exile target artifact or enchantment. If you cast this spell during your main phase, you may exile up to one other target artifact or enchantment"; + } + + private ReturnToDustEffect(final ReturnToDustEffect effect) { + super(effect); + } + + @Override + public Effect copy() { + return new ReturnToDustEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + int targetsCleared = 0; + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent == null) { + continue; + } + if (targetsCleared == 0) { + player.moveCards(permanent, Zone.EXILED, source, game); + targetsCleared++; + } else if (targetsCleared == 1) { + if (game.isActivePlayer(source.getControllerId()) && game.isMainPhase() + && player.chooseUse(outcome, "Exile another permanent?", source, game)) { + player.moveCards(permanent, Zone.EXILED, source, game); + targetsCleared++; + } else { + break; + } + } else { + break; + } + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/ReturnToTheRanks.java b/Mage.Sets/src/mage/cards/r/ReturnToTheRanks.java index c0b4ec5645f..326369bf415 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnToTheRanks.java +++ b/Mage.Sets/src/mage/cards/r/ReturnToTheRanks.java @@ -1,7 +1,6 @@ package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; @@ -14,41 +13,26 @@ import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ReturnToTheRanks extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards with converted mana cost 2 or less from your graveyard"); - - static { - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3)); - } - public ReturnToTheRanks(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{W}{W}"); // Convoke this.addAbility(new ConvokeAbility()); + // Return X target creature cards with converted mana cost 2 or less from your graveyard to the battlefield. Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); effect.setText("Return X target creature cards with converted mana cost 2 or less from your graveyard to the battlefield"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0,Integer.MAX_VALUE, filter)); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - for (Effect effect : ability.getEffects()) { - if (effect instanceof ReturnFromGraveyardToBattlefieldTargetEffect) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInYourGraveyard(xValue,xValue, filter)); - } - } + this.getSpellAbility().setTargetAdjuster(ReturnToTheRanksAdjuster.instance); } public ReturnToTheRanks(final ReturnToTheRanks card) { @@ -60,3 +44,19 @@ public final class ReturnToTheRanks extends CardImpl { return new ReturnToTheRanks(this); } } + +enum ReturnToTheRanksAdjuster implements TargetAdjuster { + instance; + private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards with converted mana cost 2 or less from your graveyard"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3)); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard(xValue, xValue, filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RevealingWind.java b/Mage.Sets/src/mage/cards/r/RevealingWind.java index a097878a84d..053ddac0b13 100644 --- a/Mage.Sets/src/mage/cards/r/RevealingWind.java +++ b/Mage.Sets/src/mage/cards/r/RevealingWind.java @@ -51,7 +51,7 @@ class RevealingWindEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterAttackingOrBlockingCreature("face-down creature that's attacking or blocking"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public RevealingWindEffect() { diff --git a/Mage.Sets/src/mage/cards/r/Revenge.java b/Mage.Sets/src/mage/cards/r/Revenge.java index 2674b8c0fd6..f7a7274d4dd 100644 --- a/Mage.Sets/src/mage/cards/r/Revenge.java +++ b/Mage.Sets/src/mage/cards/r/Revenge.java @@ -62,10 +62,10 @@ enum LostLifeCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); UUID player = source.getControllerId(); if (watcher != null && player != null) { - return watcher.getLiveLost(player) > 0; + return watcher.getLifeLost(player) > 0; } return false; } diff --git a/Mage.Sets/src/mage/cards/r/ReversalOfFortune.java b/Mage.Sets/src/mage/cards/r/ReversalOfFortune.java index d68cf096483..80f2f9310c0 100644 --- a/Mage.Sets/src/mage/cards/r/ReversalOfFortune.java +++ b/Mage.Sets/src/mage/cards/r/ReversalOfFortune.java @@ -74,7 +74,7 @@ class ReversalOfFortuneEffect extends OneShotEffect { TargetCard target = new TargetCard(1, Zone.HAND, new FilterInstantOrSorceryCard()); target.setRequired(false); if (controller.choose(outcome, revealedCards, target, game)) { - Card card = revealedCards.get((UUID) target.getFirstTarget(), game); + Card card = revealedCards.get(target.getFirstTarget(), game); //If you do, you may cast the copy without paying its mana cost if (card != null) { Card copiedCard = game.copyCard(card, source, source.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/r/ReversePolarity.java b/Mage.Sets/src/mage/cards/r/ReversePolarity.java index ca3a31fcb01..ec43bed5856 100644 --- a/Mage.Sets/src/mage/cards/r/ReversePolarity.java +++ b/Mage.Sets/src/mage/cards/r/ReversePolarity.java @@ -46,7 +46,7 @@ class ReversePolarityAmount implements DynamicValue { @Override public int calculate(Game game, Ability source, Effect effect) { - ReversePolarityWatcher watcher = (ReversePolarityWatcher) game.getState().getWatchers().get(ReversePolarityWatcher.class.getSimpleName()); + ReversePolarityWatcher watcher = game.getState().getWatcher(ReversePolarityWatcher.class); if(watcher != null) { return watcher.getArtifactDamageReceivedThisTurn(source.getControllerId()) * 2; } diff --git a/Mage.Sets/src/mage/cards/r/RevivalRevenge.java b/Mage.Sets/src/mage/cards/r/RevivalRevenge.java new file mode 100644 index 00000000000..61846ac538e --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RevivalRevenge.java @@ -0,0 +1,86 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RevivalRevenge extends SplitCard { + + private static final FilterCard filter + = new FilterCreatureCard("creature card with converted mana cost 3 or less from your graveyard"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4)); + } + + public RevivalRevenge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W/B}{W/B}", "{4}{W}{B}", SpellAbilityType.SPLIT); + + // Revival + // Return target creature card with converted mana cost 3 or less from your graveyard to the battlefield. + this.getLeftHalfCard().getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCardInYourGraveyard(filter)); + + // Revenge + // Double your life total. Target opponent loses half their life, rounded up. + this.getRightHalfCard().getSpellAbility().addEffect(new RevivalRevengeEffect()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetOpponent()); + } + + private RevivalRevenge(final RevivalRevenge card) { + super(card); + } + + @Override + public RevivalRevenge copy() { + return new RevivalRevenge(this); + } +} + +class RevivalRevengeEffect extends OneShotEffect { + + RevivalRevengeEffect() { + super(Outcome.Benefit); + staticText = "Double your life total. Target opponent loses half their life, rounded up."; + } + + private RevivalRevengeEffect(final RevivalRevengeEffect effect) { + super(effect); + } + + @Override + public RevivalRevengeEffect copy() { + return new RevivalRevengeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(source.getFirstTarget()); + if (controller == null || player == null) { + return false; + } + controller.gainLife(controller.getLife(), game, source); + int life = player.getLife(); + player.loseLife(Math.floorDiv(life, 2) + (life % 2), game, false); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RewardsOfDiversity.java b/Mage.Sets/src/mage/cards/r/RewardsOfDiversity.java index 76fe7e8c9d5..dd1270a20c0 100644 --- a/Mage.Sets/src/mage/cards/r/RewardsOfDiversity.java +++ b/Mage.Sets/src/mage/cards/r/RewardsOfDiversity.java @@ -22,7 +22,7 @@ public final class RewardsOfDiversity extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public RewardsOfDiversity(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java b/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java index 7428ba1dce1..cdb37cef16d 100644 --- a/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java +++ b/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java @@ -34,7 +34,7 @@ public final class RhonasTheIndomitable extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RhonasTheIndomitable(UUID ownerId, CardSetInfo setInfo) { @@ -105,7 +105,7 @@ class RhonasTheIndomitableRestrictionEffect extends RestrictionEffect { public boolean applies(Permanent permanent, Ability source, Game game) { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); if (permanent.getId().equals(source.getSourceId())) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { diff --git a/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java b/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java index 1a46092cb31..800680e4ef5 100644 --- a/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java +++ b/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java @@ -69,7 +69,7 @@ class RhysTheRedeemedEffect extends OneShotEffect { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public RhysTheRedeemedEffect() { diff --git a/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java b/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java new file mode 100644 index 00000000000..be889e972fc --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RhythmOfTheWild.java @@ -0,0 +1,63 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.CantBeCounteredControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreatureSpell; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; + +/** + * @author TheElk801 + */ +public final class RhythmOfTheWild extends CardImpl { + + private static final FilterSpell filter + = new FilterCreatureSpell("Creature spells you control"); + private static final FilterPermanent filter2 + = new FilterControlledCreaturePermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter2.add(Predicates.not(TokenPredicate.instance)); + } + + public RhythmOfTheWild(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{G}"); + + // Creature spells you control can't be countered. + this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect( + filter, null, Duration.WhileOnBattlefield + ))); + + // Nontoken creatures you control have riot. + Ability ability = new SimpleStaticAbility(new GainAbilityControlledSpellsEffect( + new RiotAbility(), new FilterCreatureSpell()).setText("Nontoken creatures you control have riot. (They enter the battlefield with your choice of a +1/+1 counter or haste.)")); + ability.addEffect(new GainAbilityControlledEffect( + new RiotAbility(), Duration.WhileOnBattlefield, filter2 + ).setText("")); + this.addAbility(ability); + } + + private RhythmOfTheWild(final RhythmOfTheWild card) { + super(card); + } + + @Override + public RhythmOfTheWild copy() { + return new RhythmOfTheWild(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RicochetTrap.java b/Mage.Sets/src/mage/cards/r/RicochetTrap.java index 414dafbf65f..5f3f059febe 100644 --- a/Mage.Sets/src/mage/cards/r/RicochetTrap.java +++ b/Mage.Sets/src/mage/cards/r/RicochetTrap.java @@ -61,7 +61,7 @@ enum RicochetTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { List spells = watcher.getSpellsCastThisTurn(opponentId); diff --git a/Mage.Sets/src/mage/cards/r/RideDown.java b/Mage.Sets/src/mage/cards/r/RideDown.java index ad68abe732e..65e87b36d84 100644 --- a/Mage.Sets/src/mage/cards/r/RideDown.java +++ b/Mage.Sets/src/mage/cards/r/RideDown.java @@ -30,7 +30,7 @@ public final class RideDown extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocking creature"); static { - filter.add(new BlockingPredicate()); + filter.add(BlockingPredicate.instance); } public RideDown(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RidgescaleTusker.java b/Mage.Sets/src/mage/cards/r/RidgescaleTusker.java index aad9662f1d4..47deb75e59a 100644 --- a/Mage.Sets/src/mage/cards/r/RidgescaleTusker.java +++ b/Mage.Sets/src/mage/cards/r/RidgescaleTusker.java @@ -22,7 +22,7 @@ public final class RidgescaleTusker extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RidgescaleTusker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/Riftsweeper.java b/Mage.Sets/src/mage/cards/r/Riftsweeper.java index 050ee181043..8fc19bea158 100644 --- a/Mage.Sets/src/mage/cards/r/Riftsweeper.java +++ b/Mage.Sets/src/mage/cards/r/Riftsweeper.java @@ -27,7 +27,7 @@ public final class Riftsweeper extends CardImpl { private static final FilterCard filter = new FilterCard("face-up exiled card"); static { - filter.add(Predicates.not(new FaceDownPredicate())); + filter.add(Predicates.not(FaceDownPredicate.instance)); } public Riftsweeper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RighteousAuthority.java b/Mage.Sets/src/mage/cards/r/RighteousAuthority.java index 8e066aae9a4..399c1a17cfe 100644 --- a/Mage.Sets/src/mage/cards/r/RighteousAuthority.java +++ b/Mage.Sets/src/mage/cards/r/RighteousAuthority.java @@ -2,7 +2,6 @@ package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfDrawTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -21,18 +20,18 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RighteousAuthority extends CardImpl { - public RighteousAuthority (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{U}"); + public RighteousAuthority(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{U}"); this.subtype.add(SubType.AURA); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -48,7 +47,7 @@ public final class RighteousAuthority extends CardImpl { this.addAbility(new BeginningOfDrawTriggeredAbility(new DrawCardTargetEffect(1), TargetController.CONTROLLER_ATTACHED_TO, false)); } - public RighteousAuthority (final RighteousAuthority card) { + public RighteousAuthority(final RighteousAuthority card) { super(card); } @@ -79,7 +78,7 @@ class CardsInEnchantedControllerHandCount implements DynamicValue { @Override public DynamicValue copy() { - return new mage.abilities.dynamicvalue.common.CardsInControllerHandCount(); + return new CardsInEnchantedControllerHandCount(); } @Override diff --git a/Mage.Sets/src/mage/cards/r/RighteousFury.java b/Mage.Sets/src/mage/cards/r/RighteousFury.java index c7cc019ffc1..6aa334fe0ea 100644 --- a/Mage.Sets/src/mage/cards/r/RighteousFury.java +++ b/Mage.Sets/src/mage/cards/r/RighteousFury.java @@ -60,7 +60,7 @@ class RighteousFuryEffect extends OneShotEffect { if (controller != null) { int destroyedCreature = 0; FilterCreaturePermanent filter = new FilterCreaturePermanent("all tapped creatures"); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); for(Permanent creature: game.getState().getBattlefield().getActivePermanents(filter, controller.getId(), game)) { if (creature.destroy(source.getSourceId(), game, false)) { destroyedCreature++; diff --git a/Mage.Sets/src/mage/cards/r/RikuOfTwoReflections.java b/Mage.Sets/src/mage/cards/r/RikuOfTwoReflections.java index ba5d5bab919..255c570ecfd 100644 --- a/Mage.Sets/src/mage/cards/r/RikuOfTwoReflections.java +++ b/Mage.Sets/src/mage/cards/r/RikuOfTwoReflections.java @@ -1,22 +1,16 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CopyTargetSpellEffect; -import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SetTargetPointer; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterSpell; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; @@ -24,8 +18,9 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.permanent.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RikuOfTwoReflections extends CardImpl { @@ -37,8 +32,8 @@ public final class RikuOfTwoReflections extends CardImpl { filter.add(Predicates.or( new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); - filterPermanent.add(Predicates.not(new TokenPredicate())); - filterPermanent.add(new AnotherPredicate()); + filterPermanent.add(Predicates.not(TokenPredicate.instance)); + filterPermanent.add(AnotherPredicate.instance); } @@ -53,7 +48,6 @@ public final class RikuOfTwoReflections extends CardImpl { // Whenever you cast an instant or sorcery spell, you may pay {U}{R}. If you do, copy that spell. You may choose new targets for the copy. Effect effect = new CopyTargetSpellEffect(true); - effect.setText("copy that spell. You may choose new targets for the copy"); this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(effect, new ManaCostsImpl("{U}{R}")), filter, false, true)); // Whenever another nontoken creature enters the battlefield under your control, you may pay {G}{U}. If you do, create a token that's a copy of that creature. diff --git a/Mage.Sets/src/mage/cards/r/RimehornAurochs.java b/Mage.Sets/src/mage/cards/r/RimehornAurochs.java index 1976045e926..b1488d7428a 100644 --- a/Mage.Sets/src/mage/cards/r/RimehornAurochs.java +++ b/Mage.Sets/src/mage/cards/r/RimehornAurochs.java @@ -32,8 +32,8 @@ public final class RimehornAurochs extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.AUROCHS, "other attacking Aurochs"); static { - filter.add(new AttackingPredicate()); - filter.add(new AnotherPredicate()); + filter.add(AttackingPredicate.instance); + filter.add(AnotherPredicate.instance); } public RimehornAurochs(UUID ownerId, CardSetInfo setInfo) { @@ -87,9 +87,9 @@ class RimehornAurochsEffect extends RequirementEffect { Permanent blocker = game.getPermanent(source.getTargets().get(0).getFirstTarget()); if (blocker != null && blocker.canBlock(source.getTargets().get(1).getFirstTarget(), game)) { - Permanent attacker = (Permanent) game.getPermanent(source.getTargets().get(1).getFirstTarget()); + Permanent attacker = game.getPermanent(source.getTargets().get(1).getFirstTarget()); if (attacker != null) { - BlockedAttackerWatcher blockedAttackerWatcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher blockedAttackerWatcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attacker, blocker, game)) { // has already blocked this turn, so no need to do again diff --git a/Mage.Sets/src/mage/cards/r/Ringskipper.java b/Mage.Sets/src/mage/cards/r/Ringskipper.java index 82e16e5b1f8..fceb01e0ce0 100644 --- a/Mage.Sets/src/mage/cards/r/Ringskipper.java +++ b/Mage.Sets/src/mage/cards/r/Ringskipper.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.DoIfClashWonEffect; @@ -12,24 +10,25 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author Styxo */ public final class Ringskipper extends CardImpl { public Ringskipper(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add(SubType.FAERIE); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(1); - //Flying + // Flying this.addAbility(FlyingAbility.getInstance()); - //When {this} is put into graveyard from play, clash with an opponent. If you win return {this} to its owner's hand + // When {this} is put into graveyard from play, clash with an opponent. If you win return {this} to its owner's hand this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DoIfClashWonEffect(new ReturnToHandSourceEffect()))); } diff --git a/Mage.Sets/src/mage/cards/r/RishadanPawnshop.java b/Mage.Sets/src/mage/cards/r/RishadanPawnshop.java index af392346648..a51c3ece190 100644 --- a/Mage.Sets/src/mage/cards/r/RishadanPawnshop.java +++ b/Mage.Sets/src/mage/cards/r/RishadanPawnshop.java @@ -32,7 +32,7 @@ public final class RishadanPawnshop extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("nontoken permanent you control"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java b/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java index 5b34fdd0d17..591437ed8f0 100644 --- a/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java +++ b/Mage.Sets/src/mage/cards/r/RishkarPeemaRenegade.java @@ -31,7 +31,7 @@ public final class RishkarPeemaRenegade extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each creature you control with a counter on it"); static { - filter.add(new CounterAnyPredicate()); + filter.add(CounterAnyPredicate.instance); } public RishkarPeemaRenegade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java b/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java index 35ff9c2d529..4dd55e8cdc5 100644 --- a/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java +++ b/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java @@ -19,7 +19,7 @@ public final class RishkarsExpertise extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}"); // Draw cards equal to the greatest power among creatures you control. - Effect effect = new DrawCardSourceControllerEffect(new GreatestPowerAmongControlledCreaturesValue()); + Effect effect = new DrawCardSourceControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance); effect.setText("Draw cards equal to the greatest power among creatures you control"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/r/RiskyMove.java b/Mage.Sets/src/mage/cards/r/RiskyMove.java index 7b5c9c8cc69..b72f91ad8dc 100644 --- a/Mage.Sets/src/mage/cards/r/RiskyMove.java +++ b/Mage.Sets/src/mage/cards/r/RiskyMove.java @@ -76,8 +76,8 @@ class RiskyMoveGetControlEffect extends OneShotEffect { // remove old control effects of the same player for (ContinuousEffect effect : game.getState().getContinuousEffects().getLayeredEffects(game)) { if (effect instanceof GainControlTargetEffect) { - UUID checkId = (UUID) ((GainControlTargetEffect) effect).getValue("RiskyMoveSourceId"); - UUID controllerId = (UUID) ((GainControlTargetEffect) effect).getValue("RiskyMoveControllerId"); + UUID checkId = (UUID) effect.getValue("RiskyMoveSourceId"); + UUID controllerId = (UUID) effect.getValue("RiskyMoveControllerId"); if (source.getSourceId().equals(checkId) && newController.getId().equals(controllerId)) { effect.discard(); } @@ -162,7 +162,7 @@ class RiskyMoveFlipCoinEffect extends OneShotEffect { } Permanent permanent = game.getPermanent(target1.getFirstTarget()); Player chosenOpponent = game.getPlayer(target2.getFirstTarget()); - if (!controller.flipCoin(game)) { + if (!controller.flipCoin(source, game, true)) { if (permanent != null && chosenOpponent != null) { ContinuousEffect effect = new RiskyMoveCreatureGainControlEffect(Duration.Custom, chosenOpponent.getId()); effect.setTargetPointer(new FixedTarget(permanent.getId())); diff --git a/Mage.Sets/src/mage/cards/r/RiverSneak.java b/Mage.Sets/src/mage/cards/r/RiverSneak.java index ccb15f52abd..ce86dc98cf0 100644 --- a/Mage.Sets/src/mage/cards/r/RiverSneak.java +++ b/Mage.Sets/src/mage/cards/r/RiverSneak.java @@ -27,7 +27,7 @@ public final class RiverSneak extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another Merfolk"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new SubtypePredicate(SubType.MERFOLK)); } diff --git a/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java b/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java index 0f8e1c76a96..4f4dcf71c38 100644 --- a/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java +++ b/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java @@ -72,9 +72,9 @@ class PlayerLostLifePredicate implements Predicate { @Override public boolean apply(Player input, Game game) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { - return (0 < watcher.getLiveLost(input.getId())); + return (0 < watcher.getLifeLost(input.getId())); } return false; } diff --git a/Mage.Sets/src/mage/cards/r/RoarOfJukai.java b/Mage.Sets/src/mage/cards/r/RoarOfJukai.java index 153308f339e..0945b7fbdfa 100644 --- a/Mage.Sets/src/mage/cards/r/RoarOfJukai.java +++ b/Mage.Sets/src/mage/cards/r/RoarOfJukai.java @@ -59,7 +59,7 @@ class RoarOfJukaiEffect extends OneShotEffect { static { filter.add(new SubtypePredicate(SubType.FOREST)); - filterBlocked.add(new BlockedPredicate()); + filterBlocked.add(BlockedPredicate.instance); } diff --git a/Mage.Sets/src/mage/cards/r/RockSlide.java b/Mage.Sets/src/mage/cards/r/RockSlide.java index e1bb04fa43c..fe4a7869d98 100644 --- a/Mage.Sets/src/mage/cards/r/RockSlide.java +++ b/Mage.Sets/src/mage/cards/r/RockSlide.java @@ -26,8 +26,8 @@ public final class RockSlide extends CardImpl { static { filter.add(Predicates.or( - new AttackingPredicate(), - new BlockingPredicate() + AttackingPredicate.instance, + BlockingPredicate.instance )); filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); } @@ -36,7 +36,7 @@ public final class RockSlide extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}"); // Rock Slide deals X damage divided as you choose among any number of target attacking or blocking creatures without flying. - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new DamageMultiEffect(xValue)); this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue, filter)); } diff --git a/Mage.Sets/src/mage/cards/r/RocketLauncher.java b/Mage.Sets/src/mage/cards/r/RocketLauncher.java index 5fb0060a450..7d988810e14 100644 --- a/Mage.Sets/src/mage/cards/r/RocketLauncher.java +++ b/Mage.Sets/src/mage/cards/r/RocketLauncher.java @@ -56,7 +56,7 @@ class RocketLauncherWatcher extends Watcher { UUID cardId = null; public RocketLauncherWatcher(UUID cardId) { - super(RocketLauncherWatcher.class.getSimpleName(), WatcherScope.GAME); + super(RocketLauncherWatcher.class, WatcherScope.GAME); this.changedControllerOR1stTurn = true; this.cardId = cardId; } @@ -97,9 +97,9 @@ enum ControlledTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - RocketLauncherWatcher watcher = (RocketLauncherWatcher) game.getState().getWatchers().get(RocketLauncherWatcher.class.getSimpleName()); + RocketLauncherWatcher watcher = game.getState().getWatcher(RocketLauncherWatcher.class); - return !watcher.changedControllerOR1stTurn; + return watcher != null && !watcher.changedControllerOR1stTurn; } @Override diff --git a/Mage.Sets/src/mage/cards/r/RollingEarthquake.java b/Mage.Sets/src/mage/cards/r/RollingEarthquake.java index 005778c3c55..5e201d51401 100644 --- a/Mage.Sets/src/mage/cards/r/RollingEarthquake.java +++ b/Mage.Sets/src/mage/cards/r/RollingEarthquake.java @@ -29,7 +29,7 @@ public final class RollingEarthquake extends CardImpl { // Rolling Earthquake deals X damage to each creature without horsemanship and each player. - this.getSpellAbility().addEffect(new DamageEverythingEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageEverythingEffect(ManacostVariableValue.instance, filter)); } public RollingEarthquake(final RollingEarthquake card) { diff --git a/Mage.Sets/src/mage/cards/r/RollingThunder.java b/Mage.Sets/src/mage/cards/r/RollingThunder.java index b4b7e696ffb..696e3ed0f68 100644 --- a/Mage.Sets/src/mage/cards/r/RollingThunder.java +++ b/Mage.Sets/src/mage/cards/r/RollingThunder.java @@ -20,7 +20,7 @@ public final class RollingThunder extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}{R}"); // Rolling Thunder deals X damage divided as you choose among any number of target creatures and/or players. - DynamicValue xValue = new ManacostVariableValue(); + DynamicValue xValue = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new DamageMultiEffect(xValue)); this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue)); } diff --git a/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java b/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java index 99e6b0c3a62..22072f622de 100644 --- a/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java +++ b/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java @@ -38,7 +38,7 @@ public final class RoonOfTheHiddenRealm extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RoonOfTheHiddenRealm(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RootKinAlly.java b/Mage.Sets/src/mage/cards/r/RootKinAlly.java index 75a457b9e7d..8c148e5d98b 100644 --- a/Mage.Sets/src/mage/cards/r/RootKinAlly.java +++ b/Mage.Sets/src/mage/cards/r/RootKinAlly.java @@ -26,7 +26,7 @@ public final class RootKinAlly extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public RootKinAlly(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RotHulk.java b/Mage.Sets/src/mage/cards/r/RotHulk.java index 152f27ddcac..81b82e55263 100644 --- a/Mage.Sets/src/mage/cards/r/RotHulk.java +++ b/Mage.Sets/src/mage/cards/r/RotHulk.java @@ -55,7 +55,7 @@ public final class RotHulk extends CardImpl { // up to X target Zombie cards from your graveyard // X is the number of opponents you have. ability.getTargets().clear(); - int numbTargets = new OpponentsCount().calculate(game, ability, null); + int numbTargets = OpponentsCount.instance.calculate(game, ability, null); ability.addTarget(new TargetCardInYourGraveyard(0, numbTargets, filterZombie)); } } diff --git a/Mage.Sets/src/mage/cards/r/RotShambler.java b/Mage.Sets/src/mage/cards/r/RotShambler.java index b719faaf28c..8358cd49b08 100644 --- a/Mage.Sets/src/mage/cards/r/RotShambler.java +++ b/Mage.Sets/src/mage/cards/r/RotShambler.java @@ -24,7 +24,7 @@ public final class RotShambler extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/r/RowanKenrith.java b/Mage.Sets/src/mage/cards/r/RowanKenrith.java index a5ef32577d5..02e58898614 100644 --- a/Mage.Sets/src/mage/cards/r/RowanKenrith.java +++ b/Mage.Sets/src/mage/cards/r/RowanKenrith.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; @@ -13,14 +11,9 @@ import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.GetEmblemTargetPlayerEffect; import mage.abilities.keyword.PartnerWithAbility; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TurnPhase; +import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.TappedPredicate; @@ -29,8 +22,9 @@ import mage.game.command.emblems.RowanKenrithEmblem; import mage.game.permanent.Permanent; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class RowanKenrith extends CardImpl { @@ -54,11 +48,6 @@ public final class RowanKenrith extends CardImpl { // -8: Target player gets an emblem with "Whenever you activate an ability that isn't a mana ability, copy it. You may choose new targets for the copy." Effect effect = new GetEmblemTargetPlayerEffect(new RowanKenrithEmblem()); - effect.setText( - "Target player gets an emblem with " - + "\"Whenever you activate an ability that isn't a mana ability, " - + "copy it. You may choose new targets for the copy.\"" - ); ability = new LoyaltyAbility(effect, -8); ability.addTarget(new TargetPlayer()); this.addAbility(ability); @@ -149,7 +138,7 @@ class RowanKenrithDamageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerIdPredicate(source.getFirstTarget())); return new DamageAllEffect(3, filter).apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/r/RoyalAssassin.java b/Mage.Sets/src/mage/cards/r/RoyalAssassin.java index 402c7d8ad5e..a73c8b82cdc 100644 --- a/Mage.Sets/src/mage/cards/r/RoyalAssassin.java +++ b/Mage.Sets/src/mage/cards/r/RoyalAssassin.java @@ -26,7 +26,7 @@ public final class RoyalAssassin extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public RoyalAssassin(UUID ownerId, CardSetInfo setInfo){ diff --git a/Mage.Sets/src/mage/cards/r/RubbleReading.java b/Mage.Sets/src/mage/cards/r/RubbleReading.java new file mode 100644 index 00000000000..5146f93aadf --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RubbleReading.java @@ -0,0 +1,34 @@ +package mage.cards.r; + +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RubbleReading extends CardImpl { + + public RubbleReading(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); + + // Destroy target land. Scry 2. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addEffect(new ScryEffect(2)); + this.getSpellAbility().addTarget(new TargetLandPermanent()); + } + + private RubbleReading(final RubbleReading card) { + super(card); + } + + @Override + public RubbleReading copy() { + return new RubbleReading(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RubbleSlinger.java b/Mage.Sets/src/mage/cards/r/RubbleSlinger.java new file mode 100644 index 00000000000..5fafc01ba6f --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RubbleSlinger.java @@ -0,0 +1,37 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RubbleSlinger extends CardImpl { + + public RubbleSlinger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R/G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Reach + this.addAbility(ReachAbility.getInstance()); + } + + private RubbleSlinger(final RubbleSlinger card) { + super(card); + } + + @Override + public RubbleSlinger copy() { + return new RubbleSlinger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RubblebeltRecluse.java b/Mage.Sets/src/mage/cards/r/RubblebeltRecluse.java new file mode 100644 index 00000000000..432cfad5f3b --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RubblebeltRecluse.java @@ -0,0 +1,37 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.common.AttacksEachCombatStaticAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RubblebeltRecluse extends CardImpl { + + public RubblebeltRecluse(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.BERSERKER); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + + // Rubblebelt Recluse attacks each combat if able. + this.addAbility(new AttacksEachCombatStaticAbility()); + } + + private RubblebeltRecluse(final RubblebeltRecluse card) { + super(card); + } + + @Override + public RubblebeltRecluse copy() { + return new RubblebeltRecluse(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RubblebeltRunner.java b/Mage.Sets/src/mage/cards/r/RubblebeltRunner.java new file mode 100644 index 00000000000..dacc541e571 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RubblebeltRunner.java @@ -0,0 +1,50 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.common.SimpleEvasionAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TokenPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RubblebeltRunner extends CardImpl { + + public static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creature tokens"); + + static { + filter.add(TokenPredicate.instance); + } + + public RubblebeltRunner(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Rubblebelt Runner can't be blocked by creature tokens. + this.addAbility(new SimpleEvasionAbility( + new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield) + )); + } + + private RubblebeltRunner(final RubblebeltRunner card) { + super(card); + } + + @Override + public RubblebeltRunner copy() { + return new RubblebeltRunner(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RuinationGuide.java b/Mage.Sets/src/mage/cards/r/RuinationGuide.java index b008a9d3621..c552cb5bca7 100644 --- a/Mage.Sets/src/mage/cards/r/RuinationGuide.java +++ b/Mage.Sets/src/mage/cards/r/RuinationGuide.java @@ -25,7 +25,7 @@ public final class RuinationGuide extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creatures"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public RuinationGuide(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java b/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java index f9754711db5..b43ee672514 100644 --- a/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java +++ b/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java @@ -27,7 +27,7 @@ public final class RuinsOfOranRief extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creature that entered the battlefield this turn"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); filter.add(new EnteredThisTurnPredicate()); } diff --git a/Mage.Sets/src/mage/cards/r/RumblingRuin.java b/Mage.Sets/src/mage/cards/r/RumblingRuin.java new file mode 100644 index 00000000000..f4a611f453e --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RumblingRuin.java @@ -0,0 +1,77 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.combat.CantBlockAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterOpponentsCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RumblingRuin extends CardImpl { + + public RumblingRuin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}"); + + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // When Rumbling Ruin enters the battlefield, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new RumblingRuinEffect())); + } + + private RumblingRuin(final RumblingRuin card) { + super(card); + } + + @Override + public RumblingRuin copy() { + return new RumblingRuin(this); + } +} + +class RumblingRuinEffect extends OneShotEffect { + + RumblingRuinEffect() { + super(Outcome.Benefit); + staticText = "count the number of +1/+1 counters on creatures you control. " + + "Creatures your opponents control with power less than or equal to that number can't block this turn."; + } + + private RumblingRuinEffect(final RumblingRuinEffect effect) { + super(effect); + } + + @Override + public RumblingRuinEffect copy() { + return new RumblingRuinEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int counter = 1; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { + if (permanent == null || !permanent.isCreature()) { + continue; + } + counter += permanent.getCounters(game).getCount(CounterType.P1P1); + } + FilterCreaturePermanent filter = new FilterOpponentsCreaturePermanent(); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, counter)); + game.addEffect(new CantBlockAllEffect(filter, Duration.EndOfTurn), source); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RuneflareTrap.java b/Mage.Sets/src/mage/cards/r/RuneflareTrap.java index c446765d2a5..90900deb328 100644 --- a/Mage.Sets/src/mage/cards/r/RuneflareTrap.java +++ b/Mage.Sets/src/mage/cards/r/RuneflareTrap.java @@ -83,7 +83,7 @@ enum RuneflareTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { CardsAmountDrawnThisTurnWatcher watcher = - (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.class.getSimpleName()); + game.getState().getWatcher(CardsAmountDrawnThisTurnWatcher.class); return watcher != null && watcher.opponentDrewXOrMoreCards(source.getControllerId(), 3, game); } diff --git a/Mage.Sets/src/mage/cards/r/Runesword.java b/Mage.Sets/src/mage/cards/r/Runesword.java index 0a79d2da0ec..5692512b9ee 100644 --- a/Mage.Sets/src/mage/cards/r/Runesword.java +++ b/Mage.Sets/src/mage/cards/r/Runesword.java @@ -136,7 +136,7 @@ class RuneswordCantBeRegeneratedEffect extends ContinuousRuleModifyingEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { if (targetCreatureId != null) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), targetCreatureId); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, targetCreatureId); if (watcher != null) { return watcher.wasDamaged(event.getTargetId(), game); } diff --git a/Mage.Sets/src/mage/cards/r/RushOfBlood.java b/Mage.Sets/src/mage/cards/r/RushOfBlood.java index 3a1b06858ce..09daee68f03 100644 --- a/Mage.Sets/src/mage/cards/r/RushOfBlood.java +++ b/Mage.Sets/src/mage/cards/r/RushOfBlood.java @@ -22,7 +22,7 @@ public final class RushOfBlood extends CardImpl { // Target creature gets +X/+0 until end of turn, where X is its power. - this.getSpellAbility().addEffect(new BoostTargetEffect(new TargetPermanentPowerCount(), new StaticValue(0), Duration.EndOfTurn, true)); + this.getSpellAbility().addEffect(new BoostTargetEffect(TargetPermanentPowerCount.instance, new StaticValue(0), Duration.EndOfTurn, true)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/r/RushingRiver.java b/Mage.Sets/src/mage/cards/r/RushingRiver.java index 3f0ac959ed0..b5211042160 100644 --- a/Mage.Sets/src/mage/cards/r/RushingRiver.java +++ b/Mage.Sets/src/mage/cards/r/RushingRiver.java @@ -1,9 +1,7 @@ package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.decorator.ConditionalOneShotEffect; @@ -17,23 +15,25 @@ import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetNonlandPermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RushingRiver extends CardImpl { public RushingRiver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Kicker-Sacrifice a land. this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land"))))); // Return target nonland permanent to its owner's hand. If Rushing River was kicked, return another target nonland permanent to its owner's hand. - this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); Effect effect = new ConditionalOneShotEffect( new ReturnToHandTargetEffect(), KickedCondition.instance, @@ -41,16 +41,7 @@ public final class RushingRiver extends CardImpl { effect.setTargetPointer(new SecondTargetPointer()); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetNonlandPermanent()); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility && KickedCondition.instance.apply(game, ability)) { - ability.getTargets().clear(); - ability.addTarget(new TargetNonlandPermanent(2)); - } - + this.getSpellAbility().setTargetAdjuster(RushingRiverAdjuster.instance); } public RushingRiver(final RushingRiver card) { @@ -62,3 +53,15 @@ public final class RushingRiver extends CardImpl { return new RushingRiver(this); } } + +enum RushingRiverAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + if (KickedCondition.instance.apply(game, ability)) { + ability.getTargets().clear(); + ability.addTarget(new TargetNonlandPermanent(2)); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RushwoodGrove.java b/Mage.Sets/src/mage/cards/r/RushwoodGrove.java index 670f8b8f6b1..604f7383f53 100644 --- a/Mage.Sets/src/mage/cards/r/RushwoodGrove.java +++ b/Mage.Sets/src/mage/cards/r/RushwoodGrove.java @@ -34,7 +34,7 @@ public final class RushwoodGrove extends CardImpl { // {T}, Remove any number of storage counters from Rushwood Grove: Add {G} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.GreenMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {G} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/r/RustElemental.java b/Mage.Sets/src/mage/cards/r/RustElemental.java index a7ae9da7f5e..d6893f89802 100644 --- a/Mage.Sets/src/mage/cards/r/RustElemental.java +++ b/Mage.Sets/src/mage/cards/r/RustElemental.java @@ -53,7 +53,7 @@ class RustElementalEffect extends OneShotEffect { private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("artifact"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public RustElementalEffect() { diff --git a/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java b/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java index 6d186763b37..0a3524d1796 100644 --- a/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java +++ b/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java @@ -30,8 +30,8 @@ public final class RuthlessInstincts extends CardImpl { private static final FilterCreaturePermanent filterAttacking = new FilterCreaturePermanent("attacking creature"); static { - filter.add(Predicates.not(new AttackingPredicate())); - filterAttacking.add(new AttackingPredicate()); + filter.add(Predicates.not(AttackingPredicate.instance)); + filterAttacking.add(AttackingPredicate.instance); } public RuthlessInstincts(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SabaccGame.java b/Mage.Sets/src/mage/cards/s/SabaccGame.java index 3d42eaf52fe..4cfd1b6b467 100644 --- a/Mage.Sets/src/mage/cards/s/SabaccGame.java +++ b/Mage.Sets/src/mage/cards/s/SabaccGame.java @@ -88,7 +88,7 @@ class SabaccGameEffect extends OneShotEffect { if (target.chooseTarget(outcome, opponent.getId(), source, game)) { chosenPermanent = game.getPermanent(target.getFirstTarget()); } - boolean flipWin = controller.flipCoin(game); + boolean flipWin = controller.flipCoin(source, game, true); if (flipWin) { ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, controller.getId()); effect.setTargetPointer(new FixedTarget(targetPermanent, game)); diff --git a/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java b/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java index e962f95c8b2..70c1b8ab3e2 100644 --- a/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java +++ b/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java @@ -23,7 +23,7 @@ public final class SaddlebackLagac extends CardImpl { private final static FilterCreaturePermanent FILTER = new FilterCreaturePermanent("target creatures"); static { - FILTER.add(new AnotherPredicate()); + FILTER.add(AnotherPredicate.instance); } public SaddlebackLagac(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java index dcecae03c61..159e756f99b 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java +++ b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java @@ -43,7 +43,7 @@ public final class SageOfAncientLore extends CardImpl { this.secondSideCardClazz = mage.cards.w.WerewolfOfAncientHunger.class; // Sage of Ancient Lore's power and toughness are each equal to the number of cards in your hand. - DynamicValue xValue = new CardsInControllerHandCount(); + DynamicValue xValue = CardsInControllerHandCount.instance; this.addAbility(new SimpleStaticAbility(Zone.ALL, new ConditionalContinuousEffect(new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame), new TransformedCondition(true), "{this}'s power and toughness are each equal to the total number of cards in your hand"))); diff --git a/Mage.Sets/src/mage/cards/s/SagesRowDenizen.java b/Mage.Sets/src/mage/cards/s/SagesRowDenizen.java index ca6f76b1090..2d69340779a 100644 --- a/Mage.Sets/src/mage/cards/s/SagesRowDenizen.java +++ b/Mage.Sets/src/mage/cards/s/SagesRowDenizen.java @@ -29,7 +29,7 @@ public final class SagesRowDenizen extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.BLUE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/s/SagesRowSavant.java b/Mage.Sets/src/mage/cards/s/SagesRowSavant.java new file mode 100644 index 00000000000..f459b8ccaf1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SagesRowSavant.java @@ -0,0 +1,38 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SagesRowSavant extends CardImpl { + + public SagesRowSavant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.VEDALKEN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // When Sage's Row Savant enters the battlefield, scry 2. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(2))); + } + + private SagesRowSavant(final SagesRowSavant card) { + super(card); + } + + @Override + public SagesRowSavant copy() { + return new SagesRowSavant(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SagittarsVolley.java b/Mage.Sets/src/mage/cards/s/SagittarsVolley.java new file mode 100644 index 00000000000..1a017f2a8ca --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SagittarsVolley.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterOpponentsCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SagittarsVolley extends CardImpl { + + private static final FilterPermanent filter + = new FilterCreaturePermanent("creature with flying"); + private static final FilterPermanent filter2 + = new FilterOpponentsCreaturePermanent("creature with flying your opponents control"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + filter2.add(new AbilityPredicate(FlyingAbility.class)); + } + + public SagittarsVolley(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); + + // Destroy target creature with flying. Sagittars' Volley deals 1 damage to each creature with flying your opponents control. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + this.getSpellAbility().addEffect(new DamageAllEffect(1, filter2)); + } + + private SagittarsVolley(final SagittarsVolley card) { + super(card); + } + + @Override + public SagittarsVolley copy() { + return new SagittarsVolley(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java b/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java index 4d577674f82..f3fd326e190 100644 --- a/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java +++ b/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java @@ -86,7 +86,7 @@ class SaheeliTheGiftedCostReductionEffect extends CostModificationEffectImpl { @Override public void init(Ability source, Game game) { super.init(source, game); - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()); } @@ -104,7 +104,7 @@ class SaheeliTheGiftedCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) > spellsCast) { discard(); // only one use diff --git a/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java b/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java index 233d60d5f93..3329be28191 100644 --- a/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java +++ b/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java @@ -51,7 +51,7 @@ class SaltRoadAmbushersTriggeredAbility extends TurnedFaceUpAllTriggeredAbility private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another permanent you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SaltRoadAmbushersTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/s/SaltcrustedSteppe.java b/Mage.Sets/src/mage/cards/s/SaltcrustedSteppe.java index 8bc8e64d083..9b20de817dc 100644 --- a/Mage.Sets/src/mage/cards/s/SaltcrustedSteppe.java +++ b/Mage.Sets/src/mage/cards/s/SaltcrustedSteppe.java @@ -36,7 +36,7 @@ public final class SaltcrustedSteppe extends CardImpl { this.addAbility(ability); // {1}, Remove X storage counters from Saltcrusted Steppe: Add X mana in any combination of {G} and/or {W}. ability = new SimpleManaAbility(Zone.BATTLEFIELD, - new AddManaInAnyCombinationEffect(new RemovedCountersForCostValue(), ColoredManaSymbol.G, ColoredManaSymbol.W), + new AddManaInAnyCombinationEffect(RemovedCountersForCostValue.instance, ColoredManaSymbol.G, ColoredManaSymbol.W), new GenericManaCost(1)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance())); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/Saltskitter.java b/Mage.Sets/src/mage/cards/s/Saltskitter.java index 6c73c55ab05..e97c2651aea 100644 --- a/Mage.Sets/src/mage/cards/s/Saltskitter.java +++ b/Mage.Sets/src/mage/cards/s/Saltskitter.java @@ -22,7 +22,7 @@ public final class Saltskitter extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Saltskitter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SamuraiOfThePaleCurtain.java b/Mage.Sets/src/mage/cards/s/SamuraiOfThePaleCurtain.java index 27de3fc8b66..06b0e682567 100644 --- a/Mage.Sets/src/mage/cards/s/SamuraiOfThePaleCurtain.java +++ b/Mage.Sets/src/mage/cards/s/SamuraiOfThePaleCurtain.java @@ -1,8 +1,5 @@ - - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -10,39 +7,37 @@ import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.BushidoAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; /** - * * @author LevelX */ public final class SamuraiOfThePaleCurtain extends CardImpl { - public SamuraiOfThePaleCurtain (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{W}"); + public SamuraiOfThePaleCurtain(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}"); this.subtype.add(SubType.FOX); this.subtype.add(SubType.SAMURAI); this.power = new MageInt(2); this.toughness = new MageInt(2); - + // Bushido 1 (When this blocks or becomes blocked, it gets +1/+1 until end of turn.) this.addAbility(new BushidoAbility(1)); + // If a permanent would be put into a graveyard, exile it instead. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SamuraiOfThePaleCurtainEffect())); - } - public SamuraiOfThePaleCurtain (final SamuraiOfThePaleCurtain card) { + public SamuraiOfThePaleCurtain(final SamuraiOfThePaleCurtain card) { super(card); } @@ -56,12 +51,12 @@ public final class SamuraiOfThePaleCurtain extends CardImpl { class SamuraiOfThePaleCurtainEffect extends ReplacementEffectImpl { - public SamuraiOfThePaleCurtainEffect() { + SamuraiOfThePaleCurtainEffect() { super(Duration.WhileOnBattlefield, Outcome.Exile); staticText = "If a permanent would be put into a graveyard, exile it instead"; } - public SamuraiOfThePaleCurtainEffect(final SamuraiOfThePaleCurtainEffect effect) { + private SamuraiOfThePaleCurtainEffect(final SamuraiOfThePaleCurtainEffect effect) { super(effect); } @@ -72,9 +67,12 @@ class SamuraiOfThePaleCurtainEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = ((ZoneChangeEvent)event).getTarget(); + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent != null) { - return permanent.moveToExile(null, "", source.getSourceId(), game); + Player player = game.getPlayer(permanent.getControllerId()); + if (player != null) { + return player.moveCards(permanent, Zone.EXILED, source, game); + } } return false; } @@ -83,10 +81,10 @@ class SamuraiOfThePaleCurtainEffect extends ReplacementEffectImpl { public boolean checksEventType(GameEvent event, Game game) { return event.getType() == EventType.ZONE_CHANGE; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; return zEvent.getToZone() == Zone.GRAVEYARD; } diff --git a/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java b/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java index a5fb791345e..d42b0d88745 100644 --- a/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java +++ b/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java @@ -36,8 +36,8 @@ public final class SamutVoiceOfDissent extends CardImpl { private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); - filter2.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); + filter2.add(AnotherPredicate.instance); } public SamutVoiceOfDissent(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SanctifierOfSouls.java b/Mage.Sets/src/mage/cards/s/SanctifierOfSouls.java index 996c9946c3a..24b24ee0569 100644 --- a/Mage.Sets/src/mage/cards/s/SanctifierOfSouls.java +++ b/Mage.Sets/src/mage/cards/s/SanctifierOfSouls.java @@ -31,7 +31,7 @@ public final class SanctifierOfSouls extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SanctifierOfSouls(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfTheSun.java b/Mage.Sets/src/mage/cards/s/SanctumOfTheSun.java index 46269e831e2..0a8238c866c 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfTheSun.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfTheSun.java @@ -32,7 +32,7 @@ public final class SanctumOfTheSun extends CardImpl { new InfoEffect("(Transforms from Azor's Gateway.)")).setRuleAtTheTop(true)); // {T}: Add X mana of any one color, where X is your life total. - this.addAbility(new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), new ControllerLifeCount(), new TapSourceCost(), + this.addAbility(new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), ControllerLifeCount.instance, new TapSourceCost(), "Add X mana of any one color, where X is is your life total", true)); } diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfUgin.java b/Mage.Sets/src/mage/cards/s/SanctumOfUgin.java index bc747932c77..68c6258fc6e 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfUgin.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfUgin.java @@ -27,8 +27,8 @@ public final class SanctumOfUgin extends CardImpl { private static final FilterSpell filterSpells = new FilterSpell("colorless spell with converted mana cost 7 or greater"); static { - filter.add(new ColorlessPredicate()); - filterSpells.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); + filterSpells.add(ColorlessPredicate.instance); filterSpells.add(new ConvertedManaCostPredicate(ComparisonType.MORE_THAN, 6)); } diff --git a/Mage.Sets/src/mage/cards/s/SandSilos.java b/Mage.Sets/src/mage/cards/s/SandSilos.java index 360ca7ffc87..61b800e3bd9 100644 --- a/Mage.Sets/src/mage/cards/s/SandSilos.java +++ b/Mage.Sets/src/mage/cards/s/SandSilos.java @@ -44,7 +44,7 @@ public final class SandSilos extends CardImpl { // {tap}, Remove any number of storage counters from Sand Silos: Add {U} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.BlueMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {U} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java b/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java index cbbb1c6011b..f10c51c2bff 100644 --- a/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java +++ b/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java @@ -25,7 +25,7 @@ public final class SandsOfDelirium extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); // {X}, {tap}: Target player puts the top X cards of their library into their graveyard. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(new ManacostVariableValue()), new VariableManaCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(ManacostVariableValue.instance), new VariableManaCost()); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/Sandsower.java b/Mage.Sets/src/mage/cards/s/Sandsower.java index d53256882ed..0e295fac41c 100644 --- a/Mage.Sets/src/mage/cards/s/Sandsower.java +++ b/Mage.Sets/src/mage/cards/s/Sandsower.java @@ -27,7 +27,7 @@ public final class Sandsower extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Sandsower(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SanguineGlorifier.java b/Mage.Sets/src/mage/cards/s/SanguineGlorifier.java index be19360531b..df998da5726 100644 --- a/Mage.Sets/src/mage/cards/s/SanguineGlorifier.java +++ b/Mage.Sets/src/mage/cards/s/SanguineGlorifier.java @@ -25,7 +25,7 @@ public final class SanguineGlorifier extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another target Vampire you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/s/SanguineSacrament.java b/Mage.Sets/src/mage/cards/s/SanguineSacrament.java index f80c3580cac..bbccf8ba5c8 100644 --- a/Mage.Sets/src/mage/cards/s/SanguineSacrament.java +++ b/Mage.Sets/src/mage/cards/s/SanguineSacrament.java @@ -1,9 +1,8 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ReturnToLibrarySpellEffect; @@ -12,8 +11,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.game.Game; +import java.util.UUID; + /** - * * @author spjspj */ public final class SanguineSacrament extends CardImpl { @@ -22,11 +22,11 @@ public final class SanguineSacrament extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{W}{W}"); // You gain twice X life. Put Sanguine Sacrament on the bottom of its owner's library. - this.getSpellAbility().addEffect(new GainLifeEffect(new SanguineSacramentValue())); + this.getSpellAbility().addEffect(new GainLifeEffect(SanguineSacramentValue.instance)); this.getSpellAbility().addEffect(new ReturnToLibrarySpellEffect(false)); } - public SanguineSacrament(final SanguineSacrament card) { + private SanguineSacrament(final SanguineSacrament card) { super(card); } @@ -36,16 +36,22 @@ public final class SanguineSacrament extends CardImpl { } } -class SanguineSacramentValue extends ManacostVariableValue { +enum SanguineSacramentValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - return super.calculate(game, sourceAbility, effect) * 2; + return sourceAbility.getManaCostsToPay().getX() * 2; } @Override public SanguineSacramentValue copy() { - return new SanguineSacramentValue(); + return instance; + } + + @Override + public String getMessage() { + return ""; } @Override diff --git a/Mage.Sets/src/mage/cards/s/SaprazzanCove.java b/Mage.Sets/src/mage/cards/s/SaprazzanCove.java index 9f1c510d2a7..5806b041e15 100644 --- a/Mage.Sets/src/mage/cards/s/SaprazzanCove.java +++ b/Mage.Sets/src/mage/cards/s/SaprazzanCove.java @@ -34,7 +34,7 @@ public final class SaprazzanCove extends CardImpl { // {tap}, Remove any number of storage counters from Saprazzan Cove: Add {U} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.BlueMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {U} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/s/SaruliCaretaker.java b/Mage.Sets/src/mage/cards/s/SaruliCaretaker.java new file mode 100644 index 00000000000..41e1e31fdf9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SaruliCaretaker.java @@ -0,0 +1,55 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SaruliCaretaker extends CardImpl { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("an untapped creature you control"); + + static { + filter.add(Predicates.not(TappedPredicate.instance)); + } + + public SaruliCaretaker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); + + this.subtype.add(SubType.DRYAD); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // {T}, Tap an untapped creature you control: Add one mana of any color. + Ability ability = new AnyColorManaAbility(); + ability.addCost(new TapTargetCost(new TargetControlledPermanent(filter))); + this.addAbility(ability); + } + + private SaruliCaretaker(final SaruliCaretaker card) { + super(card); + } + + @Override + public SaruliCaretaker copy() { + return new SaruliCaretaker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java index 107565da511..19e16e50ca8 100644 --- a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java +++ b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java @@ -1,10 +1,6 @@ package mage.cards.s; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -14,8 +10,8 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; @@ -26,8 +22,13 @@ import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * @author LevelX2 */ @@ -48,18 +49,6 @@ public final class SatyrFiredancer extends CardImpl { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SatyrFiredancerTriggeredAbility) { - Player opponent = game.getPlayer(ability.getEffects().get(0).getTargetPointer().getFirst(game, ability)); - if (opponent != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponent.getId())); - ability.getTargets().add(new TargetCreaturePermanent(filter)); - } - } - } - @Override public SatyrFiredancer copy() { return new SatyrFiredancer(this); @@ -72,6 +61,7 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { public SatyrFiredancerTriggeredAbility() { super(Zone.BATTLEFIELD, new SatyrFiredancerDamageEffect(), false); + targetAdjuster = SatyrFiredancerAdjuster.instance; } public SatyrFiredancerTriggeredAbility(final SatyrFiredancerTriggeredAbility ability) { @@ -154,3 +144,17 @@ class SatyrFiredancerDamageEffect extends OneShotEffect { return false; } } + +enum SatyrFiredancerAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Player opponent = game.getPlayer(ability.getEffects().get(0).getTargetPointer().getFirst(game, ability)); + if (opponent != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); + filter.add(new ControllerIdPredicate(opponent.getId())); + ability.getTargets().add(new TargetCreaturePermanent(filter)); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SauroformHybrid.java b/Mage.Sets/src/mage/cards/s/SauroformHybrid.java new file mode 100644 index 00000000000..a26c167f88b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SauroformHybrid.java @@ -0,0 +1,38 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.keyword.AdaptAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SauroformHybrid extends CardImpl { + + public SauroformHybrid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.LIZARD); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {4}{G}{G}: Adapt 4. + this.addAbility(new AdaptAbility(4, "{4}{G}{G}")); + } + + private SauroformHybrid(final SauroformHybrid card) { + super(card); + } + + @Override + public SauroformHybrid copy() { + return new SauroformHybrid(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SavageSmash.java b/Mage.Sets/src/mage/cards/s/SavageSmash.java new file mode 100644 index 00000000000..feea5a1e649 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SavageSmash.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import mage.abilities.effects.common.FightTargetsEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SavageSmash extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creature you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + } + + public SavageSmash(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}{G}"); + + // Target creature you control gets +2/+2 until end of turn. It fights target creature you don't control. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + this.getSpellAbility().addEffect( + new FightTargetsEffect().setText("It fights target creature you don't control") + ); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + private SavageSmash(final SavageSmash card) { + super(card); + } + + @Override + public SavageSmash copy() { + return new SavageSmash(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SavageStomp.java b/Mage.Sets/src/mage/cards/s/SavageStomp.java index 8a080176193..0b03f1085ee 100644 --- a/Mage.Sets/src/mage/cards/s/SavageStomp.java +++ b/Mage.Sets/src/mage/cards/s/SavageStomp.java @@ -1,11 +1,9 @@ package mage.cards.s; -import java.util.Iterator; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceTargetsPermanentCondition; import mage.abilities.effects.Effect; import mage.abilities.effects.common.FightTargetsEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; @@ -17,35 +15,39 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class SavageStomp extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control"); + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creature you don't control"); + private static final FilterPermanent filter2 + = new FilterControlledCreaturePermanent(SubType.DINOSAUR, "a Dinosaur you control"); static { filter.add(new ControllerPredicate(TargetController.NOT_YOU)); } + private static final Condition condition = new SourceTargetsPermanentCondition(filter2); + public SavageStomp(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); // Savage Stomp costs {2} less to cast if it targets a Dinosaur you control. - this.addAbility(new SimpleStaticAbility(Zone.STACK, - new SpellCostReductionSourceEffect(2, SavageStompCondition.instance)) - .setRuleAtTheTop(true)); + this.addAbility(new SimpleStaticAbility( + Zone.STACK, new SpellCostReductionSourceEffect(2, condition) + ).setRuleAtTheTop(true)); // Put a +1/+1 counter on target creature you control. Then that creature fights target creature you don't control. Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); @@ -67,34 +69,3 @@ public final class SavageStomp extends CardImpl { return new SavageStomp(this); } } - -enum SavageStompCondition implements Condition { - instance; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Dinosaur you control"); - - static { - filter.add(new SubtypePredicate(SubType.DINOSAUR)); - filter.add(new ControllerPredicate(TargetController.YOU)); - } - - @Override - public boolean apply(Game game, Ability source) { - StackObject sourceSpell = game.getStack().getStackObject(source.getSourceId()); - if (sourceSpell != null) { - Iterator targets = sourceSpell.getStackAbility().getTargets().iterator(); - while (targets.hasNext()) { - Permanent permanent = game.getPermanentOrLKIBattlefield(targets.next().getFirstTarget()); - if (permanent != null && filter.match(permanent, game) && permanent.isControlledBy(source.getControllerId())) { - return true; - } - } - } - return false; - } - - @Override - public String toString() { - return "it targets a Dinosaur you control"; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/SavageSummoning.java b/Mage.Sets/src/mage/cards/s/SavageSummoning.java index e92658aa331..a5ed8cf4fca 100644 --- a/Mage.Sets/src/mage/cards/s/SavageSummoning.java +++ b/Mage.Sets/src/mage/cards/s/SavageSummoning.java @@ -75,7 +75,7 @@ class SavageSummoningAsThoughEffect extends AsThoughEffectImpl { @Override public void init(Ability source, Game game) { - watcher = (SavageSummoningWatcher) game.getState().getWatchers().get(SavageSummoningWatcher.class.getSimpleName(), source.getControllerId()); + watcher = game.getState().getWatcher(SavageSummoningWatcher.class, source.getControllerId()); Card card = game.getCard(source.getSourceId()); if (watcher != null && card != null) { watcher.setSavageSummoningSpellActive(card, game); @@ -122,7 +122,7 @@ class SavageSummoningWatcher extends Watcher { private Map> cardsCastWithSavageSummoning = new LinkedHashMap<>(); public SavageSummoningWatcher() { - super(SavageSummoningWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(SavageSummoningWatcher.class, WatcherScope.PLAYER); } public SavageSummoningWatcher(final SavageSummoningWatcher watcher) { @@ -207,7 +207,7 @@ class SavageSummoningCantCounterEffect extends ContinuousRuleModifyingEffectImpl @Override public void init(Ability source, Game game) { - watcher = (SavageSummoningWatcher) game.getState().getWatchers().get(SavageSummoningWatcher.class.getSimpleName(), source.getControllerId()); + watcher = game.getState().getWatcher(SavageSummoningWatcher.class, source.getControllerId()); Card card = game.getCard(source.getSourceId()); if (watcher == null || card == null) { throw new IllegalArgumentException("Consume Savage watcher or card could not be found"); @@ -265,7 +265,7 @@ class SavageSummoningEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public void init(Ability source, Game game) { - watcher = (SavageSummoningWatcher) game.getState().getWatchers().get(SavageSummoningWatcher.class.getSimpleName(), source.getControllerId()); + watcher = game.getState().getWatcher(SavageSummoningWatcher.class, source.getControllerId()); Card card = game.getCard(source.getSourceId()); if (watcher == null || card == null) { throw new IllegalArgumentException("Consume Savage watcher or card could not be found"); diff --git a/Mage.Sets/src/mage/cards/s/SavageTwister.java b/Mage.Sets/src/mage/cards/s/SavageTwister.java index 26acebbd855..0b9090439b0 100644 --- a/Mage.Sets/src/mage/cards/s/SavageTwister.java +++ b/Mage.Sets/src/mage/cards/s/SavageTwister.java @@ -20,7 +20,7 @@ public final class SavageTwister extends CardImpl { // Savage Twister deals X damage to each creature. - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), new FilterCreaturePermanent())); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, new FilterCreaturePermanent())); } public SavageTwister(final SavageTwister card) { diff --git a/Mage.Sets/src/mage/cards/s/ScaldingSalamander.java b/Mage.Sets/src/mage/cards/s/ScaldingSalamander.java index c7b0d4f9e38..efb5f5926d3 100644 --- a/Mage.Sets/src/mage/cards/s/ScaldingSalamander.java +++ b/Mage.Sets/src/mage/cards/s/ScaldingSalamander.java @@ -26,7 +26,7 @@ public final class ScaldingSalamander extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); } diff --git a/Mage.Sets/src/mage/cards/s/ScaleguardSentinels.java b/Mage.Sets/src/mage/cards/s/ScaleguardSentinels.java index ee693bf611a..6f0341a4e00 100644 --- a/Mage.Sets/src/mage/cards/s/ScaleguardSentinels.java +++ b/Mage.Sets/src/mage/cards/s/ScaleguardSentinels.java @@ -83,7 +83,7 @@ enum ScaleguardSentinelsCondition implements Condition { public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentEntering(source.getSourceId()); if (sourcePermanent != null) { - DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = (DragonOnTheBattlefieldWhileSpellWasCastWatcher) game.getState().getWatchers().get(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class.getSimpleName()); + DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); return (watcher != null && watcher.castWithConditionTrue(sourcePermanent.getSpellAbility().getId())); } return false; diff --git a/Mage.Sets/src/mage/cards/s/ScavengingGhoul.java b/Mage.Sets/src/mage/cards/s/ScavengingGhoul.java index 103d57b3604..d71e11b07bf 100644 --- a/Mage.Sets/src/mage/cards/s/ScavengingGhoul.java +++ b/Mage.Sets/src/mage/cards/s/ScavengingGhoul.java @@ -32,7 +32,7 @@ public final class ScavengingGhoul extends CardImpl { // At the beginning of each end step, put a corpse counter on Scavenging Ghoul for each creature that died this turn. this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.CORPSE.createInstance(), - new CreaturesDiedThisTurnCount(), true), TargetController.ANY, false), new CreaturesDiedWatcher()); + CreaturesDiedThisTurnCount.instance, true), TargetController.ANY, false), new CreaturesDiedWatcher()); // Remove a corpse counter from Scavenging Ghoul: Regenerate Scavenging Ghoul. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new RemoveCountersSourceCost(CounterType.CORPSE.createInstance()))); diff --git a/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java b/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java index cc9c89b986f..aebf8005de6 100644 --- a/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java +++ b/Mage.Sets/src/mage/cards/s/ScholarOfAthreos.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -10,10 +9,11 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; +import mage.players.Player; /** * @@ -22,7 +22,7 @@ import mage.game.Game; public final class ScholarOfAthreos extends CardImpl { public ScholarOfAthreos(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); @@ -33,7 +33,7 @@ public final class ScholarOfAthreos extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScholarOfAthreosEffect(), new ManaCostsImpl("{2}{B}"))); } - public ScholarOfAthreos(final ScholarOfAthreos card) { + private ScholarOfAthreos(final ScholarOfAthreos card) { super(card); } @@ -50,17 +50,20 @@ class ScholarOfAthreosEffect extends OneShotEffect { staticText = "Each opponent loses 1 life. You gain life equal to the life lost this way"; } - public ScholarOfAthreosEffect(final ScholarOfAthreosEffect effect) { + private ScholarOfAthreosEffect(final ScholarOfAthreosEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - int damage = 0; - for (UUID opponentId: game.getOpponents(source.getControllerId())) { - damage += game.getPlayer(opponentId).damage(1, source.getSourceId(), game, false, true); + int lifeLost = 0; + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if(opponent != null) { + lifeLost += opponent.loseLife(1, game, false); + } } - game.getPlayer(source.getControllerId()).gainLife(damage, game, source); + game.getPlayer(source.getControllerId()).gainLife(lifeLost, game, source); return true; } diff --git a/Mage.Sets/src/mage/cards/s/ScorchedEarth.java b/Mage.Sets/src/mage/cards/s/ScorchedEarth.java index bc2c406e14a..0c578f5129b 100644 --- a/Mage.Sets/src/mage/cards/s/ScorchedEarth.java +++ b/Mage.Sets/src/mage/cards/s/ScorchedEarth.java @@ -1,36 +1,36 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.common.FilterLandCard; import mage.filter.common.FilterLandPermanent; import mage.game.Game; import mage.target.common.TargetCardInHand; import mage.target.common.TargetLandPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ScorchedEarth extends CardImpl { public ScorchedEarth(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}"); // As an additional cost to cast Scorched Earth, discard X land cards. - Ability ability = new SimpleStaticAbility(Zone.ALL, new ScorchedEarthRuleEffect()); + Ability ability = new SimpleStaticAbility(Zone.ALL, new InfoEffect("as an additional cost to cast this spell, discard X land cards")); ability.setRuleAtTheTop(true); this.addAbility(ability); @@ -39,53 +39,39 @@ public final class ScorchedEarth extends CardImpl { effect.setText("Destroy X target lands"); this.getSpellAbility().addTarget(new TargetLandPermanent()); this.getSpellAbility().addEffect(effect); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetLandPermanent(xValue, xValue, new FilterLandPermanent(), false)); - } + this.getSpellAbility().setTargetAdjuster(ScorchedEarthTargetAdjuster.instance); + this.getSpellAbility().setCostAdjuster(ScorchedEarthCostAdjuster.instance); } public ScorchedEarth(final ScorchedEarth card) { super(card); } - @Override - public void adjustCosts(Ability ability, Game game) { - int xValue = ability.getManaCostsToPay().getX(); - if (xValue > 0) { - ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, new FilterLandCard("land cards")))); - } - } - @Override public ScorchedEarth copy() { return new ScorchedEarth(this); } } -class ScorchedEarthRuleEffect extends OneShotEffect { - - public ScorchedEarthRuleEffect() { - super(Outcome.Benefit); - this.staticText = "as an additional cost to cast this spell, discard X land cards"; - } - - public ScorchedEarthRuleEffect(final ScorchedEarthRuleEffect effect) { - super(effect); - } +enum ScorchedEarthTargetAdjuster implements TargetAdjuster { + instance; @Override - public ScorchedEarthRuleEffect copy() { - return new ScorchedEarthRuleEffect(this); + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetLandPermanent(xValue, xValue, new FilterLandPermanent(), false)); } +} + +enum ScorchedEarthCostAdjuster implements CostAdjuster { + instance; @Override - public boolean apply(Game game, Ability source) { - return true; + public void adjustCosts(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + if (xValue > 0) { + ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, new FilterLandCard("land cards")))); + } } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/ScorchedRuins.java b/Mage.Sets/src/mage/cards/s/ScorchedRuins.java index f211684d462..7aad42b4399 100644 --- a/Mage.Sets/src/mage/cards/s/ScorchedRuins.java +++ b/Mage.Sets/src/mage/cards/s/ScorchedRuins.java @@ -29,7 +29,7 @@ public final class ScorchedRuins extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("two untapped lands"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ScorchedRuins(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/Scorchmark.java b/Mage.Sets/src/mage/cards/s/Scorchmark.java new file mode 100644 index 00000000000..7cb97562073 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Scorchmark.java @@ -0,0 +1,34 @@ +package mage.cards.s; + +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ExileTargetIfDiesEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Scorchmark extends CardImpl { + + public Scorchmark(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); + + // Scorchmark deals 2 damage to target creature. If that creature would die this turn, exile it instead. + this.getSpellAbility().addEffect(new DamageTargetEffect(2)); + this.getSpellAbility().addEffect(new ExileTargetIfDiesEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private Scorchmark(final Scorchmark card) { + super(card); + } + + @Override + public Scorchmark copy() { + return new Scorchmark(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ScoriaCat.java b/Mage.Sets/src/mage/cards/s/ScoriaCat.java index 26dc4a4b403..718623d998e 100644 --- a/Mage.Sets/src/mage/cards/s/ScoriaCat.java +++ b/Mage.Sets/src/mage/cards/s/ScoriaCat.java @@ -27,7 +27,7 @@ public final class ScoriaCat extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ScoriaCat(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ScoriaWurm.java b/Mage.Sets/src/mage/cards/s/ScoriaWurm.java index 4c05f8d3502..5f02aba6f93 100644 --- a/Mage.Sets/src/mage/cards/s/ScoriaWurm.java +++ b/Mage.Sets/src/mage/cards/s/ScoriaWurm.java @@ -60,7 +60,7 @@ class ScoriaWurmEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { return true; } else { new ReturnToHandSourceEffect().apply(game, source); diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfKherRidges.java b/Mage.Sets/src/mage/cards/s/ScourgeOfKherRidges.java index ec103fb903e..56a7d280b34 100644 --- a/Mage.Sets/src/mage/cards/s/ScourgeOfKherRidges.java +++ b/Mage.Sets/src/mage/cards/s/ScourgeOfKherRidges.java @@ -30,7 +30,7 @@ public final class ScourgeOfKherRidges extends CardImpl { static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); filter2.add(new AbilityPredicate(FlyingAbility.class)); - filter2.add(new AnotherPredicate()); + filter2.add(AnotherPredicate.instance); } public ScourgeOfKherRidges(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ScoutsWarning.java b/Mage.Sets/src/mage/cards/s/ScoutsWarning.java index 0c1816f4a34..6ff40c6cb78 100644 --- a/Mage.Sets/src/mage/cards/s/ScoutsWarning.java +++ b/Mage.Sets/src/mage/cards/s/ScoutsWarning.java @@ -65,7 +65,7 @@ class ScoutsWarningAsThoughEffect extends AsThoughEffectImpl { @Override public void init(Ability source, Game game) { - watcher = (ScoutsWarningWatcher) game.getState().getWatchers().get(ScoutsWarningWatcher.class.getSimpleName(), source.getControllerId()); + watcher = game.getState().getWatcher(ScoutsWarningWatcher.class, source.getControllerId()); Card card = game.getCard(source.getSourceId()); if (watcher != null && card != null) { zoneChangeCounter = card.getZoneChangeCounter(game); diff --git a/Mage.Sets/src/mage/cards/s/ScrabblingClaws.java b/Mage.Sets/src/mage/cards/s/ScrabblingClaws.java index b06aa9a731c..357f45b6bbb 100644 --- a/Mage.Sets/src/mage/cards/s/ScrabblingClaws.java +++ b/Mage.Sets/src/mage/cards/s/ScrabblingClaws.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -23,8 +22,9 @@ import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ScrabblingClaws extends CardImpl { @@ -33,18 +33,27 @@ public final class ScrabblingClaws extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {tap}: Target player exiles a card from their graveyard. - Ability firstAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScrabblingClawsEffect(), new TapSourceCost()); - firstAbility.addTarget(new TargetPlayer()); - this.addAbility(firstAbility); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new ScrabblingClawsEffect(), new + TapSourceCost() + ); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + // {1}, Sacrifice Scrabbling Claws: Exile target card from a graveyard. Draw a card. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new SacrificeSourceCost()); - ability.addCost(new GenericManaCost(1)); + ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new ExileTargetEffect(), + new GenericManaCost(1) + ); + ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCardInGraveyard()); ability.addEffect(new DrawCardSourceControllerEffect(1)); this.addAbility(ability); } - public ScrabblingClaws(final ScrabblingClaws card) { + private ScrabblingClaws(final ScrabblingClaws card) { super(card); } @@ -56,12 +65,12 @@ public final class ScrabblingClaws extends CardImpl { class ScrabblingClawsEffect extends OneShotEffect { - public ScrabblingClawsEffect() { + ScrabblingClawsEffect() { super(Outcome.Exile); this.staticText = "Target player exiles a card from their graveyard"; } - public ScrabblingClawsEffect(final ScrabblingClawsEffect effect) { + private ScrabblingClawsEffect(final ScrabblingClawsEffect effect) { super(effect); } @@ -73,18 +82,16 @@ class ScrabblingClawsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(source.getFirstTarget()); - if (targetPlayer != null) { - FilterCard filter = new FilterCard("card from your graveyard"); - filter.add(new OwnerIdPredicate(targetPlayer.getId())); - TargetCardInGraveyard target = new TargetCardInGraveyard(filter); - if (targetPlayer.chooseTarget(Outcome.Exile, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - targetPlayer.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true); - } - return true; - } + if (targetPlayer == null) { + return false; } - return false; + FilterCard filter = new FilterCard("card from your graveyard"); + filter.add(new OwnerIdPredicate(targetPlayer.getId())); + TargetCardInGraveyard target = new TargetCardInGraveyard(filter); + if (!targetPlayer.chooseTarget(Outcome.Exile, target, source, game)) { + return false; + } + Card card = game.getCard(target.getFirstTarget()); + return card != null && targetPlayer.moveCards(card, Zone.EXILED, source, game); } } diff --git a/Mage.Sets/src/mage/cards/s/ScreamingShield.java b/Mage.Sets/src/mage/cards/s/ScreamingShield.java new file mode 100644 index 00000000000..a31cb67e01a --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScreamingShield.java @@ -0,0 +1,56 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ScreamingShield extends CardImpl { + + public ScreamingShield(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature gets +0/+3 and has "{2}, {T}: Target player puts the top three cards of their library into their graveyard." + Ability toAdd = new SimpleActivatedAbility( + new PutLibraryIntoGraveTargetEffect(3), new GenericManaCost(2) + ); + toAdd.addCost(new TapSourceCost()); + toAdd.addTarget(new TargetPlayer()); + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(0, 3)); + ability.addEffect(new GainAbilityAttachedEffect( + toAdd, AttachmentType.EQUIPMENT + ).setText("and has \"{2}, {T}: Target player puts the top three cards of their library into their graveyard.\"")); + this.addAbility(ability); + + // Equip {3} + this.addAbility(new EquipAbility(3)); + } + + private ScreamingShield(final ScreamingShield card) { + super(card); + } + + @Override + public ScreamingShield copy() { + return new ScreamingShield(this); + } +} +// AAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHH diff --git a/Mage.Sets/src/mage/cards/s/ScroungingBandar.java b/Mage.Sets/src/mage/cards/s/ScroungingBandar.java index 13c98760f37..c9421d3b053 100644 --- a/Mage.Sets/src/mage/cards/s/ScroungingBandar.java +++ b/Mage.Sets/src/mage/cards/s/ScroungingBandar.java @@ -32,7 +32,7 @@ public final class ScroungingBandar extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ScroungingBandar(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ScryingGlass.java b/Mage.Sets/src/mage/cards/s/ScryingGlass.java index 8f53b6f0333..bb535f3a52a 100644 --- a/Mage.Sets/src/mage/cards/s/ScryingGlass.java +++ b/Mage.Sets/src/mage/cards/s/ScryingGlass.java @@ -1,87 +1,87 @@ -package mage.cards.s; - -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.choices.ChoiceColor; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetOpponent; - -/** - * - * @author jeffwadsworth - */ -public final class ScryingGlass extends CardImpl { - - public ScryingGlass(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - - // {3}, {tap}: Choose a number greater than 0 and a color. Target opponent reveals his or her hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScryingGlassEffect(), new ManaCostsImpl("{3}")); - ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetOpponent()); - this.addAbility(ability); - - } - - public ScryingGlass(final ScryingGlass card) { - super(card); - } - - @Override - public ScryingGlass copy() { - return new ScryingGlass(this); - } -} - -class ScryingGlassEffect extends OneShotEffect { - - public ScryingGlassEffect() { - super(Outcome.Neutral); - staticText = "Choose a number greater than 0 and a color. Target opponent reveals his or her hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card"; - } - - public ScryingGlassEffect(final ScryingGlassEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Player targetOpponent = game.getPlayer(source.getFirstTarget()); - ChoiceColor color = new ChoiceColor(); - int amount = 0; - if (controller != null - && targetOpponent != null) { - amount = controller.getAmount(1, Integer.MAX_VALUE, "Choose a number", game); - controller.choose(Outcome.Discard, color, game); - FilterCard filter = new FilterCard(); - filter.add(new ColorPredicate(color.getColor())); - targetOpponent.revealCards(source, targetOpponent.getHand(), game); - if (targetOpponent.getHand().count(filter, game) == amount) { - game.informPlayers(controller.getName() + " has chosen the exact number and color of the revealed cards from " + targetOpponent.getName() + "'s hand. They draw a card."); - controller.drawCards(1, game); - return true; - } else { - game.informPlayers(controller.getName() + " has chosen incorrectly and will not draw a card."); - } - } - return false; - } - - @Override - public ScryingGlassEffect copy() { - return new ScryingGlassEffect(this); - } -} +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author jeffwadsworth + */ +public final class ScryingGlass extends CardImpl { + + public ScryingGlass(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + // {3}, {tap}: Choose a number greater than 0 and a color. Target opponent reveals their hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScryingGlassEffect(), new ManaCostsImpl("{3}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + + } + + public ScryingGlass(final ScryingGlass card) { + super(card); + } + + @Override + public ScryingGlass copy() { + return new ScryingGlass(this); + } +} + +class ScryingGlassEffect extends OneShotEffect { + + public ScryingGlassEffect() { + super(Outcome.Neutral); + staticText = "Choose a number greater than 0 and a color. Target opponent reveals their hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card"; + } + + public ScryingGlassEffect(final ScryingGlassEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetOpponent = game.getPlayer(source.getFirstTarget()); + ChoiceColor color = new ChoiceColor(); + int amount = 0; + if (controller != null + && targetOpponent != null) { + amount = controller.getAmount(1, Integer.MAX_VALUE, "Choose a number", game); + controller.choose(Outcome.Discard, color, game); + FilterCard filter = new FilterCard(); + filter.add(new ColorPredicate(color.getColor())); + targetOpponent.revealCards(source, targetOpponent.getHand(), game); + if (targetOpponent.getHand().count(filter, game) == amount) { + game.informPlayers(controller.getName() + " has chosen the exact number and color of the revealed cards from " + targetOpponent.getName() + "'s hand. They draw a card."); + controller.drawCards(1, game); + return true; + } else { + game.informPlayers(controller.getName() + " has chosen incorrectly and will not draw a card."); + } + } + return false; + } + + @Override + public ScryingGlassEffect copy() { + return new ScryingGlassEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/Scuttlegator.java b/Mage.Sets/src/mage/cards/s/Scuttlegator.java new file mode 100644 index 00000000000..9cde2f38b48 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Scuttlegator.java @@ -0,0 +1,59 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalAsThoughEffect; +import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Scuttlegator extends CardImpl { + + public Scuttlegator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G/U}{G/U}"); + + this.subtype.add(SubType.CRAB); + this.subtype.add(SubType.TURTLE); + this.subtype.add(SubType.CROCODILE); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // {6}{G/U}{G/U}: Adapt 3. + this.addAbility(new AdaptAbility(3, "{6}{G/U}{G/U}")); + + // As long as Scuttlegator has a +1/+1 counter on it, it can attack as though it didn't have defender. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalAsThoughEffect( + new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield), + new SourceHasCounterCondition(CounterType.P1P1) + ).setText("As long as {this} has a +1/+1 counter on it, " + + "it can attack as though it didn't have defender.") + )); + } + + private Scuttlegator(final Scuttlegator card) { + super(card); + } + + @Override + public Scuttlegator copy() { + return new Scuttlegator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SeaTroll.java b/Mage.Sets/src/mage/cards/s/SeaTroll.java index 09a364ec860..f7fef000ca7 100644 --- a/Mage.Sets/src/mage/cards/s/SeaTroll.java +++ b/Mage.Sets/src/mage/cards/s/SeaTroll.java @@ -103,7 +103,7 @@ class SeaTrollCondition implements Condition { public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (sourcePermanent != null){ - SeaTrollWatcher watcher = (SeaTrollWatcher) game.getState().getWatchers().get(SeaTrollWatcher.class.getSimpleName()); + SeaTrollWatcher watcher = game.getState().getWatcher(SeaTrollWatcher.class); if (watcher != null) { return watcher.blockedOrBlockedByBlueCreatureThisTurn(new MageObjectReference(sourcePermanent, game)); } diff --git a/Mage.Sets/src/mage/cards/s/SealAway.java b/Mage.Sets/src/mage/cards/s/SealAway.java index ebf5fdcdb83..4550db53198 100644 --- a/Mage.Sets/src/mage/cards/s/SealAway.java +++ b/Mage.Sets/src/mage/cards/s/SealAway.java @@ -28,7 +28,7 @@ public final class SealAway extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SealAway(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SearchForSurvivors.java b/Mage.Sets/src/mage/cards/s/SearchForSurvivors.java index 278beadcfac..d961db7e4a9 100644 --- a/Mage.Sets/src/mage/cards/s/SearchForSurvivors.java +++ b/Mage.Sets/src/mage/cards/s/SearchForSurvivors.java @@ -1,104 +1,104 @@ -package mage.cards.s; - -import java.util.Arrays; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; -import mage.util.RandomUtil; - -/** - * - * @author jeffwadsworth - */ - -/* - The card is chosen at random, so the computer just picks a card at random from - the controller's graveyard. Devs, feel free to set up something else... - */ -public final class SearchForSurvivors extends CardImpl { - - public SearchForSurvivors(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); - - // Reorder your graveyard at random. An opponent chooses a card at random in your graveyard. If it's a creature card, put it onto the battlefield. Otherwise, exile it. - this.getSpellAbility().addEffect(new SearchForSurvivorsEffect()); - - } - - public SearchForSurvivors(final SearchForSurvivors card) { - super(card); - } - - @Override - public SearchForSurvivors copy() { - return new SearchForSurvivors(this); - } -} - -class SearchForSurvivorsEffect extends OneShotEffect { - - public SearchForSurvivorsEffect() { - super(Outcome.PutCardInPlay); - this.staticText = "Reorder your graveyard at random. " - + "An opponent chooses a card at random in your graveyard. " - + "If it's a creature card, put it onto the battlefield. " - + "Otherwise, exile it"; - } - - public SearchForSurvivorsEffect(final SearchForSurvivorsEffect effect) { - super(effect); - } - - @Override - public SearchForSurvivorsEffect copy() { - return new SearchForSurvivorsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - game.informPlayers("The controller of Search for Survivors will have his or her graveyard randomized. " - + " A card will be chosen at random from the controller's graveyard. " - + " The result is essentially the same as the card rule"); - // randomly arrange the graveyard - UUID[] shuffled = controller.getGraveyard().toArray(new UUID[0]); - for (int n = shuffled.length - 1; n > 0; n--) { - int r = RandomUtil.nextInt(n + 1); - UUID temp = shuffled[r]; - shuffled[r] = shuffled[n]; - shuffled[n] = temp; - } - controller.getGraveyard().clear(); - controller.getGraveyard().addAll(Arrays.asList(shuffled)); - // end of randomize - Cards cards = new CardsImpl(); - controller.getGraveyard().getCards(game).forEach((card) -> { - cards.add(card); - }); - if (!cards.isEmpty()) { - Card card = cards.getRandom(game); - cards.clear(); - cards.add(card); - controller.revealCards(source, cards, game); // reveal the card randomly chosen. - if (card.isCreature()) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } else { - controller.moveCards(card, Zone.EXILED, source, game); - } - } - return true; - } - return false; - } -} +package mage.cards.s; + +import java.util.Arrays; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.util.RandomUtil; + +/** + * + * @author jeffwadsworth + */ + +/* + The card is chosen at random, so the computer just picks a card at random from + the controller's graveyard. Devs, feel free to set up something else... + */ +public final class SearchForSurvivors extends CardImpl { + + public SearchForSurvivors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); + + // Reorder your graveyard at random. An opponent chooses a card at random in your graveyard. If it's a creature card, put it onto the battlefield. Otherwise, exile it. + this.getSpellAbility().addEffect(new SearchForSurvivorsEffect()); + + } + + public SearchForSurvivors(final SearchForSurvivors card) { + super(card); + } + + @Override + public SearchForSurvivors copy() { + return new SearchForSurvivors(this); + } +} + +class SearchForSurvivorsEffect extends OneShotEffect { + + public SearchForSurvivorsEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "Reorder your graveyard at random. " + + "An opponent chooses a card at random in your graveyard. " + + "If it's a creature card, put it onto the battlefield. " + + "Otherwise, exile it"; + } + + public SearchForSurvivorsEffect(final SearchForSurvivorsEffect effect) { + super(effect); + } + + @Override + public SearchForSurvivorsEffect copy() { + return new SearchForSurvivorsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + game.informPlayers("The controller of Search for Survivors will have their graveyard randomized. " + + " A card will be chosen at random from the controller's graveyard. " + + " The result is essentially the same as the card rule"); + // randomly arrange the graveyard + UUID[] shuffled = controller.getGraveyard().toArray(new UUID[0]); + for (int n = shuffled.length - 1; n > 0; n--) { + int r = RandomUtil.nextInt(n + 1); + UUID temp = shuffled[r]; + shuffled[r] = shuffled[n]; + shuffled[n] = temp; + } + controller.getGraveyard().clear(); + controller.getGraveyard().addAll(Arrays.asList(shuffled)); + // end of randomize + Cards cards = new CardsImpl(); + controller.getGraveyard().getCards(game).forEach((card) -> { + cards.add(card); + }); + if (!cards.isEmpty()) { + Card card = cards.getRandom(game); + cards.clear(); + cards.add(card); + controller.revealCards(source, cards, game); // reveal the card randomly chosen. + if (card.isCreature()) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } else { + controller.moveCards(card, Zone.EXILED, source, game); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SearingBlaze.java b/Mage.Sets/src/mage/cards/s/SearingBlaze.java index cda4d3ce257..03c5e9287c4 100644 --- a/Mage.Sets/src/mage/cards/s/SearingBlaze.java +++ b/Mage.Sets/src/mage/cards/s/SearingBlaze.java @@ -67,7 +67,7 @@ class SearingBlazeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - LandfallWatcher watcher = (LandfallWatcher) game.getState().getWatchers().get(LandfallWatcher.class.getSimpleName()); + LandfallWatcher watcher = game.getState().getWatcher(LandfallWatcher.class); Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); int damage = 1; if (watcher != null && watcher.landPlayed(source.getControllerId())) { diff --git a/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java b/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java index fcde9f08880..19603497bed 100644 --- a/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java +++ b/Mage.Sets/src/mage/cards/s/SeasonOfTheWitch.java @@ -87,13 +87,13 @@ class SeasonOfTheWitchEffect extends OneShotEffect { continue; } // Creatures that attacked are safe. - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null && watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))) { continue; } // Creatures that couldn't attack are safe. - CouldAttackThisTurnWatcher watcher2 = (CouldAttackThisTurnWatcher) game.getState().getWatchers().get(CouldAttackThisTurnWatcher.class.getSimpleName()); + CouldAttackThisTurnWatcher watcher2 = game.getState().getWatcher(CouldAttackThisTurnWatcher.class); if (watcher2 != null && !watcher2.getCouldAttackThisTurnCreatures().contains(new MageObjectReference(permanent, game))) { continue; @@ -112,7 +112,7 @@ class CouldAttackThisTurnWatcher extends Watcher { public final Set couldAttackThisTurnCreatures = new HashSet<>(); public CouldAttackThisTurnWatcher() { - super(CouldAttackThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(CouldAttackThisTurnWatcher.class, WatcherScope.GAME); } public CouldAttackThisTurnWatcher(final CouldAttackThisTurnWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SecondGuess.java b/Mage.Sets/src/mage/cards/s/SecondGuess.java index 140e9f74a2c..175535ad47a 100644 --- a/Mage.Sets/src/mage/cards/s/SecondGuess.java +++ b/Mage.Sets/src/mage/cards/s/SecondGuess.java @@ -49,9 +49,9 @@ class SecondSpellPredicate implements Predicate { @Override public boolean apply(StackObject input, Game game) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); - if (watcher.getSpellOrder(new MageObjectReference(input.getId(), game), game) == 2) { + if (watcher != null && watcher.getSpellOrder(new MageObjectReference(input.getId(), game), game) == 2) { return true; } diff --git a/Mage.Sets/src/mage/cards/s/SecondHarvest.java b/Mage.Sets/src/mage/cards/s/SecondHarvest.java index 747a0073d4c..841cb587374 100644 --- a/Mage.Sets/src/mage/cards/s/SecondHarvest.java +++ b/Mage.Sets/src/mage/cards/s/SecondHarvest.java @@ -60,7 +60,7 @@ class SecondHarvestEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { FilterControlledPermanent filter = new FilterControlledPermanent("each token you control"); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { if (permanent != null) { CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/s/SecondSunrise.java b/Mage.Sets/src/mage/cards/s/SecondSunrise.java index c4eed33e127..bdcc3f29aa3 100644 --- a/Mage.Sets/src/mage/cards/s/SecondSunrise.java +++ b/Mage.Sets/src/mage/cards/s/SecondSunrise.java @@ -57,7 +57,7 @@ class SecondSunriseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - SecondSunriseWatcher watcher = (SecondSunriseWatcher) game.getState().getWatchers().get(SecondSunriseWatcher.class.getSimpleName()); + SecondSunriseWatcher watcher = game.getState().getWatcher(SecondSunriseWatcher.class); if (watcher != null) { for (UUID id : watcher.cards) { Card c = game.getCard(id); @@ -82,7 +82,7 @@ class SecondSunriseWatcher extends Watcher { List cards = new ArrayList<>(); public SecondSunriseWatcher() { - super(SecondSunriseWatcher.class.getSimpleName(), WatcherScope.GAME); + super(SecondSunriseWatcher.class, WatcherScope.GAME); } public SecondSunriseWatcher(final SecondSunriseWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SecretPlans.java b/Mage.Sets/src/mage/cards/s/SecretPlans.java index 98098739409..b8ec3a1539d 100644 --- a/Mage.Sets/src/mage/cards/s/SecretPlans.java +++ b/Mage.Sets/src/mage/cards/s/SecretPlans.java @@ -24,7 +24,7 @@ public final class SecretPlans extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Face-down creatures"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public SecretPlans(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SecureTheWastes.java b/Mage.Sets/src/mage/cards/s/SecureTheWastes.java index 8d8e83e6750..2540f72bbeb 100644 --- a/Mage.Sets/src/mage/cards/s/SecureTheWastes.java +++ b/Mage.Sets/src/mage/cards/s/SecureTheWastes.java @@ -19,7 +19,7 @@ public final class SecureTheWastes extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{W}"); // create X 1/1 white Warrior creature tokens. - this.getSpellAbility().addEffect(new CreateTokenEffect(new WarriorToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new WarriorToken(), ManacostVariableValue.instance)); } public SecureTheWastes(final SecureTheWastes card) { diff --git a/Mage.Sets/src/mage/cards/s/Seedtime.java b/Mage.Sets/src/mage/cards/s/Seedtime.java index dd90232dcf7..1fe0480be89 100644 --- a/Mage.Sets/src/mage/cards/s/Seedtime.java +++ b/Mage.Sets/src/mage/cards/s/Seedtime.java @@ -53,7 +53,7 @@ enum OpponentCastBlueSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { if (opponentId != null) { diff --git a/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java b/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java index 9e1b83cbdd1..172b7a1c2bf 100644 --- a/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java +++ b/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java @@ -56,7 +56,7 @@ class CastNonCreatureSpellCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spellsCast = watcher.getSpellsCastThisTurn(source.getControllerId()); if (spellsCast != null) { diff --git a/Mage.Sets/src/mage/cards/s/SekKuarDeathkeeper.java b/Mage.Sets/src/mage/cards/s/SekKuarDeathkeeper.java index a1668e7278d..202bb00e802 100644 --- a/Mage.Sets/src/mage/cards/s/SekKuarDeathkeeper.java +++ b/Mage.Sets/src/mage/cards/s/SekKuarDeathkeeper.java @@ -28,8 +28,8 @@ public final class SekKuarDeathkeeper extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public SekKuarDeathkeeper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SelectForInspection.java b/Mage.Sets/src/mage/cards/s/SelectForInspection.java index b6dd0d29918..ebb2a820195 100644 --- a/Mage.Sets/src/mage/cards/s/SelectForInspection.java +++ b/Mage.Sets/src/mage/cards/s/SelectForInspection.java @@ -20,7 +20,7 @@ public final class SelectForInspection extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SelectForInspection(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java b/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java index a2a95ba4926..9b5a5232815 100644 --- a/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java +++ b/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java @@ -29,7 +29,7 @@ public final class SelesnyaEvangel extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SelesnyaEvangel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java b/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java index 5cec078a867..bc52232f2c9 100644 --- a/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java +++ b/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java @@ -32,7 +32,7 @@ public final class SelkieHedgeMage extends CardImpl { static { filter.add(new SubtypePredicate(SubType.FOREST)); filter2.add(new SubtypePredicate(SubType.ISLAND)); - filter3.add(new TappedPredicate()); + filter3.add(TappedPredicate.instance); } private static final String rule1 = "When {this} enters the battlefield, if you control two or more Forests, you may gain 3 life."; diff --git a/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java b/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java index 8b1325c6187..3516ba3642e 100644 --- a/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java +++ b/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java @@ -35,7 +35,7 @@ public final class SelvalaHeartOfTheWilds extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private static final String rule = "Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power."; @@ -54,7 +54,7 @@ public final class SelvalaHeartOfTheWilds extends CardImpl { // {G}, {T}: Add X mana in any combination of colors, where X is the greatest power among creatures you control. ManaEffect manaEffect = new AddManaInAnyCombinationEffect( - new GreatestPowerAmongControlledCreaturesValue(), rule2, + GreatestPowerAmongControlledCreaturesValue.instance, rule2, ColoredManaSymbol.B, ColoredManaSymbol.U, ColoredManaSymbol.R, ColoredManaSymbol.W, ColoredManaSymbol.G); Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, manaEffect, new ManaCostsImpl("{G}")); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java b/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java index 4b6a0acc3f2..dba8d34db80 100644 --- a/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java +++ b/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -21,6 +18,9 @@ import mage.players.Player; import mage.target.TargetCard; import mage.util.CardUtil; +import java.util.List; +import java.util.UUID; + /** * @author nantuko */ @@ -113,11 +113,9 @@ class SemblanceAnvilCostReductionEffect extends CostModificationEffectImpl { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { List imprinted = permanent.getImprinted(); - if (!imprinted.isEmpty()) { + if (imprinted != null && !imprinted.isEmpty()) { Card imprintedCard = game.getCard(imprinted.get(0)); - if (imprintedCard != null && imprintedCard.shareTypes(sourceCard)) { - return true; - } + return imprintedCard != null && imprintedCard.shareTypes(sourceCard); } } } diff --git a/Mage.Sets/src/mage/cards/s/SenateCourier.java b/Mage.Sets/src/mage/cards/s/SenateCourier.java new file mode 100644 index 00000000000..b016c0c4bcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SenateCourier.java @@ -0,0 +1,46 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SenateCourier extends CardImpl { + + public SenateCourier(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.BIRD); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {1}{W}: Senate Courier gains vigilance until end of turn. + this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect( + VigilanceAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl("{1}{W}"))); + } + + private SenateCourier(final SenateCourier card) { + super(card); + } + + @Override + public SenateCourier copy() { + return new SenateCourier(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SenateGriffin.java b/Mage.Sets/src/mage/cards/s/SenateGriffin.java new file mode 100644 index 00000000000..d85c995f774 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SenateGriffin.java @@ -0,0 +1,41 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SenateGriffin extends CardImpl { + + public SenateGriffin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W/U}{W/U}"); + + this.subtype.add(SubType.GRIFFIN); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Senate Griffin enters the battlefield, scry 1. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(1))); + } + + private SenateGriffin(final SenateGriffin card) { + super(card); + } + + @Override + public SenateGriffin copy() { + return new SenateGriffin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SenateGuildmage.java b/Mage.Sets/src/mage/cards/s/SenateGuildmage.java new file mode 100644 index 00000000000..d70f55d3dda --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SenateGuildmage.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class SenateGuildmage extends CardImpl { + + public SenateGuildmage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {W}, {T}: You gain 2 life. + Ability ability1 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(2), new ManaCostsImpl<>("{W}")); + ability1.addCost(new TapSourceCost()); + this.addAbility(ability1); + + // {U}, {T}: Draw a card, then discard a card. + Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(), new ManaCostsImpl("{U}")); + ability2.addCost(new TapSourceCost()); + this.addAbility(ability2); + } + + public SenateGuildmage(final SenateGuildmage card) { + super(card); + } + + @Override + public SenateGuildmage copy() { + return new SenateGuildmage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SengirAutocrat.java b/Mage.Sets/src/mage/cards/s/SengirAutocrat.java index ccfa468fd32..4355da9a6e5 100644 --- a/Mage.Sets/src/mage/cards/s/SengirAutocrat.java +++ b/Mage.Sets/src/mage/cards/s/SengirAutocrat.java @@ -27,7 +27,7 @@ public final class SengirAutocrat extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SERF)); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public SengirAutocrat(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SentinelOfTheEternalWatch.java b/Mage.Sets/src/mage/cards/s/SentinelOfTheEternalWatch.java index 04acffd490a..e3f64e774f0 100644 --- a/Mage.Sets/src/mage/cards/s/SentinelOfTheEternalWatch.java +++ b/Mage.Sets/src/mage/cards/s/SentinelOfTheEternalWatch.java @@ -1,11 +1,9 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfCombatTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -14,24 +12,26 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FirstTargetPointer; +import mage.filter.predicate.permanent.ControllerIsActivePlayerPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SentinelOfTheEternalWatch extends CardImpl { - private final UUID originalId; + private static final FilterPermanent filter = new FilterCreaturePermanent("creature controlled by the active player"); + + static { + filter.add(new ControllerIsActivePlayerPredicate()); + } public SentinelOfTheEternalWatch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}"); this.subtype.add(SubType.GIANT); this.subtype.add(SubType.SOLDIER); this.power = new MageInt(4); @@ -39,38 +39,22 @@ public final class SentinelOfTheEternalWatch extends CardImpl { // Vigilance this.addAbility(VigilanceAbility.getInstance()); - // At the beginning of combat on each opponent's turn, tap target creature that player controls. - Ability ability = new BeginningOfCombatTriggeredAbility(Zone.BATTLEFIELD, new TapTargetEffect("target creature that player controls"), TargetController.OPPONENT, false, true); - originalId = ability.getOriginalId(); - this.addAbility(ability); + // At the beginning of combat on each opponent's turn, tap target creature that player controls. + Ability ability = new BeginningOfCombatTriggeredAbility( + Zone.BATTLEFIELD, new TapTargetEffect("target creature that player controls"), + TargetController.OPPONENT, false, false + ); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } public SentinelOfTheEternalWatch(final SentinelOfTheEternalWatch card) { super(card); - this.originalId = card.originalId; } @Override public SentinelOfTheEternalWatch copy() { return new SentinelOfTheEternalWatch(this); } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - for (Effect effect : ability.getEffects()) { - UUID opponentId = effect.getTargetPointer().getFirst(game, ability); - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - effect.setTargetPointer(new FirstTargetPointer()); - FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature from the active opponent"); - filter.add(new ControllerIdPredicate(opponentId)); - Target target = new TargetCreaturePermanent(filter); - ability.addTarget(target); - } - } - } - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SentinelOfThePearlTrident.java b/Mage.Sets/src/mage/cards/s/SentinelOfThePearlTrident.java index 8d433e88531..93db168b201 100644 --- a/Mage.Sets/src/mage/cards/s/SentinelOfThePearlTrident.java +++ b/Mage.Sets/src/mage/cards/s/SentinelOfThePearlTrident.java @@ -33,7 +33,7 @@ public final class SentinelOfThePearlTrident extends CardImpl { private final static FilterControlledPermanent filter = new FilterControlledPermanent("historic permanent you control"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public SentinelOfThePearlTrident(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SentinelTower.java b/Mage.Sets/src/mage/cards/s/SentinelTower.java index 9988c741ccc..a6d9c54336f 100644 --- a/Mage.Sets/src/mage/cards/s/SentinelTower.java +++ b/Mage.Sets/src/mage/cards/s/SentinelTower.java @@ -1,9 +1,5 @@ - package mage.cards.s; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.MageObjectReference; import mage.abilities.common.SpellCastAllTriggeredAbility; @@ -20,8 +16,11 @@ import mage.game.events.GameEvent; import mage.target.common.TargetAnyTarget; import mage.watchers.Watcher; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class SentinelTower extends CardImpl { @@ -46,7 +45,7 @@ public final class SentinelTower extends CardImpl { class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility { SentinelTowerTriggeredAbility() { - super(new DamageTargetEffect(0), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); + super(new DamageTargetEffect(0), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false); this.addTarget(new TargetAnyTarget()); } @@ -63,7 +62,7 @@ class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { if (game.isActivePlayer(getControllerId()) && super.checkTrigger(event, game)) { - SentinelTowerWatcher watcher = (SentinelTowerWatcher) game.getState().getWatchers().get(SentinelTowerWatcher.class.getSimpleName()); + SentinelTowerWatcher watcher = game.getState().getWatcher(SentinelTowerWatcher.class); if (watcher == null) { return false; } @@ -102,7 +101,7 @@ class SentinelTowerWatcher extends Watcher { private final List spellsThisTurn; SentinelTowerWatcher() { - super(SentinelTowerWatcher.class.getSimpleName(), WatcherScope.GAME); + super(SentinelTowerWatcher.class, WatcherScope.GAME); this.spellsThisTurn = new ArrayList<>(); } diff --git a/Mage.Sets/src/mage/cards/s/SentinelsMark.java b/Mage.Sets/src/mage/cards/s/SentinelsMark.java new file mode 100644 index 00000000000..d22a0487adc --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SentinelsMark.java @@ -0,0 +1,67 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SentinelsMark extends CardImpl { + + public SentinelsMark(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + this.subtype.add(SubType.AURA); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets +1/+2 and has vigilance. + ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 2)); + ability.addEffect(new GainAbilityAttachedEffect( + VigilanceAbility.getInstance(), AttachmentType.AURA + ).setText("and has vigilance")); + this.addAbility(ability); + + // Addendum — When Sentinel's Mark enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new EntersBattlefieldTriggeredAbility(new GainAbilityAttachedEffect( + LifelinkAbility.getInstance(), AttachmentType.AURA, Duration.EndOfTurn + )), AddendumCondition.instance, "
Addendum — When {this} enters the battlefield, " + + "if you cast it during your main phase, enchanted creature gains lifelink until end of turn." + )); + } + + private SentinelsMark(final SentinelsMark card) { + super(card); + } + + @Override + public SentinelsMark copy() { + return new SentinelsMark(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java b/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java index b0073013b91..614a0252bc8 100644 --- a/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java +++ b/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java @@ -1,9 +1,6 @@ package mage.cards.s; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -13,8 +10,8 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; @@ -23,9 +20,13 @@ import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** - * * @author LevelX2 */ public final class SepulchralPrimordial extends CardImpl { @@ -37,28 +38,14 @@ public final class SepulchralPrimordial extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(4); - //Vigilance + // Intimidate this.addAbility(IntimidateAbility.getInstance()); // When Sepulchral Primordial enters the battlefield, for each opponent, you may put up to one // target creature card from that player's graveyard onto the battlefield under your control. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SepulchralPrimordialEffect(), false)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCard filter = new FilterCreatureCard("creature card from " + opponent.getName() + "'s graveyard"); - filter.add(new OwnerIdPredicate(opponentId)); - TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(0, 1, filter); - ability.addTarget(target); - } - } - } + Ability ability = new EntersBattlefieldTriggeredAbility(new SepulchralPrimordialEffect(), false); + ability.setTargetAdjuster(SepulchralPrimordialAdjuster.instance); + this.addAbility(ability); } public SepulchralPrimordial(final SepulchralPrimordial card) { @@ -71,6 +58,24 @@ public final class SepulchralPrimordial extends CardImpl { } } +enum SepulchralPrimordialAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterCard filter = new FilterCreatureCard("creature card from " + opponent.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(opponentId)); + TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(0, 1, filter); + ability.addTarget(target); + } + } + } +} + class SepulchralPrimordialEffect extends OneShotEffect { public SepulchralPrimordialEffect() { diff --git a/Mage.Sets/src/mage/cards/s/SeraphOfTheScales.java b/Mage.Sets/src/mage/cards/s/SeraphOfTheScales.java new file mode 100644 index 00000000000..d21c04c48f7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SeraphOfTheScales.java @@ -0,0 +1,65 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.AfterlifeAbility; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SeraphOfTheScales extends CardImpl { + + public SeraphOfTheScales(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {W}: Seraph of the Scales gains vigilance until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new GainAbilitySourceEffect( + VigilanceAbility.getInstance(), + Duration.EndOfTurn + ), new ManaCostsImpl("{W}") + )); + + // {B}: Seraph of the Scales gains deathtouch until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new GainAbilitySourceEffect( + DeathtouchAbility.getInstance(), + Duration.EndOfTurn + ), new ManaCostsImpl("{B}") + )); + + // Afterlife 2 + this.addAbility(new AfterlifeAbility(2)); + } + + private SeraphOfTheScales(final SeraphOfTheScales card) { + super(card); + } + + @Override + public SeraphOfTheScales copy() { + return new SeraphOfTheScales(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java b/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java index b0ff816b465..2b1808a1f96 100644 --- a/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java +++ b/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java @@ -26,7 +26,7 @@ public final class SerendibSorcerer extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature other than {this}"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SerendibSorcerer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SereneOffering.java b/Mage.Sets/src/mage/cards/s/SereneOffering.java index b8a0060a5aa..09a48a3deb8 100644 --- a/Mage.Sets/src/mage/cards/s/SereneOffering.java +++ b/Mage.Sets/src/mage/cards/s/SereneOffering.java @@ -22,7 +22,7 @@ public final class SereneOffering extends CardImpl { // Destroy target enchantment. You gain life equal to its converted mana cost. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - Effect effect = new GainLifeEffect(new TargetConvertedManaCost()); + Effect effect = new GainLifeEffect(TargetConvertedManaCost.instance); effect.setText("You gain life equal to its converted mana cost"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetEnchantmentPermanent()); diff --git a/Mage.Sets/src/mage/cards/s/SereneRemembrance.java b/Mage.Sets/src/mage/cards/s/SereneRemembrance.java index 15c9014ab86..b805b2f3b54 100644 --- a/Mage.Sets/src/mage/cards/s/SereneRemembrance.java +++ b/Mage.Sets/src/mage/cards/s/SereneRemembrance.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -15,20 +13,21 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInASingleGraveyard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SereneRemembrance extends CardImpl { - public SereneRemembrance (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}"); + public SereneRemembrance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); // Shuffle Serene Remembrance and up to three target cards from a single graveyard into their owners' libraries. this.getSpellAbility().addEffect(new SereneRemembranceEffect()); - this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0,3,new FilterCard("up to three target cards from a single graveyard"))); - + this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("up to three target cards from a single graveyard"))); + } public SereneRemembrance(final SereneRemembrance card) { @@ -36,30 +35,32 @@ public final class SereneRemembrance extends CardImpl { } @Override - public SereneRemembrance copy() { + public SereneRemembrance copy() { return new SereneRemembrance(this); } } class SereneRemembranceEffect extends OneShotEffect { - + public SereneRemembranceEffect() { super(Outcome.Benefit); this.staticText = "Shuffle Serene Remembrance and up to three target cards from a single graveyard into their owners' libraries"; } - + public SereneRemembranceEffect(final SereneRemembranceEffect effect) { super(effect); } - + @Override public SereneRemembranceEffect copy() { return new SereneRemembranceEffect(this); } - + @Override public boolean apply(Game game, Ability source) { boolean result = false; + + // 3 cards to graveyard Player graveyardPlayer = null; for (UUID cardInGraveyard : targetPointer.getTargets(game, source)) { Card card = game.getCard(cardInGraveyard); @@ -71,17 +72,22 @@ class SereneRemembranceEffect extends OneShotEffect { result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); } } - } + } } + + // source card to graveyard Card card = game.getCard(source.getSourceId()); - result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); - Player player = game.getPlayer(card.getOwnerId()); - if (player != null){ - player.shuffleLibrary(source, game); - } - if (graveyardPlayer != null && !graveyardPlayer.equals(player)) { - graveyardPlayer.shuffleLibrary(source, game); + if (card != null) { + result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); + Player player = game.getPlayer(card.getOwnerId()); + if (player != null) { + player.shuffleLibrary(source, game); + } + if (graveyardPlayer != null && !graveyardPlayer.equals(player)) { + graveyardPlayer.shuffleLibrary(source, game); + } } + return result; } } diff --git a/Mage.Sets/src/mage/cards/s/SerraAvatar.java b/Mage.Sets/src/mage/cards/s/SerraAvatar.java index 49680a7cc62..9fb4458a34c 100644 --- a/Mage.Sets/src/mage/cards/s/SerraAvatar.java +++ b/Mage.Sets/src/mage/cards/s/SerraAvatar.java @@ -29,7 +29,7 @@ public final class SerraAvatar extends CardImpl { this.toughness = new MageInt(0); // Serra Avatar's power and toughness are each equal to your life total. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new ControllerLifeCount(), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(ControllerLifeCount.instance, Duration.EndOfGame))); // When Serra Avatar is put into a graveyard from anywhere, shuffle it into its owner's library. this.addAbility(new PutIntoGraveFromAnywhereSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect())); diff --git a/Mage.Sets/src/mage/cards/s/SetessanTactics.java b/Mage.Sets/src/mage/cards/s/SetessanTactics.java index 20cbc8d6bbc..51e2b69656a 100644 --- a/Mage.Sets/src/mage/cards/s/SetessanTactics.java +++ b/Mage.Sets/src/mage/cards/s/SetessanTactics.java @@ -28,7 +28,7 @@ public final class SetessanTactics extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SetessanTactics(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java b/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java index 560c551805f..8c4af9f18d7 100644 --- a/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java +++ b/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java @@ -27,7 +27,7 @@ public final class SetonKrosanProtector extends CardImpl { private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Druid you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.DRUID)); } diff --git a/Mage.Sets/src/mage/cards/s/SeveredStrands.java b/Mage.Sets/src/mage/cards/s/SeveredStrands.java index a0e7278361b..523aedf125e 100644 --- a/Mage.Sets/src/mage/cards/s/SeveredStrands.java +++ b/Mage.Sets/src/mage/cards/s/SeveredStrands.java @@ -26,7 +26,7 @@ public final class SeveredStrands extends CardImpl { // You gain life equal to the sacrificed creature's toughness. Destroy target creature an opponent controls. this.getSpellAbility().addEffect(new GainLifeEffect( - new SacrificeCostCreaturesToughness(), + SacrificeCostCreaturesToughness.instance, "You gain life equal to the " + "sacrificed creature's toughness." )); diff --git a/Mage.Sets/src/mage/cards/s/ShadowAlleyDenizen.java b/Mage.Sets/src/mage/cards/s/ShadowAlleyDenizen.java index 7efd4395a89..99013be6f09 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowAlleyDenizen.java +++ b/Mage.Sets/src/mage/cards/s/ShadowAlleyDenizen.java @@ -29,7 +29,7 @@ public final class ShadowAlleyDenizen extends CardImpl { static { filter.add(new ColorPredicate(ObjectColor.BLACK)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ShadowAlleyDenizen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java b/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java index c85fcab35df..68795142d2d 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java +++ b/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java @@ -58,7 +58,7 @@ class ShadowOfTheGraveEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - CardsCycledOrDiscardedThisTurnWatcher watcher = (CardsCycledOrDiscardedThisTurnWatcher) game.getState().getWatchers().get(CardsCycledOrDiscardedThisTurnWatcher.class.getSimpleName()); + CardsCycledOrDiscardedThisTurnWatcher watcher = game.getState().getWatcher(CardsCycledOrDiscardedThisTurnWatcher.class); if (controller != null && watcher != null) { for (Card card : watcher.getCardsCycledOrDiscardedThisTurn(controller.getId()).getCards(game)) { diff --git a/Mage.Sets/src/mage/cards/s/ShaleskinBruiser.java b/Mage.Sets/src/mage/cards/s/ShaleskinBruiser.java index 1b093b930cf..c666d6d3bfe 100644 --- a/Mage.Sets/src/mage/cards/s/ShaleskinBruiser.java +++ b/Mage.Sets/src/mage/cards/s/ShaleskinBruiser.java @@ -27,7 +27,7 @@ public final class ShaleskinBruiser extends CardImpl { static { filter.add(new SubtypePredicate(SubType.BEAST)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } diff --git a/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java b/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java index 6041c378550..51cb113f7b1 100644 --- a/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java +++ b/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java @@ -101,7 +101,7 @@ class ShannaSisaysLegacyEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Card targetCard = game.getCard(event.getTargetId()); - StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); if (targetCard != null && stackObject != null && targetCard.getId().equals(source.getSourceId())) { if (stackObject instanceof Ability) { if (!stackObject.isControlledBy(source.getControllerId())) { diff --git a/Mage.Sets/src/mage/cards/s/ShapeAnew.java b/Mage.Sets/src/mage/cards/s/ShapeAnew.java index 63a7595fadd..feaef70514d 100644 --- a/Mage.Sets/src/mage/cards/s/ShapeAnew.java +++ b/Mage.Sets/src/mage/cards/s/ShapeAnew.java @@ -74,7 +74,7 @@ public final class ShapeAnew extends CardImpl { if (artifactCard != null) { targetController.moveCards(artifactCard, Zone.BATTLEFIELD, source, game); } - // 1/1/2011: If the first card the player reveals is an artifact card, he or she will still have to shuffle his or her library even though no other cards were revealed this way. + // 1/1/2011: If the first card the player reveals is an artifact card, he or she will still have to shuffle their library even though no other cards were revealed this way. targetController.shuffleLibrary(source, game); return true; } diff --git a/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java b/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java index 3e33b199b6b..78de80fc8ac 100644 --- a/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java +++ b/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java @@ -70,7 +70,7 @@ class AttachedAttackedOrBlockedSinceYourLastUpkeepCondition implements Condition @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); - AttackedOrBlockedSinceYourLastUpkeepWatcher watcher = (AttackedOrBlockedSinceYourLastUpkeepWatcher) game.getState().getWatchers().get(AttackedOrBlockedSinceYourLastUpkeepWatcher.class.getSimpleName()); + AttackedOrBlockedSinceYourLastUpkeepWatcher watcher = game.getState().getWatcher(AttackedOrBlockedSinceYourLastUpkeepWatcher.class); if (permanent != null && permanent.getAttachedTo() != null && watcher != null) { Permanent attachedTo = game.getBattlefield().getPermanent(permanent.getAttachedTo()); if (attachedTo == null) { @@ -95,7 +95,7 @@ class AttackedOrBlockedSinceYourLastUpkeepWatcher extends Watcher{ private final Map> attackedOrBlockedCreatures = new HashMap<>(); public AttackedOrBlockedSinceYourLastUpkeepWatcher() { - super(AttackedOrBlockedSinceYourLastUpkeepWatcher.class.getSimpleName(), WatcherScope.GAME); + super(AttackedOrBlockedSinceYourLastUpkeepWatcher.class, WatcherScope.GAME); } public AttackedOrBlockedSinceYourLastUpkeepWatcher(AttackedOrBlockedSinceYourLastUpkeepWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/ShaperApprentice.java b/Mage.Sets/src/mage/cards/s/ShaperApprentice.java index 32fa83dc11e..69e437c9265 100644 --- a/Mage.Sets/src/mage/cards/s/ShaperApprentice.java +++ b/Mage.Sets/src/mage/cards/s/ShaperApprentice.java @@ -28,7 +28,7 @@ public final class ShaperApprentice extends CardImpl { static { filter.add(new SubtypePredicate(SubType.MERFOLK)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ShaperApprentice(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SharedAnimosity.java b/Mage.Sets/src/mage/cards/s/SharedAnimosity.java index a51cea36fba..5cc7288616b 100644 --- a/Mage.Sets/src/mage/cards/s/SharedAnimosity.java +++ b/Mage.Sets/src/mage/cards/s/SharedAnimosity.java @@ -73,7 +73,7 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(Predicates.not(new PermanentIdPredicate(this.targetPointer.getFirst(game, source)))); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); boolean allCreatureTypes = false; if (permanent.isAllCreatureTypes()) { allCreatureTypes = true; @@ -98,7 +98,7 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - Permanent target = (Permanent) game.getPermanent(this.targetPointer.getFirst(game, source)); + Permanent target = game.getPermanent(this.targetPointer.getFirst(game, source)); if (target != null) { target.addPower(power); return true; diff --git a/Mage.Sets/src/mage/cards/s/SharedDiscovery.java b/Mage.Sets/src/mage/cards/s/SharedDiscovery.java index ec2df78cad8..5f79ba960e9 100644 --- a/Mage.Sets/src/mage/cards/s/SharedDiscovery.java +++ b/Mage.Sets/src/mage/cards/s/SharedDiscovery.java @@ -21,7 +21,7 @@ public final class SharedDiscovery extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SharedDiscovery(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/Sharktocrab.java b/Mage.Sets/src/mage/cards/s/Sharktocrab.java new file mode 100644 index 00000000000..64c91d73a15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Sharktocrab.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.OneOrMoreCountersAddedTriggeredAbility; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Sharktocrab extends CardImpl { + + public Sharktocrab(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); + + this.subtype.add(SubType.FISH); + this.subtype.add(SubType.OCTOPUS); + this.subtype.add(SubType.CRAB); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // {2}{G}{U}: Adapt 1. + this.addAbility(new AdaptAbility(1, "{2}{G}{U}")); + + // Whenever one or more +1/+1 counter are put on Sharktocrab, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step. + Ability ability = new OneOrMoreCountersAddedTriggeredAbility(new TapTargetEffect()); + ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That creature")); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + private Sharktocrab(final Sharktocrab card) { + super(card); + } + + @Override + public Sharktocrab copy() { + return new Sharktocrab(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShatteredCrypt.java b/Mage.Sets/src/mage/cards/s/ShatteredCrypt.java index 340152cd769..7ce9d8e1525 100644 --- a/Mage.Sets/src/mage/cards/s/ShatteredCrypt.java +++ b/Mage.Sets/src/mage/cards/s/ShatteredCrypt.java @@ -1,9 +1,7 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; @@ -15,9 +13,11 @@ import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ShatteredCrypt extends CardImpl { @@ -29,18 +29,8 @@ public final class ShatteredCrypt extends CardImpl { Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return X target creature cards from your graveyard to your hand"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(new ManacostVariableValue())); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(1, new FilterCreatureCard())); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard((xValue != 1 ? " creature cards" : "creature card") + " from your graveyard")); - ability.addTarget(target); - } + this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(ManacostVariableValue.instance)); + this.getSpellAbility().setTargetAdjuster(ShatteredCryptAdjuster.instance); } public ShatteredCrypt(final ShatteredCrypt card) { @@ -52,3 +42,15 @@ public final class ShatteredCrypt extends CardImpl { return new ShatteredCrypt(this); } } + +enum ShatteredCryptAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard((xValue != 1 ? " creature cards" : "creature card") + " from your graveyard")); + ability.addTarget(target); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/ShaukuEndbringer.java b/Mage.Sets/src/mage/cards/s/ShaukuEndbringer.java index 7ed79f033b0..1a700a7b3cf 100644 --- a/Mage.Sets/src/mage/cards/s/ShaukuEndbringer.java +++ b/Mage.Sets/src/mage/cards/s/ShaukuEndbringer.java @@ -72,7 +72,7 @@ public final class ShaukuEndbringer extends CardImpl{ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ShaukuEndbringerEffect() { diff --git a/Mage.Sets/src/mage/cards/s/SheerDrop.java b/Mage.Sets/src/mage/cards/s/SheerDrop.java index b0b89c1a29f..de325c267f2 100644 --- a/Mage.Sets/src/mage/cards/s/SheerDrop.java +++ b/Mage.Sets/src/mage/cards/s/SheerDrop.java @@ -20,7 +20,7 @@ public final class SheerDrop extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SheerDrop(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ShieldhideDragon.java b/Mage.Sets/src/mage/cards/s/ShieldhideDragon.java index b89b5bde7d1..68d416731e1 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldhideDragon.java +++ b/Mage.Sets/src/mage/cards/s/ShieldhideDragon.java @@ -27,7 +27,7 @@ public final class ShieldhideDragon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other Dragon creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/s/ShieldmageElder.java b/Mage.Sets/src/mage/cards/s/ShieldmageElder.java index f31d93ea593..b79d1d0544a 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldmageElder.java +++ b/Mage.Sets/src/mage/cards/s/ShieldmageElder.java @@ -30,13 +30,13 @@ public final class ShieldmageElder extends CardImpl { private static final FilterControlledPermanent filter1 = new FilterControlledPermanent("untapped Clerics you control"); static { - filter1.add(Predicates.not(new TappedPredicate())); + filter1.add(Predicates.not(TappedPredicate.instance)); filter1.add(new SubtypePredicate(SubType.CLERIC)); } private static final FilterControlledPermanent filter2 = new FilterControlledPermanent("untapped Wizards you control"); static { - filter2.add(Predicates.not(new TappedPredicate())); + filter2.add(Predicates.not(TappedPredicate.instance)); filter2.add(new SubtypePredicate(SubType.WIZARD)); } diff --git a/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java b/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java index 34d307add14..5729db0fec3 100644 --- a/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java +++ b/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java @@ -31,7 +31,7 @@ public final class ShimianNightStalker extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public ShimianNightStalker(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ShimmerOfPossibility.java b/Mage.Sets/src/mage/cards/s/ShimmerOfPossibility.java new file mode 100644 index 00000000000..7922d3035bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShimmerOfPossibility.java @@ -0,0 +1,36 @@ +package mage.cards.s; + +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ShimmerOfPossibility extends CardImpl { + + public ShimmerOfPossibility(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); + + // Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect( + new StaticValue(4), false, new StaticValue(1), StaticFilters.FILTER_CARD, Zone.LIBRARY, + false, false, false, Zone.HAND, false, false, false + )); + } + + private ShimmerOfPossibility(final ShimmerOfPossibility card) { + super(card); + } + + @Override + public ShimmerOfPossibility copy() { + return new ShimmerOfPossibility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShiningShoal.java b/Mage.Sets/src/mage/cards/s/ShiningShoal.java index 79ad6ea8bfb..f4d8b7a9082 100644 --- a/Mage.Sets/src/mage/cards/s/ShiningShoal.java +++ b/Mage.Sets/src/mage/cards/s/ShiningShoal.java @@ -44,7 +44,7 @@ public final class ShiningShoal extends CardImpl { this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter), true))); // The next X damage that a source of your choice would deal to you and/or creatures you control this turn is dealt to any target instead. - this.getSpellAbility().addEffect(new ShiningShoalRedirectDamageTargetEffect(Duration.EndOfTurn, new ExileFromHandCostCardConvertedMana())); + this.getSpellAbility().addEffect(new ShiningShoalRedirectDamageTargetEffect(Duration.EndOfTurn, ExileFromHandCostCardConvertedMana.instance)); this.getSpellAbility().addTarget(new TargetSource()); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java b/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java index a207a9a8b58..de016872aea 100644 --- a/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java +++ b/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java @@ -33,7 +33,7 @@ public final class ShipwreckSinger extends CardImpl { private static final FilterCreaturePermanent filterAttacking = new FilterCreaturePermanent("Attacking creatures"); static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); - filterAttacking.add(new AttackingPredicate()); + filterAttacking.add(AttackingPredicate.instance); } public ShipwreckSinger(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java b/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java index 6e0d7d255f4..5af0b2937ee 100644 --- a/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java +++ b/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -13,11 +11,7 @@ import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEf import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -25,8 +19,9 @@ import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author emerald000 */ public final class ShireiShizosCaretaker extends CardImpl { @@ -78,8 +73,8 @@ class ShireiShizosCaretakerTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; Permanent LKIpermanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId()); Card card = game.getCard(zEvent.getTargetId()); - - if (card != null && LKIpermanent != null + if (card != null + && LKIpermanent != null && card.isOwnedBy(this.controllerId) && zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.BATTLEFIELD diff --git a/Mage.Sets/src/mage/cards/s/ShriekingMogg.java b/Mage.Sets/src/mage/cards/s/ShriekingMogg.java index 63260a809a4..2df0930767c 100644 --- a/Mage.Sets/src/mage/cards/s/ShriekingMogg.java +++ b/Mage.Sets/src/mage/cards/s/ShriekingMogg.java @@ -23,7 +23,7 @@ public final class ShriekingMogg extends CardImpl { static final FilterCreaturePermanent filter = new FilterCreaturePermanent("all other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ShriekingMogg(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ShrineOfTheForsakenGods.java b/Mage.Sets/src/mage/cards/s/ShrineOfTheForsakenGods.java index 992ffd901ce..0dac6ffc82b 100644 --- a/Mage.Sets/src/mage/cards/s/ShrineOfTheForsakenGods.java +++ b/Mage.Sets/src/mage/cards/s/ShrineOfTheForsakenGods.java @@ -25,7 +25,7 @@ public final class ShrineOfTheForsakenGods extends CardImpl { private static final FilterSpell filter = new FilterSpell("colorless spells"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public ShrineOfTheForsakenGods(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/ShroudedLore.java b/Mage.Sets/src/mage/cards/s/ShroudedLore.java index 16abab99ed2..b4042febd67 100644 --- a/Mage.Sets/src/mage/cards/s/ShroudedLore.java +++ b/Mage.Sets/src/mage/cards/s/ShroudedLore.java @@ -1,16 +1,10 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -23,14 +17,15 @@ import mage.players.Player; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author LoneFox */ public final class ShroudedLore extends CardImpl { public ShroudedLore(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); // Target opponent chooses a card in your graveyard. You may pay {B}. If you do, repeat this process except that opponent can't choose a card already chosen for Shrouded Lore. Then put the last chosen card into your hand. this.getSpellAbility().addEffect(new ShroudedLoreEffect()); @@ -67,8 +62,7 @@ class ShroudedLoreEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); - if(you != null && opponent != null) - { + if (you != null && opponent != null) { FilterCard filter = new FilterCard(); filter.add(new OwnerIdPredicate(you.getId())); Cost cost = new ManaCostsImpl("{B}"); @@ -78,31 +72,31 @@ class ShroudedLoreEffect extends OneShotEffect { do { chosenCard = new TargetCardInGraveyard(filter); chosenCard.setNotTarget(true); - if(chosenCard.canChoose(opponent.getId(), game)) { + if (chosenCard.canChoose(opponent.getId(), game)) { opponent.chooseTarget(Outcome.ReturnToHand, chosenCard, source, game); card = game.getCard(chosenCard.getFirstTarget()); - filter.add(Predicates.not(new CardIdPredicate(card.getId()))); - game.informPlayers("Shrouded Lore: " + opponent.getLogName() + " has chosen " + card.getLogName()); - } - else { + if (card != null) { + filter.add(Predicates.not(new CardIdPredicate(card.getId()))); + game.informPlayers("Shrouded Lore: " + opponent.getLogName() + " has chosen " + card.getLogName()); + } + } else { done = true; } - if(!done) { - if(cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {B} to choose a different card ?", source, game)) { + if (!done) { + if (cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {B} to choose a different card ?", source, game)) { cost.clearPaid(); - if(!cost.pay(source, game, source.getSourceId(), you.getId(), false, null)) { + if (!cost.pay(source, game, source.getSourceId(), you.getId(), false, null)) { done = true; } - } - else { + } else { done = true; } } - } while(!done); + } while (!done); - if(card != null) { + if (card != null) { Cards cardsToHand = new CardsImpl(); cardsToHand.add(card); you.moveCards(cardsToHand, Zone.HAND, source, game); diff --git a/Mage.Sets/src/mage/cards/s/SickeningDreams.java b/Mage.Sets/src/mage/cards/s/SickeningDreams.java index ba51c255802..3a74c9e7eec 100644 --- a/Mage.Sets/src/mage/cards/s/SickeningDreams.java +++ b/Mage.Sets/src/mage/cards/s/SickeningDreams.java @@ -30,7 +30,7 @@ public final class SickeningDreams extends CardImpl { this.getSpellAbility().addCost(new SickeningDreamsAdditionalCost()); // Sickening Dreams deals X damage to each creature and each player. - this.getSpellAbility().addEffect(new DamageEverythingEffect(new GetXValue(), new FilterCreaturePermanent())); + this.getSpellAbility().addEffect(new DamageEverythingEffect(GetXValue.instance, new FilterCreaturePermanent())); } public SickeningDreams(final SickeningDreams card) { diff --git a/Mage.Sets/src/mage/cards/s/SickeningShoal.java b/Mage.Sets/src/mage/cards/s/SickeningShoal.java index 32b4fb3587f..5bec8f2fe76 100644 --- a/Mage.Sets/src/mage/cards/s/SickeningShoal.java +++ b/Mage.Sets/src/mage/cards/s/SickeningShoal.java @@ -40,7 +40,7 @@ public final class SickeningShoal extends CardImpl { this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter), true))); // Target creature gets -X/-X until end of turn. - DynamicValue x = new SignInversionDynamicValue(new ExileFromHandCostCardConvertedMana()); + DynamicValue x = new SignInversionDynamicValue(ExileFromHandCostCardConvertedMana.instance); this.getSpellAbility().addEffect(new BoostTargetEffect(x, x, Duration.EndOfTurn, true)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/s/SickleDancer.java b/Mage.Sets/src/mage/cards/s/SickleDancer.java index ec80b693b90..c5d70a1f745 100644 --- a/Mage.Sets/src/mage/cards/s/SickleDancer.java +++ b/Mage.Sets/src/mage/cards/s/SickleDancer.java @@ -24,7 +24,7 @@ public final class SickleDancer extends CardImpl { private static final FilterTeamPermanent filter = new FilterTeamPermanent(SubType.WARRIOR, "Warrior creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SickleDancer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SidarJabari.java b/Mage.Sets/src/mage/cards/s/SidarJabari.java index 75cd2d644d9..73f1b6593ef 100644 --- a/Mage.Sets/src/mage/cards/s/SidarJabari.java +++ b/Mage.Sets/src/mage/cards/s/SidarJabari.java @@ -24,7 +24,7 @@ public final class SidarJabari extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public SidarJabari(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SiftThroughSands.java b/Mage.Sets/src/mage/cards/s/SiftThroughSands.java index bb581423064..2926888d8db 100644 --- a/Mage.Sets/src/mage/cards/s/SiftThroughSands.java +++ b/Mage.Sets/src/mage/cards/s/SiftThroughSands.java @@ -66,7 +66,7 @@ class SiftThroughSandsCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SiftThroughSandsWatcher watcher = (SiftThroughSandsWatcher) game.getState().getWatchers().get(SiftThroughSandsWatcher.class.getSimpleName(), source.getControllerId()); + SiftThroughSandsWatcher watcher = game.getState().getWatcher(SiftThroughSandsWatcher.class, source.getControllerId()); if (watcher != null) { return watcher.conditionMet(); } @@ -80,7 +80,7 @@ class SiftThroughSandsWatcher extends Watcher { boolean castReachThroughMists = false; public SiftThroughSandsWatcher() { - super(SiftThroughSandsWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(SiftThroughSandsWatcher.class, WatcherScope.PLAYER); } public SiftThroughSandsWatcher(final SiftThroughSandsWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SifterOfSkulls.java b/Mage.Sets/src/mage/cards/s/SifterOfSkulls.java index fd5064b8613..cf4e0048679 100644 --- a/Mage.Sets/src/mage/cards/s/SifterOfSkulls.java +++ b/Mage.Sets/src/mage/cards/s/SifterOfSkulls.java @@ -28,8 +28,8 @@ public final class SifterOfSkulls extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another nontoken creature you control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public SifterOfSkulls(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SigilOfSleep.java b/Mage.Sets/src/mage/cards/s/SigilOfSleep.java index 2a84a060c08..9e054e1d7f2 100644 --- a/Mage.Sets/src/mage/cards/s/SigilOfSleep.java +++ b/Mage.Sets/src/mage/cards/s/SigilOfSleep.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -19,6 +18,7 @@ import mage.game.Game; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FirstTargetPointer; /** @@ -27,10 +27,8 @@ import mage.target.targetpointer.FirstTargetPointer; */ public final class SigilOfSleep extends CardImpl { - private final UUID originalId; - public SigilOfSleep(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -39,34 +37,17 @@ public final class SigilOfSleep extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Whenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand. Effect effect = new ReturnToHandTargetEffect(); effect.setText("return target creature that player controls to its owner's hand"); ability = new DealsDamageToAPlayerAttachedTriggeredAbility(effect, "enchanted", false, true, false); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(SigilOfSleepAdjuster.instance); this.addAbility(ability); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - UUID playerId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); - if (playerId != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that player controls"); - filter.add(new ControllerIdPredicate(playerId)); - Target target = new TargetCreaturePermanent(filter); - ability.getTargets().clear(); - ability.addTarget(target); - ability.getEffects().get(0).setTargetPointer(new FirstTargetPointer()); - } - - } } public SigilOfSleep(final SigilOfSleep card) { super(card); - this.originalId = card.originalId; } @Override @@ -74,3 +55,20 @@ public final class SigilOfSleep extends CardImpl { return new SigilOfSleep(this); } } + +enum SigilOfSleepAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + UUID playerId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + if (playerId != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that player controls"); + filter.add(new ControllerIdPredicate(playerId)); + Target target = new TargetCreaturePermanent(filter); + ability.getTargets().clear(); + ability.addTarget(target); + ability.getEffects().get(0).setTargetPointer(new FirstTargetPointer()); + } + } +} diff --git a/Mage.Sets/src/mage/cards/s/SigilTracer.java b/Mage.Sets/src/mage/cards/s/SigilTracer.java index bcce031f3be..d8658b60d9f 100644 --- a/Mage.Sets/src/mage/cards/s/SigilTracer.java +++ b/Mage.Sets/src/mage/cards/s/SigilTracer.java @@ -29,7 +29,7 @@ public final class SigilTracer extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Wizards you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.WIZARD)); } diff --git a/Mage.Sets/src/mage/cards/s/SignalTheClans.java b/Mage.Sets/src/mage/cards/s/SignalTheClans.java index 4c466105572..bcd225c68e1 100644 --- a/Mage.Sets/src/mage/cards/s/SignalTheClans.java +++ b/Mage.Sets/src/mage/cards/s/SignalTheClans.java @@ -69,7 +69,7 @@ class SignalTheClansEffect extends SearchEffect { if (player.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { Cards cards = new CardsImpl(); - for (UUID cardId: (List)target.getTargets()) { + for (UUID cardId: target.getTargets()) { Card card = player.getLibrary().remove(cardId, game); if (card != null){ cards.add(card); diff --git a/Mage.Sets/src/mage/cards/s/SilburlindSnapper.java b/Mage.Sets/src/mage/cards/s/SilburlindSnapper.java index bf16032e77e..bc605e466fd 100644 --- a/Mage.Sets/src/mage/cards/s/SilburlindSnapper.java +++ b/Mage.Sets/src/mage/cards/s/SilburlindSnapper.java @@ -69,7 +69,7 @@ class SilburlindSnapperEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(source.getSourceId())) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spellsCast = watcher.getSpellsCastThisTurn(source.getControllerId()); if (spellsCast != null) { diff --git a/Mage.Sets/src/mage/cards/s/SilentChantZubera.java b/Mage.Sets/src/mage/cards/s/SilentChantZubera.java index 8854eb990ec..b2d0ec1e0bc 100644 --- a/Mage.Sets/src/mage/cards/s/SilentChantZubera.java +++ b/Mage.Sets/src/mage/cards/s/SilentChantZubera.java @@ -48,8 +48,11 @@ class SilentChantZuberaDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - ZuberasDiedWatcher watcher = (ZuberasDiedWatcher) game.getState().getWatchers().get(ZuberasDiedWatcher.class.getSimpleName()); - return watcher.zuberasDiedThisTurn * 2; + ZuberasDiedWatcher watcher = game.getState().getWatcher(ZuberasDiedWatcher.class); + if(watcher != null) { + return watcher.getZuberasDiedThisTurn() * 2; + } + return 0; } @Override diff --git a/Mage.Sets/src/mage/cards/s/SilhanaWayfinder.java b/Mage.Sets/src/mage/cards/s/SilhanaWayfinder.java new file mode 100644 index 00000000000..c6aa18b579f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SilhanaWayfinder.java @@ -0,0 +1,60 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SilhanaWayfinder extends CardImpl { + + private static final FilterCard filter + = new FilterCard("a creature or land card"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND) + )); + } + + public SilhanaWayfinder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.SCOUT); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // When Silhana Wayfinder enters the battlefield, look at the top four cards of your library. You may reveal a creature or land card from among them and put it on top of your library. Put the rest on the bottom of your library in a random order. + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( + new StaticValue(4), false, new StaticValue(1), filter, Zone.LIBRARY, false, + true, true, Zone.LIBRARY, false, true, false + ).setText("look at the top four cards of your library. " + + "You may reveal a creature or land card from among them " + + "and put it on top of your library. Put the rest " + + "on the bottom of your library in a random order."), false + )); + } + + private SilhanaWayfinder(final SilhanaWayfinder card) { + super(card); + } + + @Override + public SilhanaWayfinder copy() { + return new SilhanaWayfinder(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SilklashSpider.java b/Mage.Sets/src/mage/cards/s/SilklashSpider.java index 0cd6ebd1353..05b44bcf58a 100644 --- a/Mage.Sets/src/mage/cards/s/SilklashSpider.java +++ b/Mage.Sets/src/mage/cards/s/SilklashSpider.java @@ -40,7 +40,7 @@ public final class SilklashSpider extends CardImpl { this.addAbility(ReachAbility.getInstance()); // {X}{G}{G}: Silklash Spider deals X damage to each creature with flying. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new DamageAllEffect(new ManacostVariableValue(), filter), + new DamageAllEffect(ManacostVariableValue.instance, filter), new ManaCostsImpl("{X}{G}{G}"))); } diff --git a/Mage.Sets/src/mage/cards/s/SilumgarsScorn.java b/Mage.Sets/src/mage/cards/s/SilumgarsScorn.java index ed30b202d87..c275bbc3a67 100644 --- a/Mage.Sets/src/mage/cards/s/SilumgarsScorn.java +++ b/Mage.Sets/src/mage/cards/s/SilumgarsScorn.java @@ -93,7 +93,7 @@ class SilumgarsScornCounterEffect extends OneShotEffect { if (spell != null) { Player player = game.getPlayer(spell.getControllerId()); if (player != null) { - DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = (DragonOnTheBattlefieldWhileSpellWasCastWatcher) game.getState().getWatchers().get(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class.getSimpleName()); + DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); boolean condition = watcher != null && watcher.castWithConditionTrue(source.getId()); if (!condition) { for (Cost cost: source.getCosts()) { diff --git a/Mage.Sets/src/mage/cards/s/SimicAscendancy.java b/Mage.Sets/src/mage/cards/s/SimicAscendancy.java new file mode 100644 index 00000000000..6316d881f74 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SimicAscendancy.java @@ -0,0 +1,107 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author jmharmon + */ + +public final class SimicAscendancy extends CardImpl { + + public SimicAscendancy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}{U}"); + + // {1}{G}{U}: Put a +1/+1 counter on target creature you control. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{1}{G}{U}")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // Whenever one or more +1/+1 counters are put on a creature you control, put that many growth counters on Simic Ascendancy. + this.addAbility(new SimicAscendancyTriggeredAbility()); + + // At the beginning of your upkeep, if Simic Ascendancy has twenty or more growth counters on it, you win the game. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, new WinGameSourceControllerEffect(), + TargetController.YOU, false + ), new SourceHasCounterCondition(CounterType.GROWTH, 20, Integer.MAX_VALUE), + "At the beginning of your upkeep, if {this} has twenty " + + "or more growth counters on it, you win the game" + )); + } + + private SimicAscendancy(final SimicAscendancy card) { + super(card); + } + + @Override + public SimicAscendancy copy() { + return new SimicAscendancy(this); + } +} + +class SimicAscendancyTriggeredAbility extends TriggeredAbilityImpl { + + SimicAscendancyTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.GROWTH.createInstance()), false); + } + + private SimicAscendancyTriggeredAbility(final SimicAscendancyTriggeredAbility ability) { + super(ability); + } + + @Override + public SimicAscendancyTriggeredAbility copy() { + return new SimicAscendancyTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_ADDED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getData().equals(CounterType.P1P1.getName()) && event.getAmount() > 0) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent == null) { + permanent = game.getPermanentEntering(event.getTargetId()); + } + if (permanent != null + && !event.getTargetId().equals(this.getSourceId()) + && permanent.isCreature() + && permanent.isControlledBy(this.getControllerId())) { + this.getEffects().clear(); + this.addEffect(new AddCountersSourceEffect(CounterType.GROWTH.createInstance(event.getAmount()))); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever one or more +1/+1 counters are put on a creature you control, put that many growth counters on {this}."; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SimicLocket.java b/Mage.Sets/src/mage/cards/s/SimicLocket.java new file mode 100644 index 00000000000..f301f9cb590 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SimicLocket.java @@ -0,0 +1,47 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class SimicLocket extends CardImpl { + + public SimicLocket(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {T}: Add {G} or {U}. + this.addAbility(new GreenManaAbility()); + this.addAbility(new BlueManaAbility()); + + // {G/U}{G/U}{G/U}{G/U}, {T}, Sacrifice Simic Locket: Draw two cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), new ManaCostsImpl<>("{G/U}{G/U}{G/U}{G/U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public SimicLocket(final SimicLocket card) { + super(card); + } + + @Override + public SimicLocket copy() { + return new SimicLocket(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/Simulacrum.java b/Mage.Sets/src/mage/cards/s/Simulacrum.java index a810a5f4c99..f1afc1603df 100644 --- a/Mage.Sets/src/mage/cards/s/Simulacrum.java +++ b/Mage.Sets/src/mage/cards/s/Simulacrum.java @@ -47,7 +47,7 @@ class SimulacrumAmount implements DynamicValue { @Override public int calculate(Game game, Ability source, Effect effect) { - AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = (AmountOfDamageAPlayerReceivedThisTurnWatcher) game.getState().getWatchers().get(AmountOfDamageAPlayerReceivedThisTurnWatcher.class.getSimpleName()); + AmountOfDamageAPlayerReceivedThisTurnWatcher watcher = game.getState().getWatcher(AmountOfDamageAPlayerReceivedThisTurnWatcher.class); if(watcher != null) { return watcher.getAmountOfDamageReceivedThisTurn(source.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/s/SirensCall.java b/Mage.Sets/src/mage/cards/s/SirensCall.java index 9512ea85e43..e37225124eb 100644 --- a/Mage.Sets/src/mage/cards/s/SirensCall.java +++ b/Mage.Sets/src/mage/cards/s/SirensCall.java @@ -120,7 +120,7 @@ class SirensCallDestroyEffect extends OneShotEffect { continue; } // Creatures that attacked are safe. - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher != null && watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))) { continue; } diff --git a/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java b/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java index c32c0bcd377..ab178a600c2 100644 --- a/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java +++ b/Mage.Sets/src/mage/cards/s/SistersOfStoneDeath.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.LinkedList; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -14,11 +11,7 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; @@ -30,8 +23,10 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetCreaturePermanent; +import java.util.LinkedList; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SistersOfStoneDeath extends CardImpl { @@ -39,7 +34,7 @@ public final class SistersOfStoneDeath extends CardImpl { private UUID exileId = UUID.randomUUID(); public SistersOfStoneDeath(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}{G}{G}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.GORGON); @@ -100,7 +95,9 @@ class SistersOfStoneDeathEffect extends OneShotEffect { LinkedList cards = new LinkedList<>(exile); for (UUID cardId : cards) { Card card = game.getCard(cardId); - cardsInExile.add(card); + if (card != null) { + cardsInExile.add(card); + } } if (controller.choose(Outcome.PutCreatureInPlay, cardsInExile, target, game)) { Card chosenCard = game.getCard(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/s/SivvisValor.java b/Mage.Sets/src/mage/cards/s/SivvisValor.java index 631c739f70b..307d3a3f45a 100644 --- a/Mage.Sets/src/mage/cards/s/SivvisValor.java +++ b/Mage.Sets/src/mage/cards/s/SivvisValor.java @@ -38,7 +38,7 @@ public final class SivvisValor extends CardImpl { static { filter.add(new SubtypePredicate(SubType.PLAINS)); - filterCreature.add(Predicates.not(new TappedPredicate())); + filterCreature.add(Predicates.not(TappedPredicate.instance)); } public SivvisValor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java b/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java index 9f445da7730..63368b9c1ee 100644 --- a/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java +++ b/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java @@ -61,8 +61,8 @@ class OpponentWasDealtDamageCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get(BloodthirstWatcher.class.getSimpleName(), source.getControllerId()); - return watcher.conditionMet(); + BloodthirstWatcher watcher = game.getState().getWatcher(BloodthirstWatcher.class, source.getControllerId()); + return watcher != null && watcher.conditionMet(); } @Override diff --git a/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java b/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java new file mode 100644 index 00000000000..91818d5cc2a --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java @@ -0,0 +1,58 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.DamageMultiEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetAnyTargetAmount; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SkarrganHellkite extends CardImpl { + + public SkarrganHellkite(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Riot + this.addAbility(new RiotAbility()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {3}{R}: Skarrgan Hellkite deals 2 damage divided as you choose among one or two targets. Activate this ability only if Skarrgan Hellkite has a +1/+1 counter on it. + Ability ability = new ConditionalActivatedAbility( + Zone.BATTLEFIELD, new DamageMultiEffect(2), + new ManaCostsImpl("{3}{R}"), new SourceHasCounterCondition(CounterType.P1P1), + "{3}{R}: {this} deals 2 damage divided as you choose among one or two targets. " + + "Activate this ability only if {this} has a +1/+1 counter on it." + ); + ability.addTarget(new TargetAnyTargetAmount(2)); + this.addAbility(ability); + } + + private SkarrganHellkite(final SkarrganHellkite card) { + super(card); + } + + @Override + public SkarrganHellkite copy() { + return new SkarrganHellkite(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkatewingSpy.java b/Mage.Sets/src/mage/cards/s/SkatewingSpy.java new file mode 100644 index 00000000000..5e548117717 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkatewingSpy.java @@ -0,0 +1,64 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.CounterPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SkatewingSpy extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(new CounterPredicate(CounterType.P1P1)); + } + + public SkatewingSpy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.VEDALKEN); + this.subtype.add(SubType.ROGUE); + this.subtype.add(SubType.MUTANT); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // {5}{U}: Adapt 2. + this.addAbility(new AdaptAbility(2, "{5}{U}")); + + // Each creature you control with a +1/+1 counter on it has flying. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityAllEffect( + FlyingAbility.getInstance(), + Duration.WhileOnBattlefield, + filter, "Each creature you control " + + "with a +1/+1 counter on it has flying" + ) + )); + } + + private SkatewingSpy(final SkatewingSpy card) { + super(card); + } + + @Override + public SkatewingSpy copy() { + return new SkatewingSpy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkeletalScrying.java b/Mage.Sets/src/mage/cards/s/SkeletalScrying.java index 712f565e937..558d6319396 100644 --- a/Mage.Sets/src/mage/cards/s/SkeletalScrying.java +++ b/Mage.Sets/src/mage/cards/s/SkeletalScrying.java @@ -34,7 +34,7 @@ public final class SkeletalScrying extends CardImpl { ability.setRuleAtTheTop(true); this.addAbility(ability); // You draw X cards and you lose X life. - this.getSpellAbility().addEffect(new SkeletalScryingEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new SkeletalScryingEffect(ManacostVariableValue.instance)); } diff --git a/Mage.Sets/src/mage/cards/s/Skeletonize.java b/Mage.Sets/src/mage/cards/s/Skeletonize.java index 7eba0bdead6..d00c5ef3749 100644 --- a/Mage.Sets/src/mage/cards/s/Skeletonize.java +++ b/Mage.Sets/src/mage/cards/s/Skeletonize.java @@ -95,7 +95,7 @@ class SkeletonizeDelayedTriggeredAbility extends DelayedTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zce = (ZoneChangeEvent) event; if (zce.isDiesEvent()) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), this.getSourceId()); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, this.getSourceId()); if (watcher != null) { return watcher.wasDamaged(zce.getTarget(), game); } diff --git a/Mage.Sets/src/mage/cards/s/SkewerTheCritics.java b/Mage.Sets/src/mage/cards/s/SkewerTheCritics.java new file mode 100644 index 00000000000..808d6637fa5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkewerTheCritics.java @@ -0,0 +1,37 @@ +package mage.cards.s; + +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SpectacleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetAnyTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SkewerTheCritics extends CardImpl { + + public SkewerTheCritics(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); + + // Skewer the Critics deals 3 damage to any target. + this.getSpellAbility().addEffect(new DamageTargetEffect(3)); + this.getSpellAbility().addTarget(new TargetAnyTarget()); + + // Spectacle {R} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{R}"))); + } + + private SkewerTheCritics(final SkewerTheCritics card) { + super(card); + } + + @Override + public SkewerTheCritics copy() { + return new SkewerTheCritics(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java b/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java index f7f8cb1518f..72d6ed3a653 100644 --- a/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java +++ b/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java @@ -35,7 +35,7 @@ public final class SkirkAlarmist extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face-down creature you control"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/s/SkirkFireMarshal.java b/Mage.Sets/src/mage/cards/s/SkirkFireMarshal.java index 0ad0bc887db..fe57a459ed9 100644 --- a/Mage.Sets/src/mage/cards/s/SkirkFireMarshal.java +++ b/Mage.Sets/src/mage/cards/s/SkirkFireMarshal.java @@ -29,7 +29,7 @@ public final class SkirkFireMarshal extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Goblins you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.GOBLIN)); } diff --git a/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java b/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java index 15b2be1cafd..736b0a2bde7 100644 --- a/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java +++ b/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java @@ -30,7 +30,7 @@ public final class SkirsdagHighPriest extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SkirsdagHighPriest(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SkitterEel.java b/Mage.Sets/src/mage/cards/s/SkitterEel.java new file mode 100644 index 00000000000..ffd78c8f395 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkitterEel.java @@ -0,0 +1,37 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.keyword.AdaptAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SkitterEel extends CardImpl { + + public SkitterEel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.FISH); + this.subtype.add(SubType.CRAB); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {2}{U}: Adapt 2. + this.addAbility(new AdaptAbility(2, "{2}{U}")); + } + + private SkitterEel(final SkitterEel card) { + super(card); + } + + @Override + public SkitterEel copy() { + return new SkitterEel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkitterOfLizards.java b/Mage.Sets/src/mage/cards/s/SkitterOfLizards.java index 95353e03aa7..b4a9f5a5244 100644 --- a/Mage.Sets/src/mage/cards/s/SkitterOfLizards.java +++ b/Mage.Sets/src/mage/cards/s/SkitterOfLizards.java @@ -35,7 +35,7 @@ public final class SkitterOfLizards extends CardImpl { // Skitter of Lizards enters the battlefield with a +1/+1 counter on it for each time it was kicked. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true), + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true), "with a +1/+1 counter on it for each time it was kicked")); } diff --git a/Mage.Sets/src/mage/cards/s/Skitterskin.java b/Mage.Sets/src/mage/cards/s/Skitterskin.java index a61b9b0d392..0ce710eb673 100644 --- a/Mage.Sets/src/mage/cards/s/Skitterskin.java +++ b/Mage.Sets/src/mage/cards/s/Skitterskin.java @@ -28,8 +28,8 @@ public final class Skitterskin extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("you control another colorless creature"); static { - filter.add(new AnotherPredicate()); - filter.add(new ColorlessPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(ColorlessPredicate.instance); } public Skitterskin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SkittishValesk.java b/Mage.Sets/src/mage/cards/s/SkittishValesk.java index 8ba58f3f855..604f9a2e6d0 100644 --- a/Mage.Sets/src/mage/cards/s/SkittishValesk.java +++ b/Mage.Sets/src/mage/cards/s/SkittishValesk.java @@ -63,7 +63,7 @@ class SkittishValeskEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); - if (controller != null && permanent != null && !controller.flipCoin(game)) { + if (controller != null && permanent != null && !controller.flipCoin(source, game, true)) { return permanent.turnFaceDown(game, source.getControllerId()); } return false; diff --git a/Mage.Sets/src/mage/cards/s/SkullbriarTheWalkingGrave.java b/Mage.Sets/src/mage/cards/s/SkullbriarTheWalkingGrave.java index 7c217863635..d37ca591ece 100644 --- a/Mage.Sets/src/mage/cards/s/SkullbriarTheWalkingGrave.java +++ b/Mage.Sets/src/mage/cards/s/SkullbriarTheWalkingGrave.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.StaticAbility; @@ -22,15 +21,15 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; +import java.util.UUID; + /** - * * @author anonymous */ public final class SkullbriarTheWalkingGrave extends CardImpl { - private Counters counters; public SkullbriarTheWalkingGrave(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{G}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ZOMBIE); this.subtype.add(SubType.ELEMENTAL); @@ -46,7 +45,9 @@ public final class SkullbriarTheWalkingGrave extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.ALL, new SkullbriarEffect())); } - public SkullbriarTheWalkingGrave(SkullbriarTheWalkingGrave card) { super(card); } + public SkullbriarTheWalkingGrave(SkullbriarTheWalkingGrave card) { + super(card); + } @Override public SkullbriarTheWalkingGrave copy() { @@ -58,7 +59,7 @@ public final class SkullbriarTheWalkingGrave extends CardImpl { public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) { boolean skullBriarEffectApplied = false; if (event.getToZone() != Zone.HAND && event.getToZone() != Zone.LIBRARY) { - for (StaticAbility ability : getAbilities (game).getStaticAbilities(event.getFromZone())) { + for (StaticAbility ability : getAbilities(game).getStaticAbilities(event.getFromZone())) { for (Effect effect : ability.getEffects(game, EffectType.REPLACEMENT)) { if (effect instanceof SkullbriarEffect && event.getAppliedEffects().contains(effect.getId())) { skullBriarEffectApplied = true; @@ -84,7 +85,7 @@ public final class SkullbriarTheWalkingGrave extends CardImpl { copyTo = this.getCounters(game); } if (copyTo != null && copyFrom != null) { - for(Counter counter : copyFrom.values()) { + for (Counter counter : copyFrom.values()) { copyTo.addCounter(counter); } } diff --git a/Mage.Sets/src/mage/cards/s/Skullsnatcher.java b/Mage.Sets/src/mage/cards/s/Skullsnatcher.java index 4ff8480c451..484a2c9b310 100644 --- a/Mage.Sets/src/mage/cards/s/Skullsnatcher.java +++ b/Mage.Sets/src/mage/cards/s/Skullsnatcher.java @@ -32,7 +32,7 @@ public final class Skullsnatcher extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("unblocked attacker you control"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } public Skullsnatcher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SkyHussar.java b/Mage.Sets/src/mage/cards/s/SkyHussar.java index 074294d3056..eb73ff2f48c 100644 --- a/Mage.Sets/src/mage/cards/s/SkyHussar.java +++ b/Mage.Sets/src/mage/cards/s/SkyHussar.java @@ -29,7 +29,7 @@ public final class SkyHussar extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white and/or blue creatures you control"); static { filter.add(Predicates.or(new ColorPredicate(ObjectColor.WHITE), new ColorPredicate(ObjectColor.BLUE))); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SkyHussar(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SkyScourer.java b/Mage.Sets/src/mage/cards/s/SkyScourer.java index 0350d7c4731..c5f8142e32e 100644 --- a/Mage.Sets/src/mage/cards/s/SkyScourer.java +++ b/Mage.Sets/src/mage/cards/s/SkyScourer.java @@ -24,7 +24,7 @@ public final class SkyScourer extends CardImpl { private static final FilterSpell filterSpell = new FilterSpell("a colorless spell"); static { - filterSpell.add(new ColorlessPredicate()); + filterSpell.add(ColorlessPredicate.instance); } public SkyScourer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SkyTether.java b/Mage.Sets/src/mage/cards/s/SkyTether.java new file mode 100644 index 00000000000..d24831c3186 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkyTether.java @@ -0,0 +1,54 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.common.continuous.LoseAbilityAttachedEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SkyTether extends CardImpl { + + public SkyTether(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature has defender and loses flying. + ability = new SimpleStaticAbility(new GainAbilityAttachedEffect( + DefenderAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield + )); + ability.addEffect(new LoseAbilityAttachedEffect( + FlyingAbility.getInstance(), AttachmentType.AURA + ).concatBy("and")); + this.addAbility(ability); + } + + private SkyTether(final SkyTether card) { + super(card); + } + + @Override + public SkyTether copy() { + return new SkyTether(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkyclawThrash.java b/Mage.Sets/src/mage/cards/s/SkyclawThrash.java index 3e9bf12b52b..b0a9e3f91b4 100644 --- a/Mage.Sets/src/mage/cards/s/SkyclawThrash.java +++ b/Mage.Sets/src/mage/cards/s/SkyclawThrash.java @@ -70,7 +70,7 @@ class SkyclawThrashEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (controller.flipCoin(game) && sourcePermanent != null) { + if (controller.flipCoin(source, game, true) && sourcePermanent != null) { ContinuousEffect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); effect.setTargetPointer(new FixedTarget(sourcePermanent, game)); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/s/SkyfireKirin.java b/Mage.Sets/src/mage/cards/s/SkyfireKirin.java index 03b12415075..899b0aa5aab 100644 --- a/Mage.Sets/src/mage/cards/s/SkyfireKirin.java +++ b/Mage.Sets/src/mage/cards/s/SkyfireKirin.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -22,6 +21,7 @@ import mage.game.stack.Spell; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; /** @@ -29,8 +29,6 @@ import mage.target.targetpointer.FixedTarget; */ public final class SkyfireKirin extends CardImpl { - private final UUID originalId; - public SkyfireKirin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); addSuperType(SuperType.LEGENDARY); @@ -43,30 +41,17 @@ public final class SkyfireKirin extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever you cast a Spirit or Arcane spell, you may gain control of target creature with that spell's converted mana cost until end of turn. - Ability ability = new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD, new SkyfireKirinEffect(), StaticFilters.SPIRIT_OR_ARCANE_CARD, true, true); + Ability ability = new SpellCastControllerTriggeredAbility( + Zone.BATTLEFIELD, new SkyfireKirinEffect(), + StaticFilters.SPIRIT_OR_ARCANE_CARD, true, true + ); ability.addTarget(new TargetCreaturePermanent()); - originalId = ability.getOriginalId(); + ability.setTargetAdjuster(SkyfireKirinAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - Spell spell = game.getStack().getSpell(ability.getEffects().get(0).getTargetPointer().getFirst(game, ability)); - if (spell != null) { - int cmc = spell.getConvertedManaCost(); - ability.getTargets().clear(); - FilterPermanent filter = new FilterCreaturePermanent("creature with converted mana costs of " + cmc); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, cmc)); - Target target = new TargetPermanent(filter); - ability.addTarget(target); - } - } - } - public SkyfireKirin(final SkyfireKirin card) { super(card); - this.originalId = card.originalId; } @Override @@ -75,6 +60,22 @@ public final class SkyfireKirin extends CardImpl { } } +enum SkyfireKirinAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + Spell spell = game.getStack().getSpell(ability.getEffects().get(0).getTargetPointer().getFirst(game, ability)); + if (spell != null) { + int cmc = spell.getConvertedManaCost(); + ability.getTargets().clear(); + FilterPermanent filter = new FilterCreaturePermanent("creature with converted mana cost " + cmc); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, cmc)); + ability.addTarget(new TargetPermanent(filter)); + } + } +} + class SkyfireKirinEffect extends OneShotEffect { public SkyfireKirinEffect() { diff --git a/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java b/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java index 25fde9c0a68..c7119a81835 100644 --- a/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java +++ b/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java @@ -95,7 +95,7 @@ class SkyriderPatrolReflexiveTriggeredAbility extends DelayedTriggeredAbility { = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SkyriderPatrolReflexiveTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/s/Skyscribing.java b/Mage.Sets/src/mage/cards/s/Skyscribing.java index eba3cb37bf5..cf37f0c5c6d 100644 --- a/Mage.Sets/src/mage/cards/s/Skyscribing.java +++ b/Mage.Sets/src/mage/cards/s/Skyscribing.java @@ -20,7 +20,7 @@ public final class Skyscribing extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}{U}"); // Each player draws X cards. - this.getSpellAbility().addEffect(new DrawCardAllEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardAllEffect(ManacostVariableValue.instance)); // Forecast - {2}{U}, Reveal Skyscribing from your hand: Each player draws a card. this.addAbility(new ForecastAbility(new DrawCardAllEffect(1), new ManaCostsImpl("{2}{U}"))); } diff --git a/Mage.Sets/src/mage/cards/s/Slimebind.java b/Mage.Sets/src/mage/cards/s/Slimebind.java new file mode 100644 index 00000000000..345de79d54c --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Slimebind.java @@ -0,0 +1,51 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Slimebind extends CardImpl { + + public Slimebind(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + + this.subtype.add(SubType.AURA); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets -4/-0. + this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(-4, 0))); + } + + private Slimebind(final Slimebind card) { + super(card); + } + + @Override + public Slimebind copy() { + return new Slimebind(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SliverLegion.java b/Mage.Sets/src/mage/cards/s/SliverLegion.java index 37aa4dc6754..16e7d5dc518 100644 --- a/Mage.Sets/src/mage/cards/s/SliverLegion.java +++ b/Mage.Sets/src/mage/cards/s/SliverLegion.java @@ -24,7 +24,7 @@ public final class SliverLegion extends CardImpl { private static final FilterPermanent countfilter = new FilterPermanent(SubType.SLIVER, "other Sliver on the battlefield"); static { - countfilter.add(new AnotherPredicate()); + countfilter.add(AnotherPredicate.instance); } public SliverLegion(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SludgeStrider.java b/Mage.Sets/src/mage/cards/s/SludgeStrider.java index 219edc42f9a..fb389b73932 100644 --- a/Mage.Sets/src/mage/cards/s/SludgeStrider.java +++ b/Mage.Sets/src/mage/cards/s/SludgeStrider.java @@ -61,7 +61,7 @@ class SludgeStriderTriggeredAbility extends TriggeredAbilityImpl { private static final FilterArtifactCard filter = new FilterArtifactCard("another artifact under your control"); static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SludgeStriderTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/s/SlyRequisitioner.java b/Mage.Sets/src/mage/cards/s/SlyRequisitioner.java index 08ca61777e0..5b04d9e138c 100644 --- a/Mage.Sets/src/mage/cards/s/SlyRequisitioner.java +++ b/Mage.Sets/src/mage/cards/s/SlyRequisitioner.java @@ -24,7 +24,7 @@ public final class SlyRequisitioner extends CardImpl { private static final FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("a nontoken artifact you control"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public SlyRequisitioner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java b/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java new file mode 100644 index 00000000000..df72e415edf --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java @@ -0,0 +1,63 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SmeltWardIgnus extends CardImpl { + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creature with power 3 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4)); + } + + public SmeltWardIgnus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {2}{R}, Sacrifice Smelt-Ward Ignus: Gain control of target creature with power 3 or less until end of turn. Untap that creature. It gains haste until end of turn. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, + new GainControlTargetEffect( + Duration.EndOfTurn, true + ), new ManaCostsImpl("{2}{R}") + ); + ability.addEffect(new UntapTargetEffect().setText("Untap that creature")); + ability.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("It gains haste until end of turn")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + private SmeltWardIgnus(final SmeltWardIgnus card) { + super(card); + } + + @Override + public SmeltWardIgnus copy() { + return new SmeltWardIgnus(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/Smite.java b/Mage.Sets/src/mage/cards/s/Smite.java index 67050e3b54e..f6f46285dcd 100644 --- a/Mage.Sets/src/mage/cards/s/Smite.java +++ b/Mage.Sets/src/mage/cards/s/Smite.java @@ -19,7 +19,7 @@ public final class Smite extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocked creature"); static { - filter.add(new BlockedPredicate()); + filter.add(BlockedPredicate.instance); } public Smite(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SmokeTeller.java b/Mage.Sets/src/mage/cards/s/SmokeTeller.java index 3254a12f88c..5994a8d2473 100644 --- a/Mage.Sets/src/mage/cards/s/SmokeTeller.java +++ b/Mage.Sets/src/mage/cards/s/SmokeTeller.java @@ -32,7 +32,7 @@ public final class SmokeTeller extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public SmokeTeller(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SmotheringTithe.java b/Mage.Sets/src/mage/cards/s/SmotheringTithe.java new file mode 100644 index 00000000000..e5da0997464 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SmotheringTithe.java @@ -0,0 +1,74 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.DrawCardOpponentTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.TreasureToken; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SmotheringTithe extends CardImpl { + + public SmotheringTithe(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + + // Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color." + this.addAbility(new DrawCardOpponentTriggeredAbility( + new SmotheringTitheEffect(), false, true + )); + } + + private SmotheringTithe(final SmotheringTithe card) { + super(card); + } + + @Override + public SmotheringTithe copy() { + return new SmotheringTithe(this); + } +} + +class SmotheringTitheEffect extends OneShotEffect { + + SmotheringTitheEffect() { + super(Outcome.Benefit); + staticText = "that player may pay {2}. If the player doesn't, " + + "you create a colorless Treasure artifact token " + + "with \"{T}, Sacrifice this artifact: Add one mana of any color.\""; + } + + private SmotheringTitheEffect(final SmotheringTitheEffect effect) { + super(effect); + } + + @Override + public SmotheringTitheEffect copy() { + return new SmotheringTitheEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + if (player == null) { + return false; + } + Cost cost = new GenericManaCost(2); + if (!player.chooseUse(Outcome.Detriment, "Pay {2} to prevent this effect?", source, game) + || !cost.pay(source, game, source.getSourceId(), player.getId(), false)) { + return new CreateTokenEffect(new TreasureToken()).apply(game, source); + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/Snag.java b/Mage.Sets/src/mage/cards/s/Snag.java index 877484cf1fa..4c016086e68 100644 --- a/Mage.Sets/src/mage/cards/s/Snag.java +++ b/Mage.Sets/src/mage/cards/s/Snag.java @@ -29,7 +29,7 @@ public final class Snag extends CardImpl { static { filter.add(new SubtypePredicate(SubType.FOREST)); - filter2.add(Predicates.not(new BlockedPredicate())); + filter2.add(Predicates.not(BlockedPredicate.instance)); } public Snag(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SnakeBasket.java b/Mage.Sets/src/mage/cards/s/SnakeBasket.java index 66862965c22..6cc0acd59d0 100644 --- a/Mage.Sets/src/mage/cards/s/SnakeBasket.java +++ b/Mage.Sets/src/mage/cards/s/SnakeBasket.java @@ -25,7 +25,7 @@ public final class SnakeBasket extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); // {X}, Sacrifice Snake Basket: create X 1/1 green Snake creature tokens. Activate this ability only any time you could cast a sorcery. - Effect effect = new CreateTokenEffect(new SnakeToken(), new ManacostVariableValue()); + Effect effect = new CreateTokenEffect(new SnakeToken(), ManacostVariableValue.instance); Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java b/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java index 8f515860bce..bc72bae2dd4 100644 --- a/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java +++ b/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java @@ -8,10 +8,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -26,8 +23,7 @@ public final class SnickeringSquirrel extends CardImpl { public SnickeringSquirrel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); - this.subtype.add("Squirrel"); - this.subtype.add("Advisor"); + this.subtype.add(SubType.SQUIRREL, SubType.ADVISOR); this.power = new MageInt(1); this.toughness = new MageInt(1); diff --git a/Mage.Sets/src/mage/cards/s/SnowDevil.java b/Mage.Sets/src/mage/cards/s/SnowDevil.java new file mode 100644 index 00000000000..69ae57ac5bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SnowDevil.java @@ -0,0 +1,98 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author jeffwadsworth + */ +public final class SnowDevil extends CardImpl { + + public SnowDevil(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature has flying. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield))); + + // Enchanted creature has first strike as long as it's blocking and you control a snow land. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilityAttachedEffect( + FirstStrikeAbility.getInstance(), + AttachmentType.AURA, + Duration.WhileOnBattlefield), + SnowDevilCondition.instance, + "Enchanted creature has first strike as long as it's blocking and you control a snow land" + ))); + } + + private SnowDevil(final SnowDevil card) { + super(card); + } + + @Override + public SnowDevil copy() { + return new SnowDevil(this); + } +} + +enum SnowDevilCondition implements Condition { + + instance; + + @Override + public boolean apply(Game game, Ability source) { + FilterLandPermanent filter = new FilterLandPermanent(); + filter.add(new SupertypePredicate(SuperType.SNOW)); + Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment != null) { + Player controller = game.getPlayer(enchantment.getControllerId()); + Permanent creature = game.getPermanent(enchantment.getAttachedTo()); + if (creature != null + && controller != null) { + CombatGroup combatGroup = game.getCombat().findGroupOfBlocker(creature.getId()); + if (combatGroup != null + && !game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game).isEmpty()) { + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SokenzanSpellblade.java b/Mage.Sets/src/mage/cards/s/SokenzanSpellblade.java index fda9d9d9987..56e925fe0ce 100644 --- a/Mage.Sets/src/mage/cards/s/SokenzanSpellblade.java +++ b/Mage.Sets/src/mage/cards/s/SokenzanSpellblade.java @@ -35,7 +35,7 @@ public final class SokenzanSpellblade extends CardImpl { // Bushido 1 this.addAbility(new BushidoAbility(1)); // {1}{R}: Sokenzan Spellblade gets +X/+0 until end of turn, where X is the number of cards in your hand. - Effect effect = new BoostSourceEffect(new CardsInControllerHandCount(), new StaticValue(0), Duration.EndOfTurn, true); + Effect effect = new BoostSourceEffect(CardsInControllerHandCount.instance, new StaticValue(0), Duration.EndOfTurn, true); effect.setText("{this} gets +X/+0 until end of turn, where X is the number of cards in your hand"); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{R}") diff --git a/Mage.Sets/src/mage/cards/s/SoldeviExcavations.java b/Mage.Sets/src/mage/cards/s/SoldeviExcavations.java index 6ab8ca59385..21cb2308132 100644 --- a/Mage.Sets/src/mage/cards/s/SoldeviExcavations.java +++ b/Mage.Sets/src/mage/cards/s/SoldeviExcavations.java @@ -33,7 +33,7 @@ public final class SoldeviExcavations extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ISLAND)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SoldeviExcavations(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SoldeviGolem.java b/Mage.Sets/src/mage/cards/s/SoldeviGolem.java index b4192c145ae..b2c0364d087 100644 --- a/Mage.Sets/src/mage/cards/s/SoldeviGolem.java +++ b/Mage.Sets/src/mage/cards/s/SoldeviGolem.java @@ -30,7 +30,7 @@ public final class SoldeviGolem extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SoldeviGolem(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SoldierOfThePantheon.java b/Mage.Sets/src/mage/cards/s/SoldierOfThePantheon.java index 90b2c056dc5..be3cbe31477 100644 --- a/Mage.Sets/src/mage/cards/s/SoldierOfThePantheon.java +++ b/Mage.Sets/src/mage/cards/s/SoldierOfThePantheon.java @@ -24,7 +24,7 @@ public final class SoldierOfThePantheon extends CardImpl { private static final FilterObject filter = new FilterObject("multicolored"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public SoldierOfThePantheon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SongOfSerenity.java b/Mage.Sets/src/mage/cards/s/SongOfSerenity.java index 2d583036531..1e62cc3cb35 100644 --- a/Mage.Sets/src/mage/cards/s/SongOfSerenity.java +++ b/Mage.Sets/src/mage/cards/s/SongOfSerenity.java @@ -44,7 +44,7 @@ class SongOfSerenityRestrictionEffect extends RestrictionEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); } public SongOfSerenityRestrictionEffect() { diff --git a/Mage.Sets/src/mage/cards/s/Soothsaying.java b/Mage.Sets/src/mage/cards/s/Soothsaying.java index fe88a0035c8..2f67392f252 100644 --- a/Mage.Sets/src/mage/cards/s/Soothsaying.java +++ b/Mage.Sets/src/mage/cards/s/Soothsaying.java @@ -27,7 +27,7 @@ public final class Soothsaying extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShuffleLibrarySourceEffect(), new ManaCostsImpl<>("{3}{U}{U}"))); // {X}: Look at the top X cards of your library, then put them back in any order. - Effect effect = new LookLibraryControllerEffect(new ManacostVariableValue()); + Effect effect = new LookLibraryControllerEffect(ManacostVariableValue.instance); effect.setText("Look at the top X cards of your library, then put them back in any order"); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("X"))); } diff --git a/Mage.Sets/src/mage/cards/s/SophicCentaur.java b/Mage.Sets/src/mage/cards/s/SophicCentaur.java index d28ffa11afa..76ed6c4d03f 100644 --- a/Mage.Sets/src/mage/cards/s/SophicCentaur.java +++ b/Mage.Sets/src/mage/cards/s/SophicCentaur.java @@ -33,7 +33,7 @@ public final class SophicCentaur extends CardImpl { this.toughness = new MageInt(1); // {2}{G}{G}, {tap}, Discard a card: You gain 2 life for each card in your hand. - DynamicValue lifeToGainAmount = new MultipliedValue(new CardsInControllerHandCount(), 2); + DynamicValue lifeToGainAmount = new MultipliedValue(CardsInControllerHandCount.instance, 2); Effect effect = new GainLifeEffect(lifeToGainAmount); effect.setText("You gain 2 life for each card in your hand"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}{G}{G}")); diff --git a/Mage.Sets/src/mage/cards/s/SoramaroFirstToDream.java b/Mage.Sets/src/mage/cards/s/SoramaroFirstToDream.java index d197ae5806d..62a0867b8b0 100644 --- a/Mage.Sets/src/mage/cards/s/SoramaroFirstToDream.java +++ b/Mage.Sets/src/mage/cards/s/SoramaroFirstToDream.java @@ -39,7 +39,7 @@ public final class SoramaroFirstToDream extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Soramaro, First to Dream's power and toughness are each equal to the number of cards in your hand. - DynamicValue xValue= new CardsInControllerHandCount(); + DynamicValue xValue= CardsInControllerHandCount.instance; this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame))); // {4}, Return a land you control to its owner's hand: Draw a card. diff --git a/Mage.Sets/src/mage/cards/s/SorceressQueen.java b/Mage.Sets/src/mage/cards/s/SorceressQueen.java index f3b81ce4496..e455408d290 100644 --- a/Mage.Sets/src/mage/cards/s/SorceressQueen.java +++ b/Mage.Sets/src/mage/cards/s/SorceressQueen.java @@ -26,7 +26,7 @@ public final class SorceressQueen extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature other than {this}"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SorceressQueen(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SorrowsPath.java b/Mage.Sets/src/mage/cards/s/SorrowsPath.java index dc056479a8e..ee972bc336e 100644 --- a/Mage.Sets/src/mage/cards/s/SorrowsPath.java +++ b/Mage.Sets/src/mage/cards/s/SorrowsPath.java @@ -36,7 +36,7 @@ public final class SorrowsPath extends CardImpl { private static final FilterOpponentsCreaturePermanent filter = new FilterOpponentsCreaturePermanent("blocking creatures an opponent controls"); static { - filter.add(new BlockingPredicate()); + filter.add(BlockingPredicate.instance); } public SorrowsPath(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SosukesSummons.java b/Mage.Sets/src/mage/cards/s/SosukesSummons.java index b3afeaf79fb..8e8de879153 100644 --- a/Mage.Sets/src/mage/cards/s/SosukesSummons.java +++ b/Mage.Sets/src/mage/cards/s/SosukesSummons.java @@ -26,7 +26,7 @@ public final class SosukesSummons extends CardImpl { static { filter.add(new SubtypePredicate(SubType.SNAKE)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public SosukesSummons(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SoulOfTheHarvest.java b/Mage.Sets/src/mage/cards/s/SoulOfTheHarvest.java index 76a157f25db..da6115bfce6 100644 --- a/Mage.Sets/src/mage/cards/s/SoulOfTheHarvest.java +++ b/Mage.Sets/src/mage/cards/s/SoulOfTheHarvest.java @@ -25,8 +25,8 @@ public final class SoulOfTheHarvest extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another nontoken creature"); static { - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public SoulOfTheHarvest(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SoulReap.java b/Mage.Sets/src/mage/cards/s/SoulReap.java index bd70f570e80..a128edcf286 100644 --- a/Mage.Sets/src/mage/cards/s/SoulReap.java +++ b/Mage.Sets/src/mage/cards/s/SoulReap.java @@ -65,7 +65,7 @@ class CastBlackSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SoulReapWatcher watcher = (SoulReapWatcher) game.getState().getWatchers().get(SoulReapWatcher.class.getSimpleName(), source.getControllerId()); + SoulReapWatcher watcher = game.getState().getWatcher(SoulReapWatcher.class, source.getControllerId()); if (watcher != null) { return watcher.conditionMet(); } @@ -84,7 +84,7 @@ class SoulReapWatcher extends Watcher { private UUID cardId; public SoulReapWatcher(UUID cardId) { - super(SoulReapWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(SoulReapWatcher.class, WatcherScope.PLAYER); this.cardId = cardId; } diff --git a/Mage.Sets/src/mage/cards/s/SoulStrings.java b/Mage.Sets/src/mage/cards/s/SoulStrings.java index 4dc5d880609..5ae9b10d29d 100644 --- a/Mage.Sets/src/mage/cards/s/SoulStrings.java +++ b/Mage.Sets/src/mage/cards/s/SoulStrings.java @@ -23,7 +23,7 @@ public final class SoulStrings extends CardImpl { // Return two target creature cards from your graveyard to your hand unless any player pays {X}. Effect effect = new DoUnlessAnyPlayerPaysEffect( - new ReturnFromGraveyardToHandTargetEffect(), new ManacostVariableValue()); + new ReturnFromGraveyardToHandTargetEffect(), ManacostVariableValue.instance); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(2, new FilterCreatureCard("creature cards from your graveyard"))); } diff --git a/Mage.Sets/src/mage/cards/s/SoulWarden.java b/Mage.Sets/src/mage/cards/s/SoulWarden.java index 79c309845f3..c95ae0e8758 100644 --- a/Mage.Sets/src/mage/cards/s/SoulWarden.java +++ b/Mage.Sets/src/mage/cards/s/SoulWarden.java @@ -22,7 +22,7 @@ public final class SoulWarden extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SoulWarden(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SoulcatchersAerie.java b/Mage.Sets/src/mage/cards/s/SoulcatchersAerie.java index 6b82168d403..aec13a77cf6 100644 --- a/Mage.Sets/src/mage/cards/s/SoulcatchersAerie.java +++ b/Mage.Sets/src/mage/cards/s/SoulcatchersAerie.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; @@ -18,8 +16,9 @@ import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; +import java.util.UUID; + /** - * * @author LoneFox */ public final class SoulcatchersAerie extends CardImpl { @@ -33,15 +32,16 @@ public final class SoulcatchersAerie extends CardImpl { } public SoulcatchersAerie(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); // Whenever a Bird is put into your graveyard from the battlefield, put a feather counter on Soulcatchers' Aerie. this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new AddCountersSourceEffect(CounterType.FEATHER.createInstance()), - false, filter, false, true)); + false, filter, false, true)); + // Bird creatures get +1/+1 for each feather counter on Soulcatchers' Aerie. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersSourceCount(CounterType.FEATHER), - new CountersSourceCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter2, false, - "Bird creatures get +1/+1 for each feather counter on {this}."))); + new CountersSourceCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter2, false, + "Bird creatures get +1/+1 for each feather counter on {this}."))); } public SoulcatchersAerie(final SoulcatchersAerie card) { diff --git a/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java b/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java index c7b36889d63..e567d415581 100644 --- a/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java +++ b/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java @@ -101,7 +101,7 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { MageObject mageObject = game.getObject(spellId); - if (!(mageObject instanceof Spell) || ((Spell) mageObject).isCopy()) { + if (!(mageObject instanceof Spell) || mageObject.isCopy()) { return false; } else { Card sourceCard = game.getCard(spellId); diff --git a/Mage.Sets/src/mage/cards/s/SoulsAttendant.java b/Mage.Sets/src/mage/cards/s/SoulsAttendant.java index fc40b463031..fbdc7aeb6cd 100644 --- a/Mage.Sets/src/mage/cards/s/SoulsAttendant.java +++ b/Mage.Sets/src/mage/cards/s/SoulsAttendant.java @@ -22,7 +22,7 @@ public final class SoulsAttendant extends CardImpl { private static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SoulsAttendant(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SoultetherGolem.java b/Mage.Sets/src/mage/cards/s/SoultetherGolem.java index 7028c37c7fd..73d60c1aab6 100644 --- a/Mage.Sets/src/mage/cards/s/SoultetherGolem.java +++ b/Mage.Sets/src/mage/cards/s/SoultetherGolem.java @@ -30,7 +30,7 @@ public final class SoultetherGolem extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SoultetherGolem(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SpawnOfMayhem.java b/Mage.Sets/src/mage/cards/s/SpawnOfMayhem.java new file mode 100644 index 00000000000..3e0215662e7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpawnOfMayhem.java @@ -0,0 +1,94 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.SpectacleAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SpawnOfMayhem extends CardImpl { + + public SpawnOfMayhem(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + + this.subtype.add(SubType.DEMON); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Spectacle {1}{B}{B} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{1}{B}{B}"))); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // At the beginning of your upkeep, Spawn of Mayhem deals 1 damage to each player. Then if you have 10 or less life, put a +1/+1 counter on Spawn of Mayhem. + Ability ability = new BeginningOfUpkeepTriggeredAbility( + new DamagePlayersEffect(1, TargetController.ANY), + TargetController.YOU, false + ); + ability.addEffect(new SpawnOfMayhemEffect()); + this.addAbility(ability); + } + + private SpawnOfMayhem(final SpawnOfMayhem card) { + super(card); + } + + @Override + public SpawnOfMayhem copy() { + return new SpawnOfMayhem(this); + } +} + +class SpawnOfMayhemEffect extends OneShotEffect { + + SpawnOfMayhemEffect() { + super(Outcome.Benefit); + staticText = "Then if you have 10 or less life, put a +1/+1 counter on {this}."; + } + + private SpawnOfMayhemEffect(final SpawnOfMayhemEffect effect) { + super(effect); + } + + @Override + public SpawnOfMayhemEffect copy() { + return new SpawnOfMayhemEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + if (player.getLife() < 11) { + return new AddCountersSourceEffect( + CounterType.P1P1.createInstance() + ).apply(game, source); + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SpawnbinderMage.java b/Mage.Sets/src/mage/cards/s/SpawnbinderMage.java index a14197c7d7c..1a163c26c72 100644 --- a/Mage.Sets/src/mage/cards/s/SpawnbinderMage.java +++ b/Mage.Sets/src/mage/cards/s/SpawnbinderMage.java @@ -31,7 +31,7 @@ public final class SpawnbinderMage extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SpawnbinderMage(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/Spawnbroker.java b/Mage.Sets/src/mage/cards/s/Spawnbroker.java index 2e291383a38..1d83a023cd7 100644 --- a/Mage.Sets/src/mage/cards/s/Spawnbroker.java +++ b/Mage.Sets/src/mage/cards/s/Spawnbroker.java @@ -69,11 +69,6 @@ class TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent extend super(target); } - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - return super.canTarget(controllerId, id, source, game); - } - @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); diff --git a/Mage.Sets/src/mage/cards/s/SpearSpewer.java b/Mage.Sets/src/mage/cards/s/SpearSpewer.java new file mode 100644 index 00000000000..2dbb8527dc5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpearSpewer.java @@ -0,0 +1,43 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SpearSpewer extends CardImpl { + + public SpearSpewer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // {T}: Spear Spewer deals 1 damage to each player. + this.addAbility(new SimpleActivatedAbility(new DamagePlayersEffect(1), new TapSourceCost())); + } + + private SpearSpewer(final SpearSpewer card) { + super(card); + } + + @Override + public SpearSpewer copy() { + return new SpearSpewer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpectralBears.java b/Mage.Sets/src/mage/cards/s/SpectralBears.java index e4440f24191..20790a16bca 100644 --- a/Mage.Sets/src/mage/cards/s/SpectralBears.java +++ b/Mage.Sets/src/mage/cards/s/SpectralBears.java @@ -52,7 +52,7 @@ class SpectralBearsTriggeredAbility extends TriggeredAbilityImpl { static { filter.add(new ColorPredicate(ObjectColor.BLACK)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public SpectralBearsTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/s/SpellBlast.java b/Mage.Sets/src/mage/cards/s/SpellBlast.java index c1e3b3c7efa..85337f0ce54 100644 --- a/Mage.Sets/src/mage/cards/s/SpellBlast.java +++ b/Mage.Sets/src/mage/cards/s/SpellBlast.java @@ -1,9 +1,7 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,24 +10,22 @@ import mage.constants.ComparisonType; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; -import mage.target.Target; import mage.target.TargetSpell; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SpellBlast extends CardImpl { - private static final FilterSpell filter = new FilterSpell("spell with converted mana cost X"); - public SpellBlast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); // Counter target spell with converted mana cost X. - this.getSpellAbility().addEffect(new CounterTargetEffect()); - this.getSpellAbility().addTarget(new TargetSpell(filter)); + this.getSpellAbility().addEffect(new CounterTargetEffect().setText("counter target spell with converted mana cost X")); + this.getSpellAbility().setTargetAdjuster(SpellBlastAdjuster.instance); } public SpellBlast(final SpellBlast card) { @@ -40,17 +36,17 @@ public final class SpellBlast extends CardImpl { public SpellBlast copy() { return new SpellBlast(this); } +} + +enum SpellBlastAdjuster implements TargetAdjuster { + instance; @Override public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - FilterSpell newfilter = new FilterSpell("spell with converted mana cost " + xValue); - newfilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - Target target = new TargetSpell(newfilter); - ability.addTarget(target); - } - + int xValue = ability.getManaCostsToPay().getX(); + ability.getTargets().clear(); + FilterSpell filter = new FilterSpell("spell with converted mana cost " + xValue); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetSpell(filter)); } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SpellBurst.java b/Mage.Sets/src/mage/cards/s/SpellBurst.java index 35d8c2a6cce..7c2cae1ae74 100644 --- a/Mage.Sets/src/mage/cards/s/SpellBurst.java +++ b/Mage.Sets/src/mage/cards/s/SpellBurst.java @@ -1,9 +1,7 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.keyword.BuybackAbility; import mage.cards.CardImpl; @@ -14,6 +12,9 @@ import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.TargetSpell; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** * @author LevelX2 @@ -23,23 +24,12 @@ public final class SpellBurst extends CardImpl { public SpellBurst(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); - // Buyback {3} this.addAbility(new BuybackAbility("{3}")); // Counter target spell with converted mana cost X. - this.getSpellAbility().addEffect(new CounterTargetEffect()); - this.getSpellAbility().addTarget(new TargetSpell(new FilterSpell("spell with converted mana cost X"))); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - FilterSpell filter = new FilterSpell("spell with converted mana cost X"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, ability.getManaCostsToPay().getX())); - ability.addTarget(new TargetSpell(filter)); - } + this.getSpellAbility().addEffect(new CounterTargetEffect().setText("counter target spell with converted mana cost X")); + this.getSpellAbility().setTargetAdjuster(SpellBurstAdjuster.instance); } public SpellBurst(final SpellBurst card) { @@ -51,3 +41,16 @@ public final class SpellBurst extends CardImpl { return new SpellBurst(this); } } + +enum SpellBurstAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + ability.getTargets().clear(); + FilterSpell filter = new FilterSpell("spell with converted mana cost " + xValue); + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + ability.addTarget(new TargetSpell(filter)); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpellContortion.java b/Mage.Sets/src/mage/cards/s/SpellContortion.java index aab49c9ab4f..fd89cb7298f 100644 --- a/Mage.Sets/src/mage/cards/s/SpellContortion.java +++ b/Mage.Sets/src/mage/cards/s/SpellContortion.java @@ -29,7 +29,7 @@ public final class SpellContortion extends CardImpl { // Counter target spell unless its controller pays {2}. Draw a card for each time Spell Contortion was kicked. this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(2))); - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new MultikickerCount())); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(MultikickerCount.instance)); this.getSpellAbility().addTarget(new TargetSpell()); } diff --git a/Mage.Sets/src/mage/cards/s/SpellShrivel.java b/Mage.Sets/src/mage/cards/s/SpellShrivel.java index 6ab606a1991..bd58d7ab541 100644 --- a/Mage.Sets/src/mage/cards/s/SpellShrivel.java +++ b/Mage.Sets/src/mage/cards/s/SpellShrivel.java @@ -76,7 +76,7 @@ class SpellShrivelCounterUnlessPaysEffect extends OneShotEffect { StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, source.getFirstTarget(), source.getSourceId(), stackObject.getControllerId()))) { game.informPlayers(sourceObject.getIdName() + ": cost wasn't payed - countering " + stackObject.getName()); - game.rememberLKI(source.getFirstTarget(), Zone.STACK, (Spell) stackObject); + game.rememberLKI(source.getFirstTarget(), Zone.STACK, stackObject); controller.moveCards((Spell) spell, Zone.EXILED, source, game); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, source.getFirstTarget(), source.getSourceId(), stackObject.getControllerId())); return true; diff --git a/Mage.Sets/src/mage/cards/s/SpellstutterSprite.java b/Mage.Sets/src/mage/cards/s/SpellstutterSprite.java index 9c63519a992..1126c9bcbc0 100644 --- a/Mage.Sets/src/mage/cards/s/SpellstutterSprite.java +++ b/Mage.Sets/src/mage/cards/s/SpellstutterSprite.java @@ -1,40 +1,40 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.FilterSpell; -import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; -import mage.game.stack.StackObject; import mage.target.TargetSpell; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SpellstutterSprite extends CardImpl { - - static final FilterPermanent filter = new FilterPermanent("number of Faeries you control"); + + private static final FilterSpell filter = new FilterSpell("spell with converted mana cost X or less, where X is the number of Faeries you control"); + static { - filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new SubtypePredicate(SubType.FAERIE)); + filter.add(SpellstutterSpritePredicate.instance); } public SpellstutterSprite(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); this.subtype.add(SubType.FAERIE); this.subtype.add(SubType.WIZARD); @@ -43,71 +43,37 @@ public final class SpellstutterSprite extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); + // Flying this.addAbility(FlyingAbility.getInstance()); + // When Spellstutter Sprite enters the battlefield, counter target spell with converted mana cost X or less, where X is the number of Faeries you control. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SpellstutterSpriteCounterTargetEffect())); + Ability ability = new EntersBattlefieldTriggeredAbility(new CounterTargetEffect()); + ability.addTarget(new TargetSpell(filter)); + this.addAbility(ability); } public SpellstutterSprite(final SpellstutterSprite card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - int numberFaeries = game.getState().getBattlefield().countAll(filter, ability.getControllerId(), game); - FilterSpell xFilter = new FilterSpell("spell with converted mana cost " + numberFaeries + " or less"); - xFilter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, numberFaeries + 1)); - ability.getTargets().clear(); - ability.addTarget(new TargetSpell(xFilter)); - } - } - @Override public SpellstutterSprite copy() { return new SpellstutterSprite(this); } } -class SpellstutterSpriteCounterTargetEffect extends OneShotEffect { +enum SpellstutterSpritePredicate implements ObjectSourcePlayerPredicate> { + instance; + private static final FilterPermanent filter = new FilterPermanent(); - public SpellstutterSpriteCounterTargetEffect() { - super(Outcome.Detriment); - } - - public SpellstutterSpriteCounterTargetEffect(final SpellstutterSpriteCounterTargetEffect effect) { - super(effect); + static { + filter.add(new SubtypePredicate(SubType.FAERIE)); } @Override - public SpellstutterSpriteCounterTargetEffect copy() { - return new SpellstutterSpriteCounterTargetEffect(this); + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().getConvertedManaCost() <= + game.getBattlefield().countAll(filter, game.getControllerId(input.getSourceId()), game); } - - @Override - public boolean apply(Game game, Ability source) { - /* - * The value of X needs to be determined both when the ability triggers (so you can choose - * a target) and again when the ability resolves (to check if that target is still legal). - * If the number of Faeries you control has decreased enough in that time to make the target - * illegal, Spellstutter Sprite's ability will be countered (and the targeted spell will - * resolve as normal). - */ - int numberFaeries = game.getState().getBattlefield().countAll(SpellstutterSprite.filter, source.getControllerId(), game); - StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); - // If do'nt have any spell targeted - if (stackObject != null && stackObject.getConvertedManaCost() <= numberFaeries) { - if (game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game)) { - return true; - } - } - return false; - } - - @Override - public String getText(Mode mode) { - return "counter target spell with converted mana cost X or less, where X is the number of Faeries you control"; - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java b/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java index af159683349..3114e8cf727 100644 --- a/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java +++ b/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java @@ -24,7 +24,7 @@ public final class SpellweaverDuo extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SpellweaverDuo(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfForesight.java b/Mage.Sets/src/mage/cards/s/SphinxOfForesight.java new file mode 100644 index 00000000000..a3aac1877c6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SphinxOfForesight.java @@ -0,0 +1,85 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.ChancellorAbility; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SphinxOfForesight extends CardImpl { + + public SphinxOfForesight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // You may reveal this card from your opening hand. If you do, scry 3 at the beginning of your first upkeep. + Ability ability = new ChancellorAbility( + new SphinxOfForesightDelayedTriggeredAbility(), + "scry 3 at the beginning of your first upkeep." + ); + ability.setRuleAtTheTop(true); + this.addAbility(ability); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of your upkeep, scry 1. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, new ScryEffect(1), + TargetController.YOU, false + )); + } + + private SphinxOfForesight(final SphinxOfForesight card) { + super(card); + } + + @Override + public SphinxOfForesight copy() { + return new SphinxOfForesight(this); + } +} + +class SphinxOfForesightDelayedTriggeredAbility extends DelayedTriggeredAbility { + + SphinxOfForesightDelayedTriggeredAbility() { + super(new ScryEffect(3)); + } + + private SphinxOfForesightDelayedTriggeredAbility(SphinxOfForesightDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return game.getActivePlayerId().equals(this.controllerId); + } + + @Override + public SphinxOfForesightDelayedTriggeredAbility copy() { + return new SphinxOfForesightDelayedTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java b/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java new file mode 100644 index 00000000000..690a8c7f3b9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java @@ -0,0 +1,97 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SphinxOfNewPrahv extends CardImpl { + + public SphinxOfNewPrahv(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}{U}{U}"); + + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Spells your opponents cast that target Sphinx of New Prahv cost {2} more to cast. + this.addAbility(new SimpleStaticAbility(new SphinxOfNewPrahvCostIncreaseEffect())); + } + + private SphinxOfNewPrahv(final SphinxOfNewPrahv card) { + super(card); + } + + @Override + public SphinxOfNewPrahv copy() { + return new SphinxOfNewPrahv(this); + } +} + +class SphinxOfNewPrahvCostIncreaseEffect extends CostModificationEffectImpl { + + SphinxOfNewPrahvCostIncreaseEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST); + staticText = "Spells your opponents cast that target {this} cost {2} more to cast"; + } + + private SphinxOfNewPrahvCostIncreaseEffect(SphinxOfNewPrahvCostIncreaseEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + CardUtil.adjustCost(spellAbility, -2); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null + || !(abilityToModify instanceof SpellAbility) + || !controller.hasOpponent(abilityToModify.getControllerId(), game)) { + return false; + } + for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { + Mode mode = abilityToModify.getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetUUID : target.getTargets()) { + if (targetUUID.equals(source.getSourceId())) { + return true; + } + } + } + } + return false; + } + + @Override + public SphinxOfNewPrahvCostIncreaseEffect copy() { + return new SphinxOfNewPrahvCostIncreaseEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java b/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java index 5d81e776167..07a18848269 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java +++ b/Mage.Sets/src/mage/cards/s/SphinxOfTheChimes.java @@ -1,22 +1,12 @@ - package mage.cards.s; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.cards.SplitCard; +import mage.cards.*; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; @@ -27,8 +17,12 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SphinxOfTheChimes extends CardImpl { @@ -91,7 +85,7 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { Set newPossibleTargets = new HashSet<>(); Set possibleTargets = new HashSet<>(); Player player = game.getPlayer(sourceControllerId); - if(player == null){ + if (player == null) { return newPossibleTargets; } for (Card card : player.getHand().getCards(filter, game)) { @@ -116,9 +110,11 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { for (UUID cardToCheck : cardsToCheck) { FilterCard nameFilter = new FilterCard(); Card card = game.getCard(cardToCheck); - nameFilter.add(new NamePredicate(card.isSplitCard() ? ((SplitCard) card).getLeftHalfCard().getName() : card.getName())); - if (cardsToCheck.count(nameFilter, game) > 1) { - newPossibleTargets.add(cardToCheck); + if (card != null) { + nameFilter.add(new NamePredicate(card.isSplitCard() ? ((SplitCard) card).getLeftHalfCard().getName() : card.getName())); + if (cardsToCheck.count(nameFilter, game) > 1) { + newPossibleTargets.add(cardToCheck); + } } } } @@ -129,7 +125,7 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { public boolean canChoose(UUID sourceControllerId, Game game) { Cards cardsToCheck = new CardsImpl(); Player player = game.getPlayer(sourceControllerId); - if(player == null){ + if (player == null) { return false; } for (Card card : player.getHand().getCards(filter, game)) { @@ -153,16 +149,12 @@ class TargetTwoNonLandCardsWithSameNameInHand extends TargetCardInHand { if (card != null) { if (targets.size() == 1) { Card card2 = game.getCard(targets.entrySet().iterator().next().getKey()); - if (card2 != null && card2.getName().equals(card.getName())) { - return true; - } + return card2 != null && card2.getName().equals(card.getName()); } else { FilterCard nameFilter = new FilterCard(); nameFilter.add(new NamePredicate(card.isSplitCard() ? ((SplitCard) card).getLeftHalfCard().getName() : card.getName())); Player player = game.getPlayer(card.getOwnerId()); - if (player != null && player.getHand().getCards(nameFilter, game).size() > 1) { - return true; - } + return player != null && player.getHand().getCards(nameFilter, game).size() > 1; } } } diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfTheGuildpact.java b/Mage.Sets/src/mage/cards/s/SphinxOfTheGuildpact.java new file mode 100644 index 00000000000..97c09111cab --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SphinxOfTheGuildpact.java @@ -0,0 +1,51 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofFromMonocoloredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SphinxOfTheGuildpact extends CardImpl { + + public SphinxOfTheGuildpact(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); + + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Sphinx of the Guildpact is all colors. + this.color.setWhite(true); + this.color.setBlue(true); + this.color.setBlack(true); + this.color.setRed(true); + this.color.setGreen(true); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this} is all colors"))); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Hexproof from mono colored + this.addAbility(HexproofFromMonocoloredAbility.getInstance()); + } + + private SphinxOfTheGuildpact(final SphinxOfTheGuildpact card) { + super(card); + } + + @Override + public SphinxOfTheGuildpact copy() { + return new SphinxOfTheGuildpact(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SphinxsInsight.java b/Mage.Sets/src/mage/cards/s/SphinxsInsight.java index d0c8fb18ad8..44f5a6d158a 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxsInsight.java +++ b/Mage.Sets/src/mage/cards/s/SphinxsInsight.java @@ -1,6 +1,6 @@ package mage.cards.s; -import mage.abilities.condition.common.MyMainPhaseCondition; +import mage.abilities.condition.common.AddendumCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -24,7 +24,7 @@ public final class SphinxsInsight extends CardImpl { // Addendum — If you cast this spell during your main phase, you gain 2 life. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new GainLifeEffect(2), MyMainPhaseCondition.instance, + new GainLifeEffect(2), AddendumCondition.instance, "
Addendum — If you cast this spell during your main phase, you gain 2 life." )); } diff --git a/Mage.Sets/src/mage/cards/s/SphinxsRevelation.java b/Mage.Sets/src/mage/cards/s/SphinxsRevelation.java index 4658f434502..9a982e8c060 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxsRevelation.java +++ b/Mage.Sets/src/mage/cards/s/SphinxsRevelation.java @@ -21,7 +21,7 @@ public final class SphinxsRevelation extends CardImpl { // You gain X life and draw X cards. - ManacostVariableValue manaX = new ManacostVariableValue(); + ManacostVariableValue manaX = ManacostVariableValue.instance; this.getSpellAbility().addEffect(new GainLifeEffect(manaX)); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(manaX)); } diff --git a/Mage.Sets/src/mage/cards/s/SpikewheelAcrobat.java b/Mage.Sets/src/mage/cards/s/SpikewheelAcrobat.java new file mode 100644 index 00000000000..fc751f41703 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpikewheelAcrobat.java @@ -0,0 +1,38 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.SpectacleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SpikewheelAcrobat extends CardImpl { + + public SpikewheelAcrobat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(5); + this.toughness = new MageInt(2); + + // Spectacle {2}{R} + this.addAbility(new SpectacleAbility(this, new ManaCostsImpl("{2}{R}"))); + } + + private SpikewheelAcrobat(final SpikewheelAcrobat card) { + super(card); + } + + @Override + public SpikewheelAcrobat copy() { + return new SpikewheelAcrobat(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java b/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java index 2bbd0596be3..04a75201c2f 100644 --- a/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java +++ b/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java @@ -68,7 +68,7 @@ class SpinerockKnollCondition extends IntCompareCondition { @Override protected int getInputValue(Game game, Ability source) { int maxDamageReceived = 0; - SpinerockKnollWatcher watcher = (SpinerockKnollWatcher) game.getState().getWatchers().get(SpinerockKnollWatcher.class.getSimpleName(), source.getSourceId()); + SpinerockKnollWatcher watcher = game.getState().getWatcher(SpinerockKnollWatcher.class, source.getSourceId()); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { int damageReceived = watcher.getDamageReceived(opponentId); diff --git a/Mage.Sets/src/mage/cards/s/SpinyStarfish.java b/Mage.Sets/src/mage/cards/s/SpinyStarfish.java index c2760bd3218..7719b2424be 100644 --- a/Mage.Sets/src/mage/cards/s/SpinyStarfish.java +++ b/Mage.Sets/src/mage/cards/s/SpinyStarfish.java @@ -70,7 +70,7 @@ enum SpinyStarfishCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpinyStarfishWatcher watcher = (SpinyStarfishWatcher) game.getState().getWatchers().get(SpinyStarfishWatcher.class.getSimpleName()); + SpinyStarfishWatcher watcher = game.getState().getWatcher(SpinyStarfishWatcher.class); return watcher != null && watcher.regeneratedCount(source.getSourceId()) != 0; } @@ -88,7 +88,7 @@ class SpinyStarfishWatcher extends Watcher { private final Map regeneratedCount = new HashMap<>(); public SpinyStarfishWatcher() { - super(SpinyStarfishWatcher.class.getSimpleName(), WatcherScope.GAME); + super(SpinyStarfishWatcher.class, WatcherScope.GAME); } public SpinyStarfishWatcher(final SpinyStarfishWatcher watcher) { @@ -132,8 +132,8 @@ class SpinyStarfishDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - SpinyStarfishWatcher watcher = (SpinyStarfishWatcher) game.getState().getWatchers().get( - SpinyStarfishWatcher.class.getSimpleName()); + SpinyStarfishWatcher watcher = game.getState().getWatcher( + SpinyStarfishWatcher.class); if (watcher != null) { return watcher.regeneratedCount(sourceAbility.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/s/SpiralingEmbers.java b/Mage.Sets/src/mage/cards/s/SpiralingEmbers.java index 68696268cab..f6b5adc9204 100644 --- a/Mage.Sets/src/mage/cards/s/SpiralingEmbers.java +++ b/Mage.Sets/src/mage/cards/s/SpiralingEmbers.java @@ -23,7 +23,7 @@ public final class SpiralingEmbers extends CardImpl { // Spiraling Embers deals damage to any target equal to the number of cards in your hand. - Effect effect = new DamageTargetEffect(new CardsInControllerHandCount()); + Effect effect = new DamageTargetEffect(CardsInControllerHandCount.instance); effect.setText("{this} deals damage to any target equal to the number of cards in your hand."); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/s/SpireMangler.java b/Mage.Sets/src/mage/cards/s/SpireMangler.java new file mode 100644 index 00000000000..e5faeef3d6d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpireMangler.java @@ -0,0 +1,59 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SpireMangler extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("creature with flying you control"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public SpireMangler(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.INSECT); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Spire Mangler enters the battlefield, target creature with flying you control gets +2/+0 until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(2, 0)); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private SpireMangler(final SpireMangler card) { + super(card); + } + + @Override + public SpireMangler copy() { + return new SpireMangler(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java b/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java index 2508964cb9f..c6651fc0fe3 100644 --- a/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java +++ b/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java @@ -28,7 +28,7 @@ public final class SpiresOfOrazca extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature an opponent controls"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(new ControllerPredicate(TargetController.OPPONENT)); } diff --git a/Mage.Sets/src/mage/cards/s/SpiritBonds.java b/Mage.Sets/src/mage/cards/s/SpiritBonds.java index 58d4d817625..6af79400d5f 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritBonds.java +++ b/Mage.Sets/src/mage/cards/s/SpiritBonds.java @@ -39,7 +39,7 @@ public final class SpiritBonds extends CardImpl { static { filter.add(Predicates.not(new SubtypePredicate(SubType.SPIRIT))); filterSpirit.add(new SubtypePredicate(SubType.SPIRIT)); - filterNontoken.add(Predicates.not(new TokenPredicate())); + filterNontoken.add(Predicates.not(TokenPredicate.instance)); } public SpiritBonds(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SpiritMirror.java b/Mage.Sets/src/mage/cards/s/SpiritMirror.java index 136789f012e..de02cbfc464 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritMirror.java +++ b/Mage.Sets/src/mage/cards/s/SpiritMirror.java @@ -29,7 +29,7 @@ public final class SpiritMirror extends CardImpl { static { filterToken.add(new SubtypePredicate(SubType.REFLECTION)); - filterToken.add(new TokenPredicate()); + filterToken.add(TokenPredicate.instance); filter.add(new SubtypePredicate(SubType.REFLECTION)); } diff --git a/Mage.Sets/src/mage/cards/s/SpiritOfTheLabyrinth.java b/Mage.Sets/src/mage/cards/s/SpiritOfTheLabyrinth.java index 31da7b75e82..5494b6d1bf8 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritOfTheLabyrinth.java +++ b/Mage.Sets/src/mage/cards/s/SpiritOfTheLabyrinth.java @@ -113,7 +113,7 @@ class SpiritOfTheLabyrinthEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - SpiritOfTheLabyrinthWatcher watcher = (SpiritOfTheLabyrinthWatcher) game.getState().getWatchers().get(SpiritOfTheLabyrinthWatcher.class.getSimpleName()); + SpiritOfTheLabyrinthWatcher watcher = game.getState().getWatcher(SpiritOfTheLabyrinthWatcher.class); if (watcher != null && watcher.hasPlayerDrewCardThisTurn(event.getPlayerId())) { return true; } diff --git a/Mage.Sets/src/mage/cards/s/SpiritOfTheSpires.java b/Mage.Sets/src/mage/cards/s/SpiritOfTheSpires.java new file mode 100644 index 00000000000..796e7540afa --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpiritOfTheSpires.java @@ -0,0 +1,56 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; + +import java.util.UUID; +import mage.abilities.effects.Effect; + +/** + * @author TheElk801 + */ +public final class SpiritOfTheSpires extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent(); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public SpiritOfTheSpires(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Other creatures you control with flying get +0/+1. + Effect effect = new BoostControlledEffect( + 0, 1, Duration.WhileOnBattlefield, filter, true + ); + effect.setText("Other creatures you control with flying get +0/+1"); + this.addAbility(new SimpleStaticAbility(effect)); + } + + private SpiritOfTheSpires(final SpiritOfTheSpires card) { + super(card); + } + + @Override + public SpiritOfTheSpires copy() { + return new SpiritOfTheSpires(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpoilsOfBlood.java b/Mage.Sets/src/mage/cards/s/SpoilsOfBlood.java index 4a056003b45..4f276c5f25a 100644 --- a/Mage.Sets/src/mage/cards/s/SpoilsOfBlood.java +++ b/Mage.Sets/src/mage/cards/s/SpoilsOfBlood.java @@ -59,7 +59,7 @@ class SpoilsOfBloodEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - CreaturesDiedThisTurnWatcher watcher = (CreaturesDiedThisTurnWatcher) game.getState().getWatchers().get(CreaturesDiedThisTurnWatcher.class.getSimpleName()); + CreaturesDiedThisTurnWatcher watcher = game.getState().getWatcher(CreaturesDiedThisTurnWatcher.class); if (watcher != null) { new CreateTokenEffect(new SpoilsOfBloodHorrorToken(watcher.creaturesDiedThisTurn)).apply(game, source); } @@ -80,7 +80,7 @@ class CreaturesDiedThisTurnWatcher extends Watcher { public int creaturesDiedThisTurn = 0; public CreaturesDiedThisTurnWatcher() { - super(CreaturesDiedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(CreaturesDiedThisTurnWatcher.class, WatcherScope.GAME); } public CreaturesDiedThisTurnWatcher(final CreaturesDiedThisTurnWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SpontaneousGeneration.java b/Mage.Sets/src/mage/cards/s/SpontaneousGeneration.java index eab38e464ee..6820a1e7ddb 100644 --- a/Mage.Sets/src/mage/cards/s/SpontaneousGeneration.java +++ b/Mage.Sets/src/mage/cards/s/SpontaneousGeneration.java @@ -19,7 +19,7 @@ public final class SpontaneousGeneration extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{G}"); // Create a 1/1 green Saproling creature token for each card in your hand. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new CardsInControllerHandCount())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), CardsInControllerHandCount.instance)); } public SpontaneousGeneration(final SpontaneousGeneration card) { diff --git a/Mage.Sets/src/mage/cards/s/SporeCloud.java b/Mage.Sets/src/mage/cards/s/SporeCloud.java index 02109f10359..c7c9d494a09 100644 --- a/Mage.Sets/src/mage/cards/s/SporeCloud.java +++ b/Mage.Sets/src/mage/cards/s/SporeCloud.java @@ -32,7 +32,7 @@ public final class SporeCloud extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocking creatures"); static { - filter.add(new BlockingPredicate()); + filter.add(BlockingPredicate.instance); } public SporeCloud(UUID ownerId, CardSetInfo setInfo) { @@ -60,7 +60,7 @@ class SporeCloudEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each attacking creature and each blocking creature"); static { - filter.add(Predicates.or(new AttackingPredicate(), new BlockingPredicate())); + filter.add(Predicates.or(AttackingPredicate.instance, BlockingPredicate.instance)); } public SporeCloudEffect() { diff --git a/Mage.Sets/src/mage/cards/s/Sporogenesis.java b/Mage.Sets/src/mage/cards/s/Sporogenesis.java index 99f5cee4dcd..3512d42361e 100644 --- a/Mage.Sets/src/mage/cards/s/Sporogenesis.java +++ b/Mage.Sets/src/mage/cards/s/Sporogenesis.java @@ -39,7 +39,7 @@ public final class Sporogenesis extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public Sporogenesis(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SpringMind.java b/Mage.Sets/src/mage/cards/s/SpringMind.java index abd520704fb..c1f4493fcb7 100644 --- a/Mage.Sets/src/mage/cards/s/SpringMind.java +++ b/Mage.Sets/src/mage/cards/s/SpringMind.java @@ -29,7 +29,7 @@ public final class SpringMind extends SplitCard { // Mind // Aftermath // Draw two cards. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); } diff --git a/Mage.Sets/src/mage/cards/s/SpringjackPasture.java b/Mage.Sets/src/mage/cards/s/SpringjackPasture.java index c5f7f6a91ab..d4ba3405d73 100644 --- a/Mage.Sets/src/mage/cards/s/SpringjackPasture.java +++ b/Mage.Sets/src/mage/cards/s/SpringjackPasture.java @@ -49,12 +49,12 @@ public final class SpringjackPasture extends CardImpl { // {tap}, Sacrifice X Goats: Add X mana of any one color. You gain X life. ability = new DynamicManaAbility( new Mana(0,0,0,0,0,0,1,0), - new GetXValue(), + GetXValue.instance, new TapSourceCost(), "Add X mana of any one color", true); ability.addCost(new SacrificeXTargetCost(filter)); - ability.addEffect(new GainLifeEffect(new GetXValue())); + ability.addEffect(new GainLifeEffect(GetXValue.instance)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpringleafDrum.java b/Mage.Sets/src/mage/cards/s/SpringleafDrum.java index 7bf0a7908f9..b5c988ccb5e 100644 --- a/Mage.Sets/src/mage/cards/s/SpringleafDrum.java +++ b/Mage.Sets/src/mage/cards/s/SpringleafDrum.java @@ -21,7 +21,7 @@ public final class SpringleafDrum extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SpringleafDrum(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SpurGrappler.java b/Mage.Sets/src/mage/cards/s/SpurGrappler.java index c0f048f8860..fc6865d049f 100644 --- a/Mage.Sets/src/mage/cards/s/SpurGrappler.java +++ b/Mage.Sets/src/mage/cards/s/SpurGrappler.java @@ -27,7 +27,7 @@ public final class SpurGrappler extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SpurGrappler(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SpurredWolverine.java b/Mage.Sets/src/mage/cards/s/SpurredWolverine.java index b21ef4ee91c..016d81b0725 100644 --- a/Mage.Sets/src/mage/cards/s/SpurredWolverine.java +++ b/Mage.Sets/src/mage/cards/s/SpurredWolverine.java @@ -30,7 +30,7 @@ public final class SpurredWolverine extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Beasts you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.BEAST)); } diff --git a/Mage.Sets/src/mage/cards/s/SpyNetwork.java b/Mage.Sets/src/mage/cards/s/SpyNetwork.java index daf78dbba88..4daf571ac02 100644 --- a/Mage.Sets/src/mage/cards/s/SpyNetwork.java +++ b/Mage.Sets/src/mage/cards/s/SpyNetwork.java @@ -103,7 +103,7 @@ class SpyNetworkFaceDownEffect extends OneShotEffect { MageObject mageObject = game.getObject(source.getSourceId()); if (controller != null && player != null && mageObject != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature controlled by " + player.getLogName()); - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); filter.add(new ControllerIdPredicate(player.getId())); TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); if (target.canChoose(source.getSourceId(), controller.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/s/SquallLine.java b/Mage.Sets/src/mage/cards/s/SquallLine.java index b2b8c822011..37e98c9e647 100644 --- a/Mage.Sets/src/mage/cards/s/SquallLine.java +++ b/Mage.Sets/src/mage/cards/s/SquallLine.java @@ -27,7 +27,7 @@ public final class SquallLine extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{G}{G}"); // Squall Line deals X damage to each creature with flying and each player. - this.getSpellAbility().addEffect(new DamageEverythingEffect(new ManacostVariableValue(), filter)); } + this.getSpellAbility().addEffect(new DamageEverythingEffect(ManacostVariableValue.instance, filter)); } public SquallLine(final SquallLine card) { super(card); diff --git a/Mage.Sets/src/mage/cards/s/SqueesRevenge.java b/Mage.Sets/src/mage/cards/s/SqueesRevenge.java index b999d689034..f30ec04673e 100644 --- a/Mage.Sets/src/mage/cards/s/SqueesRevenge.java +++ b/Mage.Sets/src/mage/cards/s/SqueesRevenge.java @@ -56,7 +56,7 @@ class SqueesRevengeEffect extends OneShotEffect { int number = player.announceXMana(0, Integer.MAX_VALUE, "Choose how many times to flip a coin", game, source); game.informPlayers(player.getLogName() + " chooses " + number + '.'); for(int i = 0; i < number; i++) { - if(!player.flipCoin(game)) { + if(!player.flipCoin(source, game, true)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/StagBeetle.java b/Mage.Sets/src/mage/cards/s/StagBeetle.java index 4918fae8bfe..4da1d698ec7 100644 --- a/Mage.Sets/src/mage/cards/s/StagBeetle.java +++ b/Mage.Sets/src/mage/cards/s/StagBeetle.java @@ -23,7 +23,7 @@ public final class StagBeetle extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public StagBeetle(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StalkingAssassin.java b/Mage.Sets/src/mage/cards/s/StalkingAssassin.java index ef7528461a3..78a1c8bad52 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingAssassin.java +++ b/Mage.Sets/src/mage/cards/s/StalkingAssassin.java @@ -28,7 +28,7 @@ public final class StalkingAssassin extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public StalkingAssassin(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StalkingVengeance.java b/Mage.Sets/src/mage/cards/s/StalkingVengeance.java index 5b1347dac6a..b51f4e9fcce 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingVengeance.java +++ b/Mage.Sets/src/mage/cards/s/StalkingVengeance.java @@ -31,7 +31,7 @@ public final class StalkingVengeance extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public StalkingVengeance(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StampedingHorncrest.java b/Mage.Sets/src/mage/cards/s/StampedingHorncrest.java index 78d5d1f5ba2..3a9cd4b932f 100644 --- a/Mage.Sets/src/mage/cards/s/StampedingHorncrest.java +++ b/Mage.Sets/src/mage/cards/s/StampedingHorncrest.java @@ -27,7 +27,7 @@ public final class StampedingHorncrest extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Dinosaur"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DINOSAUR)); } diff --git a/Mage.Sets/src/mage/cards/s/StarCrownedStag.java b/Mage.Sets/src/mage/cards/s/StarCrownedStag.java index e05d794229b..6dc595c5d3a 100644 --- a/Mage.Sets/src/mage/cards/s/StarCrownedStag.java +++ b/Mage.Sets/src/mage/cards/s/StarCrownedStag.java @@ -22,7 +22,7 @@ public final class StarCrownedStag extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public StarCrownedStag(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java b/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java index 8ab8ec89da0..1ad2c7e2f39 100644 --- a/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java +++ b/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java @@ -80,7 +80,7 @@ class StarfieldOfNyxEffect extends ContinuousEffectImpl { static { filter.add(Predicates.not(new SubtypePredicate(SubType.AURA))); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/s/Starstorm.java b/Mage.Sets/src/mage/cards/s/Starstorm.java index 1d74ac89d2e..bdf7d1c097b 100644 --- a/Mage.Sets/src/mage/cards/s/Starstorm.java +++ b/Mage.Sets/src/mage/cards/s/Starstorm.java @@ -22,7 +22,7 @@ public final class Starstorm extends CardImpl { // Starstorm deals X damage to each creature. - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), new FilterCreaturePermanent())); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, new FilterCreaturePermanent())); // Cycling {3} this.addAbility(new CyclingAbility(new ManaCostsImpl("{3}"))); } diff --git a/Mage.Sets/src/mage/cards/s/StartFinish.java b/Mage.Sets/src/mage/cards/s/StartFinish.java index dba97d1e489..85890742ba5 100644 --- a/Mage.Sets/src/mage/cards/s/StartFinish.java +++ b/Mage.Sets/src/mage/cards/s/StartFinish.java @@ -36,7 +36,7 @@ public final class StartFinish extends SplitCard { // Finish // Aftermath // As an additional cost to cast Finish, sacrifice a creature. Destroy target creature. - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (to destoy)"))); getRightHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect("Destroy target creature")); diff --git a/Mage.Sets/src/mage/cards/s/SteamCatapult.java b/Mage.Sets/src/mage/cards/s/SteamCatapult.java index 16402a4abd4..8262509c4df 100644 --- a/Mage.Sets/src/mage/cards/s/SteamCatapult.java +++ b/Mage.Sets/src/mage/cards/s/SteamCatapult.java @@ -26,7 +26,7 @@ public final class SteamCatapult extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SteamCatapult(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SteamVines.java b/Mage.Sets/src/mage/cards/s/SteamVines.java index 5861920b9bc..317d2ba47b6 100644 --- a/Mage.Sets/src/mage/cards/s/SteamVines.java +++ b/Mage.Sets/src/mage/cards/s/SteamVines.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; import mage.abilities.effects.Effect; @@ -24,8 +22,9 @@ import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author jeffwadsworth & L_J */ public final class SteamVines extends CardImpl { @@ -76,7 +75,6 @@ class SteamVinesEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent steamVines = game.getPermanentOrLKIBattlefield(source.getSourceId()); - Card steamVinesCard = game.getCard(source.getSourceId()); if (steamVines != null) { Permanent enchantedLand = game.getPermanentOrLKIBattlefield(steamVines.getAttachedTo()); Player controller = game.getPlayer(source.getControllerId()); @@ -85,15 +83,15 @@ class SteamVinesEffect extends OneShotEffect { Player landsController = game.getPlayer(enchantedLand.getControllerId()); if (game.getState().getZone(enchantedLand.getId()) == Zone.BATTLEFIELD) { // if 2 or more Steam Vines were on a land enchantedLand.destroy(source.getId(), game, false); - if(landsController != null) { + if (landsController != null) { landsController.damage(1, source.getSourceId(), game, false, true); } } if (!game.getBattlefield().getAllActivePermanents(CardType.LAND).isEmpty()) { //lands are available on the battlefield Target target = new TargetLandPermanent(); target.setNotTarget(true); //not a target, it is chosen - if (steamVinesCard != null - && landsController != null) { + Card steamVinesCard = game.getCard(source.getSourceId()); + if (steamVinesCard != null && landsController != null) { if (landsController.choose(Outcome.DestroyPermanent, target, source.getId(), game)) { if (target.getFirstTarget() != null) { Permanent landChosen = game.getPermanent(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/s/SteelHellkite.java b/Mage.Sets/src/mage/cards/s/SteelHellkite.java index 694efcbf182..e0f6aca2726 100644 --- a/Mage.Sets/src/mage/cards/s/SteelHellkite.java +++ b/Mage.Sets/src/mage/cards/s/SteelHellkite.java @@ -84,7 +84,7 @@ class SteelHellkiteDestroyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - SteelHellkiteWatcher watcher = (SteelHellkiteWatcher) game.getState().getWatchers().get(SteelHellkiteWatcher.class.getSimpleName()); + SteelHellkiteWatcher watcher = game.getState().getWatcher(SteelHellkiteWatcher.class); if (watcher == null || watcher.getDamagedPlayers(source.getSourceId()).isEmpty()) { return false; } @@ -104,7 +104,7 @@ class SteelHellkiteWatcher extends Watcher { private final Map> damageMap = new HashMap<>(); public SteelHellkiteWatcher() { - super(SteelHellkiteWatcher.class.getSimpleName(), WatcherScope.GAME); + super(SteelHellkiteWatcher.class, WatcherScope.GAME); } public SteelHellkiteWatcher(final SteelHellkiteWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SteelcladSerpent.java b/Mage.Sets/src/mage/cards/s/SteelcladSerpent.java index feeccfd132e..692a6e4c256 100644 --- a/Mage.Sets/src/mage/cards/s/SteelcladSerpent.java +++ b/Mage.Sets/src/mage/cards/s/SteelcladSerpent.java @@ -51,7 +51,7 @@ class SteelcladSerpentEffect extends RestrictionEffect { static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public SteelcladSerpentEffect() { diff --git a/Mage.Sets/src/mage/cards/s/SteepleCreeper.java b/Mage.Sets/src/mage/cards/s/SteepleCreeper.java new file mode 100644 index 00000000000..ebb8958b1cb --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SteepleCreeper.java @@ -0,0 +1,45 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SteepleCreeper extends CardImpl { + + public SteepleCreeper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.FROG); + this.subtype.add(SubType.SNAKE); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // {3}{U}: Steeple Creeper gains flying until end of turn. + this.addAbility(new SimpleActivatedAbility( + new GainAbilitySourceEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl("{3}{U}") + )); + } + + private SteepleCreeper(final SteepleCreeper card) { + super(card); + } + + @Override + public SteepleCreeper copy() { + return new SteepleCreeper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StenchOfEvil.java b/Mage.Sets/src/mage/cards/s/StenchOfEvil.java new file mode 100644 index 00000000000..b85fcf0603d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StenchOfEvil.java @@ -0,0 +1,81 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author jeffwadsworth + */ +public final class StenchOfEvil extends CardImpl { + + public StenchOfEvil(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}"); + + // Destroy all Plains. For each land destroyed this way, Stench of Evil deals 1 damage to that land's controller unless he or she pays {2}. + this.getSpellAbility().addEffect(new StenchOfEvilEffect()); + + } + + private StenchOfEvil(final StenchOfEvil card) { + super(card); + } + + @Override + public StenchOfEvil copy() { + return new StenchOfEvil(this); + } +} + +class StenchOfEvilEffect extends OneShotEffect { + + private static final FilterLandPermanent filter = new FilterLandPermanent(); + + static { + filter.add(new SubtypePredicate(SubType.PLAINS)); + } + + public StenchOfEvilEffect() { + super(Outcome.Benefit); + this.staticText = "Destroy all Plains. For each land destroyed this way, {this} deals 1 damage to that land's controller unless he or she pays {2}"; + } + + public StenchOfEvilEffect(final StenchOfEvilEffect effect) { + super(effect); + } + + @Override + public StenchOfEvilEffect copy() { + return new StenchOfEvilEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent land : game.getBattlefield().getAllActivePermanents(filter, game)) { + UUID landControllerId = land.getControllerId(); + if (land.destroy(source.getSourceId(), game, false)) { + Cost cost = new ManaCostsImpl("{2}"); + Player landController = game.getPlayer(landControllerId); + if (landController != null + && cost.canPay(source, source.getSourceId(), landControllerId, game) + && !cost.pay(source, game, source.getSourceId(), landControllerId, false)) { + landController.damage(1, source.getSourceId(), game, false, true); + } + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java b/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java index 61f2a5dc8ac..ee86d460f37 100644 --- a/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java +++ b/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java @@ -35,7 +35,7 @@ public final class StensiaMasquerade extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public StensiaMasquerade(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StirTheGrave.java b/Mage.Sets/src/mage/cards/s/StirTheGrave.java index 39d56a262c3..818993060fb 100644 --- a/Mage.Sets/src/mage/cards/s/StirTheGrave.java +++ b/Mage.Sets/src/mage/cards/s/StirTheGrave.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; @@ -13,29 +12,21 @@ import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class StirTheGrave extends CardImpl { public StirTheGrave(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}"); // Return target creature card with converted mana cost X or less from your graveyard to the battlefield. - this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card with converted mana cost X or less from your graveyard"))); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - FilterCard filter = new FilterCreatureCard("creature card with converted mana cost " + xValue + " or less from your graveyard"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); - ability.getTargets().add(new TargetCardInYourGraveyard(filter)); + this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect().setText("return target creature card with converted mana cost X or less from your graveyard to the battlefield")); + this.getSpellAbility().setTargetAdjuster(StirTheGraveAdjuster.instance); } public StirTheGrave(final StirTheGrave card) { @@ -47,3 +38,16 @@ public final class StirTheGrave extends CardImpl { return new StirTheGrave(this); } } + +enum StirTheGraveAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + FilterCard filter = new FilterCreatureCard("creature card with converted mana cost " + xValue + " or less from your graveyard"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + ability.getTargets().add(new TargetCardInYourGraveyard(filter)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/StitchInTime.java b/Mage.Sets/src/mage/cards/s/StitchInTime.java index 4bafd1b73bc..c1dc506c43c 100644 --- a/Mage.Sets/src/mage/cards/s/StitchInTime.java +++ b/Mage.Sets/src/mage/cards/s/StitchInTime.java @@ -52,7 +52,7 @@ class StitchInTimeEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (player.flipCoin(game)) { + if (player.flipCoin(source, game, true)) { game.getState().getTurnMods().add(new TurnMod(player.getId(), false)); return true; } diff --git a/Mage.Sets/src/mage/cards/s/StoneCatapult.java b/Mage.Sets/src/mage/cards/s/StoneCatapult.java index 594edb549f8..9a2db55b708 100644 --- a/Mage.Sets/src/mage/cards/s/StoneCatapult.java +++ b/Mage.Sets/src/mage/cards/s/StoneCatapult.java @@ -29,7 +29,7 @@ public final class StoneCatapult extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped nonblack creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); } diff --git a/Mage.Sets/src/mage/cards/s/StoneHavenOutfitter.java b/Mage.Sets/src/mage/cards/s/StoneHavenOutfitter.java index da5f4c1571e..99f376716ed 100644 --- a/Mage.Sets/src/mage/cards/s/StoneHavenOutfitter.java +++ b/Mage.Sets/src/mage/cards/s/StoneHavenOutfitter.java @@ -27,7 +27,7 @@ public final class StoneHavenOutfitter extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("equipped creatures you control"); static { - filter.add(new EquippedPredicate()); + filter.add(EquippedPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java b/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java index ec704870134..3209b413c18 100644 --- a/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java +++ b/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java @@ -51,7 +51,7 @@ class StoneIdolTrapCostReductionEffect extends CostModificationEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public StoneIdolTrapCostReductionEffect() { diff --git a/Mage.Sets/src/mage/cards/s/StoneforgeAcolyte.java b/Mage.Sets/src/mage/cards/s/StoneforgeAcolyte.java index 617c31166fb..d4e82d39c8a 100644 --- a/Mage.Sets/src/mage/cards/s/StoneforgeAcolyte.java +++ b/Mage.Sets/src/mage/cards/s/StoneforgeAcolyte.java @@ -33,7 +33,7 @@ public final class StoneforgeAcolyte extends CardImpl { static { filterAlly.add(new SubtypePredicate(SubType.ALLY)); - filterAlly.add(Predicates.not(new TappedPredicate())); + filterAlly.add(Predicates.not(TappedPredicate.instance)); filterEquipment.add(new SubtypePredicate(SubType.EQUIPMENT)); } diff --git a/Mage.Sets/src/mage/cards/s/StonehoofChieftain.java b/Mage.Sets/src/mage/cards/s/StonehoofChieftain.java index cdfdd7e3779..fbd63a49a5c 100644 --- a/Mage.Sets/src/mage/cards/s/StonehoofChieftain.java +++ b/Mage.Sets/src/mage/cards/s/StonehoofChieftain.java @@ -29,7 +29,7 @@ public final class StonehoofChieftain extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public StonehoofChieftain(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StoneshakerShaman.java b/Mage.Sets/src/mage/cards/s/StoneshakerShaman.java index 75802aa16de..3454de11980 100644 --- a/Mage.Sets/src/mage/cards/s/StoneshakerShaman.java +++ b/Mage.Sets/src/mage/cards/s/StoneshakerShaman.java @@ -23,7 +23,7 @@ public final class StoneshakerShaman extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent("untapped land"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public StoneshakerShaman(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/StonyStrength.java b/Mage.Sets/src/mage/cards/s/StonyStrength.java new file mode 100644 index 00000000000..643b81cd9db --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StonyStrength.java @@ -0,0 +1,35 @@ +package mage.cards.s; + +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class StonyStrength extends CardImpl { + + public StonyStrength(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); + + // Put a +1/+1 counter on target creature you control. Untap that creature. + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap that creature")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + private StonyStrength(final StonyStrength card) { + super(card); + } + + @Override + public StonyStrength copy() { + return new StonyStrength(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StormEntity.java b/Mage.Sets/src/mage/cards/s/StormEntity.java index e0a2f1adf0f..33516f8d260 100644 --- a/Mage.Sets/src/mage/cards/s/StormEntity.java +++ b/Mage.Sets/src/mage/cards/s/StormEntity.java @@ -54,8 +54,11 @@ class OtherSpellsCastThisTurnCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); - return watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() - 1; + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); + if(watcher != null ) { + return watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() - 1; + } + return 0; } @Override diff --git a/Mage.Sets/src/mage/cards/s/StormHerd.java b/Mage.Sets/src/mage/cards/s/StormHerd.java index 9ba7cb1bc33..c2fac4e69c0 100644 --- a/Mage.Sets/src/mage/cards/s/StormHerd.java +++ b/Mage.Sets/src/mage/cards/s/StormHerd.java @@ -19,7 +19,7 @@ public final class StormHerd extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{8}{W}{W}"); // create X 1/1 white Pegasus creature tokens with flying, where X is your life total. - this.getSpellAbility().addEffect(new CreateTokenEffect(new PegasusToken(), new ControllerLifeCount())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new PegasusToken(), ControllerLifeCount.instance)); } public StormHerd(final StormHerd card) { diff --git a/Mage.Sets/src/mage/cards/s/StormSeeker.java b/Mage.Sets/src/mage/cards/s/StormSeeker.java index 63460d878c8..173b24552c7 100644 --- a/Mage.Sets/src/mage/cards/s/StormSeeker.java +++ b/Mage.Sets/src/mage/cards/s/StormSeeker.java @@ -20,7 +20,7 @@ public final class StormSeeker extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{G}"); // Storm Seeker deals damage to target player equal to the number of cards in that player's hand. - Effect effect = new DamageTargetEffect(new CardsInTargetHandCount()); + Effect effect = new DamageTargetEffect(CardsInTargetHandCount.instance); effect.setText("{this} deals damage to target player equal to the number of cards in that player's hand."); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/s/StormStrike.java b/Mage.Sets/src/mage/cards/s/StormStrike.java new file mode 100644 index 00000000000..bfccf2c5907 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StormStrike.java @@ -0,0 +1,43 @@ +package mage.cards.s; + +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class StormStrike extends CardImpl { + + public StormStrike(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); + + // Target creature gets +1/+0 and gains first strike until end of turn. Scry 1. + this.getSpellAbility().addEffect( + new BoostTargetEffect(1, 0) + .setText("target creature gets +1/+0") + ); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains first strike until end of turn")); + this.getSpellAbility().addEffect(new ScryEffect(1)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private StormStrike(final StormStrike card) { + super(card); + } + + @Override + public StormStrike copy() { + return new StormStrike(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StormwingDragon.java b/Mage.Sets/src/mage/cards/s/StormwingDragon.java index c03b2124fd1..b5d89492458 100644 --- a/Mage.Sets/src/mage/cards/s/StormwingDragon.java +++ b/Mage.Sets/src/mage/cards/s/StormwingDragon.java @@ -27,7 +27,7 @@ public final class StormwingDragon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other Dragon creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.DRAGON)); } diff --git a/Mage.Sets/src/mage/cards/s/StreamOfLife.java b/Mage.Sets/src/mage/cards/s/StreamOfLife.java index 97e91d04b33..51924a217bd 100644 --- a/Mage.Sets/src/mage/cards/s/StreamOfLife.java +++ b/Mage.Sets/src/mage/cards/s/StreamOfLife.java @@ -20,7 +20,7 @@ public final class StreamOfLife extends CardImpl { // Target player gains X life. - this.getSpellAbility().addEffect(new GainLifeTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new GainLifeTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/s/StreetSpasm.java b/Mage.Sets/src/mage/cards/s/StreetSpasm.java index fa0f2d43e83..e10d340862f 100644 --- a/Mage.Sets/src/mage/cards/s/StreetSpasm.java +++ b/Mage.Sets/src/mage/cards/s/StreetSpasm.java @@ -37,10 +37,10 @@ public final class StreetSpasm extends CardImpl { // Street Spasm deals X damage to target creature without flying you don't control. this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); // Overload {X}{X}{R}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") - this.addAbility(new OverloadAbility(this, new DamageAllEffect(new ManacostVariableValue(), filter), new ManaCostsImpl("{X}{X}{R}{R}"))); + this.addAbility(new OverloadAbility(this, new DamageAllEffect(ManacostVariableValue.instance, filter), new ManaCostsImpl("{X}{X}{R}{R}"))); } public StreetSpasm(final StreetSpasm card) { diff --git a/Mage.Sets/src/mage/cards/s/StrengthOfTheTajuru.java b/Mage.Sets/src/mage/cards/s/StrengthOfTheTajuru.java index 93d7d0d141b..73a007d69f0 100644 --- a/Mage.Sets/src/mage/cards/s/StrengthOfTheTajuru.java +++ b/Mage.Sets/src/mage/cards/s/StrengthOfTheTajuru.java @@ -1,9 +1,7 @@ - package mage.cards.s; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.MultikickerAbility; @@ -16,7 +14,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; - +import mage.target.targetadjustment.TargetAdjuster; /** * @author noxx @@ -24,7 +22,7 @@ import mage.target.common.TargetCreaturePermanent; public final class StrengthOfTheTajuru extends CardImpl { public StrengthOfTheTajuru(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{G}{G}"); // Multikicker (You may pay an additional {1} any number of times as you cast this spell.) this.addAbility(new MultikickerAbility("{1}")); @@ -32,15 +30,7 @@ public final class StrengthOfTheTajuru extends CardImpl { // Choose target creature, then choose another target creature for each time Strength of the Tajuru was kicked. Put X +1/+1 counters on each of them. this.getSpellAbility().addEffect(new StrengthOfTheTajuruAddCountersTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numbTargets = new MultikickerCount().calculate(game, ability, null) + 1; - ability.addTarget(new TargetCreaturePermanent(0, numbTargets)); - } + this.getSpellAbility().setTargetAdjuster(StrengthOfTheTajuruAdjuster.instance); } public StrengthOfTheTajuru(final StrengthOfTheTajuru card) { @@ -53,6 +43,17 @@ public final class StrengthOfTheTajuru extends CardImpl { } } +enum StrengthOfTheTajuruAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numbTargets = MultikickerCount.instance.calculate(game, ability, null) + 1; + ability.addTarget(new TargetCreaturePermanent(0, numbTargets)); + } +} + class StrengthOfTheTajuruAddCountersTargetEffect extends OneShotEffect { public StrengthOfTheTajuruAddCountersTargetEffect() { @@ -73,7 +74,7 @@ class StrengthOfTheTajuruAddCountersTargetEffect extends OneShotEffect { Permanent permanent = game.getPermanent(uuid); if (permanent != null) { permanent.addCounters(counter.copy(), source, game); - affectedTargets ++; + affectedTargets++; } } return affectedTargets > 0; @@ -84,5 +85,4 @@ class StrengthOfTheTajuruAddCountersTargetEffect extends OneShotEffect { return new StrengthOfTheTajuruAddCountersTargetEffect(this); } - } diff --git a/Mage.Sets/src/mage/cards/s/StrokeOfGenius.java b/Mage.Sets/src/mage/cards/s/StrokeOfGenius.java index f9d0145f2cf..8effb656273 100644 --- a/Mage.Sets/src/mage/cards/s/StrokeOfGenius.java +++ b/Mage.Sets/src/mage/cards/s/StrokeOfGenius.java @@ -21,7 +21,7 @@ public final class StrokeOfGenius extends CardImpl { // Target player draws X cards. - this.getSpellAbility().addEffect(new DrawCardTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DrawCardTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/s/StromkirkMentor.java b/Mage.Sets/src/mage/cards/s/StromkirkMentor.java index 7dc780d5d67..187ba8c4389 100644 --- a/Mage.Sets/src/mage/cards/s/StromkirkMentor.java +++ b/Mage.Sets/src/mage/cards/s/StromkirkMentor.java @@ -25,7 +25,7 @@ public final class StromkirkMentor extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another target Vampire you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/s/StruggleSurvive.java b/Mage.Sets/src/mage/cards/s/StruggleSurvive.java index 10e45160ed7..fbe4e1050ef 100644 --- a/Mage.Sets/src/mage/cards/s/StruggleSurvive.java +++ b/Mage.Sets/src/mage/cards/s/StruggleSurvive.java @@ -39,7 +39,7 @@ public final class StruggleSurvive extends SplitCard { // Survive // Aftermath - ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); // Each player shuffles his or graveyard into their library. getRightHalfCard().getSpellAbility().addEffect(new SurviveEffect()); diff --git a/Mage.Sets/src/mage/cards/s/Sturmgeist.java b/Mage.Sets/src/mage/cards/s/Sturmgeist.java index 6bc161a0d45..f21efdda143 100644 --- a/Mage.Sets/src/mage/cards/s/Sturmgeist.java +++ b/Mage.Sets/src/mage/cards/s/Sturmgeist.java @@ -31,7 +31,7 @@ public final class Sturmgeist extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Sturmgeist's power and toughness are each equal to the number of cards in your hand. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInControllerHandCount(), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(CardsInControllerHandCount.instance, Duration.EndOfGame))); // Whenever Sturmgeist deals combat damage to a player, draw a card. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); } diff --git a/Mage.Sets/src/mage/cards/s/Subdue.java b/Mage.Sets/src/mage/cards/s/Subdue.java index 63ac77351e7..970e3df7882 100644 --- a/Mage.Sets/src/mage/cards/s/Subdue.java +++ b/Mage.Sets/src/mage/cards/s/Subdue.java @@ -24,7 +24,7 @@ public final class Subdue extends CardImpl { // Prevent all combat damage that would be dealt by target creature this turn. That creature gets +0/+X until end of turn, where X is its converted mana cost. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true)); - this.getSpellAbility().addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true) + this.getSpellAbility().addEffect(new BoostTargetEffect(new StaticValue(0), TargetConvertedManaCost.instance, Duration.EndOfTurn, true) .setText("That creature gets +0/+X until end of turn, where X is its converted mana cost")); } diff --git a/Mage.Sets/src/mage/cards/s/SubterraneanHangar.java b/Mage.Sets/src/mage/cards/s/SubterraneanHangar.java index 9676c73977b..9ddc675a34b 100644 --- a/Mage.Sets/src/mage/cards/s/SubterraneanHangar.java +++ b/Mage.Sets/src/mage/cards/s/SubterraneanHangar.java @@ -34,7 +34,7 @@ public final class SubterraneanHangar extends CardImpl { // {tap}, Remove any number of storage counters from Subterranean Hangar: Add {B} for each storage counter removed this way. Ability ability = new DynamicManaAbility( Mana.BlackMana(1), - new RemovedCountersForCostValue(), + RemovedCountersForCostValue.instance, new TapSourceCost(), "Add {B} for each storage counter removed this way", true, new CountersSourceCount(CounterType.STORAGE)); diff --git a/Mage.Sets/src/mage/cards/s/SuddenImpact.java b/Mage.Sets/src/mage/cards/s/SuddenImpact.java index b3affd23630..6f889719a28 100644 --- a/Mage.Sets/src/mage/cards/s/SuddenImpact.java +++ b/Mage.Sets/src/mage/cards/s/SuddenImpact.java @@ -21,7 +21,7 @@ public final class SuddenImpact extends CardImpl { // Sudden Impact deals damage to target player equal to the number of cards in that player's hand. - Effect effect = new DamageTargetEffect(new CardsInTargetHandCount()); + Effect effect = new DamageTargetEffect(CardsInTargetHandCount.instance); effect.setText("{this} deals damage to target player equal to the number of cards in that player's hand."); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/s/SulfurousBlast.java b/Mage.Sets/src/mage/cards/s/SulfurousBlast.java index cb0bab1e203..3c1d0eda7fb 100644 --- a/Mage.Sets/src/mage/cards/s/SulfurousBlast.java +++ b/Mage.Sets/src/mage/cards/s/SulfurousBlast.java @@ -2,7 +2,7 @@ package mage.cards.s; import java.util.UUID; -import mage.abilities.condition.common.MyMainPhaseCondition; +import mage.abilities.condition.common.AddendumCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DamageEverythingEffect; import mage.cards.CardImpl; @@ -22,7 +22,7 @@ public final class SulfurousBlast extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new DamageEverythingEffect(3), new DamageEverythingEffect(2), - MyMainPhaseCondition.instance, + AddendumCondition.instance, "Sulfurous Blast deals 2 damage to each creature and each player. If you cast this spell during your main phase, Sulfurous Blast deals 3 damage to each creature and each player instead")); } diff --git a/Mage.Sets/src/mage/cards/s/SultaiCharm.java b/Mage.Sets/src/mage/cards/s/SultaiCharm.java index 2594e59fc19..f0e4f8f0839 100644 --- a/Mage.Sets/src/mage/cards/s/SultaiCharm.java +++ b/Mage.Sets/src/mage/cards/s/SultaiCharm.java @@ -25,7 +25,7 @@ public final class SultaiCharm extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("monocolored creature"); static { - filter.add(new MonocoloredPredicate()); + filter.add(MonocoloredPredicate.instance); } public SultaiCharm(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SummaryDismissal.java b/Mage.Sets/src/mage/cards/s/SummaryDismissal.java index 6b49a28762a..e695e38f296 100644 --- a/Mage.Sets/src/mage/cards/s/SummaryDismissal.java +++ b/Mage.Sets/src/mage/cards/s/SummaryDismissal.java @@ -66,7 +66,7 @@ class SummaryDismissalEffect extends OneShotEffect { ((Spell) stackObject).moveToExile(null, "", null, game); } if (stackObject instanceof Ability) { - game.getStack().counter(((Ability) stackObject).getId(), source.getSourceId(), game); + game.getStack().counter(stackObject.getId(), source.getSourceId(), game); } } return true; diff --git a/Mage.Sets/src/mage/cards/s/SummaryJudgment.java b/Mage.Sets/src/mage/cards/s/SummaryJudgment.java new file mode 100644 index 00000000000..87c6989019e --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SummaryJudgment.java @@ -0,0 +1,79 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SummaryJudgment extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(TappedPredicate.instance); + } + + public SummaryJudgment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Summary Judgement deals 3 damage to target tapped creature. + // Addendum — If you cast this spell during your main phase, it deals 5 damage to that creature instead. + this.getSpellAbility().addEffect(new SummaryJudgementEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + } + + private SummaryJudgment(final SummaryJudgment card) { + super(card); + } + + @Override + public SummaryJudgment copy() { + return new SummaryJudgment(this); + } +} + +class SummaryJudgementEffect extends OneShotEffect { + + SummaryJudgementEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 3 damage to target tapped creature." + + "
Addendum — f you cast this spell during your main phase, " + + "it deals 5 damage to that creature instead."; + } + + private SummaryJudgementEffect(final SummaryJudgementEffect effect) { + super(effect); + } + + @Override + public SummaryJudgementEffect copy() { + return new SummaryJudgementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + int damage = 3; + if (AddendumCondition.instance.apply(game, source)) { + damage = 5; + } + return permanent.damage(damage, source.getSourceId(), game) > 0; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SummonTheSchool.java b/Mage.Sets/src/mage/cards/s/SummonTheSchool.java index 8c7f797016a..eaccfa4c286 100644 --- a/Mage.Sets/src/mage/cards/s/SummonTheSchool.java +++ b/Mage.Sets/src/mage/cards/s/SummonTheSchool.java @@ -27,7 +27,7 @@ public final class SummonTheSchool extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Merfolk you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.MERFOLK)); } diff --git a/Mage.Sets/src/mage/cards/s/SummoningTrap.java b/Mage.Sets/src/mage/cards/s/SummoningTrap.java index 8bc4391c423..b8dd0e4593e 100644 --- a/Mage.Sets/src/mage/cards/s/SummoningTrap.java +++ b/Mage.Sets/src/mage/cards/s/SummoningTrap.java @@ -55,7 +55,7 @@ enum SummoningTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SummoningTrapWatcher watcher = (SummoningTrapWatcher) game.getState().getWatchers().get(SummoningTrapWatcher.class.getSimpleName()); + SummoningTrapWatcher watcher = game.getState().getWatcher(SummoningTrapWatcher.class); return watcher != null && watcher.creatureSpellOfPlayerWasCountered(source.getControllerId()); } @@ -70,7 +70,7 @@ class SummoningTrapWatcher extends Watcher { Set players = new HashSet<>(); public SummoningTrapWatcher() { - super(SummoningTrapWatcher.class.getSimpleName(), WatcherScope.GAME); + super(SummoningTrapWatcher.class, WatcherScope.GAME); } public SummoningTrapWatcher(final SummoningTrapWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SunClasp.java b/Mage.Sets/src/mage/cards/s/SunClasp.java index d48b9bf7e51..7ca4f36f6c7 100644 --- a/Mage.Sets/src/mage/cards/s/SunClasp.java +++ b/Mage.Sets/src/mage/cards/s/SunClasp.java @@ -71,7 +71,7 @@ class SunClaspReturnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) game.getPermanentOrLKIBattlefield(source.getSourceId()); + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && permanent != null && permanent.getAttachedTo() != null) { Permanent enchantedCreature = game.getPermanent(permanent.getAttachedTo()); diff --git a/Mage.Sets/src/mage/cards/s/SunCrestedPterodon.java b/Mage.Sets/src/mage/cards/s/SunCrestedPterodon.java index 9d1cd7d2056..55157dfa6ee 100644 --- a/Mage.Sets/src/mage/cards/s/SunCrestedPterodon.java +++ b/Mage.Sets/src/mage/cards/s/SunCrestedPterodon.java @@ -29,7 +29,7 @@ public final class SunCrestedPterodon extends CardImpl { private static final FilterControlledCreaturePermanent filterAnotherDino = new FilterControlledCreaturePermanent(); static { - filterAnotherDino.add(new AnotherPredicate()); + filterAnotherDino.add(AnotherPredicate.instance); filterAnotherDino.add(new SubtypePredicate(SubType.DINOSAUR)); } diff --git a/Mage.Sets/src/mage/cards/s/SunDroplet.java b/Mage.Sets/src/mage/cards/s/SunDroplet.java index 6ff432b37d1..08b3f4e79c8 100644 --- a/Mage.Sets/src/mage/cards/s/SunDroplet.java +++ b/Mage.Sets/src/mage/cards/s/SunDroplet.java @@ -1,22 +1,15 @@ package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; @@ -24,26 +17,28 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SunDroplet extends CardImpl { public SunDroplet(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // Whenever you're dealt damage, put that many charge counters on Sun Droplet. this.addAbility(new SunDropletTriggeredAbility()); + // At the beginning of each upkeep, you may remove a charge counter from Sun Droplet. If you do, you gain 1 life. - //TODO this shouldn't be conditional because you can respond to the trigger by adding counters. - Effect effect = new DoIfCostPaid(new GainLifeEffect(1), new RemoveCountersSourceCost(CounterType.CHARGE.createInstance(1))); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.ANY, false), - new SourceHasCounterCondition(CounterType.CHARGE, 1), - "At the beginning of each upkeep, you may remove a charge counter from Sun Droplet. If you do, you gain 1 life")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new DoIfCostPaid( + new GainLifeEffect(1), new RemoveCountersSourceCost(CounterType.CHARGE.createInstance()) + ), TargetController.ANY, false + )); } - public SunDroplet(final SunDroplet card) { + private SunDroplet(final SunDroplet card) { super(card); } @@ -55,11 +50,11 @@ public final class SunDroplet extends CardImpl { class SunDropletTriggeredAbility extends TriggeredAbilityImpl { - public SunDropletTriggeredAbility() { - super(Zone.BATTLEFIELD, new SunDropletEffect(), false); + SunDropletTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), false); } - public SunDropletTriggeredAbility(final SunDropletTriggeredAbility ability) { + private SunDropletTriggeredAbility(final SunDropletTriggeredAbility ability) { super(ability); } @@ -76,7 +71,8 @@ class SunDropletTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getTargetId().equals(this.getControllerId())) { - this.getEffects().get(0).setValue("damageAmount", event.getAmount()); + this.getEffects().clear(); + this.addEffect(new AddCountersSourceEffect(CounterType.CHARGE.createInstance(event.getAmount()))); return true; } return false; @@ -87,24 +83,3 @@ class SunDropletTriggeredAbility extends TriggeredAbilityImpl { return "Whenever you're dealt damage, put that many charge counters on {this}."; } } - -class SunDropletEffect extends OneShotEffect { - - public SunDropletEffect() { - super(Outcome.Benefit); - } - - public SunDropletEffect(final SunDropletEffect effect) { - super(effect); - } - - @Override - public SunDropletEffect copy() { - return new SunDropletEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return new AddCountersSourceEffect(CounterType.CHARGE.createInstance((Integer) this.getValue("damageAmount"))).apply(game, source); - } -} diff --git a/Mage.Sets/src/mage/cards/s/SunblastAngel.java b/Mage.Sets/src/mage/cards/s/SunblastAngel.java index 16d1491dcdb..a089f3485d3 100644 --- a/Mage.Sets/src/mage/cards/s/SunblastAngel.java +++ b/Mage.Sets/src/mage/cards/s/SunblastAngel.java @@ -24,7 +24,7 @@ public final class SunblastAngel extends CardImpl { private static final FilterPermanent tappedFilter = new FilterCreaturePermanent("tapped creatures"); static { - tappedFilter.add(new TappedPredicate()); + tappedFilter.add(TappedPredicate.instance); } public SunblastAngel (UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SunbringersTouch.java b/Mage.Sets/src/mage/cards/s/SunbringersTouch.java index d1a1104cd42..1cca7cfa8c3 100644 --- a/Mage.Sets/src/mage/cards/s/SunbringersTouch.java +++ b/Mage.Sets/src/mage/cards/s/SunbringersTouch.java @@ -30,7 +30,7 @@ public final class SunbringersTouch extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}{G}"); // Bolster X, where X is the number of cards in your hand. - this.getSpellAbility().addEffect(new BolsterEffect(new CardsInControllerHandCount())); + this.getSpellAbility().addEffect(new BolsterEffect(CardsInControllerHandCount.instance)); // Each creature you control with a +1/+1 counter on it gains trample until end of turn. Effect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filter); diff --git a/Mage.Sets/src/mage/cards/s/SunderShaman.java b/Mage.Sets/src/mage/cards/s/SunderShaman.java new file mode 100644 index 00000000000..c60b70ff8df --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SunderShaman.java @@ -0,0 +1,92 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByMoreThanOneSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SunderShaman extends CardImpl { + + public SunderShaman(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{R}{G}{G}"); + + this.subtype.add(SubType.GIANT); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Sunder Shaman can't be blocked by more than one creature. + this.addAbility(new SimpleStaticAbility(new CantBeBlockedByMoreThanOneSourceEffect())); + + // Whenever Sunder Shaman deals combat damage to a player, destroy target artifact or enchantment that player controls. + this.addAbility(new SunderShamanTriggeredAbility()); + } + + private SunderShaman(final SunderShaman card) { + super(card); + } + + @Override + public SunderShaman copy() { + return new SunderShaman(this); + } +} + +class SunderShamanTriggeredAbility extends TriggeredAbilityImpl { + + SunderShamanTriggeredAbility() { + super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false); + } + + private SunderShamanTriggeredAbility(final SunderShamanTriggeredAbility ability) { + super(ability); + } + + @Override + public SunderShamanTriggeredAbility copy() { + return new SunderShamanTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player opponent = game.getPlayer(event.getPlayerId()); + if (opponent != null && event.getSourceId().equals(this.sourceId)) { + FilterPermanent filter = StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT.copy(); + filter.setMessage("artifact or enchantment controlled by" + opponent.getLogName()); + filter.add(new ControllerIdPredicate(opponent.getId())); + this.getTargets().clear(); + this.addTarget(new TargetPermanent(filter)); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "destroy target artifact or enchantment that player controls."; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java b/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java index 38d7bedb37b..e9a0bec6af2 100644 --- a/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java +++ b/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java @@ -32,7 +32,7 @@ public final class SunstrikeLegionnaire extends CardImpl { private static final FilterCreaturePermanent tapFilter = new FilterCreaturePermanent("creature with converted mana cost 3 or less"); static { - untapFilter.add(new AnotherPredicate()); + untapFilter.add(AnotherPredicate.instance); tapFilter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4)); } diff --git a/Mage.Sets/src/mage/cards/s/SupplyCaravan.java b/Mage.Sets/src/mage/cards/s/SupplyCaravan.java index cb76066914c..763394039d3 100644 --- a/Mage.Sets/src/mage/cards/s/SupplyCaravan.java +++ b/Mage.Sets/src/mage/cards/s/SupplyCaravan.java @@ -25,7 +25,7 @@ public final class SupplyCaravan extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SupplyCaravan(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SupplyDemand.java b/Mage.Sets/src/mage/cards/s/SupplyDemand.java index deec3a02d5a..a9ca239a289 100644 --- a/Mage.Sets/src/mage/cards/s/SupplyDemand.java +++ b/Mage.Sets/src/mage/cards/s/SupplyDemand.java @@ -23,7 +23,7 @@ public final class SupplyDemand extends SplitCard { private static final FilterCard filter = new FilterCard("multicolored card"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public SupplyDemand(UUID ownerId, CardSetInfo setInfo) { @@ -31,7 +31,7 @@ public final class SupplyDemand extends SplitCard { // Supply // create X 1/1 green Saproling creature tokens. - getLeftHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new ManacostVariableValue())); + getLeftHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), ManacostVariableValue.instance)); // Demand // Search your library for a multicolored card, reveal it, and put it into your hand. Then shuffle your library. diff --git a/Mage.Sets/src/mage/cards/s/SupremeInquisitor.java b/Mage.Sets/src/mage/cards/s/SupremeInquisitor.java index aef0f732e95..17fb5d6f117 100644 --- a/Mage.Sets/src/mage/cards/s/SupremeInquisitor.java +++ b/Mage.Sets/src/mage/cards/s/SupremeInquisitor.java @@ -36,7 +36,7 @@ public final class SupremeInquisitor extends CardImpl { static { filter.add(new SubtypePredicate(SubType.WIZARD)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SupremeInquisitor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java index c894340e3a7..4ddba10eb01 100644 --- a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java +++ b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java @@ -11,13 +11,16 @@ import mage.abilities.costs.common.PayVariableLoyaltyCost; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.*; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.HasteAbility; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.counters.Counter; import mage.counters.CounterType; import mage.filter.StaticFilters; @@ -26,19 +29,17 @@ import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; import mage.watchers.common.PlayerLostLifeNonCombatWatcher; /** - * * @author NinthWorld */ public final class SupremeLeaderSnoke extends CardImpl { - UUID ability3Id; - public SupremeLeaderSnoke(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{U}{B}{R}"); - + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.SNOKE); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); @@ -54,35 +55,17 @@ public final class SupremeLeaderSnoke extends CardImpl { // -X: Gain control of target creature with converted mana cost X. Untap that creature. It gains haste. Sacrifice that creature at the beginning of the next end step. Ability ability3 = new LoyaltyAbility(new GainControlTargetEffect(Duration.WhileOnBattlefield) - .setText("Gain control of target creature with converted mana cost X")); + .setText("Gain control of target creature with converted mana cost X")); ability3.addEffect(new UntapTargetEffect().setText("Untap that creature")); ability3.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield).setText("It gains haste")); ability3.addEffect(new GainAbilityTargetEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()), Duration.WhileOnBattlefield) - .setText("Sacrifice that creature at the beginning of the next end step")); - ability3Id = ability3.getOriginalId(); - ability3.addTarget(new TargetCreaturePermanent()); + .setText("Sacrifice that creature at the beginning of the next end step")); + ability3.setTargetAdjuster(SupremeLeaderSnokeAdjuster.instance); this.addAbility(ability3); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(ability3Id)) { - int cmc = 0; - for (Cost cost : ability.getCosts()) { - if (cost instanceof PayVariableLoyaltyCost) { - cmc = ((PayVariableLoyaltyCost) cost).getAmount(); - } - } - FilterCreaturePermanent newFilter = StaticFilters.FILTER_PERMANENT_CREATURE.copy(); - newFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, cmc)); - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(newFilter)); - } - } - public SupremeLeaderSnoke(final SupremeLeaderSnoke card) { super(card); - this.ability3Id = card.ability3Id; } @Override @@ -91,11 +74,29 @@ public final class SupremeLeaderSnoke extends CardImpl { } } +enum SupremeLeaderSnokeAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + int cmc = 0; + for (Cost cost : ability.getCosts()) { + if (cost instanceof PayVariableLoyaltyCost) { + cmc = ((PayVariableLoyaltyCost) cost).getAmount(); + } + } + FilterCreaturePermanent newFilter = StaticFilters.FILTER_PERMANENT_CREATURE.copy(); + newFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, cmc)); + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(newFilter)); + } +} + class OpponentNoncombatLostLifeCount implements DynamicValue { @Override public int calculate(Game game, Ability source, Effect effect) { - PlayerLostLifeNonCombatWatcher watcher = (PlayerLostLifeNonCombatWatcher) game.getState().getWatchers().get(PlayerLostLifeNonCombatWatcher.class.getSimpleName()); + PlayerLostLifeNonCombatWatcher watcher = game.getState().getWatcher(PlayerLostLifeNonCombatWatcher.class); if(watcher != null) { return watcher.getAllOppLifeLost(source.getControllerId(), game); } @@ -131,9 +132,9 @@ class SupremeLeaderSnokeCounterEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - if(permanent != null) { + if (permanent != null) { int amount = new OpponentNoncombatLostLifeCount().calculate(game, source, this); - if(amount > 0) { + if (amount > 0) { Counter counterToAdd = counter.copy(); counterToAdd.add(amount - counter.getCount()); permanent.addCounters(counterToAdd, source, game); diff --git a/Mage.Sets/src/mage/cards/s/SurgeOfStrength.java b/Mage.Sets/src/mage/cards/s/SurgeOfStrength.java index 7a9a5d79248..d71e125bb65 100644 --- a/Mage.Sets/src/mage/cards/s/SurgeOfStrength.java +++ b/Mage.Sets/src/mage/cards/s/SurgeOfStrength.java @@ -42,7 +42,7 @@ public final class SurgeOfStrength extends CardImpl { Effect effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); effect.setText("Target creature gains trample"); this.getSpellAbility().addEffect(effect); - effect = new BoostTargetEffect(new TargetConvertedManaCost(), new StaticValue(0), Duration.EndOfTurn, true); + effect = new BoostTargetEffect(TargetConvertedManaCost.instance, new StaticValue(0), Duration.EndOfTurn, true); effect.setText("and gets +X/+0 until end of turn, where X is that creature's converted mana cost"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java b/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java index 723ea2cc6ee..e1f0e8ff73d 100644 --- a/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java +++ b/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java @@ -1,11 +1,11 @@ - package mage.cards.s; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.*; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; @@ -21,8 +21,10 @@ import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInLibrary; +import java.util.List; +import java.util.UUID; + /** - * * @author North */ public final class SurgicalExtraction extends CardImpl { @@ -71,12 +73,12 @@ class SurgicalExtractionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Card chosenCard = game.getCard(source.getFirstTarget()); - Player controller = game.getPlayer(source.getControllerId()); - // 6/1/2011 "Any number of cards" means just that. If you wish, you can choose to // leave some or all of the cards with the same name as the targeted card, // including that card, in the zone they're in. + + Card chosenCard = game.getCard(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); if (chosenCard != null && controller != null) { Player owner = game.getPlayer(chosenCard.getOwnerId()); if (owner != null) { diff --git a/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java b/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java index a52604f7541..94db2f76643 100644 --- a/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java +++ b/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java @@ -23,7 +23,7 @@ public final class SurrakarBanisher extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SurrakarBanisher(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java b/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java index b50fa4d1480..aae6ff535e8 100644 --- a/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java +++ b/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java @@ -24,7 +24,7 @@ public final class SurvivorsEncampment extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SurvivorsEncampment(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SwallowingPlague.java b/Mage.Sets/src/mage/cards/s/SwallowingPlague.java index 9b17abee582..7392aca66bb 100644 --- a/Mage.Sets/src/mage/cards/s/SwallowingPlague.java +++ b/Mage.Sets/src/mage/cards/s/SwallowingPlague.java @@ -23,8 +23,8 @@ public final class SwallowingPlague extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}{B}"); this.subtype.add(SubType.ARCANE); - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); - this.getSpellAbility().addEffect(new GainLifeEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); + this.getSpellAbility().addEffect(new GainLifeEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/s/SwarmSurge.java b/Mage.Sets/src/mage/cards/s/SwarmSurge.java index 2bf4f0104e5..74c0ca260d0 100644 --- a/Mage.Sets/src/mage/cards/s/SwarmSurge.java +++ b/Mage.Sets/src/mage/cards/s/SwarmSurge.java @@ -23,7 +23,7 @@ public final class SwarmSurge extends CardImpl { private static final FilterCreaturePermanent FILTER = new FilterCreaturePermanent("Colorless creatures you control"); static { - FILTER.add(new ColorlessPredicate()); + FILTER.add(ColorlessPredicate.instance); } public SwarmSurge(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SwellOfCourage.java b/Mage.Sets/src/mage/cards/s/SwellOfCourage.java index 372a09d6c5a..457048a651c 100644 --- a/Mage.Sets/src/mage/cards/s/SwellOfCourage.java +++ b/Mage.Sets/src/mage/cards/s/SwellOfCourage.java @@ -24,7 +24,7 @@ public final class SwellOfCourage extends CardImpl { // Creatures you control get +2/+2 until end of turn. this.getSpellAbility().addEffect(new BoostControlledEffect(2,2, Duration.EndOfTurn)); // Reinforce X-{X}{W}{W} - this.addAbility(new ReinforceAbility(new ManacostVariableValue(), new ManaCostsImpl("{X}{W}{W}"))); + this.addAbility(new ReinforceAbility(ManacostVariableValue.instance, new ManaCostsImpl("{X}{W}{W}"))); } public SwellOfCourage(final SwellOfCourage card) { diff --git a/Mage.Sets/src/mage/cards/s/SwiftReckoning.java b/Mage.Sets/src/mage/cards/s/SwiftReckoning.java index b2034ce917a..3d252b1d339 100644 --- a/Mage.Sets/src/mage/cards/s/SwiftReckoning.java +++ b/Mage.Sets/src/mage/cards/s/SwiftReckoning.java @@ -26,7 +26,7 @@ public final class SwiftReckoning extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public SwiftReckoning(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SwirlingTorrent.java b/Mage.Sets/src/mage/cards/s/SwirlingTorrent.java new file mode 100644 index 00000000000..a2c2837a26b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SwirlingTorrent.java @@ -0,0 +1,43 @@ +package mage.cards.s; + +import mage.abilities.Mode; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SwirlingTorrent extends CardImpl { + + public SwirlingTorrent(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{U}"); + + // Choose one or both — + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(2); + + // • Put target creature on top of its owner's library. + this.getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // • Return target creature to its owner's hand. + Mode mode = new Mode(new ReturnToHandTargetEffect()); + mode.addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addMode(mode); + } + + private SwirlingTorrent(final SwirlingTorrent card) { + super(card); + } + + @Override + public SwirlingTorrent copy() { + return new SwirlingTorrent(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SwordOfTheParuns.java b/Mage.Sets/src/mage/cards/s/SwordOfTheParuns.java index a8581ef580b..5c610773a70 100644 --- a/Mage.Sets/src/mage/cards/s/SwordOfTheParuns.java +++ b/Mage.Sets/src/mage/cards/s/SwordOfTheParuns.java @@ -37,8 +37,8 @@ public final class SwordOfTheParuns extends CardImpl { private static final FilterCreaturePermanent filterTapped = new FilterCreaturePermanent(); private static final FilterCreaturePermanent filterUntapped = new FilterCreaturePermanent(); static { - filterTapped.add(new TappedPredicate()); - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterTapped.add(TappedPredicate.instance); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } public SwordOfTheParuns(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SwordOfWarAndPeace.java b/Mage.Sets/src/mage/cards/s/SwordOfWarAndPeace.java index d0035791005..9968d14771f 100644 --- a/Mage.Sets/src/mage/cards/s/SwordOfWarAndPeace.java +++ b/Mage.Sets/src/mage/cards/s/SwordOfWarAndPeace.java @@ -69,7 +69,7 @@ class SwordOfWarAndPeaceAbility extends TriggeredAbilityImpl { public SwordOfWarAndPeaceAbility() { super(Zone.BATTLEFIELD, new SwordOfWarAndPeaceDamageEffect()); - this.addEffect(new GainLifeEffect(new CardsInControllerHandCount())); + this.addEffect(new GainLifeEffect(CardsInControllerHandCount.instance)); } public SwordOfWarAndPeaceAbility(final SwordOfWarAndPeaceAbility ability) { diff --git a/Mage.Sets/src/mage/cards/s/SylvanBrushstrider.java b/Mage.Sets/src/mage/cards/s/SylvanBrushstrider.java new file mode 100644 index 00000000000..c7182ee0d96 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SylvanBrushstrider.java @@ -0,0 +1,37 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SylvanBrushstrider extends CardImpl { + + public SylvanBrushstrider(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Sylvan Brushstrider enters the battlefield, you gain 2 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2))); + } + + private SylvanBrushstrider(final SylvanBrushstrider card) { + super(card); + } + + @Override + public SylvanBrushstrider copy() { + return new SylvanBrushstrider(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SylvanLibrary.java b/Mage.Sets/src/mage/cards/s/SylvanLibrary.java index 751a5ab5444..5db817e5a72 100644 --- a/Mage.Sets/src/mage/cards/s/SylvanLibrary.java +++ b/Mage.Sets/src/mage/cards/s/SylvanLibrary.java @@ -72,7 +72,7 @@ class SylvanLibraryEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { controller.drawCards(2, game); - SylvanLibraryCardsDrawnThisTurnWatcher watcher = (SylvanLibraryCardsDrawnThisTurnWatcher) game.getState().getWatchers().get(SylvanLibraryCardsDrawnThisTurnWatcher.class.getSimpleName()); + SylvanLibraryCardsDrawnThisTurnWatcher watcher = game.getState().getWatcher(SylvanLibraryCardsDrawnThisTurnWatcher.class); if (watcher != null) { Cards cards = new CardsImpl(); Set cardsDrawnThisTurn = watcher.getCardsDrawnThisTurn(controller.getId()); @@ -119,7 +119,7 @@ class SylvanLibraryCardsDrawnThisTurnWatcher extends Watcher { private final Map> cardsDrawnThisTurn = new HashMap<>(); public SylvanLibraryCardsDrawnThisTurnWatcher() { - super(SylvanLibraryCardsDrawnThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(SylvanLibraryCardsDrawnThisTurnWatcher.class, WatcherScope.GAME); } public SylvanLibraryCardsDrawnThisTurnWatcher(final SylvanLibraryCardsDrawnThisTurnWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java b/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java index 625bcf609b9..b6c63993d5a 100644 --- a/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java +++ b/Mage.Sets/src/mage/cards/s/SylvanPrimordial.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -25,15 +24,17 @@ import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SylvanPrimordial extends CardImpl { public SylvanPrimordial(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); this.subtype.add(SubType.AVATAR); this.power = new MageInt(6); @@ -43,24 +44,9 @@ public final class SylvanPrimordial extends CardImpl { this.addAbility(ReachAbility.getInstance()); // When Sylvan Primordial enters the battlefield, for each opponent, destroy target noncreature permanent that player controls. For each permanent destroyed this way, search your library for a Forest card and put that card onto the battlefield tapped. Then shuffle your library. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SylvanPrimordialEffect(),false)); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - ability.getTargets().clear(); - for(UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterPermanent filter = new FilterPermanent("noncreature permanent from opponent " + opponent.getLogName()); - filter.add(new ControllerIdPredicate(opponentId)); - filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); - TargetPermanent target = new TargetPermanent(0,1, filter,false); - ability.addTarget(target); - } - } - } + Ability ability = new EntersBattlefieldTriggeredAbility(new SylvanPrimordialEffect(), false); + ability.setTargetAdjuster(SylvanPrimordialAdjuster.instance); + this.addAbility(ability); } public SylvanPrimordial(final SylvanPrimordial card) { @@ -73,10 +59,30 @@ public final class SylvanPrimordial extends CardImpl { } } +enum SylvanPrimordialAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + FilterPermanent filter = new FilterPermanent("noncreature permanent from opponent " + opponent.getLogName()); + filter.add(new ControllerIdPredicate(opponentId)); + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + TargetPermanent target = new TargetPermanent(0, 1, filter, false); + ability.addTarget(target); + } + } + } +} + class SylvanPrimordialEffect extends OneShotEffect { private static final FilterLandCard filterForest = new FilterLandCard("Forest"); - static{ + + static { filterForest.add(new SubtypePredicate(SubType.FOREST)); } @@ -98,7 +104,7 @@ class SylvanPrimordialEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { boolean result = false; int destroyedCreatures = 0; - for (Target target: source.getTargets()) { + for (Target target : source.getTargets()) { if (target instanceof TargetPermanent) { Permanent targetPermanent = game.getPermanent(target.getFirstTarget()); if (targetPermanent != null) { @@ -109,7 +115,7 @@ class SylvanPrimordialEffect extends OneShotEffect { } } if (destroyedCreatures > 0) { - new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(destroyedCreatures,filterForest), true, true).apply(game, source); + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(destroyedCreatures, filterForest), true, true).apply(game, source); } return result; } diff --git a/Mage.Sets/src/mage/cards/s/SylvanYeti.java b/Mage.Sets/src/mage/cards/s/SylvanYeti.java index 688718f865e..d402b7450b6 100644 --- a/Mage.Sets/src/mage/cards/s/SylvanYeti.java +++ b/Mage.Sets/src/mage/cards/s/SylvanYeti.java @@ -27,7 +27,7 @@ public final class SylvanYeti extends CardImpl { this.toughness = new MageInt(4); // Sylvan Yeti's power is equal to the number of cards in your hand. - Effect effect = new SetPowerSourceEffect(new CardsInControllerHandCount(), Duration.EndOfGame); + Effect effect = new SetPowerSourceEffect(CardsInControllerHandCount.instance, Duration.EndOfGame); this.addAbility(new SimpleStaticAbility(Zone.ALL, effect)); } diff --git a/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java b/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java index 55000ba822c..3cb81da2ec0 100644 --- a/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java +++ b/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java @@ -27,7 +27,7 @@ public final class SymbioticDeployment extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public SymbioticDeployment(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/Syncopate.java b/Mage.Sets/src/mage/cards/s/Syncopate.java index 01dd9e88258..76c656fa77f 100644 --- a/Mage.Sets/src/mage/cards/s/Syncopate.java +++ b/Mage.Sets/src/mage/cards/s/Syncopate.java @@ -71,7 +71,7 @@ class SyncopateCounterUnlessPaysEffect extends OneShotEffect { StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, source.getFirstTarget(), source.getSourceId(), stackObject.getControllerId()))) { game.informPlayers(sourceObject.getIdName() + ": cost wasn't payed - countering " + stackObject.getName()); - game.rememberLKI(source.getFirstTarget(), Zone.STACK, (Spell) stackObject); + game.rememberLKI(source.getFirstTarget(), Zone.STACK, stackObject); controller.moveCards((Spell) spell, Zone.EXILED, source, game); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, source.getFirstTarget(), source.getSourceId(), stackObject.getControllerId())); return true; diff --git a/Mage.Sets/src/mage/cards/s/SyndicateGuildmage.java b/Mage.Sets/src/mage/cards/s/SyndicateGuildmage.java new file mode 100644 index 00000000000..2103a1c94ae --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SyndicateGuildmage.java @@ -0,0 +1,67 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetOpponentOrPlaneswalker; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SyndicateGuildmage extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with power 4 or greater"); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public SyndicateGuildmage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {1}{W}, {T}: Tap target creature with power 4 or greater. + Ability ability = new SimpleActivatedAbility( + new TapTargetEffect(), new ManaCostsImpl("{1}{W}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + + // {4}{B}, {T}: Syndicate Guildmage deals 2 damage to target opponent or planeswalker. + ability = new SimpleActivatedAbility( + new DamageTargetEffect(2), new ManaCostsImpl("{4}{B}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetOpponentOrPlaneswalker()); + this.addAbility(ability); + } + + private SyndicateGuildmage(final SyndicateGuildmage card) { + super(card); + } + + @Override + public SyndicateGuildmage copy() { + return new SyndicateGuildmage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SyndicateMessenger.java b/Mage.Sets/src/mage/cards/s/SyndicateMessenger.java new file mode 100644 index 00000000000..1450ab1d262 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SyndicateMessenger.java @@ -0,0 +1,40 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.keyword.AfterlifeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SyndicateMessenger extends CardImpl { + + public SyndicateMessenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.BIRD); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Afterlife 1 + this.addAbility(new AfterlifeAbility(1)); + } + + private SyndicateMessenger(final SyndicateMessenger card) { + super(card); + } + + @Override + public SyndicateMessenger copy() { + return new SyndicateMessenger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java b/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java index 52774236e1d..c9605157dbb 100644 --- a/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java +++ b/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java @@ -25,8 +25,8 @@ public final class TacticalAdvantage extends CardImpl { static { filter.add( Predicates.or( - new BlockingPredicate(), - new BlockedPredicate() + BlockingPredicate.instance, + BlockedPredicate.instance )); filter.add(new ControllerPredicate(TargetController.YOU)); diff --git a/Mage.Sets/src/mage/cards/t/TaintedSigil.java b/Mage.Sets/src/mage/cards/t/TaintedSigil.java index 18f6f773788..424a3d31913 100644 --- a/Mage.Sets/src/mage/cards/t/TaintedSigil.java +++ b/Mage.Sets/src/mage/cards/t/TaintedSigil.java @@ -1,7 +1,6 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -16,23 +15,22 @@ import mage.constants.Zone; import mage.game.Game; import mage.watchers.common.PlayerLostLifeWatcher; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class TaintedSigil extends CardImpl { - - String rule = "You gain life equal to the total life lost by all players this turn"; + + private static final String rule = "You gain life equal to the total life lost by all players this turn"; public TaintedSigil(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}{W}{B}"); - - - + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}{B}"); // {tap}, Sacrifice Tainted Sigil: You gain life equal to the total life lost by all players this turn. - AllPlayersLostLifeCount totalLifeLostThisTurn = new AllPlayersLostLifeCount(); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(totalLifeLostThisTurn, rule), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, new GainLifeEffect(AllPlayersLostLifeCount.instance, rule), new TapSourceCost() + ); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); @@ -48,7 +46,8 @@ public final class TaintedSigil extends CardImpl { } } -class AllPlayersLostLifeCount implements DynamicValue { +enum AllPlayersLostLifeCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -56,11 +55,11 @@ class AllPlayersLostLifeCount implements DynamicValue { } public int calculate(Game game, UUID controllerId) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { int amountLifeLost = 0; for (UUID playerId : game.getState().getPlayersInRange(controllerId, game)) { - amountLifeLost += watcher.getLiveLost(playerId); + amountLifeLost += watcher.getLifeLost(playerId); } return amountLifeLost; } @@ -69,7 +68,7 @@ class AllPlayersLostLifeCount implements DynamicValue { @Override public DynamicValue copy() { - return new AllPlayersLostLifeCount(); + return instance; } @Override diff --git a/Mage.Sets/src/mage/cards/t/TajicLegionsEdge.java b/Mage.Sets/src/mage/cards/t/TajicLegionsEdge.java index faa291400c4..a396479913d 100644 --- a/Mage.Sets/src/mage/cards/t/TajicLegionsEdge.java +++ b/Mage.Sets/src/mage/cards/t/TajicLegionsEdge.java @@ -30,7 +30,7 @@ public final class TajicLegionsEdge extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("other creatures you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TajicLegionsEdge(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TakeHeart.java b/Mage.Sets/src/mage/cards/t/TakeHeart.java index b57596a3632..cdf08b872c8 100644 --- a/Mage.Sets/src/mage/cards/t/TakeHeart.java +++ b/Mage.Sets/src/mage/cards/t/TakeHeart.java @@ -23,7 +23,7 @@ public final class TakeHeart extends CardImpl { = new FilterControlledCreaturePermanent(); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public TakeHeart(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TakeVengeance.java b/Mage.Sets/src/mage/cards/t/TakeVengeance.java index 5a229b0ba18..e58e3d3f1b6 100644 --- a/Mage.Sets/src/mage/cards/t/TakeVengeance.java +++ b/Mage.Sets/src/mage/cards/t/TakeVengeance.java @@ -18,7 +18,7 @@ public final class TakeVengeance extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public TakeVengeance(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TalarasBattalion.java b/Mage.Sets/src/mage/cards/t/TalarasBattalion.java index c7ea37d9da9..a2c6153e400 100644 --- a/Mage.Sets/src/mage/cards/t/TalarasBattalion.java +++ b/Mage.Sets/src/mage/cards/t/TalarasBattalion.java @@ -94,7 +94,7 @@ class CastGreenSpellThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - TalarasBattalionWatcher watcher = (TalarasBattalionWatcher) game.getState().getWatchers().get(TalarasBattalionWatcher.class.getSimpleName(), source.getControllerId()); + TalarasBattalionWatcher watcher = game.getState().getWatcher(TalarasBattalionWatcher.class, source.getControllerId()); if (watcher != null) { return watcher.conditionMet(); } @@ -112,7 +112,7 @@ class TalarasBattalionWatcher extends Watcher { private final UUID cardId; public TalarasBattalionWatcher(UUID cardId) { - super(TalarasBattalionWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(TalarasBattalionWatcher.class, WatcherScope.PLAYER); this.cardId = cardId; } diff --git a/Mage.Sets/src/mage/cards/t/TalonOfPain.java b/Mage.Sets/src/mage/cards/t/TalonOfPain.java index 0558c9b9333..b6fa0d37241 100644 --- a/Mage.Sets/src/mage/cards/t/TalonOfPain.java +++ b/Mage.Sets/src/mage/cards/t/TalonOfPain.java @@ -42,7 +42,7 @@ public final class TalonOfPain extends CardImpl { this.addAbility(new TalonOfPainTriggeredAbility()); // {X}, {T}, Remove X charge counters from Talon of Pain: Talon of Pain deals X damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); ability.addCost(new TalonOfPainRemoveVariableCountersSourceCost(CounterType.CHARGE.createInstance())); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/t/TamiyoTheMoonSage.java b/Mage.Sets/src/mage/cards/t/TamiyoTheMoonSage.java index 6239f76dff0..06ef55dadfd 100644 --- a/Mage.Sets/src/mage/cards/t/TamiyoTheMoonSage.java +++ b/Mage.Sets/src/mage/cards/t/TamiyoTheMoonSage.java @@ -68,7 +68,7 @@ class TappedCreaturesControlledByTargetCount implements DynamicValue { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } @Override diff --git a/Mage.Sets/src/mage/cards/t/Tangle.java b/Mage.Sets/src/mage/cards/t/Tangle.java index 17631aca5e0..5efd00ec705 100644 --- a/Mage.Sets/src/mage/cards/t/Tangle.java +++ b/Mage.Sets/src/mage/cards/t/Tangle.java @@ -52,7 +52,7 @@ class TangleEffect extends OneShotEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public TangleEffect() { diff --git a/Mage.Sets/src/mage/cards/t/TangleKelp.java b/Mage.Sets/src/mage/cards/t/TangleKelp.java index d4dde772dfe..710dbc4dd7e 100644 --- a/Mage.Sets/src/mage/cards/t/TangleKelp.java +++ b/Mage.Sets/src/mage/cards/t/TangleKelp.java @@ -107,7 +107,7 @@ class DontUntapIfAttackedLastTurnEnchantedEffect extends ContinuousRuleModifying if (enchantment != null && enchantment.getAttachedTo() != null && event.getTargetId().equals(enchantment.getAttachedTo())) { Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); if (permanent != null && permanent.isControlledBy(game.getActivePlayerId())) { - AttackedLastTurnWatcher watcher = (AttackedLastTurnWatcher) game.getState().getWatchers().get(AttackedLastTurnWatcher.class.getSimpleName()); + AttackedLastTurnWatcher watcher = game.getState().getWatcher(AttackedLastTurnWatcher.class); if (watcher != null) { Set attackingCreatures = watcher.getAttackedLastTurnCreatures(permanent.getControllerId()); MageObjectReference mor = new MageObjectReference(permanent, game); diff --git a/Mage.Sets/src/mage/cards/t/TangleWire.java b/Mage.Sets/src/mage/cards/t/TangleWire.java index 54128b1f59e..befb444899a 100644 --- a/Mage.Sets/src/mage/cards/t/TangleWire.java +++ b/Mage.Sets/src/mage/cards/t/TangleWire.java @@ -51,7 +51,7 @@ class TangleWireEffect extends OneShotEffect { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped artifact, creature, or land he or she controls"); static{ - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE), diff --git a/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java b/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java index 2cccde96c9d..0c25b60d3d1 100644 --- a/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java +++ b/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java @@ -56,7 +56,7 @@ enum PlayerCastNonCreatureSpellCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerCastNonCreatureSpellWatcher watcher = (PlayerCastNonCreatureSpellWatcher) game.getState().getWatchers().get(PlayerCastNonCreatureSpellWatcher.class.getSimpleName()); + PlayerCastNonCreatureSpellWatcher watcher = game.getState().getWatcher(PlayerCastNonCreatureSpellWatcher.class); return watcher != null && watcher.playerDidCastNonCreatureSpellThisTurn(source.getControllerId()); } @@ -71,7 +71,7 @@ class PlayerCastNonCreatureSpellWatcher extends Watcher { Set playerIds = new HashSet<>(); public PlayerCastNonCreatureSpellWatcher() { - super(PlayerCastNonCreatureSpellWatcher.class.getSimpleName(), WatcherScope.GAME); + super(PlayerCastNonCreatureSpellWatcher.class, WatcherScope.GAME); } public PlayerCastNonCreatureSpellWatcher(final PlayerCastNonCreatureSpellWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/t/TattermungeWitch.java b/Mage.Sets/src/mage/cards/t/TattermungeWitch.java index 123bf0fab7d..58fb990feb4 100644 --- a/Mage.Sets/src/mage/cards/t/TattermungeWitch.java +++ b/Mage.Sets/src/mage/cards/t/TattermungeWitch.java @@ -27,7 +27,7 @@ public final class TattermungeWitch extends CardImpl { static final private FilterCreaturePermanent filter = new FilterCreaturePermanent("Each blocked creature"); static { - filter.add(new BlockedPredicate()); + filter.add(BlockedPredicate.instance); } public TattermungeWitch(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TavernSwindler.java b/Mage.Sets/src/mage/cards/t/TavernSwindler.java index 0c5645c8023..e816947ea23 100644 --- a/Mage.Sets/src/mage/cards/t/TavernSwindler.java +++ b/Mage.Sets/src/mage/cards/t/TavernSwindler.java @@ -62,7 +62,7 @@ class TavernSwindlerEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { game.informPlayers(controller.getLogName() + " got " + controller.gainLife(6, game, source)+ " live"); } } diff --git a/Mage.Sets/src/mage/cards/t/TectonicBreak.java b/Mage.Sets/src/mage/cards/t/TectonicBreak.java index c8c47de18c9..14bd9c35651 100644 --- a/Mage.Sets/src/mage/cards/t/TectonicBreak.java +++ b/Mage.Sets/src/mage/cards/t/TectonicBreak.java @@ -19,7 +19,7 @@ public final class TectonicBreak extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}{R}"); // Each player sacrifices X lands. - this.getSpellAbility().addEffect(new SacrificeAllEffect(new ManacostVariableValue(), new FilterControlledLandPermanent("lands"))); + this.getSpellAbility().addEffect(new SacrificeAllEffect(ManacostVariableValue.instance, new FilterControlledLandPermanent("lands"))); } public TectonicBreak(final TectonicBreak card) { diff --git a/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java b/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java index be586c41a5b..a43e9d15c35 100644 --- a/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java +++ b/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -17,14 +15,15 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TeferiMageOfZhalfir extends CardImpl { public TeferiMageOfZhalfir(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}{U}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -76,14 +75,14 @@ class TeferiMageOfZhalfirAddFlashEffect extends ContinuousEffectImpl { // in graveyard for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } // on Hand for (UUID cardId : controller.getHand()) { Card card = game.getCard(cardId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } @@ -103,7 +102,7 @@ class TeferiMageOfZhalfirAddFlashEffect extends ContinuousEffectImpl { for (UUID commanderId : controller.getCommandersIds()) { if (game.getState().getZone(commanderId) == Zone.COMMAND) { Card card = game.getCard(commanderId); - if (card.isCreature()) { + if (card != null && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } diff --git a/Mage.Sets/src/mage/cards/t/TeferisRealm.java b/Mage.Sets/src/mage/cards/t/TeferisRealm.java index 90c27342071..121ade4895b 100644 --- a/Mage.Sets/src/mage/cards/t/TeferisRealm.java +++ b/Mage.Sets/src/mage/cards/t/TeferisRealm.java @@ -90,7 +90,7 @@ class TeferisRealmEffect extends OneShotEffect { } String choosenType = choiceImpl.getChoice(); FilterPermanent filter = new FilterPermanent(); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); switch (choosenType) { case ARTIFACT: filter.add(new CardTypePredicate(CardType.ARTIFACT)); diff --git a/Mage.Sets/src/mage/cards/t/Telethopter.java b/Mage.Sets/src/mage/cards/t/Telethopter.java index 4ad2e92d226..06b7bdc3bb7 100644 --- a/Mage.Sets/src/mage/cards/t/Telethopter.java +++ b/Mage.Sets/src/mage/cards/t/Telethopter.java @@ -26,7 +26,7 @@ public final class Telethopter extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public Telethopter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TelimTor.java b/Mage.Sets/src/mage/cards/t/TelimTor.java index de9ec08ea0f..de1e8588503 100644 --- a/Mage.Sets/src/mage/cards/t/TelimTor.java +++ b/Mage.Sets/src/mage/cards/t/TelimTor.java @@ -25,7 +25,7 @@ public final class TelimTor extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("all attacking creatures with flanking"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(new AbilityPredicate(FlankingAbility.class)); } diff --git a/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java b/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java index 3b1325b477f..41c7f0d70c3 100644 --- a/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java +++ b/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java @@ -30,7 +30,7 @@ public final class TemmetVizierOfNaktamun extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature token you control"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public TemmetVizierOfNaktamun(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/Temper.java b/Mage.Sets/src/mage/cards/t/Temper.java index 602872e0853..b0bdd776b14 100644 --- a/Mage.Sets/src/mage/cards/t/Temper.java +++ b/Mage.Sets/src/mage/cards/t/Temper.java @@ -26,7 +26,7 @@ public final class Temper extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{1}{W}"); // Prevent the next X damage that would be dealt to target creature this turn. For each 1 damage prevented this way, put a +1/+1 counter on that creature. - this.getSpellAbility().addEffect(new TemperPreventDamageTargetEffect(new ManacostVariableValue(), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new TemperPreventDamageTargetEffect(ManacostVariableValue.instance, Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/t/TemurSabertooth.java b/Mage.Sets/src/mage/cards/t/TemurSabertooth.java index 7a454c9851b..f4802c71440 100644 --- a/Mage.Sets/src/mage/cards/t/TemurSabertooth.java +++ b/Mage.Sets/src/mage/cards/t/TemurSabertooth.java @@ -56,7 +56,7 @@ class TemurSabertoothEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TemurSabertoothEffect() { diff --git a/Mage.Sets/src/mage/cards/t/TenthDistrictVeteran.java b/Mage.Sets/src/mage/cards/t/TenthDistrictVeteran.java new file mode 100644 index 00000000000..53b0b20d970 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TenthDistrictVeteran.java @@ -0,0 +1,54 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class TenthDistrictVeteran extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + public TenthDistrictVeteran(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever Tenth District Veteran attacks, untap another target creature you control. + Ability ability = new AttacksTriggeredAbility(new UntapTargetEffect(), false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public TenthDistrictVeteran(final TenthDistrictVeteran card) { + super(card); + } + + @Override + public TenthDistrictVeteran copy() { + return new TenthDistrictVeteran(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/Terrarion.java b/Mage.Sets/src/mage/cards/t/Terrarion.java index d768113a8ff..19ea4ba0bd3 100644 --- a/Mage.Sets/src/mage/cards/t/Terrarion.java +++ b/Mage.Sets/src/mage/cards/t/Terrarion.java @@ -1,37 +1,38 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.mana.AddManaInAnyCombinationEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.mana.AddManaInAnyCombinationEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Terrarion extends CardImpl { public Terrarion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // Terrarion enters the battlefield tapped. this.addAbility(new EntersBattlefieldTappedAbility()); + // {2}, {T}, Sacrifice Terrarion: Add two mana in any combination of colors. Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaInAnyCombinationEffect(2), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); + // When Terrarion is put into a graveyard from the battlefield, draw a card. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new DrawCardSourceControllerEffect(1))); } diff --git a/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java b/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java index b13f74ec870..7c748d0d62f 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java @@ -39,7 +39,7 @@ public final class TerritorialAllosaurus extends CardImpl { Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, it fights another target creature."); FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); conditionalAbility.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(conditionalAbility); } diff --git a/Mage.Sets/src/mage/cards/t/TerritorialBoar.java b/Mage.Sets/src/mage/cards/t/TerritorialBoar.java new file mode 100644 index 00000000000..7d66f4fba48 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TerritorialBoar.java @@ -0,0 +1,58 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TerritorialBoar extends CardImpl { + + private static final FilterPermanent filter + = new FilterCreaturePermanent("a creature with power 4 or greater"); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public TerritorialBoar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.BOAR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever a creature with power 4 or greater enters the battlefield under your control, Territorial Boar gets +1/+1 and gains vigilance until end of turn. + Ability ability = new EntersBattlefieldControlledTriggeredAbility(new BoostSourceEffect( + 1, 1, Duration.EndOfTurn + ).setText("{this} gets +1/+1"), filter); + ability.addEffect(new GainAbilitySourceEffect( + VigilanceAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains vigilance until end of turn")); + this.addAbility(ability); + } + + private TerritorialBoar(final TerritorialBoar card) { + super(card); + } + + @Override + public TerritorialBoar copy() { + return new TerritorialBoar(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TerritorialHellkite.java b/Mage.Sets/src/mage/cards/t/TerritorialHellkite.java index e5644379bcb..1243212c272 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialHellkite.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialHellkite.java @@ -70,7 +70,7 @@ class AttackedLastCombatWatcher extends Watcher { public final Map> attackedLastCombatPlayers = new HashMap<>(); public AttackedLastCombatWatcher() { - super(AttackedLastCombatWatcher.class.getSimpleName(), WatcherScope.GAME); + super(AttackedLastCombatWatcher.class, WatcherScope.GAME); } public AttackedLastCombatWatcher(final AttackedLastCombatWatcher watcher) { @@ -132,7 +132,7 @@ class AttackIfAbleTargetRandoOpponentSourceEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - AttackedLastCombatWatcher watcher = (AttackedLastCombatWatcher) game.getState().getWatchers().get(AttackedLastCombatWatcher.class.getSimpleName()); + AttackedLastCombatWatcher watcher = game.getState().getWatcher(AttackedLastCombatWatcher.class); if (controller != null && sourcePermanent != null && watcher != null) { List opponents = new ArrayList<>(); Map attackedPlayers = watcher.getAttackedLastCombatPlayers(source.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/t/Tetravus.java b/Mage.Sets/src/mage/cards/t/Tetravus.java index ace6165e8ed..c0f8b59d442 100644 --- a/Mage.Sets/src/mage/cards/t/Tetravus.java +++ b/Mage.Sets/src/mage/cards/t/Tetravus.java @@ -155,7 +155,7 @@ class TetravusAddCountersEffect extends OneShotEffect { } FilterControlledPermanent filter = new FilterControlledPermanent("tokens created with " + permanent.getName()); filter.add(new TetravusPredicate(new MageObjectReference(permanent, game))); - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); ExileTargetCost cost = new ExileTargetCost(new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true)); if (cost.pay(source, game, source.getSourceId(), player.getId(), true)) { return new AddCountersSourceEffect(CounterType.P1P1.createInstance(cost.getPermanents().size())).apply(game, source); diff --git a/Mage.Sets/src/mage/cards/t/TetsuoUmezawa.java b/Mage.Sets/src/mage/cards/t/TetsuoUmezawa.java index ae0d4677a0c..70827ef6f79 100644 --- a/Mage.Sets/src/mage/cards/t/TetsuoUmezawa.java +++ b/Mage.Sets/src/mage/cards/t/TetsuoUmezawa.java @@ -34,8 +34,8 @@ public final class TetsuoUmezawa extends CardImpl { static { creatureFilter.add(Predicates.or( - new TappedPredicate(), - new BlockingPredicate())); + TappedPredicate.instance, + BlockingPredicate.instance)); } public TetsuoUmezawa(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TeysaKarlov.java b/Mage.Sets/src/mage/cards/t/TeysaKarlov.java new file mode 100644 index 00000000000..5b4c94bf5c8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TeysaKarlov.java @@ -0,0 +1,109 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.NumberOfTriggersEvent; +import mage.game.events.ZoneChangeEvent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TeysaKarlov extends CardImpl { + + public TeysaKarlov(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // If a creature dying causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time. + this.addAbility(new SimpleStaticAbility(new TeysaKarlovEffect())); + + // Creature tokens you control have vigilance and lifelink. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), + Duration.WhileOnBattlefield, + StaticFilters.FILTER_CREATURE_TOKENS + ).setText("creature tokens you control have vigilance") + ); + ability.addEffect(new GainAbilityControlledEffect( + LifelinkAbility.getInstance(), + Duration.WhileOnBattlefield, + StaticFilters.FILTER_CREATURE_TOKENS + ).setText("and lifelink")); + this.addAbility(ability); + } + + private TeysaKarlov(final TeysaKarlov card) { + super(card); + } + + @Override + public TeysaKarlov copy() { + return new TeysaKarlov(this); + } +} + +class TeysaKarlovEffect extends ReplacementEffectImpl { + + TeysaKarlovEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If a creature dying causes a triggered ability of a permanent you control to trigger, " + + "that ability triggers an additional time."; + } + + private TeysaKarlovEffect(final TeysaKarlovEffect effect) { + super(effect); + } + + @Override + public TeysaKarlovEffect copy() { + return new TeysaKarlovEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.NUMBER_OF_TRIGGERS; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event instanceof NumberOfTriggersEvent) { + NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; + if (source.isControlledBy(event.getPlayerId()) + && game.getPermanentOrLKIBattlefield(numberOfTriggersEvent.getSourceId()) != null + && numberOfTriggersEvent.getSourceEvent() instanceof ZoneChangeEvent) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) numberOfTriggersEvent.getSourceEvent(); + return zEvent.getFromZone() == Zone.BATTLEFIELD + && zEvent.getToZone() == Zone.GRAVEYARD + && zEvent.getTarget() != null + && zEvent.getTarget().isCreature(); + } + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + event.setAmount(event.getAmount() + 1); + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java b/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java index ecf320e2bbd..41a5b34afd5 100644 --- a/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java +++ b/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java @@ -37,7 +37,7 @@ public final class TeysaOrzhovScion extends CardImpl { static { filterWhite.add(new ColorPredicate(ObjectColor.WHITE)); filterBlack.add(new ColorPredicate(ObjectColor.BLACK)); - filterBlack.add(new AnotherPredicate()); + filterBlack.add(AnotherPredicate.instance); filterBlack.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/t/ThaliasLieutenant.java b/Mage.Sets/src/mage/cards/t/ThaliasLieutenant.java index 2187bbb32cd..27a8ccc8629 100644 --- a/Mage.Sets/src/mage/cards/t/ThaliasLieutenant.java +++ b/Mage.Sets/src/mage/cards/t/ThaliasLieutenant.java @@ -25,7 +25,7 @@ public final class ThaliasLieutenant extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("each other Human you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.HUMAN)); } diff --git a/Mage.Sets/src/mage/cards/t/ThatWhichWasTaken.java b/Mage.Sets/src/mage/cards/t/ThatWhichWasTaken.java index 28494795648..cc66e70e131 100644 --- a/Mage.Sets/src/mage/cards/t/ThatWhichWasTaken.java +++ b/Mage.Sets/src/mage/cards/t/ThatWhichWasTaken.java @@ -35,7 +35,7 @@ public final class ThatWhichWasTaken extends CardImpl { private static final FilterPermanent filterIndestructible = new FilterPermanent("Each permanent with a divinity counter on it"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filterIndestructible.add(new CounterPredicate(CounterType.DIVINITY)); } diff --git a/Mage.Sets/src/mage/cards/t/TheBattleOfEndor.java b/Mage.Sets/src/mage/cards/t/TheBattleOfEndor.java index 6c6ee7f1a9a..4362c26c536 100644 --- a/Mage.Sets/src/mage/cards/t/TheBattleOfEndor.java +++ b/Mage.Sets/src/mage/cards/t/TheBattleOfEndor.java @@ -32,7 +32,7 @@ public final class TheBattleOfEndor extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{X}{G}{G}{G}"); // Create X 1/1 green Ewok creature tokens. - this.getSpellAbility().addEffect(new CreateTokenEffect(new EwokToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new EwokToken(), ManacostVariableValue.instance)); // Put X +1/+1 counters on each creature you control. this.getSpellAbility().addEffect(new TheBattleOfEndorEffect()); diff --git a/Mage.Sets/src/mage/cards/t/TheBattleOfGeonosis.java b/Mage.Sets/src/mage/cards/t/TheBattleOfGeonosis.java index 5c8f41b4c3f..7207f52b1ac 100644 --- a/Mage.Sets/src/mage/cards/t/TheBattleOfGeonosis.java +++ b/Mage.Sets/src/mage/cards/t/TheBattleOfGeonosis.java @@ -27,15 +27,15 @@ public final class TheBattleOfGeonosis extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{R}{R}"); // The Battle of Geonosis deals X + 1 damage to each opponent and each creature your opponents control. - Effect effect = new DamagePlayersEffect(Outcome.Damage, new IntPlusDynamicValue(1, new ManacostVariableValue()), TargetController.OPPONENT); + Effect effect = new DamagePlayersEffect(Outcome.Damage, new IntPlusDynamicValue(1, ManacostVariableValue.instance), TargetController.OPPONENT); effect.setText("The Battle of Geonosis deals X plus 1 damage to each opponent"); this.getSpellAbility().addEffect(effect); - effect = new DamageAllEffect(new IntPlusDynamicValue(1, new ManacostVariableValue()), new FilterOpponentsCreaturePermanent()); + effect = new DamageAllEffect(new IntPlusDynamicValue(1, ManacostVariableValue.instance), new FilterOpponentsCreaturePermanent()); effect.setText("and each creature your opponents control"); this.getSpellAbility().addEffect(effect); // Creatures you control get +X/+0 until end of turn. - this.getSpellAbility().addEffect(new BoostControlledEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostControlledEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn)); } diff --git a/Mage.Sets/src/mage/cards/t/TheBattleOfHoth.java b/Mage.Sets/src/mage/cards/t/TheBattleOfHoth.java index 3ce64d602b5..dda5b9c9b68 100644 --- a/Mage.Sets/src/mage/cards/t/TheBattleOfHoth.java +++ b/Mage.Sets/src/mage/cards/t/TheBattleOfHoth.java @@ -19,7 +19,7 @@ public final class TheBattleOfHoth extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{W}{W}{W}"); // Create X 5/5 white artifact AT-AT creature tokens wiht "When this creature dies, create two 1/1 white Trooper creature tokens." - this.getSpellAbility().addEffect(new CreateTokenEffect(new ATATToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new ATATToken(), ManacostVariableValue.instance)); } public TheBattleOfHoth(final TheBattleOfHoth card) { diff --git a/Mage.Sets/src/mage/cards/t/TheBattleOfNaboo.java b/Mage.Sets/src/mage/cards/t/TheBattleOfNaboo.java index 6945d84d350..75e60e1bf53 100644 --- a/Mage.Sets/src/mage/cards/t/TheBattleOfNaboo.java +++ b/Mage.Sets/src/mage/cards/t/TheBattleOfNaboo.java @@ -1,7 +1,6 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -13,28 +12,24 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author Styxo */ public final class TheBattleOfNaboo extends CardImpl { public TheBattleOfNaboo(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{X}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{U}{U}"); // Return X target creatures to their owner's hands. Draw twice that many cards. Effect effect = new ReturnToHandTargetEffect(); effect.setText("Return X target creatures to their owner's hands"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(new TheBattleOfNabooEffect()); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + this.getSpellAbility().setTargetAdjuster(TheBattleOfNabooAdjuster.instance); } public TheBattleOfNaboo(final TheBattleOfNaboo card) { @@ -47,6 +42,16 @@ public final class TheBattleOfNaboo extends CardImpl { } } +enum TheBattleOfNabooAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} + class TheBattleOfNabooEffect extends OneShotEffect { public TheBattleOfNabooEffect() { @@ -72,9 +77,7 @@ class TheBattleOfNabooEffect extends OneShotEffect { player.drawCards(2 * x, game); } return true; - } return false; } - } diff --git a/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java b/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java index 5377a77dc81..90ec0851cdf 100644 --- a/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java +++ b/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java @@ -65,7 +65,7 @@ class TheBattleOfYavinEffect extends OneShotEffect { return false; } - int amount = (new ManacostVariableValue()).calculate(game, source, this); + int amount = (ManacostVariableValue.instance).calculate(game, source, this); if (amount > 0) { LinkedList sacrifices = new LinkedList<>(); diff --git a/Mage.Sets/src/mage/cards/t/TheBigIdea.java b/Mage.Sets/src/mage/cards/t/TheBigIdea.java index 6bb1285d164..2ab0e150ab0 100644 --- a/Mage.Sets/src/mage/cards/t/TheBigIdea.java +++ b/Mage.Sets/src/mage/cards/t/TheBigIdea.java @@ -38,7 +38,7 @@ public final class TheBigIdea extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.BRAINIAC, "Brainiac creatures"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public TheBigIdea(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TheChainVeil.java b/Mage.Sets/src/mage/cards/t/TheChainVeil.java index 21b0484c366..850a13adb9a 100644 --- a/Mage.Sets/src/mage/cards/t/TheChainVeil.java +++ b/Mage.Sets/src/mage/cards/t/TheChainVeil.java @@ -139,7 +139,7 @@ enum TheChainVeilCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - ActivatedLoyaltyAbilityWatcher watcher = (ActivatedLoyaltyAbilityWatcher) game.getState().getWatchers().get(ActivatedLoyaltyAbilityWatcher.class.getSimpleName()); + ActivatedLoyaltyAbilityWatcher watcher = game.getState().getWatcher(ActivatedLoyaltyAbilityWatcher.class); if (watcher != null) { if (!watcher.activatedLoyaltyAbility(source.getControllerId())) { return true; diff --git a/Mage.Sets/src/mage/cards/t/TheCrowdGoesWild.java b/Mage.Sets/src/mage/cards/t/TheCrowdGoesWild.java index 6a8cc6ccb9f..52ad0363c38 100644 --- a/Mage.Sets/src/mage/cards/t/TheCrowdGoesWild.java +++ b/Mage.Sets/src/mage/cards/t/TheCrowdGoesWild.java @@ -1,9 +1,7 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.AssistAbility; @@ -17,9 +15,11 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.CounterPredicate; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class TheCrowdGoesWild extends CardImpl { @@ -41,6 +41,7 @@ public final class TheCrowdGoesWild extends CardImpl { .setText("Support X (Put a +1/+1 counter on each of up to X target creatures.)
") ); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().setTargetAdjuster(TheCrowdGoesWildAdjuster.instance); // Each creature with a +1/+1 counter on it gains trample until end of turn. this.getSpellAbility().addEffect(new GainAbilityAllEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filter)); @@ -50,17 +51,18 @@ public final class TheCrowdGoesWild extends CardImpl { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetCreaturePermanent(0, xValue)); - } - } - @Override public TheCrowdGoesWild copy() { return new TheCrowdGoesWild(this); } } + +enum TheCrowdGoesWildAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(0, ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TheFallen.java b/Mage.Sets/src/mage/cards/t/TheFallen.java index 8676d61c573..88543624ea2 100644 --- a/Mage.Sets/src/mage/cards/t/TheFallen.java +++ b/Mage.Sets/src/mage/cards/t/TheFallen.java @@ -62,7 +62,7 @@ class TheFallenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - TheFallenWatcher watcher = (TheFallenWatcher) game.getState().getWatchers().get(TheFallenWatcher.class.getSimpleName()); + TheFallenWatcher watcher = game.getState().getWatcher(TheFallenWatcher.class); if (watcher != null && watcher.getPlayersAndWalkersDealtDamageThisGame(source.getSourceId()) != null) { for (UUID playerId : watcher.getPlayersAndWalkersDealtDamageThisGame(source.getSourceId())) { if (!source.isControlledBy(playerId)) { @@ -80,7 +80,7 @@ class TheFallenWatcher extends Watcher { private Map> playersAndWalkersDealtDamageThisGame = new HashMap<>(); // Map> public TheFallenWatcher() { - super(TheFallenWatcher.class.getSimpleName(), WatcherScope.GAME); + super(TheFallenWatcher.class, WatcherScope.GAME); } public TheFallenWatcher(final TheFallenWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/t/TheRack.java b/Mage.Sets/src/mage/cards/t/TheRack.java index b6e85eb33b4..6b5ea4a93d9 100644 --- a/Mage.Sets/src/mage/cards/t/TheRack.java +++ b/Mage.Sets/src/mage/cards/t/TheRack.java @@ -64,7 +64,7 @@ class TheRackTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals((UUID) game.getState().getValue(this.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY)); + return event.getPlayerId().equals(game.getState().getValue(this.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY)); } @Override diff --git a/Mage.Sets/src/mage/cards/t/TheScorpionGod.java b/Mage.Sets/src/mage/cards/t/TheScorpionGod.java index 5a8d67ad423..b06dc525cb8 100644 --- a/Mage.Sets/src/mage/cards/t/TheScorpionGod.java +++ b/Mage.Sets/src/mage/cards/t/TheScorpionGod.java @@ -43,7 +43,7 @@ public final class TheScorpionGod extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TheScorpionGod(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TheaterOfHorrors.java b/Mage.Sets/src/mage/cards/t/TheaterOfHorrors.java new file mode 100644 index 00000000000..b046462d3f9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheaterOfHorrors.java @@ -0,0 +1,127 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponentOrPlaneswalker; +import mage.util.CardUtil; +import mage.watchers.common.PlayerLostLifeWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheaterOfHorrors extends CardImpl { + + public TheaterOfHorrors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{R}"); + + // At the beginning of your upkeep, exile the top card of your library. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new TheaterOfHorrorsExileEffect(), + TargetController.YOU, false + )); + + // During your turn, if an opponent lost life this turn, you may play cards exiled with Theater of Horrors. + this.addAbility(new SimpleStaticAbility(new TheaterOfHorrorsCastEffect())); + + // {3}{R}: Theater of Horrors deals 1 damage to target opponent or planeswalker. + Ability ability = new SimpleActivatedAbility( + new DamageTargetEffect(1), + new ManaCostsImpl("{3}{R}") + ); + ability.addTarget(new TargetOpponentOrPlaneswalker()); + this.addAbility(ability); + } + + private TheaterOfHorrors(final TheaterOfHorrors card) { + super(card); + } + + @Override + public TheaterOfHorrors copy() { + return new TheaterOfHorrors(this); + } +} + +class TheaterOfHorrorsExileEffect extends OneShotEffect { + + TheaterOfHorrorsExileEffect() { + super(Outcome.Benefit); + staticText = "exile the top card of your library."; + } + + private TheaterOfHorrorsExileEffect(final TheaterOfHorrorsExileEffect effect) { + super(effect); + } + + @Override + public TheaterOfHorrorsExileEffect copy() { + return new TheaterOfHorrorsExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + return player.moveCardsToExile( + card, source, game, true, CardUtil.getCardExileZoneId(game, source), + CardUtil.createObjectRealtedWindowTitle(source, game, null) + ); + } +} + +class TheaterOfHorrorsCastEffect extends AsThoughEffectImpl { + + TheaterOfHorrorsCastEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit); + staticText = "During your turn, if an opponent lost life this turn, " + + "you may play cards exiled with {this}"; + } + + private TheaterOfHorrorsCastEffect(final TheaterOfHorrorsCastEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public TheaterOfHorrorsCastEffect copy() { + return new TheaterOfHorrorsCastEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); + if (watcher != null && game.isActivePlayer(source.getControllerId()) + && watcher.getAllOppLifeLost(source.getControllerId(), game) > 0 + && affectedControllerId.equals(source.getControllerId()) + && game.getState().getZone(objectId) == Zone.EXILED) { + ExileZone zone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); + return zone != null && zone.contains(objectId); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheftOfDreams.java b/Mage.Sets/src/mage/cards/t/TheftOfDreams.java index 3b7cf159f26..e226a53c67a 100644 --- a/Mage.Sets/src/mage/cards/t/TheftOfDreams.java +++ b/Mage.Sets/src/mage/cards/t/TheftOfDreams.java @@ -61,7 +61,7 @@ class TheftOfDreamsEffect extends OneShotEffect { Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (opponent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ControllerIdPredicate(opponent.getId())); return new DrawCardSourceControllerEffect(game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game)).apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/t/ThelonsCurse.java b/Mage.Sets/src/mage/cards/t/ThelonsCurse.java index 9aeaf81971e..07ebd1cf241 100644 --- a/Mage.Sets/src/mage/cards/t/ThelonsCurse.java +++ b/Mage.Sets/src/mage/cards/t/ThelonsCurse.java @@ -64,7 +64,7 @@ class ThelonsCurseEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("tapped blue creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(new ColorPredicate(ObjectColor.BLUE)); } diff --git a/Mage.Sets/src/mage/cards/t/ThiefOfSanity.java b/Mage.Sets/src/mage/cards/t/ThiefOfSanity.java index f0db706fc49..90a01df9cdd 100644 --- a/Mage.Sets/src/mage/cards/t/ThiefOfSanity.java +++ b/Mage.Sets/src/mage/cards/t/ThiefOfSanity.java @@ -7,7 +7,6 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffect; @@ -26,7 +25,6 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.game.ExileZone; import mage.game.Game; import mage.players.ManaPoolItem; import mage.players.Player; @@ -54,10 +52,6 @@ public final class ThiefOfSanity extends CardImpl { // Whenever Thief of Sanity deals combat damage to a player, look at the top three cards of that player's library, exile one of them face down, then put the rest into their graveyard. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ThiefOfSanityEffect(), false, true)); - - Ability ability = new SimpleStaticAbility(Zone.ALL, new ThiefOfSanityLookEffect()); - ability.setRuleVisible(false); - this.addAbility(ability); } public ThiefOfSanity(final ThiefOfSanity card) { @@ -74,7 +68,8 @@ class ThiefOfSanityEffect extends OneShotEffect { public ThiefOfSanityEffect() { super(Outcome.Benefit); - this.staticText = "look at the top three cards of that player's library, exile one of them face down, then put the rest into their graveyard. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it"; + this.staticText = "look at the top three cards of that player's library, exile one of them face down, then put the rest into their graveyard. " + + "For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it"; } public ThiefOfSanityEffect(final ThiefOfSanityEffect effect) { @@ -102,7 +97,7 @@ class ThiefOfSanityEffect extends OneShotEffect { // move card to exile UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); card.setFaceDown(true, game); - if (controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName())) { + if (controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName() + " (" + controller.getName() + ")")) { card.setFaceDown(true, game); Set exileZones = (Set) game.getState().getValue(ThiefOfSanity.VALUE_PREFIX + source.getSourceId().toString()); if (exileZones == null) { @@ -110,12 +105,17 @@ class ThiefOfSanityEffect extends OneShotEffect { game.getState().setValue(ThiefOfSanity.VALUE_PREFIX + source.getSourceId().toString(), exileZones); } exileZones.add(exileZoneId); + // rule information: https://blogs.magicjudges.org/rulestips/2018/11/thief-of-sanity-and-control-changing/ // allow to cast the card - ContinuousEffect effect = new ThiefOfSanityCastFromExileEffect(); + ContinuousEffect effect = new ThiefOfSanityCastFromExileEffect(controller.getId()); effect.setTargetPointer(new FixedTarget(card.getId(), game)); game.addEffect(effect, source); // and you may spend mana as though it were mana of any color to cast it - effect = new ThiefOfSanitySpendAnyManaEffect(); + effect = new ThiefOfSanitySpendAnyManaEffect(controller.getId()); + effect.setTargetPointer(new FixedTarget(card.getId(), game)); + game.addEffect(effect, source); + // For as long as that card remains exiled, you may look at it + effect = new ThiefOfSanityLookEffect(controller.getId()); effect.setTargetPointer(new FixedTarget(card.getId(), game)); game.addEffect(effect, source); } @@ -132,13 +132,17 @@ class ThiefOfSanityEffect extends OneShotEffect { class ThiefOfSanityCastFromExileEffect extends AsThoughEffectImpl { - public ThiefOfSanityCastFromExileEffect() { + final UUID authorizedPlayerId; + + public ThiefOfSanityCastFromExileEffect(UUID authorizedPlayerId) { super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit); - staticText = "You may cast that card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell"; + this.authorizedPlayerId = authorizedPlayerId; + staticText = "For as long as that card remains exiled, you may cast it"; } public ThiefOfSanityCastFromExileEffect(final ThiefOfSanityCastFromExileEffect effect) { super(effect); + this.authorizedPlayerId = effect.authorizedPlayerId; } @Override @@ -153,11 +157,11 @@ class ThiefOfSanityCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - UUID targetId = getTargetPointer().getFirst(game, source); - if (targetId == null) { - this.discard(); - } else if (objectId.equals(targetId) - && affectedControllerId.equals(source.getControllerId())) { + UUID cardId = getTargetPointer().getFirst(game, source); + if (cardId == null) { + this.discard(); // card is no longer in the origin zone, effect can be discarded + } else if (objectId.equals(cardId) + && affectedControllerId.equals(authorizedPlayerId)) { Card card = game.getCard(objectId); // TODO: Allow to cast Zoetic Cavern face down return card != null && !card.isLand(); @@ -168,13 +172,17 @@ class ThiefOfSanityCastFromExileEffect extends AsThoughEffectImpl { class ThiefOfSanitySpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { - public ThiefOfSanitySpendAnyManaEffect() { + final UUID authorizedPlayerId; + + public ThiefOfSanitySpendAnyManaEffect(UUID authorizedPlayerId) { super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit); - staticText = "you may spend mana as though it were mana of any color to cast it"; + this.authorizedPlayerId = authorizedPlayerId; + staticText = "For as long as that card remains exiled, you may spend mana as though it were mana of any color to cast it"; } public ThiefOfSanitySpendAnyManaEffect(final ThiefOfSanitySpendAnyManaEffect effect) { super(effect); + this.authorizedPlayerId = effect.authorizedPlayerId; } @Override @@ -192,8 +200,8 @@ class ThiefOfSanitySpendAnyManaEffect extends AsThoughEffectImpl implements AsTh if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget()) && game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) { - if (affectedControllerId.equals(source.getControllerId())) { - // if the card moved from exile to spell the zone change counter is increased by 1 + if (affectedControllerId.equals(authorizedPlayerId)) { + // if the card moved from exile to stack the zone change counter is increased by 1 if (game.getState().getZoneChangeCounter(objectId) == ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) { return true; } @@ -214,13 +222,17 @@ class ThiefOfSanitySpendAnyManaEffect extends AsThoughEffectImpl implements AsTh class ThiefOfSanityLookEffect extends AsThoughEffectImpl { - public ThiefOfSanityLookEffect() { + final UUID authorizedPlayerId; + + public ThiefOfSanityLookEffect(UUID authorizedPlayerId) { super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit); - staticText = "You may look at the cards exiled with {this}"; + this.authorizedPlayerId = authorizedPlayerId; + staticText = "For as long as that card remains exiled, you may look at it"; } public ThiefOfSanityLookEffect(final ThiefOfSanityLookEffect effect) { super(effect); + this.authorizedPlayerId = effect.authorizedPlayerId; } @Override @@ -235,26 +247,11 @@ class ThiefOfSanityLookEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (affectedControllerId.equals(source.getControllerId()) && game.getState().getZone(objectId) == Zone.EXILED) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null) { - Card card = game.getCard(objectId); - if (card != null && card.isFaceDown(game)) { - Set exileZones = (Set) game.getState().getValue(ThiefOfSanity.VALUE_PREFIX + source.getSourceId().toString()); - if (exileZones != null) { - for (ExileZone exileZone : game.getExile().getExileZones()) { - if (exileZone.contains(objectId)) { - if (!exileZones.contains(exileZone.getId())) { - return false; - } - } - } - return true; - } - } - } + UUID cardId = getTargetPointer().getFirst(game, source); + if (cardId == null) { + this.discard(); // card is no longer in the origin zone, effect can be discarded } - return false; + return affectedControllerId.equals(authorizedPlayerId) + && objectId.equals(cardId); } } diff --git a/Mage.Sets/src/mage/cards/t/ThievesAuction.java b/Mage.Sets/src/mage/cards/t/ThievesAuction.java index e95351a1a0f..b9b27cf7438 100644 --- a/Mage.Sets/src/mage/cards/t/ThievesAuction.java +++ b/Mage.Sets/src/mage/cards/t/ThievesAuction.java @@ -52,7 +52,7 @@ class ThievesAuctionEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterPermanent("nontoken permanents"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } ThievesAuctionEffect() { diff --git a/Mage.Sets/src/mage/cards/t/ThirstingAxe.java b/Mage.Sets/src/mage/cards/t/ThirstingAxe.java index e5da2e18739..fe76f099210 100644 --- a/Mage.Sets/src/mage/cards/t/ThirstingAxe.java +++ b/Mage.Sets/src/mage/cards/t/ThirstingAxe.java @@ -72,8 +72,8 @@ class EquippedDealtCombatDamageToCreatureCondition implements Condition { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { CombatDamageToCreatureWatcher watcher = - (CombatDamageToCreatureWatcher) game.getState().getWatchers().get(CombatDamageToCreatureWatcher.BASIC_KEY); - return watcher.dealtDamage(equipment.getAttachedTo(), equipment.getAttachedToZoneChangeCounter(), game); + game.getState().getWatcher(CombatDamageToCreatureWatcher.class); + return watcher != null && watcher.dealtDamage(equipment.getAttachedTo(), equipment.getAttachedToZoneChangeCounter(), game); } return false; } diff --git a/Mage.Sets/src/mage/cards/t/ThirstingShade.java b/Mage.Sets/src/mage/cards/t/ThirstingShade.java new file mode 100644 index 00000000000..4bc4ae12c07 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThirstingShade.java @@ -0,0 +1,45 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ThirstingShade extends CardImpl { + + public ThirstingShade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.SHADE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // {2}{B}: Thirsting Shade gets +1/+1 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}") + )); + } + + private ThirstingShade(final ThirstingShade card) { + super(card); + } + + @Override + public ThirstingShade copy() { + return new ThirstingShade(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThopterAssembly.java b/Mage.Sets/src/mage/cards/t/ThopterAssembly.java index e75e7c18d5f..4d7b3a82548 100644 --- a/Mage.Sets/src/mage/cards/t/ThopterAssembly.java +++ b/Mage.Sets/src/mage/cards/t/ThopterAssembly.java @@ -57,7 +57,7 @@ class ThopterAssemblyTriggeredAbility extends TriggeredAbilityImpl { private static final FilterPermanent filter = new FilterPermanent(); static { filter.add(new SubtypePredicate(SubType.THOPTER)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } ThopterAssemblyTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/t/ThopterFoundry.java b/Mage.Sets/src/mage/cards/t/ThopterFoundry.java index 77043b03a14..2c5a4c93c5f 100644 --- a/Mage.Sets/src/mage/cards/t/ThopterFoundry.java +++ b/Mage.Sets/src/mage/cards/t/ThopterFoundry.java @@ -29,7 +29,7 @@ public final class ThopterFoundry extends CardImpl { static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public ThopterFoundry(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/ThopterSquadron.java b/Mage.Sets/src/mage/cards/t/ThopterSquadron.java index a87ca4db82d..924f154435f 100644 --- a/Mage.Sets/src/mage/cards/t/ThopterSquadron.java +++ b/Mage.Sets/src/mage/cards/t/ThopterSquadron.java @@ -34,7 +34,7 @@ public final class ThopterSquadron extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Thopter"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.THOPTER)); } diff --git a/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java b/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java new file mode 100644 index 00000000000..e09ad3f0243 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java @@ -0,0 +1,66 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ThoughtCollapse extends CardImpl { + + public ThoughtCollapse(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); + + // Counter target spell. Its controller puts the top three cards of their library into their graveyard. + this.getSpellAbility().addEffect(new ThoughtCollapseEffect()); + this.getSpellAbility().addTarget(new TargetSpell()); + } + + private ThoughtCollapse(final ThoughtCollapse card) { + super(card); + } + + @Override + public ThoughtCollapse copy() { + return new ThoughtCollapse(this); + } +} + +class ThoughtCollapseEffect extends OneShotEffect { + + ThoughtCollapseEffect() { + super(Outcome.Benefit); + staticText = "Counter target spell. Its controller puts " + + "the top three cards of their library into their graveyard."; + } + + private ThoughtCollapseEffect(final ThoughtCollapseEffect effect) { + super(effect); + } + + @Override + public ThoughtCollapseEffect copy() { + return new ThoughtCollapseEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(game.getControllerId(source.getFirstTarget())); + if (player == null) { + return false; + } + player.moveCards(player.getLibrary().getTopCards(game, 3), Zone.GRAVEYARD, source, game); + return new CounterTargetEffect().apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java index 2238235f421..f8170540896 100644 --- a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java +++ b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java @@ -49,7 +49,7 @@ public final class ThoughtDissector extends CardImpl { class ThoughtDissectorEffect extends OneShotEffect { - private static final ManacostVariableValue amount = new ManacostVariableValue(); + private static final ManacostVariableValue amount = ManacostVariableValue.instance; public ThoughtDissectorEffect() { super(Outcome.Detriment); diff --git a/Mage.Sets/src/mage/cards/t/ThoughtHarvester.java b/Mage.Sets/src/mage/cards/t/ThoughtHarvester.java index 051a00cc434..1b3cf72dc37 100644 --- a/Mage.Sets/src/mage/cards/t/ThoughtHarvester.java +++ b/Mage.Sets/src/mage/cards/t/ThoughtHarvester.java @@ -25,7 +25,7 @@ public final class ThoughtHarvester extends CardImpl { private static final FilterSpell filter = new FilterSpell("a colorless spell"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public ThoughtHarvester(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/ThousandWinds.java b/Mage.Sets/src/mage/cards/t/ThousandWinds.java index 5cdbcdf9f94..c9b591a169c 100644 --- a/Mage.Sets/src/mage/cards/t/ThousandWinds.java +++ b/Mage.Sets/src/mage/cards/t/ThousandWinds.java @@ -25,8 +25,8 @@ public final class ThousandWinds extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other tapped creatures"); static { - filter.add(new AnotherPredicate()); - filter.add(new TappedPredicate()); + filter.add(AnotherPredicate.instance); + filter.add(TappedPredicate.instance); } public ThousandWinds(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/ThousandYearStorm.java b/Mage.Sets/src/mage/cards/t/ThousandYearStorm.java index 83c624009a2..7191badab77 100644 --- a/Mage.Sets/src/mage/cards/t/ThousandYearStorm.java +++ b/Mage.Sets/src/mage/cards/t/ThousandYearStorm.java @@ -63,7 +63,7 @@ class ThousandYearStormEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Spell spell = game.getSpellOrLKIStack(getTargetPointer().getFirst(game, source)); if (spell != null) { - ThousandYearWatcher watcher = (ThousandYearWatcher) game.getState().getWatchers().get(ThousandYearWatcher.class.getSimpleName()); + ThousandYearWatcher watcher = game.getState().getWatcher(ThousandYearWatcher.class); if (watcher != null) { int numberOfCopies = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) - 1; if (numberOfCopies > 0) { diff --git a/Mage.Sets/src/mage/cards/t/ThranTemporalGateway.java b/Mage.Sets/src/mage/cards/t/ThranTemporalGateway.java index cc8b7e96ad3..a8bf44ce26d 100644 --- a/Mage.Sets/src/mage/cards/t/ThranTemporalGateway.java +++ b/Mage.Sets/src/mage/cards/t/ThranTemporalGateway.java @@ -23,7 +23,7 @@ public final class ThranTemporalGateway extends CardImpl { private static final FilterPermanentCard filter = new FilterPermanentCard("a historic permanent card"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public ThranTemporalGateway(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/ThrashOfRaptors.java b/Mage.Sets/src/mage/cards/t/ThrashOfRaptors.java index eadd8fee03a..e4267e9f10c 100644 --- a/Mage.Sets/src/mage/cards/t/ThrashOfRaptors.java +++ b/Mage.Sets/src/mage/cards/t/ThrashOfRaptors.java @@ -30,7 +30,7 @@ public final class ThrashOfRaptors extends CardImpl { static { filter.add(new SubtypePredicate(SubType.DINOSAUR)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public ThrashOfRaptors(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/ThrashThreat.java b/Mage.Sets/src/mage/cards/t/ThrashThreat.java new file mode 100644 index 00000000000..1c23dbe0f2c --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThrashThreat.java @@ -0,0 +1,57 @@ +package mage.cards.t; + +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DamageWithPowerTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.SpellAbilityType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.permanent.token.RedGreenBeastToken; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ThrashThreat extends SplitCard { + + private static final FilterPermanent filter + = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + } + + public ThrashThreat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{R/G}{R/G}", "{2}{R}{G}", SpellAbilityType.SPLIT); + + // Thrash + // Target creature you control deals damage equal to its power to target creature or planeswalker you don't control. + this.getLeftHalfCard().getSpellAbility().addEffect( + new DamageWithPowerTargetEffect() + .setText("Target creature you control deals damage equal to its power " + + "to target creature or planeswalker you don't control.") + ); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter)); + + // Threat + // Create a 4/4 red and green Beast creature token with trample. + this.getRightHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new RedGreenBeastToken())); + } + + private ThrashThreat(final ThrashThreat card) { + super(card); + } + + @Override + public ThrashThreat copy() { + return new ThrashThreat(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThrillingEncore.java b/Mage.Sets/src/mage/cards/t/ThrillingEncore.java index 67043f5be87..9a5335ceedf 100644 --- a/Mage.Sets/src/mage/cards/t/ThrillingEncore.java +++ b/Mage.Sets/src/mage/cards/t/ThrillingEncore.java @@ -58,7 +58,7 @@ class ThrillingEncoreEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = (CardsPutIntoGraveyardWatcher) game.getState().getWatchers().get(CardsPutIntoGraveyardWatcher.class.getSimpleName()); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); if (watcher != null) { for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { diff --git a/Mage.Sets/src/mage/cards/t/Thrive.java b/Mage.Sets/src/mage/cards/t/Thrive.java index 0ef155b6a8f..d4d640ab233 100644 --- a/Mage.Sets/src/mage/cards/t/Thrive.java +++ b/Mage.Sets/src/mage/cards/t/Thrive.java @@ -1,9 +1,7 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; @@ -12,21 +10,23 @@ import mage.constants.CardType; import mage.counters.CounterType; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author emerald000 */ public final class Thrive extends CardImpl { public Thrive(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{G}"); // Put a +1/+1 counter on each of X target creatures. Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setText("Put a +1/+1 counter on each of X target creatures"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1)); + this.getSpellAbility().setTargetAdjuster(ThriveAdjuster.instance); } public Thrive(final Thrive card) { @@ -37,13 +37,14 @@ public final class Thrive extends CardImpl { public Thrive copy() { return new Thrive(this); } - +} + +enum ThriveAdjuster implements TargetAdjuster { + instance; + @Override public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetCreaturePermanent(xValue)); - } + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/ThroneOfTheGodPharaoh.java b/Mage.Sets/src/mage/cards/t/ThroneOfTheGodPharaoh.java index 747ddcd3f49..4c485da6466 100644 --- a/Mage.Sets/src/mage/cards/t/ThroneOfTheGodPharaoh.java +++ b/Mage.Sets/src/mage/cards/t/ThroneOfTheGodPharaoh.java @@ -23,7 +23,7 @@ public final class ThroneOfTheGodPharaoh extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("tapped creature you control"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public ThroneOfTheGodPharaoh(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/Thud.java b/Mage.Sets/src/mage/cards/t/Thud.java index 54c775bc203..cdcc431c5ba 100644 --- a/Mage.Sets/src/mage/cards/t/Thud.java +++ b/Mage.Sets/src/mage/cards/t/Thud.java @@ -26,7 +26,7 @@ public final class Thud extends CardImpl { )); // Thud deals damage equal to the sacrificed creature's power to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new SacrificeCostCreaturesPower())); + this.getSpellAbility().addEffect(new DamageTargetEffect(SacrificeCostCreaturesPower.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/t/ThundercloudElemental.java b/Mage.Sets/src/mage/cards/t/ThundercloudElemental.java index 6d47ec49c5d..da507b1d91a 100644 --- a/Mage.Sets/src/mage/cards/t/ThundercloudElemental.java +++ b/Mage.Sets/src/mage/cards/t/ThundercloudElemental.java @@ -31,7 +31,7 @@ public final class ThundercloudElemental extends CardImpl { static { toughnessFilter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, 3)); - flyingFilter.add(new AnotherPredicate()); + flyingFilter.add(AnotherPredicate.instance); } public ThundercloudElemental(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/Thundermare.java b/Mage.Sets/src/mage/cards/t/Thundermare.java index 4ceaec87069..e62e638d66c 100644 --- a/Mage.Sets/src/mage/cards/t/Thundermare.java +++ b/Mage.Sets/src/mage/cards/t/Thundermare.java @@ -22,7 +22,7 @@ public final class Thundermare extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Thundermare(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/Thunderstaff.java b/Mage.Sets/src/mage/cards/t/Thunderstaff.java index 7e6da62765a..0436b5a396e 100644 --- a/Mage.Sets/src/mage/cards/t/Thunderstaff.java +++ b/Mage.Sets/src/mage/cards/t/Thunderstaff.java @@ -28,7 +28,7 @@ public final class Thunderstaff extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Attacking creatures"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public Thunderstaff(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TibaltTheFiendBlooded.java b/Mage.Sets/src/mage/cards/t/TibaltTheFiendBlooded.java index a83deed0d49..5805188ef9e 100644 --- a/Mage.Sets/src/mage/cards/t/TibaltTheFiendBlooded.java +++ b/Mage.Sets/src/mage/cards/t/TibaltTheFiendBlooded.java @@ -53,7 +53,7 @@ public final class TibaltTheFiendBlooded extends CardImpl { ability.addEffect(effect); this.addAbility(ability); // -4: Tibalt, the Fiend-Blooded deals damage equal to the number of cards in target player's hand to that player. - effect = new DamageTargetEffect(new CardsInTargetHandCount(), true); + effect = new DamageTargetEffect(CardsInTargetHandCount.instance, true); effect.setText("{this} deals damage equal to the number of cards in target player's hand to that player"); ability = new LoyaltyAbility(effect, -4); ability.addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/t/TideDrifter.java b/Mage.Sets/src/mage/cards/t/TideDrifter.java index 143baaff6da..e27e0d84c56 100644 --- a/Mage.Sets/src/mage/cards/t/TideDrifter.java +++ b/Mage.Sets/src/mage/cards/t/TideDrifter.java @@ -24,7 +24,7 @@ public final class TideDrifter extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creatures"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public TideDrifter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TideOfWar.java b/Mage.Sets/src/mage/cards/t/TideOfWar.java index 772b8c800d8..6c48d0af6bf 100644 --- a/Mage.Sets/src/mage/cards/t/TideOfWar.java +++ b/Mage.Sets/src/mage/cards/t/TideOfWar.java @@ -101,7 +101,7 @@ class TideOfWarEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { Set toSacrifice = new HashSet<>(); - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { // each blocking creature is sacrificed by its controller for (CombatGroup combatGroup: game.getCombat().getGroups()) { for (UUID blockerId: combatGroup.getBlockers()) { diff --git a/Mage.Sets/src/mage/cards/t/TideforceElemental.java b/Mage.Sets/src/mage/cards/t/TideforceElemental.java index 61a0188763f..bad10be690e 100644 --- a/Mage.Sets/src/mage/cards/t/TideforceElemental.java +++ b/Mage.Sets/src/mage/cards/t/TideforceElemental.java @@ -29,7 +29,7 @@ public final class TideforceElemental extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TideforceElemental(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java b/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java index 10785877a3b..7b07d3e74af 100644 --- a/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java +++ b/Mage.Sets/src/mage/cards/t/TilonallisSkinshifter.java @@ -34,8 +34,8 @@ public final class TilonallisSkinshifter extends CardImpl { static { filter.add(Predicates.not(new SupertypePredicate(SuperType.LEGENDARY))); - filter.add(new AttackingPredicate()); - filter.add(new AnotherPredicate()); + filter.add(AttackingPredicate.instance); + filter.add(AnotherPredicate.instance); } public TilonallisSkinshifter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TimberProtector.java b/Mage.Sets/src/mage/cards/t/TimberProtector.java index dd89cb5e594..05cb0d722ef 100644 --- a/Mage.Sets/src/mage/cards/t/TimberProtector.java +++ b/Mage.Sets/src/mage/cards/t/TimberProtector.java @@ -34,7 +34,7 @@ public final class TimberProtector extends CardImpl { filterBoth.add(Predicates.or( new SubtypePredicate(SubType.TREEFOLK), new SubtypePredicate(SubType.FOREST))); - filterBoth.add(new AnotherPredicate()); + filterBoth.add(AnotherPredicate.instance); } public TimberProtector(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/Timbermare.java b/Mage.Sets/src/mage/cards/t/Timbermare.java index 6cbecc485fe..db606b0db44 100644 --- a/Mage.Sets/src/mage/cards/t/Timbermare.java +++ b/Mage.Sets/src/mage/cards/t/Timbermare.java @@ -23,7 +23,7 @@ public final class Timbermare extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public Timbermare(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TimberpackWolf.java b/Mage.Sets/src/mage/cards/t/TimberpackWolf.java index fb0bf03059c..7ad215889f0 100644 --- a/Mage.Sets/src/mage/cards/t/TimberpackWolf.java +++ b/Mage.Sets/src/mage/cards/t/TimberpackWolf.java @@ -69,7 +69,7 @@ public final class TimberpackWolf extends CardImpl { public boolean apply(Game game, Ability source) { int count = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) - 1; if (count > 0) { - Permanent target = (Permanent) game.getPermanent(source.getSourceId()); + Permanent target = game.getPermanent(source.getSourceId()); if (target != null) { target.addPower(count); target.addToughness(count); diff --git a/Mage.Sets/src/mage/cards/t/TimeElemental.java b/Mage.Sets/src/mage/cards/t/TimeElemental.java index 30f7e61094d..da36a63b46b 100644 --- a/Mage.Sets/src/mage/cards/t/TimeElemental.java +++ b/Mage.Sets/src/mage/cards/t/TimeElemental.java @@ -34,7 +34,7 @@ public final class TimeElemental extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("permanent that isn't enchanted"); static { - filter.add(Predicates.not(new EnchantedPredicate())); + filter.add(Predicates.not(EnchantedPredicate.instance)); } public TimeElemental(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TimeOfIce.java b/Mage.Sets/src/mage/cards/t/TimeOfIce.java index 10780d7b643..01f9bc08d33 100644 --- a/Mage.Sets/src/mage/cards/t/TimeOfIce.java +++ b/Mage.Sets/src/mage/cards/t/TimeOfIce.java @@ -37,7 +37,7 @@ public final class TimeOfIce extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creatures"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public TimeOfIce(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TimeToReflect.java b/Mage.Sets/src/mage/cards/t/TimeToReflect.java index 3ac0599ba4d..727e2fd5b96 100644 --- a/Mage.Sets/src/mage/cards/t/TimeToReflect.java +++ b/Mage.Sets/src/mage/cards/t/TimeToReflect.java @@ -1,9 +1,7 @@ - package mage.cards.t; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -19,8 +17,8 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; - import java.util.*; +import mage.target.targetadjustment.TargetAdjuster; /** * @author jeffwadsworth @@ -34,27 +32,7 @@ public final class TimeToReflect extends CardImpl { this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("creature that blocked or was blocked by a Zombie this turn."))); this.getSpellAbility().addWatcher(new BlockedOrWasBlockedByAZombieWatcher()); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - List creaturesThatBlockedOrWereBlockedByAZombie = new ArrayList<>(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that blocked or was blocked by a Zombie this turn.").copy(); - BlockedOrWasBlockedByAZombieWatcher watcher = (BlockedOrWasBlockedByAZombieWatcher) game.getState().getWatchers().get(BlockedOrWasBlockedByAZombieWatcher.class.getSimpleName()); - if (watcher != null) { - for (MageObjectReference mor : watcher.getBlockedThisTurnCreatures()) { - Permanent permanent = mor.getPermanent(game); - if (permanent != null) { - creaturesThatBlockedOrWereBlockedByAZombie.add(new PermanentIdPredicate(permanent.getId())); - } - } - } - filter.add(Predicates.or(creaturesThatBlockedOrWereBlockedByAZombie)); - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(filter)); - } + this.getSpellAbility().setTargetAdjuster(TimeToReflectAdjuster.instance); } public TimeToReflect(final TimeToReflect card) { @@ -67,12 +45,34 @@ public final class TimeToReflect extends CardImpl { } } +enum TimeToReflectAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + List creaturesThatBlockedOrWereBlockedByAZombie = new ArrayList<>(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that blocked or was blocked by a Zombie this turn.").copy(); + BlockedOrWasBlockedByAZombieWatcher watcher = (BlockedOrWasBlockedByAZombieWatcher) game.getState().getWatchers().get(BlockedOrWasBlockedByAZombieWatcher.class.getSimpleName()); + if (watcher != null) { + for (MageObjectReference mor : watcher.getBlockedThisTurnCreatures()) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null) { + creaturesThatBlockedOrWereBlockedByAZombie.add(new PermanentIdPredicate(permanent.getId())); + } + } + } + filter.add(Predicates.or(creaturesThatBlockedOrWereBlockedByAZombie)); + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(filter)); + } +} + class BlockedOrWasBlockedByAZombieWatcher extends Watcher { private final Set blockedOrWasBlockedByAZombieWatcher; public BlockedOrWasBlockedByAZombieWatcher() { - super(BlockedOrWasBlockedByAZombieWatcher.class.getSimpleName(), WatcherScope.GAME); + super(BlockedOrWasBlockedByAZombieWatcher.class, WatcherScope.GAME); blockedOrWasBlockedByAZombieWatcher = new HashSet<>(); } diff --git a/Mage.Sets/src/mage/cards/t/TimidDrake.java b/Mage.Sets/src/mage/cards/t/TimidDrake.java index 9dbbb37c52e..bc6f6b50aa1 100644 --- a/Mage.Sets/src/mage/cards/t/TimidDrake.java +++ b/Mage.Sets/src/mage/cards/t/TimidDrake.java @@ -23,7 +23,7 @@ public final class TimidDrake extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TimidDrake(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TinStreetDodger.java b/Mage.Sets/src/mage/cards/t/TinStreetDodger.java new file mode 100644 index 00000000000..064a804c417 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TinStreetDodger.java @@ -0,0 +1,57 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TinStreetDodger extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("except by creatures with defender"); + + static { + filter.add(Predicates.not(new AbilityPredicate(DefenderAbility.class))); + } + + public TinStreetDodger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // {R}: Tin Street Dodger can't be blocked this turn except by creatures with defender. + this.addAbility(new SimpleActivatedAbility( + new CantBeBlockedByCreaturesSourceEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{R}") + )); + } + + private TinStreetDodger(final TinStreetDodger card) { + super(card); + } + + @Override + public TinStreetDodger copy() { + return new TinStreetDodger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TishanaVoiceOfThunder.java b/Mage.Sets/src/mage/cards/t/TishanaVoiceOfThunder.java index 50ec788f1a4..2a83a5105e2 100644 --- a/Mage.Sets/src/mage/cards/t/TishanaVoiceOfThunder.java +++ b/Mage.Sets/src/mage/cards/t/TishanaVoiceOfThunder.java @@ -37,7 +37,7 @@ public final class TishanaVoiceOfThunder extends CardImpl { this.toughness = new MageInt(0); // Tishana, Voice of Thunder's power and toughness are each equal to the number of cards in your hand. - DynamicValue xValue = new CardsInControllerHandCount(); + DynamicValue xValue = CardsInControllerHandCount.instance; this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame))); // You have no maximum hand size. diff --git a/Mage.Sets/src/mage/cards/t/TitanicBrawl.java b/Mage.Sets/src/mage/cards/t/TitanicBrawl.java new file mode 100644 index 00000000000..4a5aaf85cd4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TitanicBrawl.java @@ -0,0 +1,63 @@ +package mage.cards.t; + +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceTargetsPermanentCondition; +import mage.abilities.effects.common.FightTargetsEffect; +import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TitanicBrawl extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creature you don't control"); + private static final FilterPermanent filter2 + = new FilterControlledCreaturePermanent("a creature you control with a +1/+1 counter on it"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + filter2.add(new CounterPredicate(CounterType.P1P1)); + } + + private static final Condition condition = new SourceTargetsPermanentCondition(filter2); + + public TitanicBrawl(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + // This spell costs {1} less to cast if it targets a creature you control with a +1/+1 counter on it. + this.addAbility(new SimpleStaticAbility( + Zone.STACK, new SpellCostReductionSourceEffect(1, condition) + ).setRuleAtTheTop(true)); + + // Target creature you control fights target creature you don't control. + this.getSpellAbility().addEffect(new FightTargetsEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + private TitanicBrawl(final TitanicBrawl card) { + super(card); + } + + @Override + public TitanicBrawl copy() { + return new TitanicBrawl(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TitansPresence.java b/Mage.Sets/src/mage/cards/t/TitansPresence.java index 797104f9f00..fc2c7c08dce 100644 --- a/Mage.Sets/src/mage/cards/t/TitansPresence.java +++ b/Mage.Sets/src/mage/cards/t/TitansPresence.java @@ -29,7 +29,7 @@ public final class TitansPresence extends CardImpl { private static final FilterCreatureCard filter = new FilterCreatureCard("a colorless creature card from your hand"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public TitansPresence(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TitansRevenge.java b/Mage.Sets/src/mage/cards/t/TitansRevenge.java index 0ce6a02ea83..37529c24697 100644 --- a/Mage.Sets/src/mage/cards/t/TitansRevenge.java +++ b/Mage.Sets/src/mage/cards/t/TitansRevenge.java @@ -21,7 +21,7 @@ public final class TitansRevenge extends CardImpl { // Titan's Revenge deals X damage to any target. Clash with an opponent. If you win, return Titan's Revenge to its owner's hand. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); this.getSpellAbility().addEffect(ClashWinReturnToHandSpellEffect.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/t/ToilToRenown.java b/Mage.Sets/src/mage/cards/t/ToilToRenown.java index 3ea6fd3ba52..41b19713171 100644 --- a/Mage.Sets/src/mage/cards/t/ToilToRenown.java +++ b/Mage.Sets/src/mage/cards/t/ToilToRenown.java @@ -23,7 +23,7 @@ public final class ToilToRenown extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("tapped artifact, creature, and land you control"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(Predicates.or( new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.CREATURE), diff --git a/Mage.Sets/src/mage/cards/t/ToilTrouble.java b/Mage.Sets/src/mage/cards/t/ToilTrouble.java index c3783993f1d..7a18f7047c5 100644 --- a/Mage.Sets/src/mage/cards/t/ToilTrouble.java +++ b/Mage.Sets/src/mage/cards/t/ToilTrouble.java @@ -26,7 +26,7 @@ public final class ToilTrouble extends SplitCard { // Trouble // Trouble deals damage to target player equal to the number of cards in that player's hand. - Effect effect = new DamageTargetEffect(new CardsInTargetHandCount()); + Effect effect = new DamageTargetEffect(CardsInTargetHandCount.instance); effect.setText("Trouble deals damage to target player equal to the number of cards in that player's hand"); getRightHalfCard().getSpellAbility().addEffect(effect); getRightHalfCard().getSpellAbility().addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/t/TombOfTheSpiritDragon.java b/Mage.Sets/src/mage/cards/t/TombOfTheSpiritDragon.java index 6f4cebe7c37..5a7d4490158 100644 --- a/Mage.Sets/src/mage/cards/t/TombOfTheSpiritDragon.java +++ b/Mage.Sets/src/mage/cards/t/TombOfTheSpiritDragon.java @@ -25,7 +25,7 @@ public final class TombOfTheSpiritDragon extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("colorless creature you control"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public TombOfTheSpiritDragon(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TomeOfTheGuildpact.java b/Mage.Sets/src/mage/cards/t/TomeOfTheGuildpact.java new file mode 100644 index 00000000000..46f978a7131 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TomeOfTheGuildpact.java @@ -0,0 +1,39 @@ +package mage.cards.t; + +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TomeOfTheGuildpact extends CardImpl { + + public TomeOfTheGuildpact(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); + + // Whenever you cast a multicolored spell, draw a card. + this.addAbility(new SpellCastControllerTriggeredAbility( + new DrawCardSourceControllerEffect(1), + StaticFilters.FILTER_SPELL_A_MULTICOLORED, false + )); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + } + + private TomeOfTheGuildpact(final TomeOfTheGuildpact card) { + super(card); + } + + @Override + public TomeOfTheGuildpact copy() { + return new TomeOfTheGuildpact(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TopanAscetic.java b/Mage.Sets/src/mage/cards/t/TopanAscetic.java index f4d1de3e1e1..402ed8687fc 100644 --- a/Mage.Sets/src/mage/cards/t/TopanAscetic.java +++ b/Mage.Sets/src/mage/cards/t/TopanAscetic.java @@ -25,7 +25,7 @@ public final class TopanAscetic extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static{ - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } diff --git a/Mage.Sets/src/mage/cards/t/TorchCourier.java b/Mage.Sets/src/mage/cards/t/TorchCourier.java index 24566bcde9e..a6588460f4c 100644 --- a/Mage.Sets/src/mage/cards/t/TorchCourier.java +++ b/Mage.Sets/src/mage/cards/t/TorchCourier.java @@ -27,7 +27,7 @@ public final class TorchCourier extends CardImpl { = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TorchCourier(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java index 11112392a28..244ba827947 100644 --- a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java +++ b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.UUID; @@ -20,19 +19,19 @@ import mage.target.TargetPermanent; * @author LevelX2 */ public final class TormentOfHailfire extends CardImpl { - + public TormentOfHailfire(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); // Repeat the following process X times. Each opponent loses 3 life unless he or she sacrifices a nonland permanent or discards a card. this.getSpellAbility().addEffect(new TormentOfHailfireEffect()); - + } - + public TormentOfHailfire(final TormentOfHailfire card) { super(card); } - + @Override public TormentOfHailfire copy() { return new TormentOfHailfire(this); @@ -40,21 +39,21 @@ public final class TormentOfHailfire extends CardImpl { } class TormentOfHailfireEffect extends OneShotEffect { - + public TormentOfHailfireEffect() { super(Outcome.LoseLife); this.staticText = "Repeat the following process X times. Each opponent loses 3 life unless he or she sacrifices a nonland permanent or discards a card"; } - + public TormentOfHailfireEffect(final TormentOfHailfireEffect effect) { super(effect); } - + @Override public TormentOfHailfireEffect copy() { return new TormentOfHailfireEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); @@ -68,6 +67,7 @@ class TormentOfHailfireEffect extends OneShotEffect { if (permanents > 0 && opponent.chooseUse(outcome, "Sacrifices a nonland permanent? (Iteration " + i + " of " + repeat + ")", "Otherwise you have to discard a card or lose 3 life.", "Sacrifice", "Discard or life loss", source, game)) { Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); + target.setNotTarget(true); if (opponent.choose(outcome, target, source.getSourceId(), game)) { Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { @@ -85,7 +85,7 @@ class TormentOfHailfireEffect extends OneShotEffect { opponent.loseLife(3, game, false); } } - + } return true; } diff --git a/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java b/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java index 1dba874cc11..3dff8037208 100644 --- a/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java +++ b/Mage.Sets/src/mage/cards/t/ToshiroUmezawa.java @@ -119,11 +119,11 @@ class ToshiroUmezawaReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - UUID eventObject = ((ZoneChangeEvent) event).getTargetId(); + UUID eventObject = event.getTargetId(); StackObject stackObject = game.getStack().getStackObject(eventObject); if (stackObject != null) { if (stackObject instanceof Spell) { - game.rememberLKI(stackObject.getId(), Zone.STACK, (Spell) stackObject); + game.rememberLKI(stackObject.getId(), Zone.STACK, stackObject); } if (stackObject instanceof Card && eventObject.equals(cardId)) { ((Card) stackObject).moveToExile(null, null, source.getSourceId(), game); @@ -142,6 +142,6 @@ class ToshiroUmezawaReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; return zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId().equals(cardId); + && event.getTargetId().equals(cardId); } } diff --git a/Mage.Sets/src/mage/cards/t/TotalWar.java b/Mage.Sets/src/mage/cards/t/TotalWar.java index 95271513243..ab124ae9b9c 100644 --- a/Mage.Sets/src/mage/cards/t/TotalWar.java +++ b/Mage.Sets/src/mage/cards/t/TotalWar.java @@ -107,7 +107,7 @@ class TotalWarDestroyEffect extends OneShotEffect { continue; } // Creatures that attacked are safe. - AttackedOrBlockedThisCombatWatcher watcher = (AttackedOrBlockedThisCombatWatcher) game.getState().getWatchers().get(AttackedOrBlockedThisCombatWatcher.class.getSimpleName()); + AttackedOrBlockedThisCombatWatcher watcher = game.getState().getWatcher(AttackedOrBlockedThisCombatWatcher.class); if (watcher != null && watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game))) { continue; diff --git a/Mage.Sets/src/mage/cards/t/TourachsGate.java b/Mage.Sets/src/mage/cards/t/TourachsGate.java index ac999210862..72912a4b953 100644 --- a/Mage.Sets/src/mage/cards/t/TourachsGate.java +++ b/Mage.Sets/src/mage/cards/t/TourachsGate.java @@ -53,12 +53,12 @@ public final class TourachsGate extends CardImpl { private static final FilterPermanent filterUntapped = new FilterPermanent("enchanted land is untapped"); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } private static final FilterCreaturePermanent filterAttackingCreatures = new FilterCreaturePermanent("attacking creatures you control"); static { - filterAttackingCreatures.add(new AttackingPredicate()); + filterAttackingCreatures.add(AttackingPredicate.instance); filterAttackingCreatures.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java index 8d535460720..b0b6c94785b 100644 --- a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java +++ b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java @@ -28,7 +28,7 @@ public final class TownGossipmonger extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public TownGossipmonger(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/ToxicDeluge.java b/Mage.Sets/src/mage/cards/t/ToxicDeluge.java index b3f9b3e9e40..ec64b49f4fa 100644 --- a/Mage.Sets/src/mage/cards/t/ToxicDeluge.java +++ b/Mage.Sets/src/mage/cards/t/ToxicDeluge.java @@ -26,7 +26,7 @@ public final class ToxicDeluge extends CardImpl { // As an additional cost to cast Toxic Deluge, pay X life. this.getSpellAbility().addCost(new PayVariableLifeCost(true)); // All creatures get -X/-X until end of turn. - DynamicValue xValue = new SignInversionDynamicValue(new GetXValue()); + DynamicValue xValue = new SignInversionDynamicValue(GetXValue.instance); this.getSpellAbility().addEffect(new BoostAllEffect(xValue, xValue, Duration.EndOfTurn, new FilterCreaturePermanent("All creatures"), false, null, true)); } diff --git a/Mage.Sets/src/mage/cards/t/TraceOfAbundance.java b/Mage.Sets/src/mage/cards/t/TraceOfAbundance.java index 3b01224026c..361826e3480 100644 --- a/Mage.Sets/src/mage/cards/t/TraceOfAbundance.java +++ b/Mage.Sets/src/mage/cards/t/TraceOfAbundance.java @@ -1,23 +1,17 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.mana.AddManaAnyColorAttachedControllerEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.mana.AddManaAnyColorAttachedControllerEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.ShroudAbility; import mage.abilities.mana.TriggeredManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -25,16 +19,17 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class TraceOfAbundance extends CardImpl { - private String rule = "Enchanted land has shroud"; + private static final String rule = "Enchanted land has shroud"; public TraceOfAbundance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R/W}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R/W}{G}"); this.subtype.add(SubType.AURA); // Enchant land diff --git a/Mage.Sets/src/mage/cards/t/TradewindRider.java b/Mage.Sets/src/mage/cards/t/TradewindRider.java index d2e39d8ab5d..794922dfec2 100644 --- a/Mage.Sets/src/mage/cards/t/TradewindRider.java +++ b/Mage.Sets/src/mage/cards/t/TradewindRider.java @@ -28,7 +28,7 @@ public final class TradewindRider extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public TradewindRider(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TrailOfMystery.java b/Mage.Sets/src/mage/cards/t/TrailOfMystery.java index 767196131c4..544fb5147aa 100644 --- a/Mage.Sets/src/mage/cards/t/TrailOfMystery.java +++ b/Mage.Sets/src/mage/cards/t/TrailOfMystery.java @@ -27,7 +27,7 @@ public final class TrailOfMystery extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a face-down creature"); static { - filter.add(new FaceDownPredicate()); + filter.add(FaceDownPredicate.instance); } public TrailOfMystery(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TrainedCondor.java b/Mage.Sets/src/mage/cards/t/TrainedCondor.java index 5e81c9de5d1..b9e4259faa7 100644 --- a/Mage.Sets/src/mage/cards/t/TrainedCondor.java +++ b/Mage.Sets/src/mage/cards/t/TrainedCondor.java @@ -26,7 +26,7 @@ public final class TrainedCondor extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TrainedCondor(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}"); diff --git a/Mage.Sets/src/mage/cards/t/TrainingGrounds.java b/Mage.Sets/src/mage/cards/t/TrainingGrounds.java index 8a3b02c03ab..663138e691c 100644 --- a/Mage.Sets/src/mage/cards/t/TrainingGrounds.java +++ b/Mage.Sets/src/mage/cards/t/TrainingGrounds.java @@ -1,9 +1,6 @@ package mage.cards.t; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; import mage.Mana; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; @@ -12,20 +9,17 @@ import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceImpl; -import mage.constants.AbilityType; -import mage.constants.CardType; -import mage.constants.CostModificationType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author maurer.it_at_gmail.com */ public final class TrainingGrounds extends CardImpl { @@ -49,15 +43,15 @@ public final class TrainingGrounds extends CardImpl { class TrainingGroundsEffect extends CostModificationEffectImpl { - private static final String effectText = "Activated abilities of creatures you control cost up to {2} less to activate. This effect can't reduce the amount of mana an ability costs to activate to less than one mana"; - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + private static final String effectText = "Activated abilities of creatures you control cost {2} less to activate. " + + "This effect can't reduce the amount of mana an ability costs to activate to less than one mana"; - public TrainingGroundsEffect() { + TrainingGroundsEffect() { super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); staticText = effectText; } - public TrainingGroundsEffect(final TrainingGroundsEffect effect) { + private TrainingGroundsEffect(final TrainingGroundsEffect effect) { super(effect); } @@ -100,7 +94,7 @@ class TrainingGroundsEffect extends CostModificationEffectImpl { || (abilityToModify.getAbilityType() == AbilityType.MANA && (abilityToModify instanceof ActivatedAbility))) { //Activated abilities of creatures you control Permanent permanent = game.getPermanent(abilityToModify.getSourceId()); - if (permanent != null && filter.match(permanent, source.getSourceId(), source.getControllerId(), game)) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TraitorsRoar.java b/Mage.Sets/src/mage/cards/t/TraitorsRoar.java index 460722bc437..2201993bec7 100644 --- a/Mage.Sets/src/mage/cards/t/TraitorsRoar.java +++ b/Mage.Sets/src/mage/cards/t/TraitorsRoar.java @@ -26,7 +26,7 @@ public final class TraitorsRoar extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public TraitorsRoar(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TranquilGrove.java b/Mage.Sets/src/mage/cards/t/TranquilGrove.java index c8f3a0a6296..7687d4b236e 100644 --- a/Mage.Sets/src/mage/cards/t/TranquilGrove.java +++ b/Mage.Sets/src/mage/cards/t/TranquilGrove.java @@ -22,7 +22,7 @@ public final class TranquilGrove extends CardImpl { private static final FilterPermanent filter = new FilterEnchantmentPermanent("other enchantments"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public TranquilGrove(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TransguildCourier.java b/Mage.Sets/src/mage/cards/t/TransguildCourier.java index b480250f6bc..2161aa0e94d 100644 --- a/Mage.Sets/src/mage/cards/t/TransguildCourier.java +++ b/Mage.Sets/src/mage/cards/t/TransguildCourier.java @@ -1,30 +1,34 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; /** - * * @author Wehk */ public final class TransguildCourier extends CardImpl { public TransguildCourier(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); this.subtype.add(SubType.GOLEM); this.power = new MageInt(3); this.toughness = new MageInt(3); - + this.color.setWhite(true); this.color.setBlue(true); this.color.setBlack(true); this.color.setRed(true); this.color.setGreen(true); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this} is all colors"))); } public TransguildCourier(final TransguildCourier card) { diff --git a/Mage.Sets/src/mage/cards/t/TrapRunner.java b/Mage.Sets/src/mage/cards/t/TrapRunner.java index 54f0da4cd49..6d4b06b2f57 100644 --- a/Mage.Sets/src/mage/cards/t/TrapRunner.java +++ b/Mage.Sets/src/mage/cards/t/TrapRunner.java @@ -36,8 +36,8 @@ public final class TrapRunner extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked attacking creature"); static { - filter.add(new AttackingPredicate()); - filter.add(Predicates.not(new BlockedPredicate())); + filter.add(AttackingPredicate.instance); + filter.add(Predicates.not(BlockedPredicate.instance)); } public TrapRunner(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TravelingPlague.java b/Mage.Sets/src/mage/cards/t/TravelingPlague.java index d079c2c44b4..fdc09f1d2c9 100644 --- a/Mage.Sets/src/mage/cards/t/TravelingPlague.java +++ b/Mage.Sets/src/mage/cards/t/TravelingPlague.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; @@ -18,12 +16,7 @@ import mage.abilities.keyword.EnchantAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; @@ -34,8 +27,9 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class TravelingPlague extends CardImpl { @@ -130,10 +124,10 @@ class TravelingPlagueEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Card travelingPlague = game.getCard(source.getSourceId()); Permanent enchantedCreature = (Permanent) game.getState().getValue("travelingPlague" + source.getSourceId()); if (enchantedCreature != null) { Player controllerOfEnchantedCreature = game.getPlayer(enchantedCreature.getControllerId()); + Card travelingPlague = game.getCard(source.getSourceId()); if (travelingPlague != null && game.getState().getZone(travelingPlague.getId()) == Zone.GRAVEYARD // aura must come from the graveyard && controllerOfEnchantedCreature != null) { diff --git a/Mage.Sets/src/mage/cards/t/TrenchGorger.java b/Mage.Sets/src/mage/cards/t/TrenchGorger.java index fd5692290f4..6b2b53ec04b 100644 --- a/Mage.Sets/src/mage/cards/t/TrenchGorger.java +++ b/Mage.Sets/src/mage/cards/t/TrenchGorger.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -11,25 +9,21 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterLandCard; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TrenchGorger extends CardImpl { public TrenchGorger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}{U}"); this.subtype.add(SubType.LEVIATHAN); this.power = new MageInt(6); @@ -77,8 +71,10 @@ class TrenchGorgerEffect extends OneShotEffect { int count = 0; for (UUID cardId : target.getTargets()) { Card card = game.getCard(cardId); - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY, true); - count++; + if (card != null) { + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY, true); + count++; + } } controller.shuffleLibrary(source, game); game.addEffect(new SetPowerToughnessSourceEffect(count, count, Duration.EndOfGame, SubLayer.SetPT_7b), source); diff --git a/Mage.Sets/src/mage/cards/t/TriadOfFates.java b/Mage.Sets/src/mage/cards/t/TriadOfFates.java index c77fe608b65..472b1da334e 100644 --- a/Mage.Sets/src/mage/cards/t/TriadOfFates.java +++ b/Mage.Sets/src/mage/cards/t/TriadOfFates.java @@ -39,7 +39,7 @@ public final class TriadOfFates extends CardImpl { private static final FilterCreaturePermanent filterCounter = new FilterCreaturePermanent("creature that has a fate counter on it"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filterCounter.add(new CounterPredicate(CounterType.FATE)); } diff --git a/Mage.Sets/src/mage/cards/t/TrialError.java b/Mage.Sets/src/mage/cards/t/TrialError.java index a27bd50f602..490b6b3f2e4 100644 --- a/Mage.Sets/src/mage/cards/t/TrialError.java +++ b/Mage.Sets/src/mage/cards/t/TrialError.java @@ -32,7 +32,7 @@ public final class TrialError extends SplitCard { private static final FilterSpell filter = new FilterSpell("multicolored spell"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public TrialError(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TribalUnity.java b/Mage.Sets/src/mage/cards/t/TribalUnity.java index bb468b356d0..8d03dd04711 100644 --- a/Mage.Sets/src/mage/cards/t/TribalUnity.java +++ b/Mage.Sets/src/mage/cards/t/TribalUnity.java @@ -30,7 +30,7 @@ public final class TribalUnity extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{2}{G}"); // Creatures of the creature type of your choice get +X/+X until end of turn. - this.getSpellAbility().addEffect(new TribalUnityEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new TribalUnityEffect(ManacostVariableValue.instance)); } public TribalUnity(final TribalUnity card) { diff --git a/Mage.Sets/src/mage/cards/t/TrollbredGuardian.java b/Mage.Sets/src/mage/cards/t/TrollbredGuardian.java new file mode 100644 index 00000000000..cd197483700 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TrollbredGuardian.java @@ -0,0 +1,64 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.AdaptAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.CounterPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TrollbredGuardian extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(new CounterPredicate(CounterType.P1P1)); + } + + public TrollbredGuardian(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.subtype.add(SubType.TROLL); + this.subtype.add(SubType.FROG); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // {2}{G}: Adapt 2. + this.addAbility(new AdaptAbility(2, "{2}{G}")); + + // Each creature you control with a +1/+1 counter on it has trample. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityAllEffect( + TrampleAbility.getInstance(), + Duration.WhileOnBattlefield, + filter, "Each creature you control " + + "with a +1/+1 counter on it has trample" + ) + )); + } + + private TrollbredGuardian(final TrollbredGuardian card) { + super(card); + } + + @Override + public TrollbredGuardian copy() { + return new TrollbredGuardian(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TropicalStorm.java b/Mage.Sets/src/mage/cards/t/TropicalStorm.java index b85d7c05d0b..0178952b1a6 100644 --- a/Mage.Sets/src/mage/cards/t/TropicalStorm.java +++ b/Mage.Sets/src/mage/cards/t/TropicalStorm.java @@ -31,7 +31,7 @@ public final class TropicalStorm extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{G}"); // Tropical Storm deals X damage to each creature with flying and 1 additional damage to each blue creature. - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, filter)); this.getSpellAbility().addEffect(new DamageAllEffect(1, filter2).setText("and 1 additional damage to each blue creature")); } diff --git a/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java b/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java index 5d1a729b304..d6ff2a36a32 100644 --- a/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java +++ b/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java @@ -77,7 +77,8 @@ class TrostaniSelesnyasVoiceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.isCreature() + if (permanent != null + && permanent.isCreature() && permanent.isControlledBy(this.controllerId) && !Objects.equals(event.getTargetId(), this.getSourceId())) { Effect effect = this.getEffects().get(0); diff --git a/Mage.Sets/src/mage/cards/t/TunnelIgnus.java b/Mage.Sets/src/mage/cards/t/TunnelIgnus.java index 56eb26d80f9..13fc420221b 100644 --- a/Mage.Sets/src/mage/cards/t/TunnelIgnus.java +++ b/Mage.Sets/src/mage/cards/t/TunnelIgnus.java @@ -1,10 +1,5 @@ - package mage.cards.t; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; @@ -22,6 +17,11 @@ import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + /** * @author Loki */ @@ -53,7 +53,7 @@ class TunnelIgnusWatcher extends Watcher { protected Map counts = new HashMap<>(); public TunnelIgnusWatcher() { - super(TunnelIgnusWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(TunnelIgnusWatcher.class, WatcherScope.PLAYER); } public TunnelIgnusWatcher(final TunnelIgnusWatcher watcher) { @@ -72,8 +72,7 @@ class TunnelIgnusWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.isLand() && game.getOpponents(this.controllerId).contains(permanent.getControllerId())) { - + if (permanent != null && permanent.isLand() && game.getOpponents(this.controllerId).contains(permanent.getControllerId())) { int count = counts.getOrDefault(permanent.getControllerId(), 0); counts.put(permanent.getControllerId(), count + 1); } @@ -111,7 +110,7 @@ class TunnelIgnusTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isLand() && game.getOpponents(this.controllerId).contains(permanent.getControllerId())) { - TunnelIgnusWatcher watcher = (TunnelIgnusWatcher) game.getState().getWatchers().get(TunnelIgnusWatcher.class.getSimpleName(), this.controllerId); + TunnelIgnusWatcher watcher = game.getState().getWatcher(TunnelIgnusWatcher.class, this.controllerId); if (watcher != null && watcher.counts.get(permanent.getControllerId()) > 1) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(permanent.getControllerId())); diff --git a/Mage.Sets/src/mage/cards/t/TurbulentDreams.java b/Mage.Sets/src/mage/cards/t/TurbulentDreams.java index cd595d460ef..6dcdd74d69b 100644 --- a/Mage.Sets/src/mage/cards/t/TurbulentDreams.java +++ b/Mage.Sets/src/mage/cards/t/TurbulentDreams.java @@ -1,60 +1,58 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.common.DiscardXTargetCost; -import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterCard; import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; +import mage.filter.common.FilterNonlandPermanent; import mage.game.Game; import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class TurbulentDreams extends CardImpl { - - private static final FilterPermanent filter = new FilterPermanent("nonland permanents"); - - static { - filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - } public TurbulentDreams(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}"); // As an additional cost to cast Turbulent Dreams, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); - + this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true)); + // Return X target nonland permanents to their owners' hands. Effect effect = new ReturnToHandTargetEffect(); effect.setText("Return X target nonland permanents to their owners' hands"); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().setTargetAdjuster(TurbulentDreamsAdjuster.instance); } public TurbulentDreams(final TurbulentDreams card) { super(card); } - - @Override - public void adjustTargets(Ability ability, Game game) { - int xValue = new GetXValue().calculate(game, ability, null); - Target target = new TargetPermanent(0, xValue, filter, false); - ability.addTarget(target); - } @Override public TurbulentDreams copy() { return new TurbulentDreams(this); } } + +enum TurbulentDreamsAdjuster implements TargetAdjuster { + instance; + private static final FilterPermanent filter = new FilterNonlandPermanent("nonland permanents"); + + @Override + public void adjustTargets(Ability ability, Game game) { + Target target = new TargetPermanent(0, ability.getManaCostsToPay().getX(), filter, false); + ability.addTarget(target); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/Turnabout.java b/Mage.Sets/src/mage/cards/t/Turnabout.java index 47e2ae27a84..968a0cd1bbb 100644 --- a/Mage.Sets/src/mage/cards/t/Turnabout.java +++ b/Mage.Sets/src/mage/cards/t/Turnabout.java @@ -110,14 +110,14 @@ class TurnaboutEffect extends OneShotEffect { filter.add(new CardTypePredicate(type)); if (choiceImpl.getChoice().equals("Untap")) { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { if (permanent.isControlledBy(target)) { permanent.untap(game); } } } else { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { if (permanent.isControlledBy(target)) { permanent.tap(game); diff --git a/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java b/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java index 5af7d2b9740..233c467b0b9 100644 --- a/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java +++ b/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java @@ -95,10 +95,10 @@ class TuvasaTheSunlitTriggeredAbility extends SpellCastControllerTriggeredAbilit @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - TuvasaTheSunlitWatcher watcher = (TuvasaTheSunlitWatcher) game.getState().getWatchers().get( - TuvasaTheSunlitWatcher.class.getSimpleName() + TuvasaTheSunlitWatcher watcher = game.getState().getWatcher( + TuvasaTheSunlitWatcher.class ); - return event.getTargetId().equals(watcher.getFirstEnchantmentThisTurn(this.getControllerId())); + return watcher != null && event.getTargetId().equals(watcher.getFirstEnchantmentThisTurn(this.getControllerId())); } return false; } @@ -119,7 +119,7 @@ class TuvasaTheSunlitWatcher extends Watcher { private final Map firstEnchantmentThisTurn = new HashMap(); public TuvasaTheSunlitWatcher() { - super(TuvasaTheSunlitWatcher.class.getSimpleName(), WatcherScope.GAME); + super(TuvasaTheSunlitWatcher.class, WatcherScope.GAME); } public TuvasaTheSunlitWatcher(final TuvasaTheSunlitWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/t/TwilightDrover.java b/Mage.Sets/src/mage/cards/t/TwilightDrover.java index 95a2edf861b..9b230eea489 100644 --- a/Mage.Sets/src/mage/cards/t/TwilightDrover.java +++ b/Mage.Sets/src/mage/cards/t/TwilightDrover.java @@ -29,7 +29,7 @@ public final class TwilightDrover extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature token"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public TwilightDrover(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TwilightPanther.java b/Mage.Sets/src/mage/cards/t/TwilightPanther.java new file mode 100644 index 00000000000..68955242d36 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TwilightPanther.java @@ -0,0 +1,43 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TwilightPanther extends CardImpl { + + public TwilightPanther(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {B}: Twilight Panther gains deathtouch until end of turn. + this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect( + DeathtouchAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl("{B}"))); + } + + private TwilightPanther(final TwilightPanther card) { + super(card); + } + + @Override + public TwilightPanther copy() { + return new TwilightPanther(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TwilightShepherd.java b/Mage.Sets/src/mage/cards/t/TwilightShepherd.java index fe12c72f726..ec90fbcd723 100644 --- a/Mage.Sets/src/mage/cards/t/TwilightShepherd.java +++ b/Mage.Sets/src/mage/cards/t/TwilightShepherd.java @@ -81,7 +81,7 @@ class TwilightShepherdEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = (CardsPutIntoGraveyardWatcher) game.getState().getWatchers().get(CardsPutIntoGraveyardWatcher.class.getSimpleName()); + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && watcher != null) { Set cardsInGraveyard = watcher.getCardsPutToGraveyardFromBattlefield(); diff --git a/Mage.Sets/src/mage/cards/t/TwinningGlass.java b/Mage.Sets/src/mage/cards/t/TwinningGlass.java index 71c723922f7..71646c16ace 100644 --- a/Mage.Sets/src/mage/cards/t/TwinningGlass.java +++ b/Mage.Sets/src/mage/cards/t/TwinningGlass.java @@ -75,7 +75,7 @@ class TwinningGlassEffect extends OneShotEffect { filterCard.add(Predicates.not(new CardTypePredicate(CardType.LAND))); Permanent twinningGlass = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (twinningGlass == null) { twinningGlass = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); } diff --git a/Mage.Sets/src/mage/cards/t/TwoHeadedGiant.java b/Mage.Sets/src/mage/cards/t/TwoHeadedGiant.java index 996d78d67b4..e786e0bb8e8 100644 --- a/Mage.Sets/src/mage/cards/t/TwoHeadedGiant.java +++ b/Mage.Sets/src/mage/cards/t/TwoHeadedGiant.java @@ -69,8 +69,8 @@ class TwoHeadedGiantEffect extends OneShotEffect { if (player == null) { return false; } - boolean head1 = player.flipCoin(game); - boolean head2 = player.flipCoin(game); + boolean head1 = player.flipCoin(source, game, false); + boolean head2 = player.flipCoin(source, game, false); if (head1 == head2) { if (head1) { game.addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), source); diff --git a/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java b/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java index 087b53f3045..87ec9fafdb4 100644 --- a/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java +++ b/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java @@ -76,7 +76,7 @@ class TymnaTheWeaverEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - TymnaTheWeaverWatcher watcher = (TymnaTheWeaverWatcher) game.getState().getWatchers().get(TymnaTheWeaverWatcher.class.getSimpleName()); + TymnaTheWeaverWatcher watcher = game.getState().getWatcher(TymnaTheWeaverWatcher.class); if (watcher != null) { int cardsToDraw = watcher.opponentsThatGotCombatDamage(source.getControllerId(), game); Cost cost = new PayLifeCost(cardsToDraw); @@ -97,7 +97,7 @@ class TymnaTheWeaverWatcher extends Watcher { private final Map> players = new HashMap<>(); public TymnaTheWeaverWatcher() { - super(TymnaTheWeaverWatcher.class.getSimpleName(), WatcherScope.GAME); + super(TymnaTheWeaverWatcher.class, WatcherScope.GAME); } public TymnaTheWeaverWatcher(final TymnaTheWeaverWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/t/TyrantsFamiliar.java b/Mage.Sets/src/mage/cards/t/TyrantsFamiliar.java index d52c153360a..a0cd5f70185 100644 --- a/Mage.Sets/src/mage/cards/t/TyrantsFamiliar.java +++ b/Mage.Sets/src/mage/cards/t/TyrantsFamiliar.java @@ -30,7 +30,7 @@ public final class TyrantsFamiliar extends CardImpl { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public TyrantsFamiliar(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UbaMask.java b/Mage.Sets/src/mage/cards/u/UbaMask.java index 94e4fdad29f..e58325f4295 100644 --- a/Mage.Sets/src/mage/cards/u/UbaMask.java +++ b/Mage.Sets/src/mage/cards/u/UbaMask.java @@ -68,7 +68,7 @@ class UbaMaskReplacementEffect extends ReplacementEffectImpl { Card card = player.getLibrary().getFromTop(game); if (card != null) { if (player.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName())) { - UbaMaskExiledCardsWatcher watcher = (UbaMaskExiledCardsWatcher) game.getState().getWatchers().get(UbaMaskExiledCardsWatcher.class.getSimpleName()); + UbaMaskExiledCardsWatcher watcher = game.getState().getWatcher(UbaMaskExiledCardsWatcher.class); if (watcher != null) { watcher.addExiledCard(event.getPlayerId(), card, game); } @@ -116,7 +116,7 @@ class UbaMaskPlayEffect extends AsThoughEffectImpl { if (card != null && affectedControllerId.equals(card.getOwnerId()) && game.getState().getZone(card.getId()) == Zone.EXILED) { - UbaMaskExiledCardsWatcher watcher = (UbaMaskExiledCardsWatcher) game.getState().getWatchers().get(UbaMaskExiledCardsWatcher.class.getSimpleName()); + UbaMaskExiledCardsWatcher watcher = game.getState().getWatcher(UbaMaskExiledCardsWatcher.class); if (watcher != null) { List exiledThisTurn = watcher.getUbaMaskExiledCardsThisTurn(affectedControllerId); return exiledThisTurn != null @@ -132,7 +132,7 @@ class UbaMaskExiledCardsWatcher extends Watcher { private final Map> exiledCards = new HashMap<>(); public UbaMaskExiledCardsWatcher() { - super(UbaMaskExiledCardsWatcher.class.getSimpleName(), WatcherScope.GAME); + super(UbaMaskExiledCardsWatcher.class, WatcherScope.GAME); } public UbaMaskExiledCardsWatcher(final UbaMaskExiledCardsWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/u/UginTheSpiritDragon.java b/Mage.Sets/src/mage/cards/u/UginTheSpiritDragon.java index d508d489b39..880666f4e9e 100644 --- a/Mage.Sets/src/mage/cards/u/UginTheSpiritDragon.java +++ b/Mage.Sets/src/mage/cards/u/UginTheSpiritDragon.java @@ -100,7 +100,7 @@ class UginTheSpiritDragonEffect2 extends OneShotEffect { FilterPermanent filter = new FilterPermanent("permanent with converted mana cost X or less that's one or more colors"); filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, cmc + 1)); - filter.add(Predicates.not(new ColorlessPredicate())); + filter.add(Predicates.not(ColorlessPredicate.instance)); Set permanentsToExile = new HashSet<>(); permanentsToExile.addAll(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)); controller.moveCards(permanentsToExile, Zone.EXILED, source, game); diff --git a/Mage.Sets/src/mage/cards/u/UginsConstruct.java b/Mage.Sets/src/mage/cards/u/UginsConstruct.java index f0b36c2eafa..39e1b789dce 100644 --- a/Mage.Sets/src/mage/cards/u/UginsConstruct.java +++ b/Mage.Sets/src/mage/cards/u/UginsConstruct.java @@ -22,7 +22,7 @@ public final class UginsConstruct extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("permanent that's one or more colors"); static { - filter.add(Predicates.not(new ColorlessPredicate())); + filter.add(Predicates.not(ColorlessPredicate.instance)); } public UginsConstruct(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UktabiKong.java b/Mage.Sets/src/mage/cards/u/UktabiKong.java index d3e92b6b972..1d2f31e7eb1 100644 --- a/Mage.Sets/src/mage/cards/u/UktabiKong.java +++ b/Mage.Sets/src/mage/cards/u/UktabiKong.java @@ -31,7 +31,7 @@ public final class UktabiKong extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Apes you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.APE)); } diff --git a/Mage.Sets/src/mage/cards/u/UlashtTheHateSeed.java b/Mage.Sets/src/mage/cards/u/UlashtTheHateSeed.java index 32ae265ad15..aa1c8b6ab3d 100644 --- a/Mage.Sets/src/mage/cards/u/UlashtTheHateSeed.java +++ b/Mage.Sets/src/mage/cards/u/UlashtTheHateSeed.java @@ -78,9 +78,9 @@ class UlashtTheHateSeedEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filterRed = new FilterControlledCreaturePermanent(); static { - filterGreen.add(new AnotherPredicate()); + filterGreen.add(AnotherPredicate.instance); filterGreen.add(new ColorPredicate(ObjectColor.GREEN)); - filterRed.add(new AnotherPredicate()); + filterRed.add(AnotherPredicate.instance); filterRed.add(new ColorPredicate(ObjectColor.RED)); } diff --git a/Mage.Sets/src/mage/cards/u/UlrichsKindred.java b/Mage.Sets/src/mage/cards/u/UlrichsKindred.java index dc00e936dce..898256c9e7d 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichsKindred.java +++ b/Mage.Sets/src/mage/cards/u/UlrichsKindred.java @@ -30,7 +30,7 @@ public final class UlrichsKindred extends CardImpl { static { filter.add(Predicates.or(new SubtypePredicate(SubType.WOLF), new SubtypePredicate(SubType.WEREWOLF))); - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public UlrichsKindred(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UltimatePrice.java b/Mage.Sets/src/mage/cards/u/UltimatePrice.java index 7eee79cde8c..5b37471c239 100644 --- a/Mage.Sets/src/mage/cards/u/UltimatePrice.java +++ b/Mage.Sets/src/mage/cards/u/UltimatePrice.java @@ -19,7 +19,7 @@ public final class UltimatePrice extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("monocolored creature"); static { - filter.add(new MonocoloredPredicate()); + filter.add(MonocoloredPredicate.instance); } public UltimatePrice(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldMysteries.java b/Mage.Sets/src/mage/cards/u/UlvenwaldMysteries.java index d130f99fd02..36d32c3d71c 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldMysteries.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldMysteries.java @@ -34,7 +34,7 @@ public final class UlvenwaldMysteries extends CardImpl { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); filterClue.add(new SubtypePredicate(SubType.CLUE)); } diff --git a/Mage.Sets/src/mage/cards/u/UnbenderTine.java b/Mage.Sets/src/mage/cards/u/UnbenderTine.java index b2b522d3b0a..8e76b2c3e4e 100644 --- a/Mage.Sets/src/mage/cards/u/UnbenderTine.java +++ b/Mage.Sets/src/mage/cards/u/UnbenderTine.java @@ -26,7 +26,7 @@ public final class UnbenderTine extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public UnbenderTine(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UnbreakableFormation.java b/Mage.Sets/src/mage/cards/u/UnbreakableFormation.java new file mode 100644 index 00000000000..62ced3ec1d4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnbreakableFormation.java @@ -0,0 +1,80 @@ +package mage.cards.u; + +import mage.abilities.Ability; +import mage.abilities.condition.common.AddendumCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UnbreakableFormation extends CardImpl { + + public UnbreakableFormation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Creatures you control gain indestructible until end of turn. + this.getSpellAbility().addEffect(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE + )); + + // Addendum — If you cast this spell during your main phase, put a +1/+1 counter on each of those creatures, and they also gain vigilance until end of turn. + this.getSpellAbility().addEffect(new UnbreakableFormationEffect()); + } + + private UnbreakableFormation(final UnbreakableFormation card) { + super(card); + } + + @Override + public UnbreakableFormation copy() { + return new UnbreakableFormation(this); + } +} + +class UnbreakableFormationEffect extends OneShotEffect { + + UnbreakableFormationEffect() { + super(Outcome.Benefit); + staticText = "
Addendum — If you cast this spell during your main phase, " + + "put a +1/+1 counter on each of those creatures, and they also gain vigilance until end of turn."; + } + + private UnbreakableFormationEffect(final UnbreakableFormationEffect effect) { + super(effect); + } + + @Override + public UnbreakableFormationEffect copy() { + return new UnbreakableFormationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!AddendumCondition.instance.apply(game, source)) { + return false; + } + game.addEffect(new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE + ), source); + return new AddCountersAllEffect( + CounterType.P1P1.createInstance(), + StaticFilters.FILTER_CONTROLLED_CREATURE + ).apply(game, source); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/u/UndercityNecrolisk.java b/Mage.Sets/src/mage/cards/u/UndercityNecrolisk.java index f1adb8461a8..d90196c35f6 100644 --- a/Mage.Sets/src/mage/cards/u/UndercityNecrolisk.java +++ b/Mage.Sets/src/mage/cards/u/UndercityNecrolisk.java @@ -31,7 +31,7 @@ public final class UndercityNecrolisk extends CardImpl { = new FilterControlledCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public UndercityNecrolisk(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UndercityScavenger.java b/Mage.Sets/src/mage/cards/u/UndercityScavenger.java new file mode 100644 index 00000000000..a985d82e089 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UndercityScavenger.java @@ -0,0 +1,55 @@ +package mage.cards.u; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UndercityScavenger extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("another creature"); + + static { + filter.add(AnotherPredicate.instance); + } + + public UndercityScavenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Undercity Scavenger enters the battlefield, you may sacrifice another creature. If you do, put two +1/+1 counters on Undercity Scavenger, then scry 2. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), + new SacrificeTargetCost(new TargetControlledPermanent(filter)) + ).addEffect(new ScryEffect(2).concatBy(", then")))); + } + + private UndercityScavenger(final UndercityScavenger card) { + super(card); + } + + @Override + public UndercityScavenger copy() { + return new UndercityScavenger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/u/UndercitysEmbrace.java b/Mage.Sets/src/mage/cards/u/UndercitysEmbrace.java new file mode 100644 index 00000000000..f1b575cbd9e --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UndercitysEmbrace.java @@ -0,0 +1,42 @@ +package mage.cards.u; + +import mage.abilities.condition.common.FerociousCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.SacrificeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UndercitysEmbrace extends CardImpl { + + public UndercitysEmbrace(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); + + // Target opponent sacrifices a creature. If you control a creature with power 4 or greater, you gain 4 life. + this.getSpellAbility().addEffect(new SacrificeEffect( + StaticFilters.FILTER_PERMANENT_A_CREATURE, 1, "target player" + )); + this.getSpellAbility().addTarget(new TargetOpponent()); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new GainLifeEffect(4), FerociousCondition.instance, + "If you control a creature with power 4 or greater, you gain 4 life." + )); + } + + private UndercitysEmbrace(final UndercitysEmbrace card) { + super(card); + } + + @Override + public UndercitysEmbrace copy() { + return new UndercitysEmbrace(this); + } +} diff --git a/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java b/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java index 169e39d2d9c..7e36f41f16f 100644 --- a/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java +++ b/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java @@ -26,8 +26,8 @@ public final class UnlikelyAlliance extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonattacking, nonblocking creature"); static { - filter.add(Predicates.not(new AttackingPredicate())); - filter.add(Predicates.not(new BlockingPredicate())); + filter.add(Predicates.not(AttackingPredicate.instance)); + filter.add(Predicates.not(BlockingPredicate.instance)); } public UnlikelyAlliance(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UnravelingMummy.java b/Mage.Sets/src/mage/cards/u/UnravelingMummy.java index 4320bfa1e46..ff8bf52ac88 100644 --- a/Mage.Sets/src/mage/cards/u/UnravelingMummy.java +++ b/Mage.Sets/src/mage/cards/u/UnravelingMummy.java @@ -30,7 +30,7 @@ public final class UnravelingMummy extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking Zombie"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(new SubtypePredicate(SubType.ZOMBIE)); } diff --git a/Mage.Sets/src/mage/cards/u/UnrulyMob.java b/Mage.Sets/src/mage/cards/u/UnrulyMob.java index 6ae0fb34826..7777945b626 100644 --- a/Mage.Sets/src/mage/cards/u/UnrulyMob.java +++ b/Mage.Sets/src/mage/cards/u/UnrulyMob.java @@ -24,7 +24,7 @@ public final class UnrulyMob extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/u/UnstableFooting.java b/Mage.Sets/src/mage/cards/u/UnstableFooting.java index 3682d933e10..898570d5a5f 100644 --- a/Mage.Sets/src/mage/cards/u/UnstableFooting.java +++ b/Mage.Sets/src/mage/cards/u/UnstableFooting.java @@ -1,9 +1,7 @@ package mage.cards.u; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; @@ -18,9 +16,11 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.target.common.TargetPlayerOrPlaneswalker; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class UnstableFooting extends CardImpl { @@ -36,20 +36,12 @@ public final class UnstableFooting extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new DamageTargetEffect(5), KickedCondition.instance, - "If this spell was kicked, it deals 5 damage to target player or planeswalker")); + "If this spell was kicked, it deals 5 damage to target player or planeswalker") + ); + this.getSpellAbility().setTargetAdjuster(UnstableFootingAdjuster.instance); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - if (KickedCondition.instance.apply(game, ability)) { - ability.addTarget(new TargetPlayerOrPlaneswalker()); - } - } - } - public UnstableFooting(final UnstableFooting card) { super(card); } @@ -60,6 +52,18 @@ public final class UnstableFooting extends CardImpl { } } +enum UnstableFootingAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + if (KickedCondition.instance.apply(game, ability)) { + ability.addTarget(new TargetPlayerOrPlaneswalker()); + } + } +} + class UnstableFootingEffect extends ReplacementEffectImpl { public UnstableFootingEffect() { diff --git a/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java b/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java index 99bf8748627..7b29054aaaa 100644 --- a/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java +++ b/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java @@ -30,7 +30,7 @@ public final class UnstableShapeshifter extends CardImpl { final static FilterCreaturePermanent filterAnotherCreature = new FilterCreaturePermanent("another creature"); static { - filterAnotherCreature.add(new AnotherPredicate()); + filterAnotherCreature.add(AnotherPredicate.instance); } public UnstableShapeshifter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UntamedMight.java b/Mage.Sets/src/mage/cards/u/UntamedMight.java index 3d887eced9b..9ae6aca3a47 100644 --- a/Mage.Sets/src/mage/cards/u/UntamedMight.java +++ b/Mage.Sets/src/mage/cards/u/UntamedMight.java @@ -20,7 +20,7 @@ public final class UntamedMight extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{G}"); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new BoostTargetEffect(new ManacostVariableValue(), new ManacostVariableValue(), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(ManacostVariableValue.instance, ManacostVariableValue.instance, Duration.EndOfTurn)); } public UntamedMight(final UntamedMight card) { diff --git a/Mage.Sets/src/mage/cards/u/UphillBattle.java b/Mage.Sets/src/mage/cards/u/UphillBattle.java index c64a2c80856..51e2e495ace 100644 --- a/Mage.Sets/src/mage/cards/u/UphillBattle.java +++ b/Mage.Sets/src/mage/cards/u/UphillBattle.java @@ -50,7 +50,7 @@ class PlayCreatureLandWatcher extends Watcher { final Set landPlayed = new HashSet<>(); // land played public PlayCreatureLandWatcher() { - super(PlayCreatureLandWatcher.class.getSimpleName(), WatcherScope.GAME); + super(PlayCreatureLandWatcher.class, WatcherScope.GAME); } public PlayCreatureLandWatcher(final PlayCreatureLandWatcher watcher) { @@ -108,8 +108,8 @@ class UphillBattleTapEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Permanent target = ((EntersTheBattlefieldEvent) event).getTarget(); - CreatureWasCastWatcher creatureSpellWatcher = (CreatureWasCastWatcher) game.getState().getWatchers().get(CreatureWasCastWatcher.class.getSimpleName()); - PlayCreatureLandWatcher landWatcher = (PlayCreatureLandWatcher) game.getState().getWatchers().get(PlayCreatureLandWatcher.class.getSimpleName()); + CreatureWasCastWatcher creatureSpellWatcher = game.getState().getWatcher(CreatureWasCastWatcher.class); + PlayCreatureLandWatcher landWatcher = game.getState().getWatcher(PlayCreatureLandWatcher.class); if (target != null && ((creatureSpellWatcher != null && creatureSpellWatcher.wasCreatureCastThisTurn(target.getId())) diff --git a/Mage.Sets/src/mage/cards/u/UrborgJustice.java b/Mage.Sets/src/mage/cards/u/UrborgJustice.java index 526a940374d..b2a73dfa77c 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgJustice.java +++ b/Mage.Sets/src/mage/cards/u/UrborgJustice.java @@ -61,7 +61,7 @@ class UrborgJusticeDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - CreaturesDiedWatcher watcher = (CreaturesDiedWatcher) game.getState().getWatchers().get(CreaturesDiedWatcher.class.getSimpleName()); + CreaturesDiedWatcher watcher = game.getState().getWatcher(CreaturesDiedWatcher.class); if (watcher != null) { return watcher.getAmountOfCreaturesDiedThisTurnByOwner(sourceAbility.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/u/UrborgSyphonMage.java b/Mage.Sets/src/mage/cards/u/UrborgSyphonMage.java index 94145a9ebec..b8374ff492d 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgSyphonMage.java +++ b/Mage.Sets/src/mage/cards/u/UrborgSyphonMage.java @@ -40,7 +40,7 @@ public final class UrborgSyphonMage extends CardImpl { this.addAbility(ability); } - public UrborgSyphonMage(final UrborgSyphonMage card) { + private UrborgSyphonMage(final UrborgSyphonMage card) { super(card); } @@ -57,7 +57,7 @@ class UrborgSyphonMageEffect extends OneShotEffect { staticText = "Each other player loses 2 life. You gain life equal to the life lost this way"; } - public UrborgSyphonMageEffect(final UrborgSyphonMageEffect effect) { + private UrborgSyphonMageEffect(final UrborgSyphonMageEffect effect) { super(effect); } @@ -67,10 +67,10 @@ class UrborgSyphonMageEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - if (!Objects.equals(playerId, source.getControllerId())) { + if (!source.isControlledBy(playerId)) { Player player = game.getPlayer(playerId); if (player != null) { - damage += player.damage(2, source.getSourceId(), game, false, true); + damage += player.loseLife(2, game, false); } } } diff --git a/Mage.Sets/src/mage/cards/u/UrgeToFeed.java b/Mage.Sets/src/mage/cards/u/UrgeToFeed.java index ca6852a51cb..e5fbd52a959 100644 --- a/Mage.Sets/src/mage/cards/u/UrgeToFeed.java +++ b/Mage.Sets/src/mage/cards/u/UrgeToFeed.java @@ -50,7 +50,7 @@ class UrgeToFeedEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.VAMPIRE)); } diff --git a/Mage.Sets/src/mage/cards/u/UrzasFilter.java b/Mage.Sets/src/mage/cards/u/UrzasFilter.java index b9fd9d10cf7..fb3d990ecd8 100644 --- a/Mage.Sets/src/mage/cards/u/UrzasFilter.java +++ b/Mage.Sets/src/mage/cards/u/UrzasFilter.java @@ -20,7 +20,7 @@ public final class UrzasFilter extends CardImpl { private static final FilterCard filter = new FilterCard("multicolored spells"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public UrzasFilter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/u/UrzasMiter.java b/Mage.Sets/src/mage/cards/u/UrzasMiter.java index d65cdd52c5d..294efa29e14 100644 --- a/Mage.Sets/src/mage/cards/u/UrzasMiter.java +++ b/Mage.Sets/src/mage/cards/u/UrzasMiter.java @@ -60,10 +60,10 @@ class UrzasMiterDoIfCostPaid extends DoIfCostPaid { @Override public boolean apply(Game game, Ability source) { - UrzasMiterWatcher watcher = (UrzasMiterWatcher) game.getState().getWatchers().get(UrzasMiterWatcher.class.getSimpleName()); - if(!watcher.cards.contains(source.getFirstTarget())) + UrzasMiterWatcher watcher = game.getState().getWatcher(UrzasMiterWatcher.class); + if(watcher != null && !watcher.cards.contains(source.getFirstTarget())) { return super.apply(game, source); - + } return false; } @@ -74,7 +74,7 @@ class UrzasMiterWatcher extends Watcher { List cards; public UrzasMiterWatcher() { - super(UrzasMiterWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(UrzasMiterWatcher.class, WatcherScope.PLAYER); this.cards = new ArrayList<>(); } diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index e69e0dc6346..ec03cc2a0de 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -152,7 +152,7 @@ class VancesBlastingCannonsFlipTrigger extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(controllerId)) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 3) { return true; } diff --git a/Mage.Sets/src/mage/cards/v/VedalkenEngineer.java b/Mage.Sets/src/mage/cards/v/VedalkenEngineer.java index 3d07356eb4b..5b573e53f2f 100644 --- a/Mage.Sets/src/mage/cards/v/VedalkenEngineer.java +++ b/Mage.Sets/src/mage/cards/v/VedalkenEngineer.java @@ -1,6 +1,7 @@ - package mage.cards.v; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.ConditionalMana; import mage.MageInt; @@ -36,7 +37,7 @@ public final class VedalkenEngineer extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // {tap}: Add two mana of any one color. Spend this mana only to cast artifact spells or activate abilities of artifacts. + // {T}: Add two mana of any one color. Spend this mana only to cast artifact spells or activate abilities of artifacts. this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new VedalkenEngineerEffect(2, new VedalkenEngineerManaBuilder()), new TapSourceCost())); } @@ -76,10 +77,7 @@ class VedalkenEngineerManaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - if (object != null && object.isArtifact()) { - return true; - } - return false; + return object != null && object.isArtifact(); } } @@ -87,11 +85,17 @@ class VedalkenEngineerEffect extends ManaEffect { private final int amount; private final ConditionalManaBuilder manaBuilder; + protected final ArrayList netMana = new ArrayList<>(); public VedalkenEngineerEffect(int amount, ConditionalManaBuilder manaBuilder) { super(); this.amount = amount; this.manaBuilder = manaBuilder; + netMana.add(Mana.GreenMana(amount)); + netMana.add(Mana.BlueMana(amount)); + netMana.add(Mana.BlackMana(amount)); + netMana.add(Mana.WhiteMana(amount)); + netMana.add(Mana.RedMana(amount)); staticText = "Add " + amount + " mana of any one color. " + manaBuilder.getRule(); } @@ -99,6 +103,7 @@ class VedalkenEngineerEffect extends ManaEffect { super(effect); this.amount = effect.amount; this.manaBuilder = effect.manaBuilder; + this.netMana.addAll(effect.netMana); } @Override @@ -117,12 +122,16 @@ class VedalkenEngineerEffect extends ManaEffect { return false; } + @Override + public List getNetMana(Game game, Ability source) { + return netMana; + } + @Override public Mana produceMana(boolean netMana, Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); ChoiceColor choiceColor = new ChoiceColor(true); if (controller != null && controller.choose(Outcome.Benefit, choiceColor, game)) { - Mana condMana = manaBuilder.setMana(choiceColor.getMana(amount), source, game).build(); return condMana; } diff --git a/Mage.Sets/src/mage/cards/v/VeneratedLoxodon.java b/Mage.Sets/src/mage/cards/v/VeneratedLoxodon.java index 34a41b9ab46..cfc3c483bec 100644 --- a/Mage.Sets/src/mage/cards/v/VeneratedLoxodon.java +++ b/Mage.Sets/src/mage/cards/v/VeneratedLoxodon.java @@ -74,7 +74,7 @@ class VeneratedLoxodonEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - VeneratedLoxodonWatcher watcher = (VeneratedLoxodonWatcher) game.getState().getWatchers().get(VeneratedLoxodonWatcher.class.getSimpleName()); + VeneratedLoxodonWatcher watcher = game.getState().getWatcher(VeneratedLoxodonWatcher.class); if (watcher != null) { MageObjectReference mor = new MageObjectReference(source.getSourceId(), source.getSourceObjectZoneChangeCounter() - 1, game); // -1 because of spell on the stack Set creatures = watcher.getConvokingCreatures(mor); @@ -97,7 +97,7 @@ class VeneratedLoxodonWatcher extends Watcher { private final Map> convokingCreatures = new HashMap<>(); public VeneratedLoxodonWatcher() { - super(VeneratedLoxodonWatcher.class.getSimpleName(), WatcherScope.GAME); + super(VeneratedLoxodonWatcher.class, WatcherScope.GAME); } public VeneratedLoxodonWatcher(final VeneratedLoxodonWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/v/Vengeance.java b/Mage.Sets/src/mage/cards/v/Vengeance.java index 10a628cdffe..297badfe894 100644 --- a/Mage.Sets/src/mage/cards/v/Vengeance.java +++ b/Mage.Sets/src/mage/cards/v/Vengeance.java @@ -18,7 +18,7 @@ public final class Vengeance extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } public Vengeance(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VengefulArchon.java b/Mage.Sets/src/mage/cards/v/VengefulArchon.java index 6921e843087..c271f2e00d2 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulArchon.java +++ b/Mage.Sets/src/mage/cards/v/VengefulArchon.java @@ -56,7 +56,7 @@ public final class VengefulArchon extends CardImpl { class VengefulArchonEffect extends PreventDamageToControllerEffect { public VengefulArchonEffect() { - super(Duration.EndOfTurn, false, true, new ManacostVariableValue()); + super(Duration.EndOfTurn, false, true, ManacostVariableValue.instance); staticText = "Prevent the next X damage that would be dealt to you this turn. If damage is prevented this way, {this} deals that much damage to target player or planeswalker"; } diff --git a/Mage.Sets/src/mage/cards/v/VengefulDreams.java b/Mage.Sets/src/mage/cards/v/VengefulDreams.java index 93f6a614520..55b4b8520df 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulDreams.java +++ b/Mage.Sets/src/mage/cards/v/VengefulDreams.java @@ -1,52 +1,58 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.common.DiscardXTargetCost; -import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterCard; +import mage.filter.FilterPermanent; import mage.filter.common.FilterAttackingCreature; import mage.game.Game; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class VengefulDreams extends CardImpl { public VengefulDreams(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{W}"); // As an additional cost to cast Vengeful Dreams, discard X cards. this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); - + // Exile X target attacking creatures. Effect effect = new ExileTargetEffect(); effect.setText("Exile X target attacking creatures"); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().setTargetAdjuster(VengefulDreamsAdjuster.instance); } public VengefulDreams(final VengefulDreams card) { super(card); } - - @Override - public void adjustTargets(Ability ability, Game game) { - int xValue = new GetXValue().calculate(game, ability, null); - Target target = new TargetCreaturePermanent(0, xValue, new FilterAttackingCreature(), false); - ability.addTarget(target); - } @Override public VengefulDreams copy() { return new VengefulDreams(this); } } + +enum VengefulDreamsAdjuster implements TargetAdjuster { + instance; + private static final FilterPermanent filter = new FilterAttackingCreature(); + + @Override + public void adjustTargets(Ability ability, Game game) { + Target target = new TargetPermanent(0, ability.getManaCostsToPay().getX(), filter, false); + ability.addTarget(target); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/v/Vengevine.java b/Mage.Sets/src/mage/cards/v/Vengevine.java index 4c179aaedd0..fd465803146 100644 --- a/Mage.Sets/src/mage/cards/v/Vengevine.java +++ b/Mage.Sets/src/mage/cards/v/Vengevine.java @@ -70,7 +70,7 @@ class VengevineAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(controllerId)) { - Watcher watcher = game.getState().getWatchers().get(VengevineWatcher.class.getSimpleName(), controllerId); + Watcher watcher = game.getState().getWatcher(VengevineWatcher.class, controllerId); if (watcher != null && watcher.conditionMet()) { return true; } @@ -91,7 +91,7 @@ class VengevineWatcher extends Watcher { int creatureSpellCount = 0; public VengevineWatcher() { - super(VengevineWatcher.class.getSimpleName(), WatcherScope.PLAYER); + super(VengevineWatcher.class, WatcherScope.PLAYER); } public VengevineWatcher(final VengevineWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/v/VenomousBreath.java b/Mage.Sets/src/mage/cards/v/VenomousBreath.java index 5741e3df3a5..4561377e443 100644 --- a/Mage.Sets/src/mage/cards/v/VenomousBreath.java +++ b/Mage.Sets/src/mage/cards/v/VenomousBreath.java @@ -97,7 +97,7 @@ class VenomousBreathEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null && targetCreature != null) { - BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher watcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (watcher != null) { List toDestroy = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { diff --git a/Mage.Sets/src/mage/cards/v/VenomousVines.java b/Mage.Sets/src/mage/cards/v/VenomousVines.java index 1b12f3b785e..9016551b5e6 100644 --- a/Mage.Sets/src/mage/cards/v/VenomousVines.java +++ b/Mage.Sets/src/mage/cards/v/VenomousVines.java @@ -19,7 +19,7 @@ public final class VenomousVines extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("enchanted permanent"); static { - filter.add(new EnchantedPredicate()); + filter.add(EnchantedPredicate.instance); } public VenomousVines(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VensersJournal.java b/Mage.Sets/src/mage/cards/v/VensersJournal.java index f3b19c26e9b..6bfa3dc7b06 100644 --- a/Mage.Sets/src/mage/cards/v/VensersJournal.java +++ b/Mage.Sets/src/mage/cards/v/VensersJournal.java @@ -30,7 +30,7 @@ public final class VensersJournal extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); // At the beginning of your upkeep, you gain 1 life for each card in your hand. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(new CardsInControllerHandCount()), TargetController.YOU, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(CardsInControllerHandCount.instance), TargetController.YOU, false)); } public VensersJournal(final VensersJournal card) { diff --git a/Mage.Sets/src/mage/cards/v/VentifactBottle.java b/Mage.Sets/src/mage/cards/v/VentifactBottle.java index 92e69ef6516..4b0c2db6e5e 100644 --- a/Mage.Sets/src/mage/cards/v/VentifactBottle.java +++ b/Mage.Sets/src/mage/cards/v/VentifactBottle.java @@ -36,7 +36,7 @@ public final class VentifactBottle extends CardImpl { // {X}{1}, {tap}: Put X charge counters on Ventifact Bottle. Activate this ability only any time you could cast a sorcery. Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, - new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), new ManacostVariableValue(), true), + new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), ManacostVariableValue.instance, true), new ManaCostsImpl("{1}{X}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/v/VerdantSuccession.java b/Mage.Sets/src/mage/cards/v/VerdantSuccession.java index d46a2412fc2..9e0f3ee8876 100644 --- a/Mage.Sets/src/mage/cards/v/VerdantSuccession.java +++ b/Mage.Sets/src/mage/cards/v/VerdantSuccession.java @@ -56,7 +56,7 @@ class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl { static { filter.add(new ColorPredicate(ObjectColor.GREEN)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } public VerdantSuccessionTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/v/VerityCircle.java b/Mage.Sets/src/mage/cards/v/VerityCircle.java new file mode 100644 index 00000000000..73f08b397fc --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VerityCircle.java @@ -0,0 +1,94 @@ +package mage.cards.v; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class VerityCircle extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature without flying"); + + static { + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } + + public VerityCircle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // Whenever a creature an opponent controls becomes tapped, if it isn't being declared as an attacker, you may draw a card. + this.addAbility(new VerityCircleTriggeredAbility()); + + // {4}{U}: Tap target creature without flying. + Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl("{4}{U}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + private VerityCircle(final VerityCircle card) { + super(card); + } + + @Override + public VerityCircle copy() { + return new VerityCircle(this); + } +} + +class VerityCircleTriggeredAbility extends TriggeredAbilityImpl { + + VerityCircleTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true); + } + + private VerityCircleTriggeredAbility(final VerityCircleTriggeredAbility ability) { + super(ability); + } + + @Override + public VerityCircleTriggeredAbility copy() { + return new VerityCircleTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TAPPED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getFlag()) { + return false; + } + Permanent permanent = game.getPermanent(event.getTargetId()); + Player player = game.getPlayer(controllerId); + return permanent != null && player != null && permanent.isCreature() + && player.hasOpponent(permanent.getControllerId(), game); + } + + @Override + public String getRule() { + return "Whenever a creature an opponent controls becomes tapped, " + + "if it isn't being declared as an attacker, you may draw a card."; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java b/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java index 08f15a6ac9d..412e468a951 100644 --- a/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java +++ b/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java @@ -40,7 +40,7 @@ public final class VeryCrypticCommandD extends CardImpl { static { filter.add(new NumberOfTargetsPredicate(1)); - filter2.add(Predicates.not(new TokenPredicate())); + filter2.add(Predicates.not(TokenPredicate.instance)); } public VeryCrypticCommandD(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java index 5794410ba0e..e7723d4f9ff 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java @@ -1,7 +1,6 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -17,12 +16,7 @@ import mage.abilities.effects.common.CopyPermanentEffect; import mage.abilities.keyword.MorphAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; @@ -32,14 +26,13 @@ import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.util.functions.ApplyToPermanent; +import java.util.UUID; + /** * @author spjspj */ public final class VesuvanShapeshifter extends CardImpl { - protected Ability turnFaceUpAbility = null; - private static final String effectText = "as a copy of any creature on the battlefield until {this} is turned faced down"; - public VesuvanShapeshifter(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.SHAPESHIFTER); @@ -53,7 +46,7 @@ public final class VesuvanShapeshifter extends CardImpl { // As Vesuvan Shapeshifter etbs, you may choose another creature. If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new VesuvanShapeShifterFaceUpApplier()); - effect.setText(effectText); + effect.setText("as a copy of any creature on the battlefield until {this} is turned faced down"); ability = new EntersBattlefieldAbility(effect, true); ability.setWorksFaceDown(false); this.addAbility(ability); @@ -121,7 +114,7 @@ class VesuvanShapeshifterEffect extends OneShotEffect { Permanent copyToCreature = game.getPermanent(source.getSourceId()); if (copyToCreature != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); diff --git a/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java b/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java index 7f90224c3ff..d1442674c93 100644 --- a/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java +++ b/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java @@ -56,7 +56,7 @@ class VeteranBodyguardEffect extends ReplacementEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked creatures"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } VeteranBodyguardEffect() { diff --git a/Mage.Sets/src/mage/cards/v/VeteranBrawlers.java b/Mage.Sets/src/mage/cards/v/VeteranBrawlers.java index 0eb7d3d8d62..bbc3d1eb1f0 100644 --- a/Mage.Sets/src/mage/cards/v/VeteranBrawlers.java +++ b/Mage.Sets/src/mage/cards/v/VeteranBrawlers.java @@ -28,7 +28,7 @@ public final class VeteranBrawlers extends CardImpl { static final private FilterLandPermanent filter = new FilterLandPermanent("an untapped land"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } final static private String rule = "{this} can't block if you control an untapped land"; diff --git a/Mage.Sets/src/mage/cards/v/VeteranWarleader.java b/Mage.Sets/src/mage/cards/v/VeteranWarleader.java index c2ec926461c..829f2ff6523 100644 --- a/Mage.Sets/src/mage/cards/v/VeteranWarleader.java +++ b/Mage.Sets/src/mage/cards/v/VeteranWarleader.java @@ -42,9 +42,9 @@ public final class VeteranWarleader extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("another untapped Ally you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public VeteranWarleader(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VeteransVoice.java b/Mage.Sets/src/mage/cards/v/VeteransVoice.java index d49a943f004..ef9a5d895b7 100644 --- a/Mage.Sets/src/mage/cards/v/VeteransVoice.java +++ b/Mage.Sets/src/mage/cards/v/VeteransVoice.java @@ -35,7 +35,7 @@ public final class VeteransVoice extends CardImpl { private static final FilterCreaturePermanent filterUntapped = new FilterCreaturePermanent("enchanted creature is untapped"); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } public VeteransVoice(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java b/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java index 2f6d1d3d3f7..14928db6afa 100644 --- a/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java +++ b/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java @@ -78,7 +78,7 @@ class VialSmasherTheFierceTriggeredAbility extends SpellCastControllerTriggeredA @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(event.getPlayerId()); if (spells != null && spells.size() == 1) { diff --git a/Mage.Sets/src/mage/cards/v/ViashinoSandswimmer.java b/Mage.Sets/src/mage/cards/v/ViashinoSandswimmer.java index 6668c1ff629..bed9581368d 100644 --- a/Mage.Sets/src/mage/cards/v/ViashinoSandswimmer.java +++ b/Mage.Sets/src/mage/cards/v/ViashinoSandswimmer.java @@ -61,7 +61,7 @@ class ViashinoSandswimmerEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { new ReturnToHandSourceEffect().apply(game, source); return true; } else { diff --git a/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java b/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java index 3d5faf818a2..526707fa82f 100644 --- a/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java +++ b/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java @@ -1,7 +1,6 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.VariableCost; import mage.abilities.costs.common.SacrificeXTargetCost; @@ -16,21 +15,22 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Plopman */ public final class ViciousBetrayal extends CardImpl { public ViciousBetrayal(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}"); // As an additional cost to cast Vicious Betrayal, sacrifice any number of creatures. this.getSpellAbility().addCost(new SacrificeXTargetCost(new FilterControlledCreaturePermanent())); // Target creature gets +2/+2 until end of turn for each creature sacrificed this way. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new BoostTargetEffect(new GetXValue(), new GetXValue(), Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new BoostTargetEffect(GetXValue.instance, GetXValue.instance, Duration.EndOfTurn)); } public ViciousBetrayal(final ViciousBetrayal card) { @@ -43,19 +43,21 @@ public final class ViciousBetrayal extends CardImpl { } } -class GetXValue implements DynamicValue { +enum GetXValue implements DynamicValue { + instance; + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { int amount = 0; - for (VariableCost cost: sourceAbility.getCosts().getVariableCosts()) { + for (VariableCost cost : sourceAbility.getCosts().getVariableCosts()) { amount += cost.getAmount(); } - return 2*amount; + return 2 * amount; } @Override public GetXValue copy() { - return new GetXValue(); + return GetXValue.instance; } @Override diff --git a/Mage.Sets/src/mage/cards/v/ViciousShadows.java b/Mage.Sets/src/mage/cards/v/ViciousShadows.java index 273cd5bf24e..c65f819cf8e 100644 --- a/Mage.Sets/src/mage/cards/v/ViciousShadows.java +++ b/Mage.Sets/src/mage/cards/v/ViciousShadows.java @@ -22,7 +22,7 @@ public final class ViciousShadows extends CardImpl { // Whenever a creature dies, you may have Vicious Shadows deal damage to target player equal to the number of cards in that player's hand. - Ability ability = new DiesCreatureTriggeredAbility(new DamageTargetEffect(new CardsInTargetHandCount()), true); + Ability ability = new DiesCreatureTriggeredAbility(new DamageTargetEffect(CardsInTargetHandCount.instance), true); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VileAggregate.java b/Mage.Sets/src/mage/cards/v/VileAggregate.java index bd4cbb2e7b8..e9bfb82417e 100644 --- a/Mage.Sets/src/mage/cards/v/VileAggregate.java +++ b/Mage.Sets/src/mage/cards/v/VileAggregate.java @@ -28,7 +28,7 @@ public final class VileAggregate extends CardImpl { private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("colorless creatures you control"); static { - filter.add(new ColorlessPredicate()); + filter.add(ColorlessPredicate.instance); } public VileAggregate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VileRedeemer.java b/Mage.Sets/src/mage/cards/v/VileRedeemer.java index 134fb3934d9..e66444d9f07 100644 --- a/Mage.Sets/src/mage/cards/v/VileRedeemer.java +++ b/Mage.Sets/src/mage/cards/v/VileRedeemer.java @@ -79,7 +79,7 @@ class VileRedeemerEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - VileRedeemerNonTokenCreaturesDiedWatcher watcher = (VileRedeemerNonTokenCreaturesDiedWatcher) game.getState().getWatchers().get(VileRedeemerNonTokenCreaturesDiedWatcher.class.getSimpleName()); + VileRedeemerNonTokenCreaturesDiedWatcher watcher = game.getState().getWatcher(VileRedeemerNonTokenCreaturesDiedWatcher.class); if (watcher != null) { int amount = watcher.getAmountOfNontokenCreatureDiedThisTurn(controller.getId()); if (amount > 0) { diff --git a/Mage.Sets/src/mage/cards/v/VindictiveVampire.java b/Mage.Sets/src/mage/cards/v/VindictiveVampire.java new file mode 100644 index 00000000000..1a49b81e000 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VindictiveVampire.java @@ -0,0 +1,54 @@ +package mage.cards.v; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class VindictiveVampire extends CardImpl { + + private static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(AnotherPredicate.instance); + } + + public VindictiveVampire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Whenever another creature you control dies, Vindictive Vampire deals 1 damage to each opponent and you gain 1 life. + Ability ability = new DiesCreatureTriggeredAbility( + new DamagePlayersEffect(1, TargetController.OPPONENT), false, + filter, true + ); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); + this.addAbility(ability); + } + + private VindictiveVampire(final VindictiveVampire card) { + super(card); + } + + @Override + public VindictiveVampire copy() { + return new VindictiveVampire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VintaraSnapper.java b/Mage.Sets/src/mage/cards/v/VintaraSnapper.java index b4b16b30f36..68f6d77c7bb 100644 --- a/Mage.Sets/src/mage/cards/v/VintaraSnapper.java +++ b/Mage.Sets/src/mage/cards/v/VintaraSnapper.java @@ -28,7 +28,7 @@ public final class VintaraSnapper extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public VintaraSnapper(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VirulentPlague.java b/Mage.Sets/src/mage/cards/v/VirulentPlague.java index 7dc9190f927..450da3f8169 100644 --- a/Mage.Sets/src/mage/cards/v/VirulentPlague.java +++ b/Mage.Sets/src/mage/cards/v/VirulentPlague.java @@ -20,7 +20,7 @@ public final class VirulentPlague extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creature tokens"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); } public VirulentPlague(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VishKalBloodArbiter.java b/Mage.Sets/src/mage/cards/v/VishKalBloodArbiter.java index 948eb6ae9e4..dc3d414a5d5 100644 --- a/Mage.Sets/src/mage/cards/v/VishKalBloodArbiter.java +++ b/Mage.Sets/src/mage/cards/v/VishKalBloodArbiter.java @@ -51,7 +51,7 @@ public final class VishKalBloodArbiter extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // Sacrifice a creature: Put X +1/+1 counters on Vish Kal, Blood Arbiter, where X is the sacrificed creature's power. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new SacrificeCostCreaturesPower(), true), + new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), SacrificeCostCreaturesPower.instance, true), new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)))); // Remove all +1/+1 counters from Vish Kal: Target creature gets -1/-1 until end of turn for each +1/+1 counter removed this way. DynamicValue removedCounters = new SignInversionDynamicValue(new VishKalBloodArbiterDynamicValue()); diff --git a/Mage.Sets/src/mage/cards/v/VitalizingCascade.java b/Mage.Sets/src/mage/cards/v/VitalizingCascade.java index bb1b0f5288f..2cf79403984 100644 --- a/Mage.Sets/src/mage/cards/v/VitalizingCascade.java +++ b/Mage.Sets/src/mage/cards/v/VitalizingCascade.java @@ -1,9 +1,8 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; @@ -11,17 +10,18 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.game.Game; +import java.util.UUID; + /** - * * @author LoneFox */ public final class VitalizingCascade extends CardImpl { public VitalizingCascade(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{G}{W}"); // You gain X plus 3 life. - this.getSpellAbility().addEffect(new GainLifeEffect(new VitalizingCascadeValue())); + this.getSpellAbility().addEffect(new GainLifeEffect(VitalizingCascadeValue.instance)); } public VitalizingCascade(final VitalizingCascade card) { @@ -34,16 +34,22 @@ public final class VitalizingCascade extends CardImpl { } } -class VitalizingCascadeValue extends ManacostVariableValue { +enum VitalizingCascadeValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - return super.calculate(game, sourceAbility, effect) + 3; + return sourceAbility.getManaCosts().getX() + 3; } @Override public VitalizingCascadeValue copy() { - return new VitalizingCascadeValue(); + return instance; + } + + @Override + public String getMessage() { + return ""; } @Override diff --git a/Mage.Sets/src/mage/cards/v/VividRevival.java b/Mage.Sets/src/mage/cards/v/VividRevival.java index 267bf076bb8..98cea2f9888 100644 --- a/Mage.Sets/src/mage/cards/v/VividRevival.java +++ b/Mage.Sets/src/mage/cards/v/VividRevival.java @@ -19,7 +19,7 @@ public final class VividRevival extends CardImpl { private static final FilterCard filter = new FilterCard("multicolored cards from your graveyard"); static { - filter.add(new MulticoloredPredicate()); + filter.add(MulticoloredPredicate.instance); } public VividRevival(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java b/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java index 227ecc40a84..6e24c93d234 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfDeferment.java @@ -1,11 +1,7 @@ package mage.cards.v; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; @@ -16,12 +12,9 @@ import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -30,8 +23,9 @@ import mage.target.targetpointer.FixedTarget; import mage.watchers.common.AttackedThisTurnWatcher; import mage.watchers.common.BlockedThisTurnWatcher; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class VizierOfDeferment extends CardImpl { @@ -49,39 +43,10 @@ public final class VizierOfDeferment extends CardImpl { // When Vizier of Deferment enters the battlefield, you may exile target creature if it attacked or blocked this turn. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new EntersBattlefieldTriggeredAbility(new VizierOfDefermentEffect(), true); + ability.addTarget(new TargetCreaturePermanent()); ability.addWatcher(new AttackedThisTurnWatcher()); ability.addWatcher(new BlockedThisTurnWatcher()); this.addAbility(ability); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof EntersBattlefieldTriggeredAbility) { - List creaturesThatCanBeTargeted = new ArrayList<>(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that attacked or blocked this turn."); - AttackedThisTurnWatcher watcherAttacked = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); - BlockedThisTurnWatcher watcherBlocked = (BlockedThisTurnWatcher) game.getState().getWatchers().get(BlockedThisTurnWatcher.class.getSimpleName()); - if (watcherAttacked != null) { - for (MageObjectReference mor : watcherAttacked.getAttackedThisTurnCreatures()) { - Permanent permanent = mor.getPermanent(game); - if (permanent != null) { - creaturesThatCanBeTargeted.add(new PermanentIdPredicate(permanent.getId())); - } - } - if (watcherBlocked != null) { - for (MageObjectReference mor : watcherBlocked.getBlockedThisTurnCreatures()) { - Permanent permanent = mor.getPermanent(game); - if (permanent != null) { - creaturesThatCanBeTargeted.add(new PermanentIdPredicate(permanent.getId())); - } - } - } - filter.add(Predicates.or(creaturesThatCanBeTargeted)); - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(filter)); - } - } } public VizierOfDeferment(final VizierOfDeferment card) { @@ -98,7 +63,8 @@ class VizierOfDefermentEffect extends OneShotEffect { public VizierOfDefermentEffect() { super(Outcome.Detriment); - staticText = "you may exile target creature if it attacked or blocked this turn. Return that card to the battlefield under its owner's control at the beginning of the next end step"; + staticText = "you may exile target creature if it attacked or blocked this turn. " + + "Return that card to the battlefield under its owner's control at the beginning of the next end step"; } public VizierOfDefermentEffect(final VizierOfDefermentEffect effect) { @@ -110,8 +76,17 @@ class VizierOfDefermentEffect extends OneShotEffect { Permanent permanent = game.getPermanent(source.getFirstTarget()); Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + AttackedThisTurnWatcher watcherAttacked = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + BlockedThisTurnWatcher watcherBlocked = (BlockedThisTurnWatcher) game.getState().getWatchers().get(BlockedThisTurnWatcher.class.getSimpleName()); + boolean attackedOrBlocked = false; + if (watcherAttacked != null && watcherAttacked.checkIfAttacked(permanent, game)) { + attackedOrBlocked = true; + } + if (watcherBlocked != null && watcherBlocked.checkIfBlocked(permanent, game)) { + attackedOrBlocked = true; + } if (controller != null - && permanent != null + && attackedOrBlocked && sourcePermanent != null) { if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java b/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java index 39c9d7a5297..69799135a60 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfManyFaces.java @@ -72,7 +72,7 @@ class VizierOfManyFacesApplyToPermanent extends ApplyToPermanent { for (Permanent entering : game.getPermanentsEntering().values()) { if (entering.getId().equals(copyToObjectId) && entering instanceof PermanentToken) { UUID originalCardId = ((PermanentToken) entering).getToken().getCopySourceCard().getId(); - EmbalmedThisTurnWatcher watcher = (EmbalmedThisTurnWatcher) game.getState().getWatchers().get(EmbalmedThisTurnWatcher.class.getSimpleName()); + EmbalmedThisTurnWatcher watcher = game.getState().getWatcher(EmbalmedThisTurnWatcher.class); if (watcher != null) { for (MageObjectReference mor : watcher.getEmbalmedThisTurnCards()) { if (mor.getSourceId().equals(originalCardId) && game.getState().getZoneChangeCounter(originalCardId) == mor.getZoneChangeCounter()) { @@ -97,7 +97,7 @@ class EmbalmedThisTurnWatcher extends Watcher { private final Set embalmedThisTurnTokens; public EmbalmedThisTurnWatcher() { - super(EmbalmedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + super(EmbalmedThisTurnWatcher.class, WatcherScope.GAME); embalmedThisTurnTokens = new HashSet<>(); } diff --git a/Mage.Sets/src/mage/cards/v/VizierOfTumblingSands.java b/Mage.Sets/src/mage/cards/v/VizierOfTumblingSands.java index 8ffc9d4ec97..3b02d878dd9 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfTumblingSands.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfTumblingSands.java @@ -29,7 +29,7 @@ public final class VizierOfTumblingSands extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public VizierOfTumblingSands(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VizkopaVampire.java b/Mage.Sets/src/mage/cards/v/VizkopaVampire.java new file mode 100644 index 00000000000..a8ca550db38 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VizkopaVampire.java @@ -0,0 +1,36 @@ +package mage.cards.v; + +import mage.MageInt; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class VizkopaVampire extends CardImpl { + + public VizkopaVampire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W/B}"); + + this.subtype.add(SubType.VAMPIRE); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + } + + private VizkopaVampire(final VizkopaVampire card) { + super(card); + } + + @Override + public VizkopaVampire copy() { + return new VizkopaVampire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java index 85ee0633314..1b7d8dde0fe 100644 --- a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java +++ b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java @@ -48,7 +48,7 @@ public final class VodalianWarMachine extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Merfolk you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.MERFOLK)); } @@ -143,7 +143,7 @@ class VodalianWarMachineEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (sourcePermanent != null) { - VodalianWarMachineWatcher watcher = (VodalianWarMachineWatcher) game.getState().getWatchers().get(VodalianWarMachineWatcher.class.getSimpleName()); + VodalianWarMachineWatcher watcher = game.getState().getWatcher(VodalianWarMachineWatcher.class); if (watcher != null && watcher.getTappedMerfolkIds(sourcePermanent, game) != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { if (watcher.getTappedMerfolkIds(sourcePermanent, game).contains(new MageObjectReference(permanent, game))) { @@ -163,7 +163,7 @@ class VodalianWarMachineWatcher extends Watcher { public Map> tappedMerfolkIds = new HashMap<>(); public VodalianWarMachineWatcher() { - super(VodalianWarMachineWatcher.class.getSimpleName(), WatcherScope.GAME); + super(VodalianWarMachineWatcher.class, WatcherScope.GAME); } public VodalianWarMachineWatcher(final VodalianWarMachineWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/v/VoiceOfTheWoods.java b/Mage.Sets/src/mage/cards/v/VoiceOfTheWoods.java index 1539f1eef85..5094e7e2991 100644 --- a/Mage.Sets/src/mage/cards/v/VoiceOfTheWoods.java +++ b/Mage.Sets/src/mage/cards/v/VoiceOfTheWoods.java @@ -28,7 +28,7 @@ public final class VoiceOfTheWoods extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Elves you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.ELF)); } diff --git a/Mage.Sets/src/mage/cards/v/VoidGrafter.java b/Mage.Sets/src/mage/cards/v/VoidGrafter.java index af9e959b4e0..c4b6d62e0f2 100644 --- a/Mage.Sets/src/mage/cards/v/VoidGrafter.java +++ b/Mage.Sets/src/mage/cards/v/VoidGrafter.java @@ -27,7 +27,7 @@ public final class VoidGrafter extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public VoidGrafter(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VolatileRig.java b/Mage.Sets/src/mage/cards/v/VolatileRig.java index 6ec037917f8..ec5ba97d616 100644 --- a/Mage.Sets/src/mage/cards/v/VolatileRig.java +++ b/Mage.Sets/src/mage/cards/v/VolatileRig.java @@ -130,7 +130,7 @@ class VolatileRigEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { return permanent.sacrifice(source.getSourceId(), game); @@ -161,7 +161,7 @@ class VolatileRigEffect2 extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { List permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); for (Permanent permanent : permanents) { diff --git a/Mage.Sets/src/mage/cards/v/VolcanicEruption.java b/Mage.Sets/src/mage/cards/v/VolcanicEruption.java index 8f2514123f5..cf6c04bafe6 100644 --- a/Mage.Sets/src/mage/cards/v/VolcanicEruption.java +++ b/Mage.Sets/src/mage/cards/v/VolcanicEruption.java @@ -1,10 +1,8 @@ - package mage.cards.v; import java.util.List; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -18,6 +16,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetLandPermanent; +import mage.target.targetadjustment.TargetAdjuster; /** * @@ -25,23 +24,12 @@ import mage.target.common.TargetLandPermanent; */ public final class VolcanicEruption extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent(SubType.MOUNTAIN, "Mountain"); - public VolcanicEruption(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}{U}{U}"); // Destroy X target Mountains. Volcanic Eruption deals damage to each creature and each player equal to the number of Mountains put into a graveyard this way. - this.getSpellAbility().addTarget(new TargetLandPermanent(filter)); this.getSpellAbility().addEffect(new VolcanicEruptionEffect()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetLandPermanent(xValue, xValue, filter, false)); - } + this.getSpellAbility().setTargetAdjuster(VolcanicEruptionAdjuster.instance); } public VolcanicEruption(final VolcanicEruption card) { @@ -54,6 +42,19 @@ public final class VolcanicEruption extends CardImpl { } } +enum VolcanicEruptionAdjuster implements TargetAdjuster { + instance; + private static final FilterLandPermanent filter + = new FilterLandPermanent(SubType.MOUNTAIN, "Mountain"); + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int xValue = ability.getManaCostsToPay().getX(); + ability.addTarget(new TargetLandPermanent(xValue, xValue, filter, false)); + } +} + class VolcanicEruptionEffect extends OneShotEffect { public VolcanicEruptionEffect() { diff --git a/Mage.Sets/src/mage/cards/v/VolcanicGeyser.java b/Mage.Sets/src/mage/cards/v/VolcanicGeyser.java index 85a3f917121..1f13748ea75 100644 --- a/Mage.Sets/src/mage/cards/v/VolcanicGeyser.java +++ b/Mage.Sets/src/mage/cards/v/VolcanicGeyser.java @@ -20,7 +20,7 @@ public final class VolcanicGeyser extends CardImpl { // Volcanic Geyser deals X damage to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); + this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.instance)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/v/VolcanicOffering.java b/Mage.Sets/src/mage/cards/v/VolcanicOffering.java index 9037d6ea455..3c9d41e2ee5 100644 --- a/Mage.Sets/src/mage/cards/v/VolcanicOffering.java +++ b/Mage.Sets/src/mage/cards/v/VolcanicOffering.java @@ -1,9 +1,7 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -22,30 +20,22 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetOpponentsChoicePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class VolcanicOffering extends CardImpl { - private static final FilterLandPermanent filterLand = new FilterLandPermanent("nonbasic land you don't control"); - private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("creature you don't control"); - static { - filterLand.add(new ControllerPredicate(TargetController.NOT_YOU)); - filterLand.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); - filterCreature.add(new ControllerPredicate(TargetController.NOT_YOU)); - } public VolcanicOffering(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); // Destroy target nonbasic land you don't control and target nonbasic land of an opponent's choice you don't control. // Volcanic Offering deals 7 damage to target creature you don't control and 7 damage to target creature of an opponent's choice you don't control. this.getSpellAbility().addEffect(new VolcanicOfferingEffect()); - this.getSpellAbility().addTarget(new TargetPermanent(filterLand)); - this.getSpellAbility().addTarget(new TargetPermanent(filterCreature)); - + this.getSpellAbility().setTargetAdjuster(VolcanicOfferingAdjuster.instance); } public VolcanicOffering(final VolcanicOffering card) { @@ -53,27 +43,39 @@ public final class VolcanicOffering extends CardImpl { } @Override - public void adjustTargets(Ability ability, Game game) { - Player controller = game.getPlayer(ability.getControllerId()); - if (controller != null && (ability instanceof SpellAbility)) { - ability.getTargets().clear(); - ability.addTarget(new TargetPermanent(filterLand)); - FilterLandPermanent filterLandForOpponent = new FilterLandPermanent("nonbasic land not controlled by " + controller.getLogName()); - filterLandForOpponent.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); - filterLandForOpponent.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); - ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, filterLandForOpponent, false, true)); + public VolcanicOffering copy() { + return new VolcanicOffering(this); + } +} - ability.addTarget(new TargetPermanent(filterCreature)); - FilterCreaturePermanent filterCreatureForOpponent = new FilterCreaturePermanent("creature not controlled by " + controller.getLogName()); - filterCreatureForOpponent.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); - ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, filterCreatureForOpponent, false, true)); - } +enum VolcanicOfferingAdjuster implements TargetAdjuster { + instance; + private static final FilterLandPermanent filterLand = new FilterLandPermanent("nonbasic land you don't control"); + private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("creature you don't control"); + static { + filterLand.add(new ControllerPredicate(TargetController.NOT_YOU)); + filterLand.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); + filterCreature.add(new ControllerPredicate(TargetController.NOT_YOU)); } @Override - public VolcanicOffering copy() { - return new VolcanicOffering(this); + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller == null) { + return; + } + ability.getTargets().clear(); + ability.addTarget(new TargetPermanent(filterLand)); + FilterLandPermanent filterLandForOpponent = new FilterLandPermanent("nonbasic land not controlled by " + controller.getLogName()); + filterLandForOpponent.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); + filterLandForOpponent.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, filterLandForOpponent, false, true)); + + ability.addTarget(new TargetPermanent(filterCreature)); + FilterCreaturePermanent filterCreatureForOpponent = new FilterCreaturePermanent("creature not controlled by " + controller.getLogName()); + filterCreatureForOpponent.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); + ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, filterCreatureForOpponent, false, true)); } } diff --git a/Mage.Sets/src/mage/cards/v/VolcanoHellion.java b/Mage.Sets/src/mage/cards/v/VolcanoHellion.java index de37cde0ff7..b8bd54d50e2 100644 --- a/Mage.Sets/src/mage/cards/v/VolcanoHellion.java +++ b/Mage.Sets/src/mage/cards/v/VolcanoHellion.java @@ -32,7 +32,7 @@ public final class VolcanoHellion extends CardImpl { this.toughness = new MageInt(5); // Volcano Hellion has echo {X}, where X is your life total. - this.addAbility(new EchoAbility(new ControllerLifeCount(), "{this} has echo {X}, where X is your life total.")); + this.addAbility(new EchoAbility(ControllerLifeCount.instance, "{this} has echo {X}, where X is your life total.")); // When Volcano Hellion enters the battlefield, it deals an amount of damage of your choice to you and target creature. The damage can't be prevented. Ability ability = new EntersBattlefieldTriggeredAbility(new VolcanoHellionEffect(), false); diff --git a/Mage.Sets/src/mage/cards/v/VoldarenPariah.java b/Mage.Sets/src/mage/cards/v/VoldarenPariah.java index 1f4be360d2d..f810467d907 100644 --- a/Mage.Sets/src/mage/cards/v/VoldarenPariah.java +++ b/Mage.Sets/src/mage/cards/v/VoldarenPariah.java @@ -28,7 +28,7 @@ public final class VoldarenPariah extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("three other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public VoldarenPariah(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VolrathTheFallen.java b/Mage.Sets/src/mage/cards/v/VolrathTheFallen.java index 3e8ebbb7e5e..d7344404e4a 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathTheFallen.java +++ b/Mage.Sets/src/mage/cards/v/VolrathTheFallen.java @@ -34,7 +34,7 @@ public final class VolrathTheFallen extends CardImpl { // {1}{B}, Discard a creature card: // Volrath the Fallen gets +X/+X until end of turn, where X is the discarded card's converted mana cost. - Effect effect = new BoostSourceEffect(new DiscardCostCardConvertedMana(),new DiscardCostCardConvertedMana(),Duration.EndOfTurn); + Effect effect = new BoostSourceEffect(DiscardCostCardConvertedMana.instance,DiscardCostCardConvertedMana.instance,Duration.EndOfTurn); effect.setText("{this} gets +X/+X until end of turn, where X is the discarded card's converted mana cost"); Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java b/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java index f3dbd4513a9..3c8444a70e4 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java +++ b/Mage.Sets/src/mage/cards/v/VolrathsDungeon.java @@ -1,135 +1,135 @@ -package mage.cards.v; - -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.ActivatedAbility; -import mage.abilities.common.ActivateAsSorceryActivatedAbility; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; -import mage.abilities.costs.CostImpl; -import mage.abilities.costs.common.DiscardCardCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DestroySourceEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetPlayer; -import mage.target.common.TargetCardInHand; - -/** - * - * @author jeffwadsworth - */ -public final class VolrathsDungeon extends CardImpl { - - public VolrathsDungeon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); - - // Pay 5 life: Destroy Volrath's Dungeon. Any player may activate this ability but only during his or her turn. - ActivatedAbility ability = new SimpleActivatedAbility( - Zone.BATTLEFIELD, - new DestroySourceEffect().setText("Destroy {this}. Any player may activate this ability but only during his or her turn."), - new PayLifeActivePlayerCost(5)); - ability.setMayActivate(TargetController.ACTIVE); - this.addAbility(ability); - - // Discard a card: Target player puts a card from his or her hand on top of his or her library. Activate this ability only any time you could cast a sorcery. - FilterCard filter = new FilterCard("a card for payment"); - Ability ability2 = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new VolrathsDungeonEffect(), new DiscardCardCost(filter)); - ability2.addTarget(new TargetPlayer()); - this.addAbility(ability2); - } - - public VolrathsDungeon(final VolrathsDungeon card) { - super(card); - } - - @Override - public VolrathsDungeon copy() { - return new VolrathsDungeon(this); - } -} - -class PayLifeActivePlayerCost extends CostImpl { - - private final DynamicValue amount; - - public PayLifeActivePlayerCost(int amount) { - this.amount = new StaticValue(amount); - this.text = "Pay " + Integer.toString(amount) + " life"; - } - - public PayLifeActivePlayerCost(DynamicValue amount, String text) { - this.amount = amount.copy(); - this.text = "Pay " + text; - } - - public PayLifeActivePlayerCost(PayLifeActivePlayerCost cost) { - super(cost); - this.amount = cost.amount.copy(); - } - - @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - int lifeToPayAmount = amount.calculate(game, ability, null); - return game.getPlayer(game.getActivePlayerId()).getLife() >= lifeToPayAmount; - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - int lifeToPayAmount = amount.calculate(game, ability, null); - Player activatingPlayer = game.getPlayer(game.getActivePlayerId()); - if (activatingPlayer != null - && activatingPlayer.chooseUse(Outcome.LoseLife, "Do you wish to pay "+ lifeToPayAmount +" life?", ability, game)) { - Player player = game.getPlayer(game.getActivePlayerId()); - if(player != null) { - this.paid = player.loseLife(lifeToPayAmount, game, false) == lifeToPayAmount; - } - } - return paid; - } - - @Override - public PayLifeActivePlayerCost copy() { - return new PayLifeActivePlayerCost(this); - } -} - -class VolrathsDungeonEffect extends OneShotEffect { - - public VolrathsDungeonEffect() { - super(Outcome.Detriment); - this.staticText = "Target player puts a card from his or her hand on top of his or her library"; - } - - public VolrathsDungeonEffect(final VolrathsDungeonEffect effect) { - super(effect); - } - - @Override - public VolrathsDungeonEffect copy() { - return new VolrathsDungeonEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player targetedPlayer = game.getPlayer(source.getFirstTarget()); - if (targetedPlayer != null) { - TargetCardInHand target = new TargetCardInHand(); - if (targetedPlayer.choose(Outcome.Detriment, targetedPlayer.getHand(), target, game)) { - Card card = game.getCard(target.getFirstTarget()); - return targetedPlayer.putCardOnTopXOfLibrary(card, game, source, 0); - } - } - return false; - } -} +package mage.cards.v; + +import mage.abilities.Ability; +import mage.abilities.ActivatedAbility; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroySourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInHand; + +import java.util.UUID; + +/** + * @author jeffwadsworth + */ +public final class VolrathsDungeon extends CardImpl { + + public VolrathsDungeon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); + + // Pay 5 life: Destroy Volrath's Dungeon. Any player may activate this ability but only during their turn. + ActivatedAbility ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DestroySourceEffect().setText("Destroy {this}. Any player may activate this ability but only during their turn."), + new PayLifeActivePlayerCost(5)); + ability.setMayActivate(TargetController.ACTIVE); + this.addAbility(ability); + + // Discard a card: Target player puts a card from their hand on top of their library. Activate this ability only any time you could cast a sorcery. + FilterCard filter = new FilterCard("a card for payment"); + Ability ability2 = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new VolrathsDungeonEffect(), new DiscardCardCost(filter)); + ability2.addTarget(new TargetPlayer()); + this.addAbility(ability2); + } + + public VolrathsDungeon(final VolrathsDungeon card) { + super(card); + } + + @Override + public VolrathsDungeon copy() { + return new VolrathsDungeon(this); + } +} + +class PayLifeActivePlayerCost extends CostImpl { + + private final DynamicValue amount; + + public PayLifeActivePlayerCost(int amount) { + this.amount = new StaticValue(amount); + this.text = "Pay " + amount + " life"; + } + + public PayLifeActivePlayerCost(DynamicValue amount, String text) { + this.amount = amount.copy(); + this.text = "Pay " + text; + } + + public PayLifeActivePlayerCost(PayLifeActivePlayerCost cost) { + super(cost); + this.amount = cost.amount.copy(); + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + int lifeToPayAmount = amount.calculate(game, ability, null); + return game.getPlayer(game.getActivePlayerId()).getLife() >= lifeToPayAmount; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + int lifeToPayAmount = amount.calculate(game, ability, null); + Player activatingPlayer = game.getPlayer(game.getActivePlayerId()); + if (activatingPlayer != null + && activatingPlayer.chooseUse(Outcome.LoseLife, "Do you wish to pay " + lifeToPayAmount + " life?", ability, game)) { + Player player = game.getPlayer(game.getActivePlayerId()); + if (player != null) { + this.paid = player.loseLife(lifeToPayAmount, game, false) == lifeToPayAmount; + } + } + return paid; + } + + @Override + public PayLifeActivePlayerCost copy() { + return new PayLifeActivePlayerCost(this); + } +} + +class VolrathsDungeonEffect extends OneShotEffect { + + public VolrathsDungeonEffect() { + super(Outcome.Detriment); + this.staticText = "Target player puts a card from their hand on top of their library"; + } + + public VolrathsDungeonEffect(final VolrathsDungeonEffect effect) { + super(effect); + } + + @Override + public VolrathsDungeonEffect copy() { + return new VolrathsDungeonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetedPlayer = game.getPlayer(source.getFirstTarget()); + if (targetedPlayer != null) { + TargetCardInHand target = new TargetCardInHand(); + if (targetedPlayer.choose(Outcome.Detriment, targetedPlayer.getHand(), target, game)) { + Card card = game.getCard(target.getFirstTarget()); + return card != null && targetedPlayer.putCardOnTopXOfLibrary(card, game, source, 0); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VolrathsGardens.java b/Mage.Sets/src/mage/cards/v/VolrathsGardens.java index e7a9f62da5f..b6378c084f3 100644 --- a/Mage.Sets/src/mage/cards/v/VolrathsGardens.java +++ b/Mage.Sets/src/mage/cards/v/VolrathsGardens.java @@ -25,7 +25,7 @@ public final class VolrathsGardens extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public VolrathsGardens(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/v/VoyagerDrake.java b/Mage.Sets/src/mage/cards/v/VoyagerDrake.java index 3db5967e0f1..058ab18bf9e 100644 --- a/Mage.Sets/src/mage/cards/v/VoyagerDrake.java +++ b/Mage.Sets/src/mage/cards/v/VoyagerDrake.java @@ -1,12 +1,9 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -14,21 +11,21 @@ import mage.abilities.keyword.MultikickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class VoyagerDrake extends CardImpl { - private final UUID originalId; - public VoyagerDrake(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.DRAKE); this.power = new MageInt(3); @@ -41,29 +38,18 @@ public final class VoyagerDrake extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Voyager Drake enters the battlefield, up to X target creatures gain flying until end of turn, where X is the number of times Voyager Drake was kicked. - //TODO this should trigger even if it wasn't kicked at all - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), false), - KickedCondition.instance, - "When {this} enters the battlefield, up to X target creatures gain flying until end of turn, where X is the number of times {this} was kicked."); - originalId = ability.getOriginalId(); + Ability ability = new EntersBattlefieldTriggeredAbility( + new GainAbilityTargetEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn + ).setText("up to X target creatures gain flying until end of turn, " + + "where X is the number of times {this} was kicked.") + ); + ability.setTargetAdjuster(VoyagerDrakeAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - int numbTargets = new MultikickerCount().calculate(game, ability, null); - if (numbTargets > 0) { - ability.addTarget(new TargetCreaturePermanent(0, numbTargets)); - } - } - } - public VoyagerDrake(final VoyagerDrake card) { super(card); - this.originalId = card.originalId; } @Override @@ -71,3 +57,16 @@ public final class VoyagerDrake extends CardImpl { return new VoyagerDrake(this); } } + +enum VoyagerDrakeAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + int numbTargets = MultikickerCount.instance.calculate(game, ability, null); + if (numbTargets > 0) { + ability.addTarget(new TargetCreaturePermanent(0, numbTargets)); + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/v/VraskaGolgariQueen.java b/Mage.Sets/src/mage/cards/v/VraskaGolgariQueen.java index bb15a7f7222..538c3b2f5df 100644 --- a/Mage.Sets/src/mage/cards/v/VraskaGolgariQueen.java +++ b/Mage.Sets/src/mage/cards/v/VraskaGolgariQueen.java @@ -37,7 +37,7 @@ public final class VraskaGolgariQueen extends CardImpl { = new FilterNonlandPermanent("nonland permanent with converted mana cost 3 or less"); static { - filter1.add(new AnotherPredicate()); + filter1.add(AnotherPredicate.instance); filter2.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4)); } diff --git a/Mage.Sets/src/mage/cards/w/WaitingInTheWeeds.java b/Mage.Sets/src/mage/cards/w/WaitingInTheWeeds.java index 727d9642efe..fe4bc242943 100644 --- a/Mage.Sets/src/mage/cards/w/WaitingInTheWeeds.java +++ b/Mage.Sets/src/mage/cards/w/WaitingInTheWeeds.java @@ -48,7 +48,7 @@ class WaitingInTheWeedsEffect extends OneShotEffect { static { filter.add(new SubtypePredicate(SubType.FOREST)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public WaitingInTheWeedsEffect() { diff --git a/Mage.Sets/src/mage/cards/w/WakeTheDead.java b/Mage.Sets/src/mage/cards/w/WakeTheDead.java index 49f0cb0087b..b4c6f60a72f 100644 --- a/Mage.Sets/src/mage/cards/w/WakeTheDead.java +++ b/Mage.Sets/src/mage/cards/w/WakeTheDead.java @@ -3,7 +3,6 @@ package mage.cards.w; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.SpellAbility; import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.common.OnOpponentsTurnCondition; @@ -18,11 +17,13 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.TurnPhase; import mage.constants.Zone; +import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTargets; import java.util.ArrayList; @@ -30,29 +31,19 @@ import java.util.List; import java.util.UUID; /** - * * @author LevelX2 */ public final class WakeTheDead extends CardImpl { public WakeTheDead(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}{B}"); // Cast Wake the Dead only during combat on an opponent's turn. this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(TurnPhase.COMBAT, OnOpponentsTurnCondition.instance)); // Return X target creature cards from your graveyard to the battlefield. Sacrifice those creatures at the beginning of the next end step. this.getSpellAbility().addEffect(new WakeTheDeadReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, new FilterCreatureCard("creature cards from your graveyard"))); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInYourGraveyard(xValue, xValue, new FilterCreatureCard("creature cards from your graveyard"))); - } + this.getSpellAbility().setTargetAdjuster(WakeTheDeadAdjuster.instance); } public WakeTheDead(final WakeTheDead card) { @@ -65,6 +56,17 @@ public final class WakeTheDead extends CardImpl { } } +enum WakeTheDeadAdjuster implements TargetAdjuster { + instance; + private static final FilterCard filter = new FilterCreatureCard("creature cards from your graveyard"); + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard(ability.getManaCostsToPay().getX(), filter)); + } +} + class WakeTheDeadReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect { public WakeTheDeadReturnFromGraveyardToBattlefieldTargetEffect() { diff --git a/Mage.Sets/src/mage/cards/w/WakerOfTheWilds.java b/Mage.Sets/src/mage/cards/w/WakerOfTheWilds.java index 77d38291e99..1504be0bf43 100644 --- a/Mage.Sets/src/mage/cards/w/WakerOfTheWilds.java +++ b/Mage.Sets/src/mage/cards/w/WakerOfTheWilds.java @@ -40,7 +40,7 @@ public final class WakerOfTheWilds extends CardImpl { Zone.BATTLEFIELD, new AddCountersTargetEffect( CounterType.P1P1.createInstance(0), - new ManacostVariableValue() + ManacostVariableValue.instance ).setText("Put X +1/+1 counters on target land you control."), new ManaCostsImpl("{X}{G}{G}") ); diff --git a/Mage.Sets/src/mage/cards/w/WallOfLostThoughts.java b/Mage.Sets/src/mage/cards/w/WallOfLostThoughts.java new file mode 100644 index 00000000000..94f2236dd2c --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WallOfLostThoughts.java @@ -0,0 +1,45 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.TargetPlayer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WallOfLostThoughts extends CardImpl { + + public WallOfLostThoughts(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.WALL); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // When Wall of Lost Thoughts enters the battlefield, target player puts the top four cards of their library into their graveyard. + Ability ability = new EntersBattlefieldTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4)); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + private WallOfLostThoughts(final WallOfLostThoughts card) { + super(card); + } + + @Override + public WallOfLostThoughts copy() { + return new WallOfLostThoughts(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WarCadence.java b/Mage.Sets/src/mage/cards/w/WarCadence.java index 57c5707a1c3..a3864feb41b 100644 --- a/Mage.Sets/src/mage/cards/w/WarCadence.java +++ b/Mage.Sets/src/mage/cards/w/WarCadence.java @@ -44,7 +44,7 @@ public final class WarCadence extends CardImpl { class WarCadenceReplacementEffect extends ReplacementEffectImpl { - DynamicValue xCosts = new ManacostVariableValue(); + DynamicValue xCosts = ManacostVariableValue.instance; WarCadenceReplacementEffect() { super(Duration.EndOfTurn, Outcome.Neutral); diff --git a/Mage.Sets/src/mage/cards/w/WarElemental.java b/Mage.Sets/src/mage/cards/w/WarElemental.java index fd2aa63c269..08fdeccdaa5 100644 --- a/Mage.Sets/src/mage/cards/w/WarElemental.java +++ b/Mage.Sets/src/mage/cards/w/WarElemental.java @@ -116,8 +116,8 @@ class OpponentWasDealtDamageCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get(BloodthirstWatcher.class.getSimpleName(), source.getControllerId()); - return watcher.conditionMet(); + BloodthirstWatcher watcher = game.getState().getWatcher(BloodthirstWatcher.class, source.getControllerId()); + return watcher != null && watcher.conditionMet(); } @Override diff --git a/Mage.Sets/src/mage/cards/w/WarTax.java b/Mage.Sets/src/mage/cards/w/WarTax.java index 3f9fb3cf9d1..e9d14ff8221 100644 --- a/Mage.Sets/src/mage/cards/w/WarTax.java +++ b/Mage.Sets/src/mage/cards/w/WarTax.java @@ -45,7 +45,7 @@ public final class WarTax extends CardImpl { class WarTaxCantAttackUnlessPaysEffect extends PayCostToAttackBlockEffectImpl { - DynamicValue xCosts = new ManacostVariableValue(); + DynamicValue xCosts = ManacostVariableValue.instance; WarTaxCantAttackUnlessPaysEffect() { super(Duration.EndOfTurn, Outcome.Neutral, RestrictType.ATTACK); diff --git a/Mage.Sets/src/mage/cards/w/WarbreakTrumpeter.java b/Mage.Sets/src/mage/cards/w/WarbreakTrumpeter.java index 9bd82846272..6e801451f6a 100644 --- a/Mage.Sets/src/mage/cards/w/WarbreakTrumpeter.java +++ b/Mage.Sets/src/mage/cards/w/WarbreakTrumpeter.java @@ -31,7 +31,7 @@ public final class WarbreakTrumpeter extends CardImpl { this.addAbility(new MorphAbility(this, new ManaCostsImpl("{X}{X}{R}"))); // When Warbreak Trumpeter is turned face up, create X 1/1 red Goblin creature tokens. - DynamicValue morphX = new MorphManacostVariableValue(); + DynamicValue morphX = MorphManacostVariableValue.instance; this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new CreateTokenEffect(new GoblinToken(), morphX))); } diff --git a/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java b/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java index 69721f930ab..be42a91567b 100644 --- a/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java +++ b/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java @@ -26,7 +26,7 @@ public final class WarkiteMarauder extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); static { - filter.add(new DefendingPlayerControlsPredicate()); + filter.add(DefendingPlayerControlsPredicate.instance); } public WarkiteMarauder(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/Warpath.java b/Mage.Sets/src/mage/cards/w/Warpath.java index d7a20a8b163..6839eb40456 100644 --- a/Mage.Sets/src/mage/cards/w/Warpath.java +++ b/Mage.Sets/src/mage/cards/w/Warpath.java @@ -21,8 +21,8 @@ public final class Warpath extends CardImpl { static { filter.add(Predicates.or( - new BlockingPredicate(), - new BlockedPredicate())); + BlockingPredicate.instance, + BlockedPredicate.instance)); } public Warpath(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WarpedPhysique.java b/Mage.Sets/src/mage/cards/w/WarpedPhysique.java index 9cfa58584cc..2f1fb5588ae 100644 --- a/Mage.Sets/src/mage/cards/w/WarpedPhysique.java +++ b/Mage.Sets/src/mage/cards/w/WarpedPhysique.java @@ -26,7 +26,7 @@ public final class WarpedPhysique extends CardImpl { // Target creature gets +X/-X until end of turn, where X is the number of cards in your hand. - DynamicValue xValue = new CardsInControllerHandCount(); + DynamicValue xValue = CardsInControllerHandCount.instance; this.getSpellAbility().addEffect(new BoostTargetEffect(xValue, new SignInversionDynamicValue(xValue), Duration.EndOfTurn, true)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/w/WarrantWarden.java b/Mage.Sets/src/mage/cards/w/WarrantWarden.java new file mode 100644 index 00000000000..f115a5cd53b --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WarrantWarden.java @@ -0,0 +1,40 @@ +package mage.cards.w; + +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.SpellAbilityType; +import mage.game.permanent.token.WardenSphinxToken; +import mage.target.common.TargetAttackingOrBlockingCreature; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class WarrantWarden extends SplitCard { + + public WarrantWarden(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{W/U}{W/U}", "{3}{W}{U}", SpellAbilityType.SPLIT); + + // Warrant + // Put target attacking or blocking creature on top of its owner’s library. + this.getLeftHalfCard().getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true)); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature()); + + // Warden + // Create a 4/4 white and blue Sphinx creature token with flying and vigilance. + this.getRightHalfCard().getSpellAbility().addEffect(new CreateTokenEffect(new WardenSphinxToken())); + } + + private WarrantWarden(final WarrantWarden card) { + super(card); + } + + @Override + public WarrantWarden copy() { + return new WarrantWarden(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WatchfulGiant.java b/Mage.Sets/src/mage/cards/w/WatchfulGiant.java new file mode 100644 index 00000000000..3fdac8a0464 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WatchfulGiant.java @@ -0,0 +1,39 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.HumanToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WatchfulGiant extends CardImpl { + + public WatchfulGiant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}"); + + this.subtype.add(SubType.GIANT); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(6); + + // When Watchful Giant enters the battlefield, create a 1/1 white Human creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new HumanToken()))); + } + + private WatchfulGiant(final WatchfulGiant card) { + super(card); + } + + @Override + public WatchfulGiant copy() { + return new WatchfulGiant(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WaterspoutDjinn.java b/Mage.Sets/src/mage/cards/w/WaterspoutDjinn.java index b657f59730a..2ccd435cb41 100644 --- a/Mage.Sets/src/mage/cards/w/WaterspoutDjinn.java +++ b/Mage.Sets/src/mage/cards/w/WaterspoutDjinn.java @@ -28,7 +28,7 @@ public final class WaterspoutDjinn extends CardImpl { static{ filter.add(new SubtypePredicate(SubType.ISLAND)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public WaterspoutDjinn(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java b/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java index 9db272b67cb..aac8ad647b9 100644 --- a/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java +++ b/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java @@ -26,7 +26,7 @@ public final class WaterspoutElemental extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WaterspoutElemental(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WaveOfIndifference.java b/Mage.Sets/src/mage/cards/w/WaveOfIndifference.java index 5ca08c5737a..2ba1c6f4aa9 100644 --- a/Mage.Sets/src/mage/cards/w/WaveOfIndifference.java +++ b/Mage.Sets/src/mage/cards/w/WaveOfIndifference.java @@ -1,21 +1,20 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.StaticFilters; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author emerald000 */ public final class WaveOfIndifference extends CardImpl { @@ -27,23 +26,25 @@ public final class WaveOfIndifference extends CardImpl { Effect effect = new CantBlockTargetEffect(Duration.EndOfTurn); effect.setText("X target creatures can't block this turn"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false)); + this.getSpellAbility().setTargetAdjuster(WaveOfIndifferenceAdjuster.instance); } public WaveOfIndifference(final WaveOfIndifference card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); - } - } - @Override public WaveOfIndifference copy() { return new WaveOfIndifference(this); } } + +enum WaveOfIndifferenceAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WaywardServant.java b/Mage.Sets/src/mage/cards/w/WaywardServant.java index a2ab8010508..19a4b2ab1fb 100644 --- a/Mage.Sets/src/mage/cards/w/WaywardServant.java +++ b/Mage.Sets/src/mage/cards/w/WaywardServant.java @@ -26,7 +26,7 @@ public final class WaywardServant extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ZOMBIE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private static final String rule = "Whenever another Zombie enters the battlefield under your control, each opponent loses 1 life and you gain 1 life."; diff --git a/Mage.Sets/src/mage/cards/w/Weakstone.java b/Mage.Sets/src/mage/cards/w/Weakstone.java index 7bb3a10a78f..e1a1b16be78 100644 --- a/Mage.Sets/src/mage/cards/w/Weakstone.java +++ b/Mage.Sets/src/mage/cards/w/Weakstone.java @@ -21,7 +21,7 @@ public final class Weakstone extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creatures"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public Weakstone(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/Weatherlight.java b/Mage.Sets/src/mage/cards/w/Weatherlight.java index 3c55c668ae5..8caf7d30bce 100644 --- a/Mage.Sets/src/mage/cards/w/Weatherlight.java +++ b/Mage.Sets/src/mage/cards/w/Weatherlight.java @@ -26,7 +26,7 @@ public final class Weatherlight extends CardImpl { private static final FilterCard filter = new FilterCard("a historic card"); static { - filter.add(new HistoricPredicate()); + filter.add(HistoricPredicate.instance); } public Weatherlight(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WeaverOfLies.java b/Mage.Sets/src/mage/cards/w/WeaverOfLies.java index 4dbfaad5ca6..f306ff9c239 100644 --- a/Mage.Sets/src/mage/cards/w/WeaverOfLies.java +++ b/Mage.Sets/src/mage/cards/w/WeaverOfLies.java @@ -34,7 +34,7 @@ public final class WeaverOfLies extends CardImpl { static { filter.add(new AbilityPredicate(MorphAbility.class)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WeaverOfLies(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java b/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java index af4efb00d17..b5a3dd962a4 100644 --- a/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java +++ b/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java @@ -25,7 +25,7 @@ public final class WeedPrunerPoplar extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature other than {this}"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WeedPrunerPoplar(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java index 43706f25802..815d0bee3d2 100644 --- a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java +++ b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java @@ -94,7 +94,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { private static final FilterControlledCreaturePermanent filterUntapped = new FilterControlledCreaturePermanent("untapped creatures you control that share a creature type"); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } WeightOfConscienceTarget() { diff --git a/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java b/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java index ee3002f48ba..e80ae567a64 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java +++ b/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java @@ -24,7 +24,7 @@ public final class WellOfDiscovery extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public WellOfDiscovery(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WellOfLife.java b/Mage.Sets/src/mage/cards/w/WellOfLife.java index 775e1a02fd3..c1e0f484416 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfLife.java +++ b/Mage.Sets/src/mage/cards/w/WellOfLife.java @@ -24,7 +24,7 @@ public final class WellOfLife extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public WellOfLife(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java b/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java index edd0537a127..26800c0af0f 100644 --- a/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java +++ b/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java @@ -27,7 +27,7 @@ public final class WellgabberApothecary extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target tapped Merfolk or Kithkin creature this turn"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); filter.add(Predicates.or(new SubtypePredicate(SubType.MERFOLK), new SubtypePredicate(SubType.KITHKIN))); } diff --git a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java index b7df1697b46..61bdd50855f 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java @@ -48,7 +48,7 @@ public final class WerewolfOfAncientHunger extends CardImpl { // Werewolf of Ancient Hunger's power and toughness are each equal to the total number of cards in all players' hands. this.addAbility(new SimpleStaticAbility(Zone.ALL, - new ConditionalContinuousEffect(new SetPowerToughnessSourceEffect(new CardsInAllHandsCount(), Duration.EndOfGame), + new ConditionalContinuousEffect(new SetPowerToughnessSourceEffect(CardsInAllHandsCount.instance, Duration.EndOfGame), new TransformedCondition(false), "{this}'s power and toughness are each equal to the total number of cards in all players' hands"))); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Werewolf of Ancient Hunger. diff --git a/Mage.Sets/src/mage/cards/w/Whetwheel.java b/Mage.Sets/src/mage/cards/w/Whetwheel.java index bb37398d793..cc09655c802 100644 --- a/Mage.Sets/src/mage/cards/w/Whetwheel.java +++ b/Mage.Sets/src/mage/cards/w/Whetwheel.java @@ -26,7 +26,7 @@ public final class Whetwheel extends CardImpl { // {X}{X}, {tap}: Target player puts the top X cards of their library into their graveyard. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect( - new ManacostVariableValue()), new ManaCostsImpl("{X}{X}")); + ManacostVariableValue.instance), new ManaCostsImpl("{X}{X}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WhiplashTrap.java b/Mage.Sets/src/mage/cards/w/WhiplashTrap.java index 0abe74629c9..26be4131c9c 100644 --- a/Mage.Sets/src/mage/cards/w/WhiplashTrap.java +++ b/Mage.Sets/src/mage/cards/w/WhiplashTrap.java @@ -52,7 +52,7 @@ enum WhiplashTrapCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getSimpleName()); + PermanentsEnteredBattlefieldWatcher watcher = game.getState().getWatcher(PermanentsEnteredBattlefieldWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { List permanents = watcher.getThisTurnEnteringPermanents(opponentId); diff --git a/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java b/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java index 6d88e9d1af0..baa075c2b9e 100644 --- a/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java +++ b/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java @@ -66,7 +66,7 @@ class WhisperingSnitchTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(getControllerId())) { - WhisperingSnitchWatcher watcher = (WhisperingSnitchWatcher) game.getState().getWatchers().get(WhisperingSnitchWatcher.class.getSimpleName()); + WhisperingSnitchWatcher watcher = game.getState().getWatcher(WhisperingSnitchWatcher.class); return watcher != null && watcher.getTimesSurveiled(getControllerId()) == 1; } return false; @@ -89,7 +89,7 @@ class WhisperingSnitchWatcher extends Watcher { private final Map timesSurveiled = new HashMap<>(); public WhisperingSnitchWatcher() { - super(WhisperingSnitchWatcher.class.getSimpleName(), WatcherScope.GAME); + super(WhisperingSnitchWatcher.class, WatcherScope.GAME); } public WhisperingSnitchWatcher(final WhisperingSnitchWatcher watcher) { diff --git a/Mage.Sets/src/mage/cards/w/WhisperwoodElemental.java b/Mage.Sets/src/mage/cards/w/WhisperwoodElemental.java index ca07645b87c..52b1ca830c1 100644 --- a/Mage.Sets/src/mage/cards/w/WhisperwoodElemental.java +++ b/Mage.Sets/src/mage/cards/w/WhisperwoodElemental.java @@ -32,8 +32,8 @@ public final class WhisperwoodElemental extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face-up, nontoken creatures you control"); static { - filter.add(Predicates.not(new FaceDownPredicate())); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(FaceDownPredicate.instance)); + filter.add(Predicates.not(TokenPredicate.instance)); } public WhisperwoodElemental(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WhiteManaBattery.java b/Mage.Sets/src/mage/cards/w/WhiteManaBattery.java index d5d28212bba..b08a197b181 100644 --- a/Mage.Sets/src/mage/cards/w/WhiteManaBattery.java +++ b/Mage.Sets/src/mage/cards/w/WhiteManaBattery.java @@ -36,7 +36,7 @@ public final class WhiteManaBattery extends CardImpl { // {tap}, Remove any number of charge counters from White Mana Battery: Add {W}, then add an additional {W} for each charge counter removed this way. ability = new DynamicManaAbility( Mana.WhiteMana(1), - new IntPlusDynamicValue(1, new RemovedCountersForCostValue()), + new IntPlusDynamicValue(1, RemovedCountersForCostValue.instance), new TapSourceCost(), "Add {W}, then add {W} for each charge counter removed this way", true, new CountersSourceCount(CounterType.CHARGE)); diff --git a/Mage.Sets/src/mage/cards/w/WhiteSunsZenith.java b/Mage.Sets/src/mage/cards/w/WhiteSunsZenith.java index b13069cf27c..772562ec28c 100644 --- a/Mage.Sets/src/mage/cards/w/WhiteSunsZenith.java +++ b/Mage.Sets/src/mage/cards/w/WhiteSunsZenith.java @@ -20,7 +20,7 @@ public final class WhiteSunsZenith extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{W}{W}{W}"); // create X 2/2 white Cat creature tokens. Shuffle White Sun's Zenith into its owner's library. - this.getSpellAbility().addEffect(new CreateTokenEffect(new CatToken(), new ManacostVariableValue())); + this.getSpellAbility().addEffect(new CreateTokenEffect(new CatToken(), ManacostVariableValue.instance)); this.getSpellAbility().addEffect(ShuffleSpellEffect.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/w/WickedAkuba.java b/Mage.Sets/src/mage/cards/w/WickedAkuba.java index 5b430956d89..48ca347de73 100644 --- a/Mage.Sets/src/mage/cards/w/WickedAkuba.java +++ b/Mage.Sets/src/mage/cards/w/WickedAkuba.java @@ -60,7 +60,7 @@ class WickedAkubaPredicate implements ObjectSourcePlayerPredicate input, Game game) { - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), input.getObject().getId()); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, input.getObject().getId()); if (watcher != null) { return watcher.hasSourceDoneDamage(input.getSourceId(), game); } diff --git a/Mage.Sets/src/mage/cards/w/WildPair.java b/Mage.Sets/src/mage/cards/w/WildPair.java index ee5d269b22a..76c38c96793 100644 --- a/Mage.Sets/src/mage/cards/w/WildPair.java +++ b/Mage.Sets/src/mage/cards/w/WildPair.java @@ -135,7 +135,7 @@ class CastFromHandTargetCondition implements Condition { return false; } } - CastFromHandWatcher watcher = (CastFromHandWatcher) game.getState().getWatchers().get(CastFromHandWatcher.class.getSimpleName()); + CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class); if (watcher != null && watcher.spellWasCastFromHand(targetId)) { return true; } diff --git a/Mage.Sets/src/mage/cards/w/WildWurm.java b/Mage.Sets/src/mage/cards/w/WildWurm.java index 84ee6709483..c56dee1803b 100644 --- a/Mage.Sets/src/mage/cards/w/WildWurm.java +++ b/Mage.Sets/src/mage/cards/w/WildWurm.java @@ -58,7 +58,7 @@ class WildWurmEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { return true; } else { new ReturnToHandSourceEffect().apply(game, source); diff --git a/Mage.Sets/src/mage/cards/w/WildernessReclamation.java b/Mage.Sets/src/mage/cards/w/WildernessReclamation.java new file mode 100644 index 00000000000..b15ee0e26f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WildernessReclamation.java @@ -0,0 +1,36 @@ +package mage.cards.w; + +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.common.UntapAllControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WildernessReclamation extends CardImpl { + + public WildernessReclamation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + // At the beginning of your end step, untap all lands you control. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new UntapAllControllerEffect(StaticFilters.FILTER_LANDS), + TargetController.YOU, false + )); + } + + private WildernessReclamation(final WildernessReclamation card) { + super(card); + } + + @Override + public WildernessReclamation copy() { + return new WildernessReclamation(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WildestDreams.java b/Mage.Sets/src/mage/cards/w/WildestDreams.java index c1623d2fe59..0f3dcf1b933 100644 --- a/Mage.Sets/src/mage/cards/w/WildestDreams.java +++ b/Mage.Sets/src/mage/cards/w/WildestDreams.java @@ -1,9 +1,7 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileSpellEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; @@ -13,9 +11,11 @@ import mage.constants.CardType; import mage.filter.StaticFilters; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class WildestDreams extends CardImpl { @@ -28,17 +28,8 @@ public final class WildestDreams extends CardImpl { Effect effect = new ReturnFromGraveyardToHandTargetEffect(); effect.setText("Return X target cards from your graveyard to your hand"); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().setTargetAdjuster(WildestDreamsAdjuster.instance); this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); - - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - int xValue = ability.getManaCostsToPay().getX(); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInYourGraveyard(xValue, StaticFilters.FILTER_CARD_FROM_YOUR_GRAVEYARD)); - } } public WildestDreams(final WildestDreams card) { @@ -50,3 +41,16 @@ public final class WildestDreams extends CardImpl { return new WildestDreams(this); } } + +enum WildestDreamsAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCardInYourGraveyard( + ability.getManaCostsToPay().getX(), + StaticFilters.FILTER_CARD_FROM_YOUR_GRAVEYARD + )); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WillKenrith.java b/Mage.Sets/src/mage/cards/w/WillKenrith.java index e1d623e8fd9..8a4c55d7265 100644 --- a/Mage.Sets/src/mage/cards/w/WillKenrith.java +++ b/Mage.Sets/src/mage/cards/w/WillKenrith.java @@ -1,7 +1,5 @@ - package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.CanBeYourCommanderAbility; @@ -16,11 +14,7 @@ import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect; import mage.abilities.keyword.PartnerWithAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -29,8 +23,9 @@ import mage.game.command.emblems.WillKenrithEmblem; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class WillKenrith extends CardImpl { @@ -60,11 +55,6 @@ public final class WillKenrith extends CardImpl { // -8: Target player gets an emblem with "Whenever you cast an instant or sorcery spell, copy it. You may choose new targets for the copy." Effect effect = new GetEmblemTargetPlayerEffect(new WillKenrithEmblem()); - effect.setText( - "Target player gets an emblem with " - + "\"Whenever you cast an instant or sorcery spell, " - + "copy it. You may choose new targets for the copy.\"" - ); ability = new LoyaltyAbility(effect, -8); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WindbriskHeights.java b/Mage.Sets/src/mage/cards/w/WindbriskHeights.java index 6777d79f330..cad956630d8 100644 --- a/Mage.Sets/src/mage/cards/w/WindbriskHeights.java +++ b/Mage.Sets/src/mage/cards/w/WindbriskHeights.java @@ -54,7 +54,7 @@ enum WindbriskHeightsAttackersCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerAttackedWatcher watcher = (PlayerAttackedWatcher) game.getState().getWatchers().get(PlayerAttackedWatcher.class.getSimpleName()); + PlayerAttackedWatcher watcher = game.getState().getWatcher(PlayerAttackedWatcher.class); return watcher != null && watcher.getNumberOfAttackersCurrentTurn(source.getControllerId()) >= 3; } diff --git a/Mage.Sets/src/mage/cards/w/WindbriskRaptor.java b/Mage.Sets/src/mage/cards/w/WindbriskRaptor.java index 1971335179d..07be1f1d175 100644 --- a/Mage.Sets/src/mage/cards/w/WindbriskRaptor.java +++ b/Mage.Sets/src/mage/cards/w/WindbriskRaptor.java @@ -27,7 +27,7 @@ public final class WindbriskRaptor extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); } public WindbriskRaptor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java b/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java index 77067c6f63a..006688c7846 100644 --- a/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java +++ b/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java @@ -1,8 +1,6 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,9 +10,11 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class WindgracesJudgment extends CardImpl { @@ -29,24 +29,7 @@ public final class WindgracesJudgment extends CardImpl { + "destroy target nonland permanent " + "that player controls") ); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - game.getOpponents(ability.getControllerId()).forEach(playerId -> { - Player player = game.getPlayer(playerId); - if (player != null) { - FilterNonlandPermanent filter = new FilterNonlandPermanent( - "nonland permanent controlled by " - + player.getLogName() - ); - filter.add(new ControllerIdPredicate(playerId)); - ability.addTarget(new TargetPermanent(0, 1, filter, false)); - } - }); - } + this.getSpellAbility().setTargetAdjuster(WindgracesJudgmentAdjuster.instance); } public WindgracesJudgment(final WindgracesJudgment card) { @@ -58,3 +41,23 @@ public final class WindgracesJudgment extends CardImpl { return new WindgracesJudgment(this); } } + +enum WindgracesJudgmentAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + game.getOpponents(ability.getControllerId()).forEach(playerId -> { + Player player = game.getPlayer(playerId); + if (player != null) { + FilterNonlandPermanent filter = new FilterNonlandPermanent( + "nonland permanent controlled by " + + player.getLogName() + ); + filter.add(new ControllerIdPredicate(playerId)); + ability.addTarget(new TargetPermanent(0, 1, filter, false)); + } + }); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WindsOfRath.java b/Mage.Sets/src/mage/cards/w/WindsOfRath.java index 559a4c83d92..84f591bef3b 100644 --- a/Mage.Sets/src/mage/cards/w/WindsOfRath.java +++ b/Mage.Sets/src/mage/cards/w/WindsOfRath.java @@ -18,7 +18,7 @@ public final class WindsOfRath extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures that aren't enchanted"); static { - filter.add(Predicates.not(new EnchantedPredicate())); + filter.add(Predicates.not(EnchantedPredicate.instance)); } public WindsOfRath(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/Windstorm.java b/Mage.Sets/src/mage/cards/w/Windstorm.java index 8d4899a342f..7ad059c67fe 100644 --- a/Mage.Sets/src/mage/cards/w/Windstorm.java +++ b/Mage.Sets/src/mage/cards/w/Windstorm.java @@ -27,7 +27,7 @@ public final class Windstorm extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{G}"); - this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filter)); + this.getSpellAbility().addEffect(new DamageAllEffect(ManacostVariableValue.instance, filter)); } public Windstorm(final Windstorm card) { diff --git a/Mage.Sets/src/mage/cards/w/WindstormDrake.java b/Mage.Sets/src/mage/cards/w/WindstormDrake.java new file mode 100644 index 00000000000..702a12621b7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WindstormDrake.java @@ -0,0 +1,56 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; + +import java.util.UUID; +import mage.abilities.effects.Effect; + +/** + * @author TheElk801 + */ +public final class WindstormDrake extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent(); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public WindstormDrake(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); + + this.subtype.add(SubType.DRAKE); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Other creatures you control with flying get +1/+0. + Effect effect = new BoostControlledEffect( + 1, 0, Duration.WhileOnBattlefield, filter, true + ); + effect.setText("Other creatures you control with flying get +1/+0"); + this.addAbility(new SimpleStaticAbility(effect)); + } + + private WindstormDrake(final WindstormDrake card) { + super(card); + } + + @Override + public WindstormDrake copy() { + return new WindstormDrake(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WineOfBloodAndIron.java b/Mage.Sets/src/mage/cards/w/WineOfBloodAndIron.java index 47f98cbfd31..f5e91428984 100644 --- a/Mage.Sets/src/mage/cards/w/WineOfBloodAndIron.java +++ b/Mage.Sets/src/mage/cards/w/WineOfBloodAndIron.java @@ -29,7 +29,7 @@ public final class WineOfBloodAndIron extends CardImpl { // {4}: Target creature gets +X/+0 until end of turn, where X is its power. Sacrifice Wine of Blood and Iron at the beginning of the next end step. SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new BoostTargetEffect(new TargetPermanentPowerCount(), new StaticValue(0), Duration.EndOfTurn, true), + new BoostTargetEffect(TargetPermanentPowerCount.instance, new StaticValue(0), Duration.EndOfTurn, true), new GenericManaCost(4)); Effect effect = new CreateDelayedTriggeredAbilityEffect( new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()), false); diff --git a/Mage.Sets/src/mage/cards/w/WingPuncture.java b/Mage.Sets/src/mage/cards/w/WingPuncture.java index e369c9664a6..45b38fff9fe 100644 --- a/Mage.Sets/src/mage/cards/w/WingPuncture.java +++ b/Mage.Sets/src/mage/cards/w/WingPuncture.java @@ -66,7 +66,7 @@ class WingPunctureEffect extends OneShotEffect { sourcePermanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); } - Permanent targetPermanent = (Permanent) game.getPermanent(source.getTargets().get(1).getFirstTarget()); + Permanent targetPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); if (sourcePermanent != null && targetPermanent != null) { targetPermanent.damage(sourcePermanent.getPower().getValue(), sourcePermanent.getId(), game, false, true); return true; diff --git a/Mage.Sets/src/mage/cards/w/WinterBlast.java b/Mage.Sets/src/mage/cards/w/WinterBlast.java index 38eb6606bb1..16f67ad957c 100644 --- a/Mage.Sets/src/mage/cards/w/WinterBlast.java +++ b/Mage.Sets/src/mage/cards/w/WinterBlast.java @@ -1,9 +1,7 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -13,9 +11,11 @@ import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class WinterBlast extends CardImpl { @@ -26,15 +26,7 @@ public final class WinterBlast extends CardImpl { // Tap X target creatures. Winter Blast deals 2 damage to each of those creatures with flying. this.getSpellAbility().addEffect(new WinterBlastEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int xValue = ability.getManaCostsToPay().getX(); - ability.addTarget(new TargetCreaturePermanent(xValue)); - } + this.getSpellAbility().setTargetAdjuster(WinterBlastAdjuster.instance); } public WinterBlast(final WinterBlast card) { @@ -47,6 +39,16 @@ public final class WinterBlast extends CardImpl { } } +enum WinterBlastAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} + class WinterBlastEffect extends OneShotEffect { WinterBlastEffect() { diff --git a/Mage.Sets/src/mage/cards/w/WinterSky.java b/Mage.Sets/src/mage/cards/w/WinterSky.java index 31ac6526b55..6f728a84087 100644 --- a/Mage.Sets/src/mage/cards/w/WinterSky.java +++ b/Mage.Sets/src/mage/cards/w/WinterSky.java @@ -52,7 +52,7 @@ class WinterSkyEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.flipCoin(game)) { + if (controller.flipCoin(source, game, true)) { new DamageEverythingEffect(1).apply(game, source); return true; } else { diff --git a/Mage.Sets/src/mage/cards/w/WirewoodHivemaster.java b/Mage.Sets/src/mage/cards/w/WirewoodHivemaster.java index 6f11431813d..87d646142aa 100644 --- a/Mage.Sets/src/mage/cards/w/WirewoodHivemaster.java +++ b/Mage.Sets/src/mage/cards/w/WirewoodHivemaster.java @@ -26,8 +26,8 @@ public final class WirewoodHivemaster extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another nontoken Elf"); static { filter.add(new SubtypePredicate(SubType.ELF)); - filter.add(new AnotherPredicate()); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(AnotherPredicate.instance); + filter.add(Predicates.not(TokenPredicate.instance)); } public WirewoodHivemaster(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); diff --git a/Mage.Sets/src/mage/cards/w/WispweaverAngel.java b/Mage.Sets/src/mage/cards/w/WispweaverAngel.java index e52cbe13d4a..2de4396f084 100644 --- a/Mage.Sets/src/mage/cards/w/WispweaverAngel.java +++ b/Mage.Sets/src/mage/cards/w/WispweaverAngel.java @@ -36,7 +36,7 @@ public final class WispweaverAngel extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WispweaverAngel(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WizardMentor.java b/Mage.Sets/src/mage/cards/w/WizardMentor.java index e2f67cfd066..580a69dbe64 100644 --- a/Mage.Sets/src/mage/cards/w/WizardMentor.java +++ b/Mage.Sets/src/mage/cards/w/WizardMentor.java @@ -26,7 +26,7 @@ public final class WizardMentor extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WizardMentor(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WolfbriarElemental.java b/Mage.Sets/src/mage/cards/w/WolfbriarElemental.java index 93d321340d4..4a96c707c5c 100644 --- a/Mage.Sets/src/mage/cards/w/WolfbriarElemental.java +++ b/Mage.Sets/src/mage/cards/w/WolfbriarElemental.java @@ -31,7 +31,7 @@ public final class WolfbriarElemental extends CardImpl { this.addAbility(new MultikickerAbility("{G}")); // When Wolfbriar Elemental enters the battlefield, create a 2/2 green Wolf creature token for each time it was kicked. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WolfToken(), new MultikickerCount()))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WolfToken(), MultikickerCount.instance))); } public WolfbriarElemental(final WolfbriarElemental card) { diff --git a/Mage.Sets/src/mage/cards/w/WoodElemental.java b/Mage.Sets/src/mage/cards/w/WoodElemental.java index 5657c3a83a6..39c7218a3e4 100644 --- a/Mage.Sets/src/mage/cards/w/WoodElemental.java +++ b/Mage.Sets/src/mage/cards/w/WoodElemental.java @@ -62,7 +62,7 @@ class WoodElementalEffect extends OneShotEffect { private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Forests you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SubtypePredicate(SubType.FOREST)); } diff --git a/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java b/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java index cf262a7e39a..4914fa15865 100644 --- a/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java +++ b/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java @@ -25,7 +25,7 @@ public final class WookieeRaidleader extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WookieeRaidleader(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WordOfBinding.java b/Mage.Sets/src/mage/cards/w/WordOfBinding.java index 23643644474..9d6782945dc 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfBinding.java +++ b/Mage.Sets/src/mage/cards/w/WordOfBinding.java @@ -1,19 +1,18 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class WordOfBinding extends CardImpl { @@ -23,25 +22,25 @@ public final class WordOfBinding extends CardImpl { // Tap X target creatures. this.getSpellAbility().addEffect(new TapTargetEffect("X target creatures")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, FILTER_PERMANENT_CREATURES, false)); + this.getSpellAbility().setTargetAdjuster(WordOfBindingAdjuster.instance); } public WordOfBinding(final WordOfBinding card) { super(card); } - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility) { - ability.getTargets().clear(); - int numberToTap = ability.getManaCostsToPay().getX(); - numberToTap = Math.min(game.getBattlefield().count(FILTER_PERMANENT_CREATURES, ability.getSourceId(), ability.getControllerId(), game), numberToTap); - ability.addTarget(new TargetCreaturePermanent(numberToTap, numberToTap, FILTER_PERMANENT_CREATURES, false)); - } - } - @Override public WordOfBinding copy() { return new WordOfBinding(this); } } + +enum WordOfBindingAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WordOfBlasting.java b/Mage.Sets/src/mage/cards/w/WordOfBlasting.java index e30c4504316..ee30e19b782 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfBlasting.java +++ b/Mage.Sets/src/mage/cards/w/WordOfBlasting.java @@ -31,7 +31,7 @@ public final class WordOfBlasting extends CardImpl { // Destroy target Wall. It can't be regenerated. Word of Blasting deals damage equal to that Wall's converted mana cost to the Wall's controller. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - Effect effect = new DamageTargetControllerEffect(new TargetConvertedManaCost()); + Effect effect = new DamageTargetControllerEffect(TargetConvertedManaCost.instance); effect.setText("{this} deals damage equal to that Wall's converted mana cost to the Wall's controller"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetPermanent(filter)); diff --git a/Mage.Sets/src/mage/cards/w/WorldAtWar.java b/Mage.Sets/src/mage/cards/w/WorldAtWar.java index 0658ecda702..01dbdcae335 100644 --- a/Mage.Sets/src/mage/cards/w/WorldAtWar.java +++ b/Mage.Sets/src/mage/cards/w/WorldAtWar.java @@ -142,7 +142,7 @@ class UntapAttackingThisTurnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Watcher watcher = game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + Watcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher instanceof AttackedThisTurnWatcher) { Set attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures(); for (MageObjectReference mor : attackedThisTurn) { diff --git a/Mage.Sets/src/mage/cards/w/WorldgorgerDragon.java b/Mage.Sets/src/mage/cards/w/WorldgorgerDragon.java index dffcbeec044..e3f967b7e36 100644 --- a/Mage.Sets/src/mage/cards/w/WorldgorgerDragon.java +++ b/Mage.Sets/src/mage/cards/w/WorldgorgerDragon.java @@ -70,7 +70,7 @@ class WorldgorgerDragonEntersEffect extends OneShotEffect { static { filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WorldgorgerDragonEntersEffect() { diff --git a/Mage.Sets/src/mage/cards/w/WormfangDrake.java b/Mage.Sets/src/mage/cards/w/WormfangDrake.java index bc3d0ffc5cf..6888edf518b 100644 --- a/Mage.Sets/src/mage/cards/w/WormfangDrake.java +++ b/Mage.Sets/src/mage/cards/w/WormfangDrake.java @@ -65,7 +65,7 @@ class WormfangDrakeExileCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WormfangDrakeExileCost() { diff --git a/Mage.Sets/src/mage/cards/w/WormfangNewt.java b/Mage.Sets/src/mage/cards/w/WormfangNewt.java index ebb66ead46c..1a27dc96ab4 100644 --- a/Mage.Sets/src/mage/cards/w/WormfangNewt.java +++ b/Mage.Sets/src/mage/cards/w/WormfangNewt.java @@ -25,7 +25,7 @@ public final class WormfangNewt extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WormfangNewt(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WormfangTurtle.java b/Mage.Sets/src/mage/cards/w/WormfangTurtle.java index b33bec0c8d8..bee8704f5d3 100644 --- a/Mage.Sets/src/mage/cards/w/WormfangTurtle.java +++ b/Mage.Sets/src/mage/cards/w/WormfangTurtle.java @@ -25,7 +25,7 @@ public final class WormfangTurtle extends CardImpl { private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WormfangTurtle(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WorthyCause.java b/Mage.Sets/src/mage/cards/w/WorthyCause.java index 4d196b4f2c3..3564befc98a 100644 --- a/Mage.Sets/src/mage/cards/w/WorthyCause.java +++ b/Mage.Sets/src/mage/cards/w/WorthyCause.java @@ -29,7 +29,7 @@ public final class WorthyCause extends CardImpl { this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); // You gain life equal to the sacrificed creature's toughness. - Effect effect = new GainLifeEffect(new SacrificeCostCreaturesToughness()); + Effect effect = new GainLifeEffect(SacrificeCostCreaturesToughness.instance); effect.setText("You gain life equal to the sacrificed creature's toughness"); this.getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/w/WoundReflection.java b/Mage.Sets/src/mage/cards/w/WoundReflection.java index 156d16384c1..460acc927ab 100644 --- a/Mage.Sets/src/mage/cards/w/WoundReflection.java +++ b/Mage.Sets/src/mage/cards/w/WoundReflection.java @@ -57,12 +57,12 @@ class WoundReflectionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (controller != null && watcher != null) { for (UUID playerId : game.getOpponents(controller.getId())) { Player opponent = game.getPlayer(playerId); if (opponent != null) { - int lifeLost = watcher.getLiveLost(playerId); + int lifeLost = watcher.getLifeLost(playerId); if (lifeLost > 0) { opponent.loseLife(lifeLost, game, false); } diff --git a/Mage.Sets/src/mage/cards/w/WreckingBeast.java b/Mage.Sets/src/mage/cards/w/WreckingBeast.java new file mode 100644 index 00000000000..f2c318e2139 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WreckingBeast.java @@ -0,0 +1,40 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.keyword.RiotAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WreckingBeast extends CardImpl { + + public WreckingBeast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Riot + this.addAbility(new RiotAbility()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + } + + private WreckingBeast(final WreckingBeast card) { + super(card); + } + + @Override + public WreckingBeast copy() { + return new WreckingBeast(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WretchedAnurid.java b/Mage.Sets/src/mage/cards/w/WretchedAnurid.java index 5fe1aa04092..e78c9a68fae 100644 --- a/Mage.Sets/src/mage/cards/w/WretchedAnurid.java +++ b/Mage.Sets/src/mage/cards/w/WretchedAnurid.java @@ -22,7 +22,7 @@ public final class WretchedAnurid extends CardImpl { private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public WretchedAnurid(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java index 5bb8dfcfd18..f30afcbf4ca 100644 --- a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java +++ b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java @@ -169,12 +169,12 @@ class WrexialReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; return zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId().equals(cardid); + && event.getTargetId().equals(cardid); } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - UUID eventObject = ((ZoneChangeEvent) event).getTargetId(); + UUID eventObject = event.getTargetId(); StackObject card = game.getStack().getStackObject(eventObject); Player controller = game.getPlayer(source.getControllerId()); if (card != null && controller != null) { diff --git a/Mage.Sets/src/mage/cards/x/XathridDemon.java b/Mage.Sets/src/mage/cards/x/XathridDemon.java index 5d229c1b8a0..0e7c174c463 100644 --- a/Mage.Sets/src/mage/cards/x/XathridDemon.java +++ b/Mage.Sets/src/mage/cards/x/XathridDemon.java @@ -81,7 +81,7 @@ class XathridDemonEffect extends OneShotEffect { } FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature other than " + sourcePermanent.getName()); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); if (target.canChoose(source.getSourceId(), controller.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/x/XenagosGodOfRevels.java b/Mage.Sets/src/mage/cards/x/XenagosGodOfRevels.java index 76662b8c009..3eada0b3a35 100644 --- a/Mage.Sets/src/mage/cards/x/XenagosGodOfRevels.java +++ b/Mage.Sets/src/mage/cards/x/XenagosGodOfRevels.java @@ -32,7 +32,7 @@ public final class XenagosGodOfRevels extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } public XenagosGodOfRevels(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java index a1d1d16c90b..3670b8a32ac 100644 --- a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java +++ b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java @@ -1,7 +1,5 @@ package mage.cards.y; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.LegendarySpellAbility; import mage.abilities.effects.OneShotEffect; @@ -9,7 +7,10 @@ import mage.abilities.effects.common.ExileSpellEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.Zone; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.Predicates; @@ -20,6 +21,8 @@ import mage.players.Player; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreatureOrPlaneswalker; +import java.util.UUID; + /** * @author JRHerlehy Created on 4/8/18. */ @@ -78,7 +81,6 @@ class YawgmothsVileOfferingEffect extends OneShotEffect { } Card returnCard = game.getCard(source.getTargets().getFirstTarget()); - if (returnCard != null) { controller.moveCards(returnCard, Zone.BATTLEFIELD, source, game); } diff --git a/Mage.Sets/src/mage/cards/y/YdwenEfreet.java b/Mage.Sets/src/mage/cards/y/YdwenEfreet.java index b1dd810f902..8f038cb3a2f 100644 --- a/Mage.Sets/src/mage/cards/y/YdwenEfreet.java +++ b/Mage.Sets/src/mage/cards/y/YdwenEfreet.java @@ -60,12 +60,12 @@ class YdwenEfreetEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent creature = game.getPermanent(source.getSourceId()); if (controller != null && creature != null) { - if (!controller.flipCoin(game)) { + if (!controller.flipCoin(source, game, true)) { creature.removeFromCombat(game); creature.setMaxBlocks(0); // Make blocked creatures unblocked - BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName()); + BlockedByOnlyOneCreatureThisCombatWatcher watcher = game.getState().getWatcher(BlockedByOnlyOneCreatureThisCombatWatcher.class); if (watcher != null) { Set combatGroups = watcher.getBlockedOnlyByCreature(creature.getId()); if (combatGroups != null) { diff --git a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java index 94bd681f28d..f2da49f6ed9 100644 --- a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java +++ b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java @@ -38,7 +38,7 @@ public final class YodaJediMaster extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another target permanent you own"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new OwnerPredicate(TargetController.YOU)); } diff --git a/Mage.Sets/src/mage/cards/y/YomijiWhoBarsTheWay.java b/Mage.Sets/src/mage/cards/y/YomijiWhoBarsTheWay.java index a9cbc11f613..7834b9820c6 100644 --- a/Mage.Sets/src/mage/cards/y/YomijiWhoBarsTheWay.java +++ b/Mage.Sets/src/mage/cards/y/YomijiWhoBarsTheWay.java @@ -31,7 +31,7 @@ public final class YomijiWhoBarsTheWay extends CardImpl { // Whenever a legendary permanent other than Yomiji, Who Bars the Way is put into a graveyard from the battlefield, return that card to its owner's hand. FilterPermanent filter = new FilterPermanent("a legendary permanent other than " + getName()); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(new SupertypePredicate(SuperType.LEGENDARY)); Effect effect = new ReturnToHandTargetEffect(); effect.setText("return that card to its owner's hand"); diff --git a/Mage.Sets/src/mage/cards/y/YoungPyromancer.java b/Mage.Sets/src/mage/cards/y/YoungPyromancer.java index 6f7b3b631f3..d5e647087f8 100644 --- a/Mage.Sets/src/mage/cards/y/YoungPyromancer.java +++ b/Mage.Sets/src/mage/cards/y/YoungPyromancer.java @@ -1,6 +1,5 @@ package mage.cards.y; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; @@ -11,8 +10,9 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.permanent.token.YoungPyromancerElementalToken; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class YoungPyromancer extends CardImpl { @@ -28,7 +28,7 @@ public final class YoungPyromancer extends CardImpl { // Whenever you cast an instant or sorcery spell, create a 1/1 red Elemental creature token. this.addAbility(new SpellCastControllerTriggeredAbility( new CreateTokenEffect(new YoungPyromancerElementalToken()), - StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false )); } diff --git a/Mage.Sets/src/mage/cards/z/ZadasCommando.java b/Mage.Sets/src/mage/cards/z/ZadasCommando.java index 123eff9f263..ee55962b5f2 100644 --- a/Mage.Sets/src/mage/cards/z/ZadasCommando.java +++ b/Mage.Sets/src/mage/cards/z/ZadasCommando.java @@ -32,7 +32,7 @@ public final class ZadasCommando extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ZadasCommando(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/z/ZahidDjinnOfTheLamp.java b/Mage.Sets/src/mage/cards/z/ZahidDjinnOfTheLamp.java index d621d2d23c6..47144a1ce1d 100644 --- a/Mage.Sets/src/mage/cards/z/ZahidDjinnOfTheLamp.java +++ b/Mage.Sets/src/mage/cards/z/ZahidDjinnOfTheLamp.java @@ -35,7 +35,7 @@ public final class ZahidDjinnOfTheLamp extends CardImpl { AlternativeCostSourceAbility alternativeCostSourceAbility = new AlternativeCostSourceAbility(new ManaCostsImpl("{3}{U}"), null, "You may pay {3}{U} and tap an untapped artifact you control rather than pay this spell's mana cost."); FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent("untapped artifact you control"); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); alternativeCostSourceAbility.addCost(new TapTargetCost(new TargetControlledPermanent(filter))); this.addAbility(alternativeCostSourceAbility); diff --git a/Mage.Sets/src/mage/cards/z/ZedruuTheGreathearted.java b/Mage.Sets/src/mage/cards/z/ZedruuTheGreathearted.java index 88c4dfcd3dc..78c292f791e 100644 --- a/Mage.Sets/src/mage/cards/z/ZedruuTheGreathearted.java +++ b/Mage.Sets/src/mage/cards/z/ZedruuTheGreathearted.java @@ -35,10 +35,10 @@ public final class ZedruuTheGreathearted extends CardImpl { this.toughness = new MageInt(4); // At the beginning of your upkeep, you gain X life and draw X cards, where X is the number of permanents you own that your opponents control. - Effect effect = new GainLifeEffect(new PermanentsYouOwnThatOpponentsControlCount()); + Effect effect = new GainLifeEffect(PermanentsYouOwnThatOpponentsControlCount.instance); effect.setText("you gain X life"); Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, false); - effect = new DrawCardSourceControllerEffect(new PermanentsYouOwnThatOpponentsControlCount()); + effect = new DrawCardSourceControllerEffect(PermanentsYouOwnThatOpponentsControlCount.instance); effect.setText("and draw X cards, where X is the number of permanents you own that your opponents control"); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java b/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java index d373a86a37b..b05e459af56 100644 --- a/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java +++ b/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java @@ -2,14 +2,12 @@ package mage.cards.z; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; -import mage.abilities.effects.keyword.AdaptEffect; +import mage.abilities.keyword.AdaptAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,7 +30,7 @@ public final class ZeganaUtopianSpeaker extends CardImpl { static { filter.add(new CounterPredicate(CounterType.P1P1)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter2.add(new CounterPredicate(CounterType.P1P1)); } @@ -56,9 +54,7 @@ public final class ZeganaUtopianSpeaker extends CardImpl { )); // {4}{G}{U}: Adapt 4. - this.addAbility(new SimpleActivatedAbility( - new AdaptEffect(4), new ManaCostsImpl("{4}{G}{U}") - )); + this.addAbility(new AdaptAbility(4, "{4}{G}{U}")); // Each creature you control with a +1/+1 counter on it has trample. this.addAbility(new SimpleStaticAbility( diff --git a/Mage.Sets/src/mage/cards/z/ZhurTaaGoblin.java b/Mage.Sets/src/mage/cards/z/ZhurTaaGoblin.java new file mode 100644 index 00000000000..79256c778af --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZhurTaaGoblin.java @@ -0,0 +1,37 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.abilities.keyword.RiotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZhurTaaGoblin extends CardImpl { + + public ZhurTaaGoblin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{G}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.BERSERKER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Riot + this.addAbility(new RiotAbility()); + } + + private ZhurTaaGoblin(final ZhurTaaGoblin card) { + super(card); + } + + @Override + public ZhurTaaGoblin copy() { + return new ZhurTaaGoblin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/z/ZombieTrailblazer.java b/Mage.Sets/src/mage/cards/z/ZombieTrailblazer.java index ea75ba5c222..6e8358a7247 100644 --- a/Mage.Sets/src/mage/cards/z/ZombieTrailblazer.java +++ b/Mage.Sets/src/mage/cards/z/ZombieTrailblazer.java @@ -34,7 +34,7 @@ public final class ZombieTrailblazer extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ZOMBIE)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ZombieTrailblazer(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/z/ZulaportChainmage.java b/Mage.Sets/src/mage/cards/z/ZulaportChainmage.java index d18e9b05d01..0ad6f5d0ab2 100644 --- a/Mage.Sets/src/mage/cards/z/ZulaportChainmage.java +++ b/Mage.Sets/src/mage/cards/z/ZulaportChainmage.java @@ -30,7 +30,7 @@ public final class ZulaportChainmage extends CardImpl { static { filter.add(new SubtypePredicate(SubType.ALLY)); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } public ZulaportChainmage(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/sets/GuildsOfRavnica.java b/Mage.Sets/src/mage/sets/GuildsOfRavnica.java index 6cf884943b1..2dcf4088b88 100644 --- a/Mage.Sets/src/mage/sets/GuildsOfRavnica.java +++ b/Mage.Sets/src/mage/sets/GuildsOfRavnica.java @@ -343,4 +343,4 @@ public final class GuildsOfRavnica extends ExpansionSet { } return specialCards; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/Homelands.java b/Mage.Sets/src/mage/sets/Homelands.java index cc54407c643..6705fa8c66e 100644 --- a/Mage.Sets/src/mage/sets/Homelands.java +++ b/Mage.Sets/src/mage/sets/Homelands.java @@ -136,7 +136,8 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Roots", 95, Rarity.UNCOMMON, mage.cards.r.Roots.class)); cards.add(new SetCardInfo("Roterothopter", 109, Rarity.COMMON, mage.cards.r.Roterothopter.class)); cards.add(new SetCardInfo("Rysorian Badger", 96, Rarity.RARE, mage.cards.r.RysorianBadger.class)); - cards.add(new SetCardInfo("Samite Alchemist", 117, Rarity.COMMON, mage.cards.s.SamiteAlchemist.class)); + cards.add(new SetCardInfo("Samite Alchemist", "13a", Rarity.COMMON, mage.cards.s.SamiteAlchemist.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Samite Alchemist", "13b", Rarity.COMMON, mage.cards.s.SamiteAlchemist.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sea Sprite", 38, Rarity.UNCOMMON, mage.cards.s.SeaSprite.class)); cards.add(new SetCardInfo("Sea Troll", 39, Rarity.UNCOMMON, mage.cards.s.SeaTroll.class)); cards.add(new SetCardInfo("Sengir Autocrat", 56, Rarity.UNCOMMON, mage.cards.s.SengirAutocrat.class)); @@ -164,4 +165,4 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Winter Sky", 80, Rarity.RARE, mage.cards.w.WinterSky.class)); cards.add(new SetCardInfo("Wizards' School", 115, Rarity.UNCOMMON, mage.cards.w.WizardsSchool.class)); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index dda83722aa0..fa4f030febe 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -100,6 +100,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Enduring Renewal", 23, Rarity.RARE, mage.cards.e.EnduringRenewal.class)); cards.add(new SetCardInfo("Energy Storm", 24, Rarity.RARE, mage.cards.e.EnergyStorm.class)); cards.add(new SetCardInfo("Enervate", 67, Rarity.COMMON, mage.cards.e.Enervate.class)); + cards.add(new SetCardInfo("Errant Minion", 68, Rarity.COMMON, mage.cards.e.ErrantMinion.class)); cards.add(new SetCardInfo("Errantry", 183, Rarity.COMMON, mage.cards.e.Errantry.class)); cards.add(new SetCardInfo("Essence Filter", 233, Rarity.COMMON, mage.cards.e.EssenceFilter.class)); cards.add(new SetCardInfo("Essence Flare", 69, Rarity.COMMON, mage.cards.e.EssenceFlare.class)); @@ -121,7 +122,9 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Formation", 25, Rarity.RARE, mage.cards.f.Formation.class)); cards.add(new SetCardInfo("Foul Familiar", 126, Rarity.COMMON, mage.cards.f.FoulFamiliar.class)); cards.add(new SetCardInfo("Foxfire", 238, Rarity.COMMON, mage.cards.f.Foxfire.class)); + cards.add(new SetCardInfo("Freyalise Supplicant", 239, Rarity.UNCOMMON, mage.cards.f.FreyaliseSupplicant.class)); cards.add(new SetCardInfo("Freyalise's Charm", 240, Rarity.UNCOMMON, mage.cards.f.FreyalisesCharm.class)); + cards.add(new SetCardInfo("Freyalise's Winds", 241, Rarity.RARE, mage.cards.f.FreyalisesWinds.class)); cards.add(new SetCardInfo("Fumarole", 291, Rarity.UNCOMMON, mage.cards.f.Fumarole.class)); cards.add(new SetCardInfo("Fyndhorn Bow", 318, Rarity.UNCOMMON, mage.cards.f.FyndhornBow.class)); cards.add(new SetCardInfo("Fyndhorn Brownie", 242, Rarity.COMMON, mage.cards.f.FyndhornBrownie.class)); @@ -137,6 +140,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Glacial Chasm", 353, Rarity.UNCOMMON, mage.cards.g.GlacialChasm.class)); cards.add(new SetCardInfo("Glacial Crevasses", 187, Rarity.RARE, mage.cards.g.GlacialCrevasses.class)); cards.add(new SetCardInfo("Glacial Wall", 71, Rarity.UNCOMMON, mage.cards.g.GlacialWall.class)); + cards.add(new SetCardInfo("Glaciers", 294, Rarity.RARE, mage.cards.g.Glaciers.class)); cards.add(new SetCardInfo("Goblin Lyre", 319, Rarity.RARE, mage.cards.g.GoblinLyre.class)); cards.add(new SetCardInfo("Goblin Mutant", 188, Rarity.UNCOMMON, mage.cards.g.GoblinMutant.class)); cards.add(new SetCardInfo("Goblin Snowman", 191, Rarity.UNCOMMON, mage.cards.g.GoblinSnowman.class)); @@ -162,6 +166,8 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Icy Manipulator", 322, Rarity.UNCOMMON, mage.cards.i.IcyManipulator.class)); cards.add(new SetCardInfo("Icy Prison", 74, Rarity.RARE, mage.cards.i.IcyPrison.class)); cards.add(new SetCardInfo("Illusionary Forces", 75, Rarity.COMMON, mage.cards.i.IllusionaryForces.class)); + cards.add(new SetCardInfo("Illusionary Presence", 76, Rarity.RARE, mage.cards.i.IllusionaryPresence.class)); + cards.add(new SetCardInfo("Illusionary Terrain", 77, Rarity.UNCOMMON, mage.cards.i.IllusionaryTerrain.class)); cards.add(new SetCardInfo("Illusionary Wall", 78, Rarity.COMMON, mage.cards.i.IllusionaryWall.class)); cards.add(new SetCardInfo("Illusions of Grandeur", 79, Rarity.RARE, mage.cards.i.IllusionsOfGrandeur.class)); cards.add(new SetCardInfo("Imposing Visage", 193, Rarity.COMMON, mage.cards.i.ImposingVisage.class)); @@ -231,6 +237,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 377, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 378, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mudslide", 204, Rarity.RARE, mage.cards.m.Mudslide.class)); + cards.add(new SetCardInfo("Musician", 85, Rarity.RARE, mage.cards.m.Musician.class)); cards.add(new SetCardInfo("Mystic Might", 86, Rarity.RARE, mage.cards.m.MysticMight.class)); cards.add(new SetCardInfo("Mystic Remora", 87, Rarity.COMMON, mage.cards.m.MysticRemora.class)); cards.add(new SetCardInfo("Nacre Talisman", 329, Rarity.UNCOMMON, mage.cards.n.NacreTalisman.class)); @@ -238,6 +245,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Nature's Lore", 255, Rarity.UNCOMMON, mage.cards.n.NaturesLore.class)); cards.add(new SetCardInfo("Necropotence", 154, Rarity.RARE, mage.cards.n.Necropotence.class)); cards.add(new SetCardInfo("Norritt", 155, Rarity.COMMON, mage.cards.n.Norritt.class)); + cards.add(new SetCardInfo("Oath of Lim-Dul", 156, Rarity.RARE, mage.cards.o.OathOfLimDul.class)); cards.add(new SetCardInfo("Onyx Talisman", 331, Rarity.UNCOMMON, mage.cards.o.OnyxTalisman.class)); cards.add(new SetCardInfo("Orcish Cannoneers", 205, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class)); cards.add(new SetCardInfo("Orcish Healer", 208, Rarity.UNCOMMON, mage.cards.o.OrcishHealer.class)); @@ -250,6 +258,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Panic", 212, Rarity.COMMON, mage.cards.p.Panic.class)); cards.add(new SetCardInfo("Pentagram of the Ages", 332, Rarity.RARE, mage.cards.p.PentagramOfTheAges.class)); cards.add(new SetCardInfo("Pestilence Rats", 157, Rarity.COMMON, mage.cards.p.PestilenceRats.class)); + cards.add(new SetCardInfo("Phantasmal Mount", 88, Rarity.UNCOMMON, mage.cards.p.PhantasmalMount.class)); cards.add(new SetCardInfo("Pit Trap", 333, Rarity.UNCOMMON, mage.cards.p.PitTrap.class)); cards.add(new SetCardInfo("Plains", 364, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 365, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); @@ -287,6 +296,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Silver Erne", 98, Rarity.UNCOMMON, mage.cards.s.SilverErne.class)); cards.add(new SetCardInfo("Skeleton Ship", 301, Rarity.RARE, mage.cards.s.SkeletonShip.class)); cards.add(new SetCardInfo("Skull Catapult", 336, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class)); + cards.add(new SetCardInfo("Snow Devil", 100, Rarity.COMMON, mage.cards.s.SnowDevil.class)); cards.add(new SetCardInfo("Snow Fortress", 337, Rarity.RARE, mage.cards.s.SnowFortress.class)); cards.add(new SetCardInfo("Snow Hound", 53, Rarity.UNCOMMON, mage.cards.s.SnowHound.class)); cards.add(new SetCardInfo("Snow-Covered Forest", 383, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); @@ -304,6 +314,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Spoils of Evil", 163, Rarity.RARE, mage.cards.s.SpoilsOfEvil.class)); cards.add(new SetCardInfo("Staff of the Ages", 340, Rarity.RARE, mage.cards.s.StaffOfTheAges.class)); cards.add(new SetCardInfo("Stampede", 265, Rarity.RARE, mage.cards.s.Stampede.class)); + cards.add(new SetCardInfo("Stench of Evil", 165, Rarity.UNCOMMON, mage.cards.s.StenchOfEvil.class)); cards.add(new SetCardInfo("Stone Rain", 217, Rarity.COMMON, mage.cards.s.StoneRain.class)); cards.add(new SetCardInfo("Stone Spirit", 218, Rarity.UNCOMMON, mage.cards.s.StoneSpirit.class)); cards.add(new SetCardInfo("Stonehands", 219, Rarity.COMMON, mage.cards.s.Stonehands.class)); diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index 134bb3b75cb..f62c528b514 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -70,6 +70,7 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); cards.add(new SetCardInfo("Clergy of the Holy Nimbus", 6, Rarity.COMMON, mage.cards.c.ClergyOfTheHolyNimbus.class)); cards.add(new SetCardInfo("Concordant Crossroads", 179, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); + cards.add(new SetCardInfo("Cocoon", 178, Rarity.UNCOMMON, mage.cards.c.Cocoon.class)); cards.add(new SetCardInfo("Cosmic Horror", 92, Rarity.RARE, mage.cards.c.CosmicHorror.class)); cards.add(new SetCardInfo("Craw Giant", 180, Rarity.UNCOMMON, mage.cards.c.CrawGiant.class)); cards.add(new SetCardInfo("Crevasse", 138, Rarity.UNCOMMON, mage.cards.c.Crevasse.class)); @@ -101,6 +102,7 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Eureka", 185, Rarity.RARE, mage.cards.e.Eureka.class)); cards.add(new SetCardInfo("Evil Eye of Orms-by-Gore", 96, Rarity.UNCOMMON, mage.cards.e.EvilEyeOfOrmsByGore.class)); cards.add(new SetCardInfo("Fallen Angel", 97, Rarity.UNCOMMON, mage.cards.f.FallenAngel.class)); + cards.add(new SetCardInfo("Feint", 146, Rarity.COMMON, mage.cards.f.Feint.class)); cards.add(new SetCardInfo("Field of Dreams", 55, Rarity.RARE, mage.cards.f.FieldOfDreams.class)); cards.add(new SetCardInfo("Fire Sprites", 186, Rarity.COMMON, mage.cards.f.FireSprites.class)); cards.add(new SetCardInfo("Flash Counter", 56, Rarity.COMMON, mage.cards.f.FlashCounter.class)); @@ -114,11 +116,13 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Gaseous Form", 59, Rarity.COMMON, mage.cards.g.GaseousForm.class)); cards.add(new SetCardInfo("Gauntlets of Chaos", 278, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); cards.add(new SetCardInfo("Ghosts of the Damned", 98, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); + cards.add(new SetCardInfo("Giant Slug", 99, Rarity.COMMON, mage.cards.g.GiantSlug.class)); cards.add(new SetCardInfo("Giant Strength", 149, Rarity.COMMON, mage.cards.g.GiantStrength.class)); cards.add(new SetCardInfo("Giant Turtle", 188, Rarity.COMMON, mage.cards.g.GiantTurtle.class)); cards.add(new SetCardInfo("Glyph of Destruction", 150, Rarity.COMMON, mage.cards.g.GlyphOfDestruction.class)); cards.add(new SetCardInfo("Glyph of Doom", 100, Rarity.COMMON, mage.cards.g.GlyphOfDoom.class)); cards.add(new SetCardInfo("Glyph of Life", 15, Rarity.COMMON, mage.cards.g.GlyphOfLife.class)); + cards.add(new SetCardInfo("Glyph of Reincarnation", 189, Rarity.COMMON, mage.cards.g.GlyphOfReincarnation.class)); cards.add(new SetCardInfo("Gosta Dirk", 227, Rarity.RARE, mage.cards.g.GostaDirk.class)); cards.add(new SetCardInfo("Gravity Sphere", 151, Rarity.RARE, mage.cards.g.GravitySphere.class)); cards.add(new SetCardInfo("Great Defender", 16, Rarity.UNCOMMON, mage.cards.g.GreatDefender.class)); @@ -172,6 +176,7 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Land Equilibrium", 64, Rarity.RARE, mage.cards.l.LandEquilibrium.class)); cards.add(new SetCardInfo("Land Tax", 26, Rarity.UNCOMMON, mage.cards.l.LandTax.class)); cards.add(new SetCardInfo("Land's Edge", 158, Rarity.RARE, mage.cards.l.LandsEdge.class)); + cards.add(new SetCardInfo("Lesser Werewolf", 110, Rarity.UNCOMMON, mage.cards.l.LesserWerewolf.class)); cards.add(new SetCardInfo("Life Chisel", 283, Rarity.UNCOMMON, mage.cards.l.LifeChisel.class)); cards.add(new SetCardInfo("Lifeblood", 27, Rarity.RARE, mage.cards.l.Lifeblood.class)); cards.add(new SetCardInfo("Living Plane", 193, Rarity.RARE, mage.cards.l.LivingPlane.class)); @@ -208,6 +213,7 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Princess Lucrezia", 249, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); cards.add(new SetCardInfo("Psionic Entity", 67, Rarity.RARE, mage.cards.p.PsionicEntity.class)); cards.add(new SetCardInfo("Psychic Purge", 68, Rarity.COMMON, mage.cards.p.PsychicPurge.class)); + cards.add(new SetCardInfo("Puppet Master", 69, Rarity.UNCOMMON, mage.cards.p.PuppetMaster.class)); cards.add(new SetCardInfo("Pyrotechnics", 161, Rarity.COMMON, mage.cards.p.Pyrotechnics.class)); cards.add(new SetCardInfo("Quagmire", 115, Rarity.UNCOMMON, mage.cards.q.Quagmire.class)); cards.add(new SetCardInfo("Rabid Wombat", 198, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); @@ -216,6 +222,7 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Ragnar", 250, Rarity.RARE, mage.cards.r.Ragnar.class)); cards.add(new SetCardInfo("Ramirez DePietro", 251, Rarity.UNCOMMON, mage.cards.r.RamirezDePietro.class)); cards.add(new SetCardInfo("Ramses Overdark", 252, Rarity.RARE, mage.cards.r.RamsesOverdark.class)); + cards.add(new SetCardInfo("Rapid Fire", 32, Rarity.RARE, mage.cards.r.RapidFire.class)); cards.add(new SetCardInfo("Rasputin Dreamweaver", 253, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); cards.add(new SetCardInfo("Recall", 70, Rarity.RARE, mage.cards.r.Recall.class)); cards.add(new SetCardInfo("Red Mana Battery", 291, Rarity.UNCOMMON, mage.cards.r.RedManaBattery.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index 932a442fc1a..891cfdbd1f0 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -161,6 +161,7 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Mishra's Groundbreaker", 215, Rarity.UNCOMMON, mage.cards.m.MishrasGroundbreaker.class)); cards.add(new SetCardInfo("Misinformation", 105, Rarity.UNCOMMON, mage.cards.m.Misinformation.class)); cards.add(new SetCardInfo("Mudslide", 136, Rarity.RARE, mage.cards.m.Mudslide.class)); + cards.add(new SetCardInfo("Musician", 56, Rarity.RARE, mage.cards.m.Musician.class)); cards.add(new SetCardInfo("Narwhal", 57, Rarity.UNCOMMON, mage.cards.n.Narwhal.class)); cards.add(new SetCardInfo("Nature's Blessing", 196, Rarity.UNCOMMON, mage.cards.n.NaturesBlessing.class)); cards.add(new SetCardInfo("Nature's Wrath", 172, Rarity.RARE, mage.cards.n.NaturesWrath.class)); @@ -178,6 +179,7 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Panic", 145, Rarity.COMMON, mage.cards.p.Panic.class)); cards.add(new SetCardInfo("Personal Tutor", 58, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); cards.add(new SetCardInfo("Phantasmal Fiend", 108, Rarity.COMMON, mage.cards.p.PhantasmalFiend.class)); + cards.add(new SetCardInfo("Phantasmal Mount", 59, Rarity.COMMON, mage.cards.p.PhantasmalMount.class)); cards.add(new SetCardInfo("Phyrexian Devourer", 216, Rarity.UNCOMMON, mage.cards.p.PhyrexianDevourer.class)); cards.add(new SetCardInfo("Pillage", 146, Rarity.UNCOMMON, mage.cards.p.Pillage.class)); cards.add(new SetCardInfo("Portent", 60, Rarity.COMMON, mage.cards.p.Portent.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionIII.java b/Mage.Sets/src/mage/sets/MastersEditionIII.java index 779517679cf..20f24d901e1 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionIII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionIII.java @@ -1,249 +1,250 @@ - -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * @author LevelX2 - */ -public final class MastersEditionIII extends ExpansionSet { - - private static final MastersEditionIII instance = new MastersEditionIII(); - - public static MastersEditionIII getInstance() { - return instance; - } - - private MastersEditionIII() { - super("Masters Edition III", "ME3", ExpansionSet.buildDate(2009, 9, 7), SetType.MAGIC_ONLINE); - this.hasBasicLands = true; - this.hasBoosters = true; - this.numBoosterLands = 1; - this.numBoosterCommon = 10; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - - cards.add(new SetCardInfo("Active Volcano", 85, Rarity.UNCOMMON, mage.cards.a.ActiveVolcano.class)); - cards.add(new SetCardInfo("Akron Legionnaire", 1, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); - cards.add(new SetCardInfo("Alabaster Potion", 2, Rarity.UNCOMMON, mage.cards.a.AlabasterPotion.class)); - cards.add(new SetCardInfo("All Hallow's Eve", 57, Rarity.RARE, mage.cards.a.AllHallowsEve.class)); - cards.add(new SetCardInfo("Amrou Kithkin", 3, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); - cards.add(new SetCardInfo("Anaba Ancestor", 86, Rarity.COMMON, mage.cards.a.AnabaAncestor.class)); - cards.add(new SetCardInfo("Anaba Spirit Crafter", 87, Rarity.COMMON, mage.cards.a.AnabaSpiritCrafter.class)); - cards.add(new SetCardInfo("Angus Mackenzie", 141, Rarity.RARE, mage.cards.a.AngusMackenzie.class)); - cards.add(new SetCardInfo("Arboria", 113, Rarity.RARE, mage.cards.a.Arboria.class)); - cards.add(new SetCardInfo("Arcades Sabboth", 142, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); - cards.add(new SetCardInfo("Arena of the Ancients", 188, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); - cards.add(new SetCardInfo("Ashes to Ashes", 58, Rarity.UNCOMMON, mage.cards.a.AshesToAshes.class)); - cards.add(new SetCardInfo("Astrolabe", 189, Rarity.COMMON, mage.cards.a.Astrolabe.class)); - cards.add(new SetCardInfo("Axelrod Gunnarson", 143, Rarity.UNCOMMON, mage.cards.a.AxelrodGunnarson.class)); - cards.add(new SetCardInfo("Banshee", 59, Rarity.UNCOMMON, mage.cards.b.Banshee.class)); - cards.add(new SetCardInfo("Barktooth Warbeard", 144, Rarity.COMMON, mage.cards.b.BarktoothWarbeard.class)); - cards.add(new SetCardInfo("Barl's Cage", 190, Rarity.RARE, mage.cards.b.BarlsCage.class)); - cards.add(new SetCardInfo("Bartel Runeaxe", 145, Rarity.UNCOMMON, mage.cards.b.BartelRuneaxe.class)); - cards.add(new SetCardInfo("Bayou", 204, Rarity.RARE, mage.cards.b.Bayou.class)); - cards.add(new SetCardInfo("Bazaar of Baghdad", 205, Rarity.RARE, mage.cards.b.BazaarOfBaghdad.class)); - cards.add(new SetCardInfo("Black Vise", 191, Rarity.RARE, mage.cards.b.BlackVise.class)); - cards.add(new SetCardInfo("Blood Lust", 88, Rarity.COMMON, mage.cards.b.BloodLust.class)); - cards.add(new SetCardInfo("Bone Flute", 192, Rarity.COMMON, mage.cards.b.BoneFlute.class)); - cards.add(new SetCardInfo("Boomerang", 30, Rarity.COMMON, mage.cards.b.Boomerang.class)); - cards.add(new SetCardInfo("Boris Devilboon", 146, Rarity.UNCOMMON, mage.cards.b.BorisDevilboon.class)); - cards.add(new SetCardInfo("Borrowing 100,000 Arrows", 31, Rarity.UNCOMMON, mage.cards.b.Borrowing100000Arrows.class)); - cards.add(new SetCardInfo("Brilliant Plan", 32, Rarity.COMMON, mage.cards.b.BrilliantPlan.class)); - cards.add(new SetCardInfo("Burning of Xinye", 89, Rarity.RARE, mage.cards.b.BurningOfXinye.class)); - cards.add(new SetCardInfo("Call to Arms", 4, Rarity.UNCOMMON, mage.cards.c.CallToArms.class)); - cards.add(new SetCardInfo("Capture of Jingzhou", 33, Rarity.RARE, mage.cards.c.CaptureOfJingzhou.class)); - cards.add(new SetCardInfo("Carrion Ants", 60, Rarity.UNCOMMON, mage.cards.c.CarrionAnts.class)); - cards.add(new SetCardInfo("Chain Lightning", 90, Rarity.COMMON, mage.cards.c.ChainLightning.class)); - cards.add(new SetCardInfo("Chromium", 147, Rarity.RARE, mage.cards.c.Chromium.class)); - cards.add(new SetCardInfo("Cinder Storm", 91, Rarity.UNCOMMON, mage.cards.c.CinderStorm.class)); - cards.add(new SetCardInfo("City of Shadows", 206, Rarity.RARE, mage.cards.c.CityOfShadows.class)); - cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); - cards.add(new SetCardInfo("Coal Golem", 193, Rarity.COMMON, mage.cards.c.CoalGolem.class)); - cards.add(new SetCardInfo("Concordant Crossroads", 114, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); - cards.add(new SetCardInfo("Corrupt Eunuchs", 92, Rarity.UNCOMMON, mage.cards.c.CorruptEunuchs.class)); - cards.add(new SetCardInfo("Cosmic Horror", 61, Rarity.RARE, mage.cards.c.CosmicHorror.class)); - cards.add(new SetCardInfo("Crimson Kobolds", 93, Rarity.COMMON, mage.cards.c.CrimsonKobolds.class)); - cards.add(new SetCardInfo("Crimson Manticore", 94, Rarity.UNCOMMON, mage.cards.c.CrimsonManticore.class)); - cards.add(new SetCardInfo("Dance of Many", 34, Rarity.UNCOMMON, mage.cards.d.DanceOfMany.class)); - cards.add(new SetCardInfo("D'Avenant Archer", 6, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); - cards.add(new SetCardInfo("Demonic Torment", 62, Rarity.COMMON, mage.cards.d.DemonicTorment.class)); - cards.add(new SetCardInfo("Desert Twister", 115, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class)); - cards.add(new SetCardInfo("Desperate Charge", 63, Rarity.COMMON, mage.cards.d.DesperateCharge.class)); - cards.add(new SetCardInfo("Didgeridoo", 194, Rarity.UNCOMMON, mage.cards.d.Didgeridoo.class)); - cards.add(new SetCardInfo("Disenchant", 7, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Disharmony", 95, Rarity.UNCOMMON, mage.cards.d.Disharmony.class)); - cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); - cards.add(new SetCardInfo("Dong Zhou, the Tyrant", 96, Rarity.RARE, mage.cards.d.DongZhouTheTyrant.class)); - cards.add(new SetCardInfo("Eightfold Maze", 9, Rarity.UNCOMMON, mage.cards.e.EightfoldMaze.class)); - cards.add(new SetCardInfo("Elves of Deep Shadow", 116, Rarity.COMMON, mage.cards.e.ElvesOfDeepShadow.class)); - cards.add(new SetCardInfo("Evil Presence", 64, Rarity.COMMON, mage.cards.e.EvilPresence.class)); - cards.add(new SetCardInfo("Exorcist", 10, Rarity.UNCOMMON, mage.cards.e.Exorcist.class)); - cards.add(new SetCardInfo("Faerie Noble", 117, Rarity.UNCOMMON, mage.cards.f.FaerieNoble.class)); - cards.add(new SetCardInfo("False Defeat", 11, Rarity.UNCOMMON, mage.cards.f.FalseDefeat.class)); - cards.add(new SetCardInfo("Famine", 65, Rarity.UNCOMMON, mage.cards.f.Famine.class)); - cards.add(new SetCardInfo("Fellwar Stone", 195, Rarity.COMMON, mage.cards.f.FellwarStone.class)); - cards.add(new SetCardInfo("Fevered Strength", 66, Rarity.COMMON, mage.cards.f.FeveredStrength.class)); - cards.add(new SetCardInfo("Fire Ambush", 97, Rarity.COMMON, mage.cards.f.FireAmbush.class)); - cards.add(new SetCardInfo("Fire Drake", 98, Rarity.COMMON, mage.cards.f.FireDrake.class)); - cards.add(new SetCardInfo("Fire Sprites", 118, Rarity.COMMON, mage.cards.f.FireSprites.class)); - cards.add(new SetCardInfo("Flash Flood", 35, Rarity.UNCOMMON, mage.cards.f.FlashFlood.class)); - cards.add(new SetCardInfo("Forced Retreat", 37, Rarity.COMMON, mage.cards.f.ForcedRetreat.class)); - cards.add(new SetCardInfo("Force Spike", 36, Rarity.COMMON, mage.cards.f.ForceSpike.class)); - cards.add(new SetCardInfo("Forest", 228, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 229, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 230, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Frost Giant", 101, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); - cards.add(new SetCardInfo("Gabriel Angelfire", 148, Rarity.RARE, mage.cards.g.GabrielAngelfire.class)); - cards.add(new SetCardInfo("Gaea's Touch", 120, Rarity.UNCOMMON, mage.cards.g.GaeasTouch.class)); - cards.add(new SetCardInfo("Gauntlets of Chaos", 196, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); - cards.add(new SetCardInfo("Ghostly Visit", 67, Rarity.COMMON, mage.cards.g.GhostlyVisit.class)); - cards.add(new SetCardInfo("Ghosts of the Damned", 68, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); - cards.add(new SetCardInfo("Giant Growth", 121, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); - cards.add(new SetCardInfo("Grim Tutor", 69, Rarity.RARE, mage.cards.g.GrimTutor.class)); - cards.add(new SetCardInfo("Guan Yu's 1,000-Li March", 13, Rarity.RARE, mage.cards.g.GuanYus1000LiMarch.class)); - cards.add(new SetCardInfo("Guan Yu, Sainted Warrior", 12, Rarity.UNCOMMON, mage.cards.g.GuanYuSaintedWarrior.class)); - cards.add(new SetCardInfo("Gwendlyn Di Corci", 149, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); - cards.add(new SetCardInfo("Halfdane", 150, Rarity.RARE, mage.cards.h.Halfdane.class)); - cards.add(new SetCardInfo("Hammerheim", 207, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); - cards.add(new SetCardInfo("Hazezon Tamar", 151, Rarity.RARE, mage.cards.h.HazezonTamar.class)); - cards.add(new SetCardInfo("Heal", 14, Rarity.COMMON, mage.cards.h.Heal.class)); - cards.add(new SetCardInfo("Heavy Fog", 122, Rarity.COMMON, mage.cards.h.HeavyFog.class)); - cards.add(new SetCardInfo("Hellfire", 70, Rarity.RARE, mage.cards.h.Hellfire.class)); - cards.add(new SetCardInfo("Hua Tuo, Honored Physician", 123, Rarity.RARE, mage.cards.h.HuaTuoHonoredPhysician.class)); - cards.add(new SetCardInfo("Hunding Gjornersen", 152, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class)); - cards.add(new SetCardInfo("Hunting Cheetah", 124, Rarity.COMMON, mage.cards.h.HuntingCheetah.class)); - cards.add(new SetCardInfo("Hurloon Minotaur", 102, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class)); - cards.add(new SetCardInfo("Immolation", 103, Rarity.COMMON, mage.cards.i.Immolation.class)); - cards.add(new SetCardInfo("Infuse", 38, Rarity.COMMON, mage.cards.i.Infuse.class)); - cards.add(new SetCardInfo("Island", 219, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 220, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 221, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ivory Guardians", 15, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); - cards.add(new SetCardInfo("Jedit Ojanen", 153, Rarity.COMMON, mage.cards.j.JeditOjanen.class)); - cards.add(new SetCardInfo("Jerrard of the Closed Fist", 154, Rarity.COMMON, mage.cards.j.JerrardOfTheClosedFist.class)); - cards.add(new SetCardInfo("Jungle Lion", 125, Rarity.COMMON, mage.cards.j.JungleLion.class)); - cards.add(new SetCardInfo("Karakas", 208, Rarity.RARE, mage.cards.k.Karakas.class)); - cards.add(new SetCardInfo("Kei Takahashi", 155, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); - cards.add(new SetCardInfo("Killer Bees", 126, Rarity.UNCOMMON, mage.cards.k.KillerBees.class)); - cards.add(new SetCardInfo("Kjeldoran Frostbeast", 156, Rarity.UNCOMMON, mage.cards.k.KjeldoranFrostbeast.class)); - cards.add(new SetCardInfo("Kobold Drill Sergeant", 104, Rarity.UNCOMMON, mage.cards.k.KoboldDrillSergeant.class)); - cards.add(new SetCardInfo("Kobold Overlord", 105, Rarity.UNCOMMON, mage.cards.k.KoboldOverlord.class)); - cards.add(new SetCardInfo("Kobolds of Kher Keep", 107, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); - cards.add(new SetCardInfo("Kobold Taskmaster", 106, Rarity.COMMON, mage.cards.k.KoboldTaskmaster.class)); - cards.add(new SetCardInfo("Kongming, 'Sleeping Dragon'", 16, Rarity.RARE, mage.cards.k.KongmingSleepingDragon.class)); - cards.add(new SetCardInfo("Labyrinth Minotaur", 39, Rarity.COMMON, mage.cards.l.LabyrinthMinotaur.class)); - cards.add(new SetCardInfo("Lady Caleria", 157, Rarity.UNCOMMON, mage.cards.l.LadyCaleria.class)); - cards.add(new SetCardInfo("Lady Evangela", 158, Rarity.UNCOMMON, mage.cards.l.LadyEvangela.class)); - cards.add(new SetCardInfo("Lady Orca", 159, Rarity.COMMON, mage.cards.l.LadyOrca.class)); - cards.add(new SetCardInfo("Land Equilibrium", 40, Rarity.RARE, mage.cards.l.LandEquilibrium.class)); - cards.add(new SetCardInfo("Land Tax", 17, Rarity.RARE, mage.cards.l.LandTax.class)); - cards.add(new SetCardInfo("Life Chisel", 199, Rarity.RARE, mage.cards.l.LifeChisel.class)); - cards.add(new SetCardInfo("Lightning Blow", 18, Rarity.COMMON, mage.cards.l.LightningBlow.class)); - cards.add(new SetCardInfo("Liu Bei, Lord of Shu", 19, Rarity.RARE, mage.cards.l.LiuBeiLordOfShu.class)); - cards.add(new SetCardInfo("Living Plane", 127, Rarity.RARE, mage.cards.l.LivingPlane.class)); - cards.add(new SetCardInfo("Livonya Silone", 160, Rarity.UNCOMMON, mage.cards.l.LivonyaSilone.class)); - cards.add(new SetCardInfo("Loyal Retainers", 20, Rarity.UNCOMMON, mage.cards.l.LoyalRetainers.class)); - cards.add(new SetCardInfo("Lu Bu, Master-at-Arms", 108, Rarity.RARE, mage.cards.l.LuBuMasterAtArms.class)); - cards.add(new SetCardInfo("Lu Meng, Wu General", 41, Rarity.UNCOMMON, mage.cards.l.LuMengWuGeneral.class)); - cards.add(new SetCardInfo("Lu Xun, Scholar General", 42, Rarity.UNCOMMON, mage.cards.l.LuXunScholarGeneral.class)); - cards.add(new SetCardInfo("Mana Drain", 43, Rarity.RARE, mage.cards.m.ManaDrain.class)); - cards.add(new SetCardInfo("Mana Vortex", 44, Rarity.RARE, mage.cards.m.ManaVortex.class)); - cards.add(new SetCardInfo("Marhault Elsdragon", 161, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); - cards.add(new SetCardInfo("Meng Huo, Barbarian King", 128, Rarity.RARE, mage.cards.m.MengHuoBarbarianKing.class)); - cards.add(new SetCardInfo("Meng Huo's Horde", 129, Rarity.COMMON, mage.cards.m.MengHuosHorde.class)); - cards.add(new SetCardInfo("Mind Twist", 72, Rarity.RARE, mage.cards.m.MindTwist.class)); - cards.add(new SetCardInfo("Misfortune's Gain", 21, Rarity.COMMON, mage.cards.m.MisfortunesGain.class)); - cards.add(new SetCardInfo("Mountain", 225, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 226, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 227, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Nebuchadnezzar", 162, Rarity.UNCOMMON, mage.cards.n.Nebuchadnezzar.class)); - cards.add(new SetCardInfo("Nether Void", 73, Rarity.RARE, mage.cards.n.NetherVoid.class)); - cards.add(new SetCardInfo("Nicol Bolas", 163, Rarity.RARE, mage.cards.n.NicolBolas.class)); - cards.add(new SetCardInfo("Nova Pentacle", 200, Rarity.RARE, mage.cards.n.NovaPentacle.class)); - cards.add(new SetCardInfo("Old Man of the Sea", 45, Rarity.RARE, mage.cards.o.OldManOfTheSea.class)); - cards.add(new SetCardInfo("Palladia-Mors", 164, Rarity.RARE, mage.cards.p.PalladiaMors.class)); - cards.add(new SetCardInfo("Pavel Maliki", 165, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); - cards.add(new SetCardInfo("Peach Garden Oath", 22, Rarity.COMMON, mage.cards.p.PeachGardenOath.class)); - cards.add(new SetCardInfo("Plains", 216, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 217, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 218, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plateau", 209, Rarity.RARE, mage.cards.p.Plateau.class)); - cards.add(new SetCardInfo("Princess Lucrezia", 166, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); - cards.add(new SetCardInfo("Raging Minotaur", 109, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); - cards.add(new SetCardInfo("Ragnar", 167, Rarity.UNCOMMON, mage.cards.r.Ragnar.class)); - cards.add(new SetCardInfo("Ramirez DePietro", 168, Rarity.COMMON, mage.cards.r.RamirezDePietro.class)); - cards.add(new SetCardInfo("Ramses Overdark", 169, Rarity.UNCOMMON, mage.cards.r.RamsesOverdark.class)); - cards.add(new SetCardInfo("Rasputin Dreamweaver", 170, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); - cards.add(new SetCardInfo("Recall", 46, Rarity.UNCOMMON, mage.cards.r.Recall.class)); - cards.add(new SetCardInfo("Reincarnation", 130, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); - cards.add(new SetCardInfo("Remove Soul", 47, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); - cards.add(new SetCardInfo("Reset", 48, Rarity.RARE, mage.cards.r.Reset.class)); - cards.add(new SetCardInfo("Reveka, Wizard Savant", 49, Rarity.UNCOMMON, mage.cards.r.RevekaWizardSavant.class)); - cards.add(new SetCardInfo("Riding the Dilu Horse", 131, Rarity.UNCOMMON, mage.cards.r.RidingTheDiluHorse.class)); - cards.add(new SetCardInfo("Riven Turnbull", 171, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); - cards.add(new SetCardInfo("Rohgahh of Kher Keep", 172, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); - cards.add(new SetCardInfo("Rolling Earthquake", 110, Rarity.RARE, mage.cards.r.RollingEarthquake.class)); - cards.add(new SetCardInfo("Rubinia Soulsinger", 173, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); - cards.add(new SetCardInfo("Scrubland", 210, Rarity.RARE, mage.cards.s.Scrubland.class)); - cards.add(new SetCardInfo("Scryb Sprites", 132, Rarity.COMMON, mage.cards.s.ScrybSprites.class)); - cards.add(new SetCardInfo("Shu Cavalry", 23, Rarity.COMMON, mage.cards.s.ShuCavalry.class)); - cards.add(new SetCardInfo("Shu Elite Companions", 24, Rarity.COMMON, mage.cards.s.ShuEliteCompanions.class)); - cards.add(new SetCardInfo("Shu General", 25, Rarity.COMMON, mage.cards.s.ShuGeneral.class)); - cards.add(new SetCardInfo("Shu Soldier-Farmers", 26, Rarity.COMMON, mage.cards.s.ShuSoldierFarmers.class)); - cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 174, Rarity.COMMON, mage.cards.s.SirShandlarOfEberyn.class)); - cards.add(new SetCardInfo("Sivitri Scarzam", 175, Rarity.COMMON, mage.cards.s.SivitriScarzam.class)); - cards.add(new SetCardInfo("Slashing Tiger", 133, Rarity.COMMON, mage.cards.s.SlashingTiger.class)); - cards.add(new SetCardInfo("Sol Grail", 201, Rarity.COMMON, mage.cards.s.SolGrail.class)); - cards.add(new SetCardInfo("Sorrow's Path", 211, Rarity.RARE, mage.cards.s.SorrowsPath.class)); - cards.add(new SetCardInfo("Spirit Shackle", 74, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); - cards.add(new SetCardInfo("Spoils of Victory", 134, Rarity.COMMON, mage.cards.s.SpoilsOfVictory.class)); - cards.add(new SetCardInfo("Stangg", 177, Rarity.UNCOMMON, mage.cards.s.Stangg.class)); - cards.add(new SetCardInfo("Stolen Grain", 75, Rarity.UNCOMMON, mage.cards.s.StolenGrain.class)); - cards.add(new SetCardInfo("Storm World", 111, Rarity.RARE, mage.cards.s.StormWorld.class)); - cards.add(new SetCardInfo("Strategic Planning", 51, Rarity.COMMON, mage.cards.s.StrategicPlanning.class)); - cards.add(new SetCardInfo("Sunastian Falconer", 178, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); - cards.add(new SetCardInfo("Sun Ce, Young Conquerer", 52, Rarity.UNCOMMON, mage.cards.s.SunCeYoungConquerer.class)); - cards.add(new SetCardInfo("Sun Quan, Lord of Wu", 53, Rarity.RARE, mage.cards.s.SunQuanLordOfWu.class)); - cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 223, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 224, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sword of the Ages", 202, Rarity.RARE, mage.cards.s.SwordOfTheAges.class)); - cards.add(new SetCardInfo("Tetsuo Umezawa", 179, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); - cards.add(new SetCardInfo("The Abyss", 77, Rarity.RARE, mage.cards.t.TheAbyss.class)); - cards.add(new SetCardInfo("The Lady of the Mountain", 180, Rarity.COMMON, mage.cards.t.TheLadyOfTheMountain.class)); - cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 212, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); - cards.add(new SetCardInfo("The Wretched", 78, Rarity.UNCOMMON, mage.cards.t.TheWretched.class)); - cards.add(new SetCardInfo("Three Visits", 135, Rarity.COMMON, mage.cards.t.ThreeVisits.class)); - cards.add(new SetCardInfo("Tobias Andrion", 181, Rarity.COMMON, mage.cards.t.TobiasAndrion.class)); - cards.add(new SetCardInfo("Torsten Von Ursus", 183, Rarity.COMMON, mage.cards.t.TorstenVonUrsus.class)); - cards.add(new SetCardInfo("Tor Wauki", 182, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); - cards.add(new SetCardInfo("Tracker", 136, Rarity.UNCOMMON, mage.cards.t.Tracker.class)); - cards.add(new SetCardInfo("Trip Wire", 137, Rarity.COMMON, mage.cards.t.TripWire.class)); - cards.add(new SetCardInfo("Tropical Island", 213, Rarity.RARE, mage.cards.t.TropicalIsland.class)); - cards.add(new SetCardInfo("Tuknir Deathlock", 184, Rarity.UNCOMMON, mage.cards.t.TuknirDeathlock.class)); - cards.add(new SetCardInfo("Urborg", 214, Rarity.UNCOMMON, mage.cards.u.Urborg.class)); - cards.add(new SetCardInfo("Vaevictis Asmadi", 185, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); - cards.add(new SetCardInfo("Volcanic Island", 215, Rarity.RARE, mage.cards.v.VolcanicIsland.class)); - cards.add(new SetCardInfo("Wall of Light", 27, Rarity.COMMON, mage.cards.w.WallOfLight.class)); - cards.add(new SetCardInfo("Wandering Mage", 186, Rarity.RARE, mage.cards.w.WanderingMage.class)); - cards.add(new SetCardInfo("Wei Elite Companions", 79, Rarity.COMMON, mage.cards.w.WeiEliteCompanions.class)); - cards.add(new SetCardInfo("Wei Infantry", 80, Rarity.COMMON, mage.cards.w.WeiInfantry.class)); - cards.add(new SetCardInfo("Wei Night Raiders", 81, Rarity.UNCOMMON, mage.cards.w.WeiNightRaiders.class)); - cards.add(new SetCardInfo("Wei Strike Force", 82, Rarity.COMMON, mage.cards.w.WeiStrikeForce.class)); - cards.add(new SetCardInfo("Willow Priestess", 138, Rarity.UNCOMMON, mage.cards.w.WillowPriestess.class)); - cards.add(new SetCardInfo("Willow Satyr", 139, Rarity.RARE, mage.cards.w.WillowSatyr.class)); - cards.add(new SetCardInfo("Wormwood Treefolk", 140, Rarity.UNCOMMON, mage.cards.w.WormwoodTreefolk.class)); - cards.add(new SetCardInfo("Wu Elite Cavalry", 54, Rarity.COMMON, mage.cards.w.WuEliteCavalry.class)); - cards.add(new SetCardInfo("Wu Longbowman", 55, Rarity.COMMON, mage.cards.w.WuLongbowman.class)); - cards.add(new SetCardInfo("Wu Warship", 56, Rarity.COMMON, mage.cards.w.WuWarship.class)); - cards.add(new SetCardInfo("Xiahou Dun, the One-Eyed", 83, Rarity.UNCOMMON, mage.cards.x.XiahouDunTheOneEyed.class)); - cards.add(new SetCardInfo("Xira Arien", 187, Rarity.RARE, mage.cards.x.XiraArien.class)); - cards.add(new SetCardInfo("Young Wei Recruits", 84, Rarity.COMMON, mage.cards.y.YoungWeiRecruits.class)); - cards.add(new SetCardInfo("Zhang Fei, Fierce Warrior", 28, Rarity.UNCOMMON, mage.cards.z.ZhangFeiFierceWarrior.class)); - cards.add(new SetCardInfo("Zodiac Dragon", 112, Rarity.RARE, mage.cards.z.ZodiacDragon.class)); - } + +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author LevelX2 + */ +public final class MastersEditionIII extends ExpansionSet { + + private static final MastersEditionIII instance = new MastersEditionIII(); + + public static MastersEditionIII getInstance() { + return instance; + } + + private MastersEditionIII() { + super("Masters Edition III", "ME3", ExpansionSet.buildDate(2009, 9, 7), SetType.MAGIC_ONLINE); + this.hasBasicLands = true; + this.hasBoosters = true; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + + cards.add(new SetCardInfo("Active Volcano", 85, Rarity.UNCOMMON, mage.cards.a.ActiveVolcano.class)); + cards.add(new SetCardInfo("Akron Legionnaire", 1, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); + cards.add(new SetCardInfo("Alabaster Potion", 2, Rarity.UNCOMMON, mage.cards.a.AlabasterPotion.class)); + cards.add(new SetCardInfo("All Hallow's Eve", 57, Rarity.RARE, mage.cards.a.AllHallowsEve.class)); + cards.add(new SetCardInfo("Amrou Kithkin", 3, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); + cards.add(new SetCardInfo("Anaba Ancestor", 86, Rarity.COMMON, mage.cards.a.AnabaAncestor.class)); + cards.add(new SetCardInfo("Anaba Spirit Crafter", 87, Rarity.COMMON, mage.cards.a.AnabaSpiritCrafter.class)); + cards.add(new SetCardInfo("Angus Mackenzie", 141, Rarity.RARE, mage.cards.a.AngusMackenzie.class)); + cards.add(new SetCardInfo("Arboria", 113, Rarity.RARE, mage.cards.a.Arboria.class)); + cards.add(new SetCardInfo("Arcades Sabboth", 142, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); + cards.add(new SetCardInfo("Arena of the Ancients", 188, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); + cards.add(new SetCardInfo("Ashes to Ashes", 58, Rarity.UNCOMMON, mage.cards.a.AshesToAshes.class)); + cards.add(new SetCardInfo("Astrolabe", 189, Rarity.COMMON, mage.cards.a.Astrolabe.class)); + cards.add(new SetCardInfo("Axelrod Gunnarson", 143, Rarity.UNCOMMON, mage.cards.a.AxelrodGunnarson.class)); + cards.add(new SetCardInfo("Banshee", 59, Rarity.UNCOMMON, mage.cards.b.Banshee.class)); + cards.add(new SetCardInfo("Barktooth Warbeard", 144, Rarity.COMMON, mage.cards.b.BarktoothWarbeard.class)); + cards.add(new SetCardInfo("Barl's Cage", 190, Rarity.RARE, mage.cards.b.BarlsCage.class)); + cards.add(new SetCardInfo("Bartel Runeaxe", 145, Rarity.UNCOMMON, mage.cards.b.BartelRuneaxe.class)); + cards.add(new SetCardInfo("Bayou", 204, Rarity.RARE, mage.cards.b.Bayou.class)); + cards.add(new SetCardInfo("Bazaar of Baghdad", 205, Rarity.RARE, mage.cards.b.BazaarOfBaghdad.class)); + cards.add(new SetCardInfo("Black Vise", 191, Rarity.RARE, mage.cards.b.BlackVise.class)); + cards.add(new SetCardInfo("Blood Lust", 88, Rarity.COMMON, mage.cards.b.BloodLust.class)); + cards.add(new SetCardInfo("Bone Flute", 192, Rarity.COMMON, mage.cards.b.BoneFlute.class)); + cards.add(new SetCardInfo("Boomerang", 30, Rarity.COMMON, mage.cards.b.Boomerang.class)); + cards.add(new SetCardInfo("Boris Devilboon", 146, Rarity.UNCOMMON, mage.cards.b.BorisDevilboon.class)); + cards.add(new SetCardInfo("Borrowing 100,000 Arrows", 31, Rarity.UNCOMMON, mage.cards.b.Borrowing100000Arrows.class)); + cards.add(new SetCardInfo("Brilliant Plan", 32, Rarity.COMMON, mage.cards.b.BrilliantPlan.class)); + cards.add(new SetCardInfo("Burning of Xinye", 89, Rarity.RARE, mage.cards.b.BurningOfXinye.class)); + cards.add(new SetCardInfo("Call to Arms", 4, Rarity.UNCOMMON, mage.cards.c.CallToArms.class)); + cards.add(new SetCardInfo("Capture of Jingzhou", 33, Rarity.RARE, mage.cards.c.CaptureOfJingzhou.class)); + cards.add(new SetCardInfo("Carrion Ants", 60, Rarity.UNCOMMON, mage.cards.c.CarrionAnts.class)); + cards.add(new SetCardInfo("Chain Lightning", 90, Rarity.COMMON, mage.cards.c.ChainLightning.class)); + cards.add(new SetCardInfo("Chromium", 147, Rarity.RARE, mage.cards.c.Chromium.class)); + cards.add(new SetCardInfo("Cinder Storm", 91, Rarity.UNCOMMON, mage.cards.c.CinderStorm.class)); + cards.add(new SetCardInfo("City of Shadows", 206, Rarity.RARE, mage.cards.c.CityOfShadows.class)); + cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); + cards.add(new SetCardInfo("Coal Golem", 193, Rarity.COMMON, mage.cards.c.CoalGolem.class)); + cards.add(new SetCardInfo("Concordant Crossroads", 114, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); + cards.add(new SetCardInfo("Corrupt Eunuchs", 92, Rarity.UNCOMMON, mage.cards.c.CorruptEunuchs.class)); + cards.add(new SetCardInfo("Cosmic Horror", 61, Rarity.RARE, mage.cards.c.CosmicHorror.class)); + cards.add(new SetCardInfo("Crimson Kobolds", 93, Rarity.COMMON, mage.cards.c.CrimsonKobolds.class)); + cards.add(new SetCardInfo("Crimson Manticore", 94, Rarity.UNCOMMON, mage.cards.c.CrimsonManticore.class)); + cards.add(new SetCardInfo("Dance of Many", 34, Rarity.UNCOMMON, mage.cards.d.DanceOfMany.class)); + cards.add(new SetCardInfo("D'Avenant Archer", 6, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); + cards.add(new SetCardInfo("Demonic Torment", 62, Rarity.COMMON, mage.cards.d.DemonicTorment.class)); + cards.add(new SetCardInfo("Desert Twister", 115, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class)); + cards.add(new SetCardInfo("Desperate Charge", 63, Rarity.COMMON, mage.cards.d.DesperateCharge.class)); + cards.add(new SetCardInfo("Didgeridoo", 194, Rarity.UNCOMMON, mage.cards.d.Didgeridoo.class)); + cards.add(new SetCardInfo("Disenchant", 7, Rarity.COMMON, mage.cards.d.Disenchant.class)); + cards.add(new SetCardInfo("Disharmony", 95, Rarity.UNCOMMON, mage.cards.d.Disharmony.class)); + cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); + cards.add(new SetCardInfo("Dong Zhou, the Tyrant", 96, Rarity.RARE, mage.cards.d.DongZhouTheTyrant.class)); + cards.add(new SetCardInfo("Eightfold Maze", 9, Rarity.UNCOMMON, mage.cards.e.EightfoldMaze.class)); + cards.add(new SetCardInfo("Elves of Deep Shadow", 116, Rarity.COMMON, mage.cards.e.ElvesOfDeepShadow.class)); + cards.add(new SetCardInfo("Evil Presence", 64, Rarity.COMMON, mage.cards.e.EvilPresence.class)); + cards.add(new SetCardInfo("Exorcist", 10, Rarity.UNCOMMON, mage.cards.e.Exorcist.class)); + cards.add(new SetCardInfo("Faerie Noble", 117, Rarity.UNCOMMON, mage.cards.f.FaerieNoble.class)); + cards.add(new SetCardInfo("False Defeat", 11, Rarity.UNCOMMON, mage.cards.f.FalseDefeat.class)); + cards.add(new SetCardInfo("Famine", 65, Rarity.UNCOMMON, mage.cards.f.Famine.class)); + cards.add(new SetCardInfo("Fellwar Stone", 195, Rarity.COMMON, mage.cards.f.FellwarStone.class)); + cards.add(new SetCardInfo("Fevered Strength", 66, Rarity.COMMON, mage.cards.f.FeveredStrength.class)); + cards.add(new SetCardInfo("Fire Ambush", 97, Rarity.COMMON, mage.cards.f.FireAmbush.class)); + cards.add(new SetCardInfo("Fire Drake", 98, Rarity.COMMON, mage.cards.f.FireDrake.class)); + cards.add(new SetCardInfo("Fire Sprites", 118, Rarity.COMMON, mage.cards.f.FireSprites.class)); + cards.add(new SetCardInfo("Flash Flood", 35, Rarity.UNCOMMON, mage.cards.f.FlashFlood.class)); + cards.add(new SetCardInfo("Forced Retreat", 37, Rarity.COMMON, mage.cards.f.ForcedRetreat.class)); + cards.add(new SetCardInfo("Force Spike", 36, Rarity.COMMON, mage.cards.f.ForceSpike.class)); + cards.add(new SetCardInfo("Forest", 228, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 229, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 230, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Freyalise's Winds", 119, Rarity.RARE, mage.cards.f.FreyalisesWinds.class)); + cards.add(new SetCardInfo("Frost Giant", 101, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); + cards.add(new SetCardInfo("Gabriel Angelfire", 148, Rarity.RARE, mage.cards.g.GabrielAngelfire.class)); + cards.add(new SetCardInfo("Gaea's Touch", 120, Rarity.UNCOMMON, mage.cards.g.GaeasTouch.class)); + cards.add(new SetCardInfo("Gauntlets of Chaos", 196, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); + cards.add(new SetCardInfo("Ghostly Visit", 67, Rarity.COMMON, mage.cards.g.GhostlyVisit.class)); + cards.add(new SetCardInfo("Ghosts of the Damned", 68, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); + cards.add(new SetCardInfo("Giant Growth", 121, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); + cards.add(new SetCardInfo("Grim Tutor", 69, Rarity.RARE, mage.cards.g.GrimTutor.class)); + cards.add(new SetCardInfo("Guan Yu's 1,000-Li March", 13, Rarity.RARE, mage.cards.g.GuanYus1000LiMarch.class)); + cards.add(new SetCardInfo("Guan Yu, Sainted Warrior", 12, Rarity.UNCOMMON, mage.cards.g.GuanYuSaintedWarrior.class)); + cards.add(new SetCardInfo("Gwendlyn Di Corci", 149, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); + cards.add(new SetCardInfo("Halfdane", 150, Rarity.RARE, mage.cards.h.Halfdane.class)); + cards.add(new SetCardInfo("Hammerheim", 207, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); + cards.add(new SetCardInfo("Hazezon Tamar", 151, Rarity.RARE, mage.cards.h.HazezonTamar.class)); + cards.add(new SetCardInfo("Heal", 14, Rarity.COMMON, mage.cards.h.Heal.class)); + cards.add(new SetCardInfo("Heavy Fog", 122, Rarity.COMMON, mage.cards.h.HeavyFog.class)); + cards.add(new SetCardInfo("Hellfire", 70, Rarity.RARE, mage.cards.h.Hellfire.class)); + cards.add(new SetCardInfo("Hua Tuo, Honored Physician", 123, Rarity.RARE, mage.cards.h.HuaTuoHonoredPhysician.class)); + cards.add(new SetCardInfo("Hunding Gjornersen", 152, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class)); + cards.add(new SetCardInfo("Hunting Cheetah", 124, Rarity.COMMON, mage.cards.h.HuntingCheetah.class)); + cards.add(new SetCardInfo("Hurloon Minotaur", 102, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class)); + cards.add(new SetCardInfo("Immolation", 103, Rarity.COMMON, mage.cards.i.Immolation.class)); + cards.add(new SetCardInfo("Infuse", 38, Rarity.COMMON, mage.cards.i.Infuse.class)); + cards.add(new SetCardInfo("Island", 219, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 220, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 221, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ivory Guardians", 15, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); + cards.add(new SetCardInfo("Jedit Ojanen", 153, Rarity.COMMON, mage.cards.j.JeditOjanen.class)); + cards.add(new SetCardInfo("Jerrard of the Closed Fist", 154, Rarity.COMMON, mage.cards.j.JerrardOfTheClosedFist.class)); + cards.add(new SetCardInfo("Jungle Lion", 125, Rarity.COMMON, mage.cards.j.JungleLion.class)); + cards.add(new SetCardInfo("Karakas", 208, Rarity.RARE, mage.cards.k.Karakas.class)); + cards.add(new SetCardInfo("Kei Takahashi", 155, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); + cards.add(new SetCardInfo("Killer Bees", 126, Rarity.UNCOMMON, mage.cards.k.KillerBees.class)); + cards.add(new SetCardInfo("Kjeldoran Frostbeast", 156, Rarity.UNCOMMON, mage.cards.k.KjeldoranFrostbeast.class)); + cards.add(new SetCardInfo("Kobold Drill Sergeant", 104, Rarity.UNCOMMON, mage.cards.k.KoboldDrillSergeant.class)); + cards.add(new SetCardInfo("Kobold Overlord", 105, Rarity.UNCOMMON, mage.cards.k.KoboldOverlord.class)); + cards.add(new SetCardInfo("Kobolds of Kher Keep", 107, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); + cards.add(new SetCardInfo("Kobold Taskmaster", 106, Rarity.COMMON, mage.cards.k.KoboldTaskmaster.class)); + cards.add(new SetCardInfo("Kongming, 'Sleeping Dragon'", 16, Rarity.RARE, mage.cards.k.KongmingSleepingDragon.class)); + cards.add(new SetCardInfo("Labyrinth Minotaur", 39, Rarity.COMMON, mage.cards.l.LabyrinthMinotaur.class)); + cards.add(new SetCardInfo("Lady Caleria", 157, Rarity.UNCOMMON, mage.cards.l.LadyCaleria.class)); + cards.add(new SetCardInfo("Lady Evangela", 158, Rarity.UNCOMMON, mage.cards.l.LadyEvangela.class)); + cards.add(new SetCardInfo("Lady Orca", 159, Rarity.COMMON, mage.cards.l.LadyOrca.class)); + cards.add(new SetCardInfo("Land Equilibrium", 40, Rarity.RARE, mage.cards.l.LandEquilibrium.class)); + cards.add(new SetCardInfo("Land Tax", 17, Rarity.RARE, mage.cards.l.LandTax.class)); + cards.add(new SetCardInfo("Life Chisel", 199, Rarity.RARE, mage.cards.l.LifeChisel.class)); + cards.add(new SetCardInfo("Lightning Blow", 18, Rarity.COMMON, mage.cards.l.LightningBlow.class)); + cards.add(new SetCardInfo("Liu Bei, Lord of Shu", 19, Rarity.RARE, mage.cards.l.LiuBeiLordOfShu.class)); + cards.add(new SetCardInfo("Living Plane", 127, Rarity.RARE, mage.cards.l.LivingPlane.class)); + cards.add(new SetCardInfo("Livonya Silone", 160, Rarity.UNCOMMON, mage.cards.l.LivonyaSilone.class)); + cards.add(new SetCardInfo("Loyal Retainers", 20, Rarity.UNCOMMON, mage.cards.l.LoyalRetainers.class)); + cards.add(new SetCardInfo("Lu Bu, Master-at-Arms", 108, Rarity.RARE, mage.cards.l.LuBuMasterAtArms.class)); + cards.add(new SetCardInfo("Lu Meng, Wu General", 41, Rarity.UNCOMMON, mage.cards.l.LuMengWuGeneral.class)); + cards.add(new SetCardInfo("Lu Xun, Scholar General", 42, Rarity.UNCOMMON, mage.cards.l.LuXunScholarGeneral.class)); + cards.add(new SetCardInfo("Mana Drain", 43, Rarity.RARE, mage.cards.m.ManaDrain.class)); + cards.add(new SetCardInfo("Mana Vortex", 44, Rarity.RARE, mage.cards.m.ManaVortex.class)); + cards.add(new SetCardInfo("Marhault Elsdragon", 161, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); + cards.add(new SetCardInfo("Meng Huo, Barbarian King", 128, Rarity.RARE, mage.cards.m.MengHuoBarbarianKing.class)); + cards.add(new SetCardInfo("Meng Huo's Horde", 129, Rarity.COMMON, mage.cards.m.MengHuosHorde.class)); + cards.add(new SetCardInfo("Mind Twist", 72, Rarity.RARE, mage.cards.m.MindTwist.class)); + cards.add(new SetCardInfo("Misfortune's Gain", 21, Rarity.COMMON, mage.cards.m.MisfortunesGain.class)); + cards.add(new SetCardInfo("Mountain", 225, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 226, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 227, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nebuchadnezzar", 162, Rarity.UNCOMMON, mage.cards.n.Nebuchadnezzar.class)); + cards.add(new SetCardInfo("Nether Void", 73, Rarity.RARE, mage.cards.n.NetherVoid.class)); + cards.add(new SetCardInfo("Nicol Bolas", 163, Rarity.RARE, mage.cards.n.NicolBolas.class)); + cards.add(new SetCardInfo("Nova Pentacle", 200, Rarity.RARE, mage.cards.n.NovaPentacle.class)); + cards.add(new SetCardInfo("Old Man of the Sea", 45, Rarity.RARE, mage.cards.o.OldManOfTheSea.class)); + cards.add(new SetCardInfo("Palladia-Mors", 164, Rarity.RARE, mage.cards.p.PalladiaMors.class)); + cards.add(new SetCardInfo("Pavel Maliki", 165, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); + cards.add(new SetCardInfo("Peach Garden Oath", 22, Rarity.COMMON, mage.cards.p.PeachGardenOath.class)); + cards.add(new SetCardInfo("Plains", 216, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 217, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 218, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plateau", 209, Rarity.RARE, mage.cards.p.Plateau.class)); + cards.add(new SetCardInfo("Princess Lucrezia", 166, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); + cards.add(new SetCardInfo("Raging Minotaur", 109, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); + cards.add(new SetCardInfo("Ragnar", 167, Rarity.UNCOMMON, mage.cards.r.Ragnar.class)); + cards.add(new SetCardInfo("Ramirez DePietro", 168, Rarity.COMMON, mage.cards.r.RamirezDePietro.class)); + cards.add(new SetCardInfo("Ramses Overdark", 169, Rarity.UNCOMMON, mage.cards.r.RamsesOverdark.class)); + cards.add(new SetCardInfo("Rasputin Dreamweaver", 170, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); + cards.add(new SetCardInfo("Recall", 46, Rarity.UNCOMMON, mage.cards.r.Recall.class)); + cards.add(new SetCardInfo("Reincarnation", 130, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); + cards.add(new SetCardInfo("Remove Soul", 47, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); + cards.add(new SetCardInfo("Reset", 48, Rarity.RARE, mage.cards.r.Reset.class)); + cards.add(new SetCardInfo("Reveka, Wizard Savant", 49, Rarity.UNCOMMON, mage.cards.r.RevekaWizardSavant.class)); + cards.add(new SetCardInfo("Riding the Dilu Horse", 131, Rarity.UNCOMMON, mage.cards.r.RidingTheDiluHorse.class)); + cards.add(new SetCardInfo("Riven Turnbull", 171, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); + cards.add(new SetCardInfo("Rohgahh of Kher Keep", 172, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); + cards.add(new SetCardInfo("Rolling Earthquake", 110, Rarity.RARE, mage.cards.r.RollingEarthquake.class)); + cards.add(new SetCardInfo("Rubinia Soulsinger", 173, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); + cards.add(new SetCardInfo("Scrubland", 210, Rarity.RARE, mage.cards.s.Scrubland.class)); + cards.add(new SetCardInfo("Scryb Sprites", 132, Rarity.COMMON, mage.cards.s.ScrybSprites.class)); + cards.add(new SetCardInfo("Shu Cavalry", 23, Rarity.COMMON, mage.cards.s.ShuCavalry.class)); + cards.add(new SetCardInfo("Shu Elite Companions", 24, Rarity.COMMON, mage.cards.s.ShuEliteCompanions.class)); + cards.add(new SetCardInfo("Shu General", 25, Rarity.COMMON, mage.cards.s.ShuGeneral.class)); + cards.add(new SetCardInfo("Shu Soldier-Farmers", 26, Rarity.COMMON, mage.cards.s.ShuSoldierFarmers.class)); + cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 174, Rarity.COMMON, mage.cards.s.SirShandlarOfEberyn.class)); + cards.add(new SetCardInfo("Sivitri Scarzam", 175, Rarity.COMMON, mage.cards.s.SivitriScarzam.class)); + cards.add(new SetCardInfo("Slashing Tiger", 133, Rarity.COMMON, mage.cards.s.SlashingTiger.class)); + cards.add(new SetCardInfo("Sol Grail", 201, Rarity.COMMON, mage.cards.s.SolGrail.class)); + cards.add(new SetCardInfo("Sorrow's Path", 211, Rarity.RARE, mage.cards.s.SorrowsPath.class)); + cards.add(new SetCardInfo("Spirit Shackle", 74, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); + cards.add(new SetCardInfo("Spoils of Victory", 134, Rarity.COMMON, mage.cards.s.SpoilsOfVictory.class)); + cards.add(new SetCardInfo("Stangg", 177, Rarity.UNCOMMON, mage.cards.s.Stangg.class)); + cards.add(new SetCardInfo("Stolen Grain", 75, Rarity.UNCOMMON, mage.cards.s.StolenGrain.class)); + cards.add(new SetCardInfo("Storm World", 111, Rarity.RARE, mage.cards.s.StormWorld.class)); + cards.add(new SetCardInfo("Strategic Planning", 51, Rarity.COMMON, mage.cards.s.StrategicPlanning.class)); + cards.add(new SetCardInfo("Sunastian Falconer", 178, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); + cards.add(new SetCardInfo("Sun Ce, Young Conquerer", 52, Rarity.UNCOMMON, mage.cards.s.SunCeYoungConquerer.class)); + cards.add(new SetCardInfo("Sun Quan, Lord of Wu", 53, Rarity.RARE, mage.cards.s.SunQuanLordOfWu.class)); + cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 223, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 224, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sword of the Ages", 202, Rarity.RARE, mage.cards.s.SwordOfTheAges.class)); + cards.add(new SetCardInfo("Tetsuo Umezawa", 179, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); + cards.add(new SetCardInfo("The Abyss", 77, Rarity.RARE, mage.cards.t.TheAbyss.class)); + cards.add(new SetCardInfo("The Lady of the Mountain", 180, Rarity.COMMON, mage.cards.t.TheLadyOfTheMountain.class)); + cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 212, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); + cards.add(new SetCardInfo("The Wretched", 78, Rarity.UNCOMMON, mage.cards.t.TheWretched.class)); + cards.add(new SetCardInfo("Three Visits", 135, Rarity.COMMON, mage.cards.t.ThreeVisits.class)); + cards.add(new SetCardInfo("Tobias Andrion", 181, Rarity.COMMON, mage.cards.t.TobiasAndrion.class)); + cards.add(new SetCardInfo("Torsten Von Ursus", 183, Rarity.COMMON, mage.cards.t.TorstenVonUrsus.class)); + cards.add(new SetCardInfo("Tor Wauki", 182, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); + cards.add(new SetCardInfo("Tracker", 136, Rarity.UNCOMMON, mage.cards.t.Tracker.class)); + cards.add(new SetCardInfo("Trip Wire", 137, Rarity.COMMON, mage.cards.t.TripWire.class)); + cards.add(new SetCardInfo("Tropical Island", 213, Rarity.RARE, mage.cards.t.TropicalIsland.class)); + cards.add(new SetCardInfo("Tuknir Deathlock", 184, Rarity.UNCOMMON, mage.cards.t.TuknirDeathlock.class)); + cards.add(new SetCardInfo("Urborg", 214, Rarity.UNCOMMON, mage.cards.u.Urborg.class)); + cards.add(new SetCardInfo("Vaevictis Asmadi", 185, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); + cards.add(new SetCardInfo("Volcanic Island", 215, Rarity.RARE, mage.cards.v.VolcanicIsland.class)); + cards.add(new SetCardInfo("Wall of Light", 27, Rarity.COMMON, mage.cards.w.WallOfLight.class)); + cards.add(new SetCardInfo("Wandering Mage", 186, Rarity.RARE, mage.cards.w.WanderingMage.class)); + cards.add(new SetCardInfo("Wei Elite Companions", 79, Rarity.COMMON, mage.cards.w.WeiEliteCompanions.class)); + cards.add(new SetCardInfo("Wei Infantry", 80, Rarity.COMMON, mage.cards.w.WeiInfantry.class)); + cards.add(new SetCardInfo("Wei Night Raiders", 81, Rarity.UNCOMMON, mage.cards.w.WeiNightRaiders.class)); + cards.add(new SetCardInfo("Wei Strike Force", 82, Rarity.COMMON, mage.cards.w.WeiStrikeForce.class)); + cards.add(new SetCardInfo("Willow Priestess", 138, Rarity.UNCOMMON, mage.cards.w.WillowPriestess.class)); + cards.add(new SetCardInfo("Willow Satyr", 139, Rarity.RARE, mage.cards.w.WillowSatyr.class)); + cards.add(new SetCardInfo("Wormwood Treefolk", 140, Rarity.UNCOMMON, mage.cards.w.WormwoodTreefolk.class)); + cards.add(new SetCardInfo("Wu Elite Cavalry", 54, Rarity.COMMON, mage.cards.w.WuEliteCavalry.class)); + cards.add(new SetCardInfo("Wu Longbowman", 55, Rarity.COMMON, mage.cards.w.WuLongbowman.class)); + cards.add(new SetCardInfo("Wu Warship", 56, Rarity.COMMON, mage.cards.w.WuWarship.class)); + cards.add(new SetCardInfo("Xiahou Dun, the One-Eyed", 83, Rarity.UNCOMMON, mage.cards.x.XiahouDunTheOneEyed.class)); + cards.add(new SetCardInfo("Xira Arien", 187, Rarity.RARE, mage.cards.x.XiraArien.class)); + cards.add(new SetCardInfo("Young Wei Recruits", 84, Rarity.COMMON, mage.cards.y.YoungWeiRecruits.class)); + cards.add(new SetCardInfo("Zhang Fei, Fierce Warrior", 28, Rarity.UNCOMMON, mage.cards.z.ZhangFeiFierceWarrior.class)); + cards.add(new SetCardInfo("Zodiac Dragon", 112, Rarity.RARE, mage.cards.z.ZodiacDragon.class)); + } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/RavnicaAllegiance.java b/Mage.Sets/src/mage/sets/RavnicaAllegiance.java index 4cfdc62336d..735ad45eb1c 100644 --- a/Mage.Sets/src/mage/sets/RavnicaAllegiance.java +++ b/Mage.Sets/src/mage/sets/RavnicaAllegiance.java @@ -23,7 +23,6 @@ public final class RavnicaAllegiance extends ExpansionSet { super("Ravnica Allegiance", "RNA", ExpansionSet.buildDate(2019, 1, 25), SetType.EXPANSION); this.blockName = "Guilds of Ravnica"; this.hasBoosters = true; - this.hasBasicLands = false; // this is temporary until the actual basics have been spoiled to prevent a test fail this.numBoosterSpecial = 1; this.numBoosterLands = 0; this.numBoosterCommon = 10; @@ -33,24 +32,278 @@ public final class RavnicaAllegiance extends ExpansionSet { this.maxCardNumberInBooster = 259; cards.add(new SetCardInfo("Absorb", 151, Rarity.RARE, mage.cards.a.Absorb.class)); + cards.add(new SetCardInfo("Act of Treason", 91, Rarity.COMMON, mage.cards.a.ActOfTreason.class)); cards.add(new SetCardInfo("Aeromunculus", 152, Rarity.COMMON, mage.cards.a.Aeromunculus.class)); + cards.add(new SetCardInfo("Amplifire", 92, Rarity.RARE, mage.cards.a.Amplifire.class)); + cards.add(new SetCardInfo("Angel of Grace", 1, Rarity.MYTHIC, mage.cards.a.AngelOfGrace.class)); + cards.add(new SetCardInfo("Angelic Exaltation", 2, Rarity.UNCOMMON, mage.cards.a.AngelicExaltation.class)); + cards.add(new SetCardInfo("Applied Biomancy", 153, Rarity.COMMON, mage.cards.a.AppliedBiomancy.class)); + cards.add(new SetCardInfo("Archway Angel", 3, Rarity.UNCOMMON, mage.cards.a.ArchwayAngel.class)); + cards.add(new SetCardInfo("Arrester's Admonition", 31, Rarity.COMMON, mage.cards.a.ArrestersAdmonition.class)); + cards.add(new SetCardInfo("Arrester's Zeal", 4, Rarity.COMMON, mage.cards.a.ArrestersZeal.class)); + cards.add(new SetCardInfo("Awaken the Erstwhile", 61, Rarity.RARE, mage.cards.a.AwakenTheErstwhile.class)); + cards.add(new SetCardInfo("Axebane Beast", 121, Rarity.COMMON, mage.cards.a.AxebaneBeast.class)); + cards.add(new SetCardInfo("Azorius Guildgate", 243, Rarity.COMMON, mage.cards.a.AzoriusGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Azorius Guildgate", 244, Rarity.COMMON, mage.cards.a.AzoriusGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Azorius Knight-Arbiter", 154, Rarity.COMMON, mage.cards.a.AzoriusKnightArbiter.class)); + cards.add(new SetCardInfo("Azorius Locket", 231, Rarity.COMMON, mage.cards.a.AzoriusLocket.class)); + cards.add(new SetCardInfo("Azorius Skyguard", 155, Rarity.UNCOMMON, mage.cards.a.AzoriusSkyguard.class)); + cards.add(new SetCardInfo("Bankrupt in Blood", 62, Rarity.UNCOMMON, mage.cards.b.BankruptInBlood.class)); + cards.add(new SetCardInfo("Basilica Bell-Haunt", 156, Rarity.UNCOMMON, mage.cards.b.BasilicaBellHaunt.class)); + cards.add(new SetCardInfo("Bedeck // Bedazzle", 221, Rarity.RARE, mage.cards.b.BedeckBedazzle.class)); cards.add(new SetCardInfo("Bedevil", 157, Rarity.RARE, mage.cards.b.Bedevil.class)); + cards.add(new SetCardInfo("Benthic Biomancer", 32, Rarity.RARE, mage.cards.b.BenthicBiomancer.class)); + cards.add(new SetCardInfo("Biogenic Ooze", 122, Rarity.MYTHIC, mage.cards.b.BiogenicOoze.class)); + cards.add(new SetCardInfo("Biogenic Upgrade", 123, Rarity.UNCOMMON, mage.cards.b.BiogenicUpgrade.class)); + cards.add(new SetCardInfo("Biomancer's Familiar", 158, Rarity.RARE, mage.cards.b.BiomancersFamiliar.class)); + cards.add(new SetCardInfo("Blade Juggler", 63, Rarity.COMMON, mage.cards.b.BladeJuggler.class)); + cards.add(new SetCardInfo("Bladebrand", 64, Rarity.COMMON, mage.cards.b.Bladebrand.class)); + cards.add(new SetCardInfo("Blood Crypt", 245, Rarity.RARE, mage.cards.b.BloodCrypt.class)); + cards.add(new SetCardInfo("Bloodmist Infiltrator", 65, Rarity.UNCOMMON, mage.cards.b.BloodmistInfiltrator.class)); + cards.add(new SetCardInfo("Bolrac-Clan Crusher", 159, Rarity.UNCOMMON, mage.cards.b.BolracClanCrusher.class)); + cards.add(new SetCardInfo("Breeding Pool", 246, Rarity.RARE, mage.cards.b.BreedingPool.class)); + cards.add(new SetCardInfo("Bring to Trial", 5, Rarity.COMMON, mage.cards.b.BringToTrial.class)); + cards.add(new SetCardInfo("Burn Bright", 93, Rarity.COMMON, mage.cards.b.BurnBright.class)); + cards.add(new SetCardInfo("Burning-Tree Vandal", 94, Rarity.COMMON, mage.cards.b.BurningTreeVandal.class)); + cards.add(new SetCardInfo("Captive Audience", 160, Rarity.MYTHIC, mage.cards.c.CaptiveAudience.class)); + cards.add(new SetCardInfo("Carnival // Carnage", 222, Rarity.UNCOMMON, mage.cards.c.CarnivalCarnage.class)); + cards.add(new SetCardInfo("Carrion Imp", 66, Rarity.COMMON, mage.cards.c.CarrionImp.class)); + cards.add(new SetCardInfo("Catacomb Crocodile", 67, Rarity.COMMON, mage.cards.c.CatacombCrocodile.class)); + cards.add(new SetCardInfo("Cavalcade of Calamity", 95, Rarity.UNCOMMON, mage.cards.c.CavalcadeOfCalamity.class)); + cards.add(new SetCardInfo("Charging War Boar", 271, Rarity.UNCOMMON, mage.cards.c.ChargingWarBoar.class)); + cards.add(new SetCardInfo("Chillbringer", 33, Rarity.COMMON, mage.cards.c.Chillbringer.class)); + cards.add(new SetCardInfo("Cindervines", 161, Rarity.RARE, mage.cards.c.Cindervines.class)); + cards.add(new SetCardInfo("Civic Stalwart", 6, Rarity.COMMON, mage.cards.c.CivicStalwart.class)); + cards.add(new SetCardInfo("Clamor Shaman", 96, Rarity.UNCOMMON, mage.cards.c.ClamorShaman.class)); + cards.add(new SetCardInfo("Clan Guildmage", 162, Rarity.UNCOMMON, mage.cards.c.ClanGuildmage.class)); + cards.add(new SetCardInfo("Clear the Mind", 34, Rarity.COMMON, mage.cards.c.ClearTheMind.class)); + cards.add(new SetCardInfo("Clear the Stage", 68, Rarity.UNCOMMON, mage.cards.c.ClearTheStage.class)); + cards.add(new SetCardInfo("Code of Constraint", 35, Rarity.UNCOMMON, mage.cards.c.CodeOfConstraint.class)); + cards.add(new SetCardInfo("Collision // Colossus", 223, Rarity.UNCOMMON, mage.cards.c.CollisionColossus.class)); + cards.add(new SetCardInfo("Combine Guildmage", 163, Rarity.UNCOMMON, mage.cards.c.CombineGuildmage.class)); + cards.add(new SetCardInfo("Consecrate // Consume", 224, Rarity.UNCOMMON, mage.cards.c.ConsecrateConsume.class)); + cards.add(new SetCardInfo("Concordia Pegasus", 7, Rarity.COMMON, mage.cards.c.ConcordiaPegasus.class)); + cards.add(new SetCardInfo("Consign to the Pit", 69, Rarity.COMMON, mage.cards.c.ConsignToThePit.class)); + cards.add(new SetCardInfo("Coral Commando", 36, Rarity.COMMON, mage.cards.c.CoralCommando.class)); + cards.add(new SetCardInfo("Cry of the Carnarium", 70, Rarity.UNCOMMON, mage.cards.c.CryOfTheCarnarium.class)); + cards.add(new SetCardInfo("Cult Guildmage", 164, Rarity.UNCOMMON, mage.cards.c.CultGuildmage.class)); + cards.add(new SetCardInfo("Dagger Caster", 97, Rarity.UNCOMMON, mage.cards.d.DaggerCaster.class)); + cards.add(new SetCardInfo("Dead Revels", 71, Rarity.COMMON, mage.cards.d.DeadRevels.class)); + cards.add(new SetCardInfo("Debtors' Transport", 72, Rarity.COMMON, mage.cards.d.DebtorsTransport.class)); + cards.add(new SetCardInfo("Deface", 98, Rarity.COMMON, mage.cards.d.Deface.class)); + cards.add(new SetCardInfo("Depose // Deploy", 225, Rarity.UNCOMMON, mage.cards.d.DeposeDeploy.class)); + cards.add(new SetCardInfo("Deputy of Detention", 165, Rarity.RARE, mage.cards.d.DeputyOfDetention.class)); + cards.add(new SetCardInfo("Domri's Nodorog", 272, Rarity.RARE, mage.cards.d.DomrisNodorog.class)); + cards.add(new SetCardInfo("Domri, Chaos Bringer", 166, Rarity.MYTHIC, mage.cards.d.DomriChaosBringer.class)); + cards.add(new SetCardInfo("Domri, City Smasher", 269, Rarity.MYTHIC, mage.cards.d.DomriCitySmasher.class)); + cards.add(new SetCardInfo("Dovin's Acuity", 168, Rarity.UNCOMMON, mage.cards.d.DovinsAcuity.class)); + cards.add(new SetCardInfo("Dovin's Automaton", 268, Rarity.UNCOMMON, mage.cards.d.DovinsAutomaton.class)); + cards.add(new SetCardInfo("Dovin's Dismissal", 267, Rarity.RARE, mage.cards.d.DovinsDismissal.class)); + cards.add(new SetCardInfo("Dovin, Architect of Law", 265, Rarity.MYTHIC, mage.cards.d.DovinArchitectOfLaw.class)); + cards.add(new SetCardInfo("Dovin, Grand Arbiter", 167, Rarity.MYTHIC, mage.cards.d.DovinGrandArbiter.class)); + cards.add(new SetCardInfo("Drill Bit", 73, Rarity.UNCOMMON, mage.cards.d.DrillBit.class)); + cards.add(new SetCardInfo("Electrodominance", 99, Rarity.RARE, mage.cards.e.Electrodominance.class)); + cards.add(new SetCardInfo("Elite Arrester", 266, Rarity.COMMON, mage.cards.e.EliteArrester.class)); cards.add(new SetCardInfo("Emergency Powers", 169, Rarity.MYTHIC, mage.cards.e.EmergencyPowers.class)); + cards.add(new SetCardInfo("End-Raze Forerunners", 124, Rarity.RARE, mage.cards.e.EndRazeForerunners.class)); + cards.add(new SetCardInfo("Enraged Ceratok", 125, Rarity.UNCOMMON, mage.cards.e.EnragedCeratok.class)); + cards.add(new SetCardInfo("Essence Capture", 37, Rarity.UNCOMMON, mage.cards.e.EssenceCapture.class)); + cards.add(new SetCardInfo("Ethereal Absolution", 170, Rarity.RARE, mage.cards.e.EtherealAbsolution.class)); + cards.add(new SetCardInfo("Expose to Daylight", 8, Rarity.COMMON, mage.cards.e.ExposeToDaylight.class)); + cards.add(new SetCardInfo("Eyes Everywhere", 38, Rarity.UNCOMMON, mage.cards.e.EyesEverywhere.class)); + cards.add(new SetCardInfo("Faerie Duelist", 39, Rarity.COMMON, mage.cards.f.FaerieDuelist.class)); + cards.add(new SetCardInfo("Feral Maaka", 100, Rarity.COMMON, mage.cards.f.FeralMaaka.class)); + cards.add(new SetCardInfo("Final Payment", 171, Rarity.COMMON, mage.cards.f.FinalPayment.class)); + cards.add(new SetCardInfo("Fireblade Artist", 172, Rarity.UNCOMMON, mage.cards.f.FirebladeArtist.class)); + cards.add(new SetCardInfo("Flames of the Raze-Boar", 101, Rarity.UNCOMMON, mage.cards.f.FlamesOfTheRazeBoar.class)); + cards.add(new SetCardInfo("Font of Agonies", 74, Rarity.RARE, mage.cards.f.FontOfAgonies.class)); + cards.add(new SetCardInfo("Footlight Fiend", 216, Rarity.COMMON, mage.cards.f.FootlightFiend.class)); + cards.add(new SetCardInfo("Forbidding Spirit", 9, Rarity.UNCOMMON, mage.cards.f.ForbiddingSpirit.class)); + cards.add(new SetCardInfo("Forest", 264, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Frenzied Arynx", 173, Rarity.COMMON, mage.cards.f.FrenziedArynx.class)); + cards.add(new SetCardInfo("Frilled Mystic", 174, Rarity.UNCOMMON, mage.cards.f.FrilledMystic.class)); + cards.add(new SetCardInfo("Galloping Lizrog", 175, Rarity.UNCOMMON, mage.cards.g.GallopingLizrog.class)); cards.add(new SetCardInfo("Gate Colossus", 232, Rarity.UNCOMMON, mage.cards.g.GateColossus.class)); + cards.add(new SetCardInfo("Gatebreaker Ram", 126, Rarity.UNCOMMON, mage.cards.g.GatebreakerRam.class)); + cards.add(new SetCardInfo("Gates Ablaze", 102, Rarity.UNCOMMON, mage.cards.g.GatesAblaze.class)); + cards.add(new SetCardInfo("Gateway Plaza", 247, Rarity.COMMON, mage.cards.g.GatewayPlaza.class)); + cards.add(new SetCardInfo("Gateway Sneak", 40, Rarity.UNCOMMON, mage.cards.g.GatewaySneak.class)); + cards.add(new SetCardInfo("Get the Point", 176, Rarity.COMMON, mage.cards.g.GetThePoint.class)); + cards.add(new SetCardInfo("Ghor-Clan Wrecker", 103, Rarity.COMMON, mage.cards.g.GhorClanWrecker.class)); + cards.add(new SetCardInfo("Gift of Strength", 127, Rarity.COMMON, mage.cards.g.GiftOfStrength.class)); + cards.add(new SetCardInfo("Glass of the Guildpact", 233, Rarity.RARE, mage.cards.g.GlassOfTheGuildpact.class)); + cards.add(new SetCardInfo("Goblin Gathering", 104, Rarity.COMMON, mage.cards.g.GoblinGathering.class)); + cards.add(new SetCardInfo("Godless Shrine", 248, Rarity.RARE, mage.cards.g.GodlessShrine.class)); + cards.add(new SetCardInfo("Grasping Thrull", 177, Rarity.COMMON, mage.cards.g.GraspingThrull.class)); + cards.add(new SetCardInfo("Gravel-Hide Goblin", 105, Rarity.COMMON, mage.cards.g.GravelHideGoblin.class)); + cards.add(new SetCardInfo("Grotesque Demise", 75, Rarity.COMMON, mage.cards.g.GrotesqueDemise.class)); cards.add(new SetCardInfo("Growth Spiral", 178, Rarity.COMMON, mage.cards.g.GrowthSpiral.class)); + cards.add(new SetCardInfo("Growth-Chamber Guardian", 128, Rarity.RARE, mage.cards.g.GrowthChamberGuardian.class)); + cards.add(new SetCardInfo("Gruul Beastmaster", 129, Rarity.UNCOMMON, mage.cards.g.GruulBeastmaster.class)); + cards.add(new SetCardInfo("Gruul Guildgate", 249, Rarity.COMMON, mage.cards.g.GruulGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Gruul Guildgate", 250, Rarity.COMMON, mage.cards.g.GruulGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Gruul Locket", 234, Rarity.COMMON, mage.cards.g.GruulLocket.class)); cards.add(new SetCardInfo("Gruul Spellbreaker", 179, Rarity.RARE, mage.cards.g.GruulSpellbreaker.class)); + cards.add(new SetCardInfo("Guardian Project", 130, Rarity.RARE, mage.cards.g.GuardianProject.class)); + cards.add(new SetCardInfo("Gutterbones", 76, Rarity.RARE, mage.cards.g.Gutterbones.class)); + cards.add(new SetCardInfo("Gyre Engineer", 180, Rarity.UNCOMMON, mage.cards.g.GyreEngineer.class)); + cards.add(new SetCardInfo("Haazda Officer", 10, Rarity.COMMON, mage.cards.h.HaazdaOfficer.class)); + cards.add(new SetCardInfo("Hackrobat", 181, Rarity.UNCOMMON, mage.cards.h.Hackrobat.class)); + cards.add(new SetCardInfo("Hallowed Fountain", 251, Rarity.RARE, mage.cards.h.HallowedFountain.class)); + cards.add(new SetCardInfo("Hero of Precinct One", 11, Rarity.RARE, mage.cards.h.HeroOfPrecinctOne.class)); + cards.add(new SetCardInfo("High Alert", 182, Rarity.UNCOMMON, mage.cards.h.HighAlert.class)); + cards.add(new SetCardInfo("Humongulus", 41, Rarity.COMMON, mage.cards.h.Humongulus.class)); + cards.add(new SetCardInfo("Hydroid Krasis", 183, Rarity.MYTHIC, mage.cards.h.HydroidKrasis.class)); + cards.add(new SetCardInfo("Ill-Gotten Inheritance", 77, Rarity.COMMON, mage.cards.i.IllGottenInheritance.class)); + cards.add(new SetCardInfo("Immolation Shaman", 106, Rarity.RARE, mage.cards.i.ImmolationShaman.class)); + cards.add(new SetCardInfo("Impassioned Orator", 12, Rarity.COMMON, mage.cards.i.ImpassionedOrator.class)); cards.add(new SetCardInfo("Imperious Oligarch", 184, Rarity.COMMON, mage.cards.i.ImperiousOligarch.class)); cards.add(new SetCardInfo("Incubation // Incongruity", 226, Rarity.UNCOMMON, mage.cards.i.IncubationIncongruity.class)); + cards.add(new SetCardInfo("Incubation Druid", 131, Rarity.RARE, mage.cards.i.IncubationDruid.class)); + cards.add(new SetCardInfo("Island", 261, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Judith, the Scourge Diva", 185, Rarity.RARE, mage.cards.j.JudithTheScourgeDiva.class)); + cards.add(new SetCardInfo("Junktroller", 235, Rarity.UNCOMMON, mage.cards.j.Junktroller.class)); + cards.add(new SetCardInfo("Justiciar's Portal", 13, Rarity.COMMON, mage.cards.j.JusticiarsPortal.class)); + cards.add(new SetCardInfo("Kaya's Wrath", 187, Rarity.RARE, mage.cards.k.KayasWrath.class)); + cards.add(new SetCardInfo("Kaya, Orzhov Usurper", 186, Rarity.MYTHIC, mage.cards.k.KayaOrzhovUsurper.class)); + cards.add(new SetCardInfo("Knight of Sorrows", 14, Rarity.COMMON, mage.cards.k.KnightOfSorrows.class)); + cards.add(new SetCardInfo("Knight of the Last Breath", 188, Rarity.UNCOMMON, mage.cards.k.KnightOfTheLastBreath.class)); + cards.add(new SetCardInfo("Lavinia, Azorius Renegade", 189, Rarity.RARE, mage.cards.l.LaviniaAzoriusRenegade.class)); + cards.add(new SetCardInfo("Lawmage's Binding", 190, Rarity.COMMON, mage.cards.l.LawmagesBinding.class)); cards.add(new SetCardInfo("Light Up the Stage", 107, Rarity.UNCOMMON, mage.cards.l.LightUpTheStage.class)); + cards.add(new SetCardInfo("Lumbering Battlement", 15, Rarity.RARE, mage.cards.l.LumberingBattlement.class)); + cards.add(new SetCardInfo("Macabre Mockery", 191, Rarity.UNCOMMON, mage.cards.m.MacabreMockery.class)); + cards.add(new SetCardInfo("Mammoth Spider", 132, Rarity.COMMON, mage.cards.m.MammothSpider.class)); + cards.add(new SetCardInfo("Mass Manipulation", 42, Rarity.RARE, mage.cards.m.MassManipulation.class)); + cards.add(new SetCardInfo("Mesmerizing Benthid", 43, Rarity.MYTHIC, mage.cards.m.MesmerizingBenthid.class)); + cards.add(new SetCardInfo("Ministrant of Obligation", 16, Rarity.UNCOMMON, mage.cards.m.MinistrantOfObligation.class)); + cards.add(new SetCardInfo("Mirror March", 108, Rarity.RARE, mage.cards.m.MirrorMarch.class)); cards.add(new SetCardInfo("Mortify", 192, Rarity.UNCOMMON, mage.cards.m.Mortify.class)); + cards.add(new SetCardInfo("Mountain", 263, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nikya of the Old Ways", 193, Rarity.RARE, mage.cards.n.NikyaOfTheOldWays.class)); + cards.add(new SetCardInfo("Noxious Groodion", 78, Rarity.COMMON, mage.cards.n.NoxiousGroodion.class)); + cards.add(new SetCardInfo("Open the Gates", 133, Rarity.COMMON, mage.cards.o.OpenTheGates.class)); + cards.add(new SetCardInfo("Orzhov Enforcer", 79, Rarity.UNCOMMON, mage.cards.o.OrzhovEnforcer.class)); + cards.add(new SetCardInfo("Orzhov Guildgate", 252, Rarity.COMMON, mage.cards.o.OrzhovGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Orzhov Guildgate", 253, Rarity.COMMON, mage.cards.o.OrzhovGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Orzhov Locket", 236, Rarity.COMMON, mage.cards.o.OrzhovLocket.class)); + cards.add(new SetCardInfo("Orzhov Racketeers", 80, Rarity.UNCOMMON, mage.cards.o.OrzhovRacketeers.class)); + cards.add(new SetCardInfo("Persistent Petitioners", 44, Rarity.COMMON, mage.cards.p.PersistentPetitioners.class)); + cards.add(new SetCardInfo("Pestilent Spirit", 81, Rarity.RARE, mage.cards.p.PestilentSpirit.class)); + cards.add(new SetCardInfo("Pitiless Pontiff", 194, Rarity.UNCOMMON, mage.cards.p.PitilessPontiff.class)); + cards.add(new SetCardInfo("Plague Wight", 82, Rarity.COMMON, mage.cards.p.PlagueWight.class)); + cards.add(new SetCardInfo("Plains", 260, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plaza of Harmony", 254, Rarity.RARE, mage.cards.p.PlazaOfHarmony.class)); + cards.add(new SetCardInfo("Precognitive Perception", 45, Rarity.RARE, mage.cards.p.PrecognitivePerception.class)); + cards.add(new SetCardInfo("Priest of Forgotten Gods", 83, Rarity.RARE, mage.cards.p.PriestOfForgottenGods.class)); + cards.add(new SetCardInfo("Prime Speaker Vannifar", 195, Rarity.MYTHIC, mage.cards.p.PrimeSpeakerVannifar.class)); + cards.add(new SetCardInfo("Prowling Caracal", 17, Rarity.COMMON, mage.cards.p.ProwlingCaracal.class)); + cards.add(new SetCardInfo("Prying Eyes", 46, Rarity.COMMON, mage.cards.p.PryingEyes.class)); + cards.add(new SetCardInfo("Pteramander", 47, Rarity.UNCOMMON, mage.cards.p.Pteramander.class)); + cards.add(new SetCardInfo("Quench", 48, Rarity.COMMON, mage.cards.q.Quench.class)); cards.add(new SetCardInfo("Rafter Demon", 196, Rarity.COMMON, mage.cards.r.RafterDemon.class)); + cards.add(new SetCardInfo("Ragefire", 270, Rarity.COMMON, mage.cards.r.Ragefire.class)); cards.add(new SetCardInfo("Rakdos Firewheeler", 197, Rarity.UNCOMMON, mage.cards.r.RakdosFirewheeler.class)); + cards.add(new SetCardInfo("Rakdos Guildgate", 255, Rarity.COMMON, mage.cards.r.RakdosGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Rakdos Guildgate", 256, Rarity.COMMON, mage.cards.r.RakdosGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Rakdos Locket", 237, Rarity.COMMON, mage.cards.r.RakdosLocket.class)); + cards.add(new SetCardInfo("Rakdos Roustabout", 198, Rarity.COMMON, mage.cards.r.RakdosRoustabout.class)); + cards.add(new SetCardInfo("Rakdos Trumpeter", 84, Rarity.COMMON, mage.cards.r.RakdosTrumpeter.class)); + cards.add(new SetCardInfo("Rakdos, the Showstopper", 199, Rarity.MYTHIC, mage.cards.r.RakdosTheShowstopper.class)); + cards.add(new SetCardInfo("Rally to Battle", 18, Rarity.UNCOMMON, mage.cards.r.RallyToBattle.class)); + cards.add(new SetCardInfo("Rampage of the Clans", 134, Rarity.RARE, mage.cards.r.RampageOfTheClans.class)); + cards.add(new SetCardInfo("Rampaging Rendhorn", 135, Rarity.COMMON, mage.cards.r.RampagingRendhorn.class)); + cards.add(new SetCardInfo("Ravager Wurm", 200, Rarity.MYTHIC, mage.cards.r.RavagerWurm.class)); + cards.add(new SetCardInfo("Regenesis", 136, Rarity.UNCOMMON, mage.cards.r.Regenesis.class)); + cards.add(new SetCardInfo("Repudiate // Replicate", 227, Rarity.RARE, mage.cards.r.RepudiateReplicate.class)); + cards.add(new SetCardInfo("Resolute Watchdog", 19, Rarity.UNCOMMON, mage.cards.r.ResoluteWatchdog.class)); + cards.add(new SetCardInfo("Revival // Revenge", 228, Rarity.RARE, mage.cards.r.RevivalRevenge.class)); + cards.add(new SetCardInfo("Rhythm of the Wild", 201, Rarity.UNCOMMON, mage.cards.r.RhythmOfTheWild.class)); cards.add(new SetCardInfo("Rix Maadi Reveler", 109, Rarity.RARE, mage.cards.r.RixMaadiReveler.class)); + cards.add(new SetCardInfo("Root Snare", 137, Rarity.COMMON, mage.cards.r.RootSnare.class)); + cards.add(new SetCardInfo("Rubble Reading", 110, Rarity.COMMON, mage.cards.r.RubbleReading.class)); + cards.add(new SetCardInfo("Rubble Slinger", 217, Rarity.COMMON, mage.cards.r.RubbleSlinger.class)); + cards.add(new SetCardInfo("Rubblebelt Recluse", 111, Rarity.COMMON, mage.cards.r.RubblebeltRecluse.class)); + cards.add(new SetCardInfo("Rubblebelt Runner", 202, Rarity.COMMON, mage.cards.r.RubblebeltRunner.class)); + cards.add(new SetCardInfo("Rumbling Ruin", 112, Rarity.UNCOMMON, mage.cards.r.RumblingRuin.class)); + cards.add(new SetCardInfo("Sage's Row Savant", 49, Rarity.COMMON, mage.cards.s.SagesRowSavant.class)); + cards.add(new SetCardInfo("Sagittars' Volley", 138, Rarity.COMMON, mage.cards.s.SagittarsVolley.class)); + cards.add(new SetCardInfo("Saruli Caretaker", 139, Rarity.COMMON, mage.cards.s.SaruliCaretaker.class)); + cards.add(new SetCardInfo("Sauroform Hybrid", 140, Rarity.COMMON, mage.cards.s.SauroformHybrid.class)); + cards.add(new SetCardInfo("Savage Smash", 203, Rarity.COMMON, mage.cards.s.SavageSmash.class)); + cards.add(new SetCardInfo("Scorchmark", 113, Rarity.COMMON, mage.cards.s.Scorchmark.class)); + cards.add(new SetCardInfo("Scrabbling Claws", 238, Rarity.UNCOMMON, mage.cards.s.ScrabblingClaws.class)); + cards.add(new SetCardInfo("Screaming Shield", 239, Rarity.UNCOMMON, mage.cards.s.ScreamingShield.class)); + cards.add(new SetCardInfo("Scuttlegator", 218, Rarity.COMMON, mage.cards.s.Scuttlegator.class)); + cards.add(new SetCardInfo("Senate Courier", 50, Rarity.COMMON, mage.cards.s.SenateCourier.class)); + cards.add(new SetCardInfo("Senate Griffin", 219, Rarity.COMMON, mage.cards.s.SenateGriffin.class)); + cards.add(new SetCardInfo("Senate Guildmage", 204, Rarity.UNCOMMON, mage.cards.s.SenateGuildmage.class)); + cards.add(new SetCardInfo("Sentinel's Mark", 20, Rarity.UNCOMMON, mage.cards.s.SentinelsMark.class)); + cards.add(new SetCardInfo("Seraph of the Scales", 205, Rarity.MYTHIC, mage.cards.s.SeraphOfTheScales.class)); + cards.add(new SetCardInfo("Sharktocrab", 206, Rarity.UNCOMMON, mage.cards.s.Sharktocrab.class)); + cards.add(new SetCardInfo("Shimmer of Possibility", 51, Rarity.COMMON, mage.cards.s.ShimmerOfPossibility.class)); + cards.add(new SetCardInfo("Silhana Wayfinder", 141, Rarity.UNCOMMON, mage.cards.s.SilhanaWayfinder.class)); + cards.add(new SetCardInfo("Simic Ascendancy", 207, Rarity.RARE, mage.cards.s.SimicAscendancy.class)); + cards.add(new SetCardInfo("Simic Guildgate", 257, Rarity.COMMON, mage.cards.s.SimicGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Simic Guildgate", 258, Rarity.COMMON, mage.cards.s.SimicGuildgate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Simic Locket", 240, Rarity.COMMON, mage.cards.s.SimicLocket.class)); + cards.add(new SetCardInfo("Skarrgan Hellkite", 114, Rarity.MYTHIC, mage.cards.s.SkarrganHellkite.class)); + cards.add(new SetCardInfo("Skatewing Spy", 52, Rarity.UNCOMMON, mage.cards.s.SkatewingSpy.class)); + cards.add(new SetCardInfo("Skewer the Critics", 115, Rarity.COMMON, mage.cards.s.SkewerTheCritics.class)); + cards.add(new SetCardInfo("Skitter Eel", 53, Rarity.COMMON, mage.cards.s.SkitterEel.class)); + cards.add(new SetCardInfo("Sky Tether", 21, Rarity.UNCOMMON, mage.cards.s.SkyTether.class)); + cards.add(new SetCardInfo("Slimebind", 54, Rarity.COMMON, mage.cards.s.Slimebind.class)); + cards.add(new SetCardInfo("Smelt-Ward Ignus", 116, Rarity.UNCOMMON, mage.cards.s.SmeltWardIgnus.class)); + cards.add(new SetCardInfo("Smothering Tithe", 22, Rarity.RARE, mage.cards.s.SmotheringTithe.class)); + cards.add(new SetCardInfo("Spawn of Mayhem", 85, Rarity.MYTHIC, mage.cards.s.SpawnOfMayhem.class)); + cards.add(new SetCardInfo("Spear Spewer", 117, Rarity.COMMON, mage.cards.s.SpearSpewer.class)); + cards.add(new SetCardInfo("Sphinx of Foresight", 55, Rarity.RARE, mage.cards.s.SphinxOfForesight.class)); + cards.add(new SetCardInfo("Sphinx of New Prahv", 208, Rarity.UNCOMMON, mage.cards.s.SphinxOfNewPrahv.class)); + cards.add(new SetCardInfo("Sphinx of the Guildpact", 241, Rarity.UNCOMMON, mage.cards.s.SphinxOfTheGuildpact.class)); cards.add(new SetCardInfo("Sphinx's Insight", 209, Rarity.COMMON, mage.cards.s.SphinxsInsight.class)); + cards.add(new SetCardInfo("Spikewheel Acrobat", 118, Rarity.COMMON, mage.cards.s.SpikewheelAcrobat.class)); + cards.add(new SetCardInfo("Spire Mangler", 86, Rarity.UNCOMMON, mage.cards.s.SpireMangler.class)); + cards.add(new SetCardInfo("Spirit of the Spires", 23, Rarity.UNCOMMON, mage.cards.s.SpiritOfTheSpires.class)); + cards.add(new SetCardInfo("Steeple Creeper", 142, Rarity.COMMON, mage.cards.s.SteepleCreeper.class)); + cards.add(new SetCardInfo("Stomping Ground", 259, Rarity.RARE, mage.cards.s.StompingGround.class)); + cards.add(new SetCardInfo("Stony Strength", 143, Rarity.COMMON, mage.cards.s.StonyStrength.class)); + cards.add(new SetCardInfo("Storm Strike", 119, Rarity.COMMON, mage.cards.s.StormStrike.class)); + cards.add(new SetCardInfo("Summary Judgment", 24, Rarity.COMMON, mage.cards.s.SummaryJudgment.class)); + cards.add(new SetCardInfo("Sunder Shaman", 210, Rarity.UNCOMMON, mage.cards.s.SunderShaman.class)); + cards.add(new SetCardInfo("Swamp", 262, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swirling Torrent", 56, Rarity.UNCOMMON, mage.cards.s.SwirlingTorrent.class)); + cards.add(new SetCardInfo("Sylvan Brushstrider", 144, Rarity.COMMON, mage.cards.s.SylvanBrushstrider.class)); + cards.add(new SetCardInfo("Syndicate Guildmage", 211, Rarity.UNCOMMON, mage.cards.s.SyndicateGuildmage.class)); + cards.add(new SetCardInfo("Syndicate Messenger", 25, Rarity.COMMON, mage.cards.s.SyndicateMessenger.class)); + cards.add(new SetCardInfo("Tenth District Veteran", 26, Rarity.COMMON, mage.cards.t.TenthDistrictVeteran.class)); + cards.add(new SetCardInfo("Territorial Boar", 145, Rarity.COMMON, mage.cards.t.TerritorialBoar.class)); + cards.add(new SetCardInfo("Teysa Karlov", 212, Rarity.RARE, mage.cards.t.TeysaKarlov.class)); cards.add(new SetCardInfo("The Haunt of Hightower", 273, Rarity.MYTHIC, mage.cards.t.TheHauntOfHightower.class)); + cards.add(new SetCardInfo("Theater of Horrors", 213, Rarity.RARE, mage.cards.t.TheaterOfHorrors.class)); + cards.add(new SetCardInfo("Thirsting Shade", 87, Rarity.COMMON, mage.cards.t.ThirstingShade.class)); + cards.add(new SetCardInfo("Thought Collapse", 57, Rarity.COMMON, mage.cards.t.ThoughtCollapse.class)); + cards.add(new SetCardInfo("Thrash // Threat", 229, Rarity.RARE, mage.cards.t.ThrashThreat.class)); + cards.add(new SetCardInfo("Tin Street Dodger", 120, Rarity.UNCOMMON, mage.cards.t.TinStreetDodger.class)); + cards.add(new SetCardInfo("Titanic Brawl", 146, Rarity.COMMON, mage.cards.t.TitanicBrawl.class)); cards.add(new SetCardInfo("Tithe Taker", 27, Rarity.RARE, mage.cards.t.TitheTaker.class)); + cards.add(new SetCardInfo("Tome of the Guildpact", 242, Rarity.RARE, mage.cards.t.TomeOfTheGuildpact.class)); + cards.add(new SetCardInfo("Tower Defense", 147, Rarity.UNCOMMON, mage.cards.t.TowerDefense.class)); + cards.add(new SetCardInfo("Trollbred Guardian", 148, Rarity.UNCOMMON, mage.cards.t.TrollbredGuardian.class)); + cards.add(new SetCardInfo("Twilight Panther", 28, Rarity.COMMON, mage.cards.t.TwilightPanther.class)); + cards.add(new SetCardInfo("Unbreakable Formation", 29, Rarity.RARE, mage.cards.u.UnbreakableFormation.class)); + cards.add(new SetCardInfo("Undercity Scavenger", 88, Rarity.COMMON, mage.cards.u.UndercityScavenger.class)); + cards.add(new SetCardInfo("Undercity's Embrace", 89, Rarity.COMMON, mage.cards.u.UndercitysEmbrace.class)); + cards.add(new SetCardInfo("Verity Circle", 58, Rarity.RARE, mage.cards.v.VerityCircle.class)); + cards.add(new SetCardInfo("Vindictive Vampire", 90, Rarity.UNCOMMON, mage.cards.v.VindictiveVampire.class)); + cards.add(new SetCardInfo("Vizkopa Vampire", 220, Rarity.COMMON, mage.cards.v.VizkopaVampire.class)); + cards.add(new SetCardInfo("Wall of Lost Thoughts", 59, Rarity.UNCOMMON, mage.cards.w.WallOfLostThoughts.class)); + cards.add(new SetCardInfo("Warrant // Warden", 230, Rarity.RARE, mage.cards.w.WarrantWarden.class)); + cards.add(new SetCardInfo("Watchful Giant", 30, Rarity.COMMON, mage.cards.w.WatchfulGiant.class)); + cards.add(new SetCardInfo("Wilderness Reclamation", 149, Rarity.UNCOMMON, mage.cards.w.WildernessReclamation.class)); + cards.add(new SetCardInfo("Windstorm Drake", 60, Rarity.UNCOMMON, mage.cards.w.WindstormDrake.class)); + cards.add(new SetCardInfo("Wrecking Beast", 150, Rarity.COMMON, mage.cards.w.WreckingBeast.class)); cards.add(new SetCardInfo("Zegana, Utopian Speaker", 214, Rarity.RARE, mage.cards.z.ZeganaUtopianSpeaker.class)); + cards.add(new SetCardInfo("Zhur-Taa Goblin", 215, Rarity.UNCOMMON, mage.cards.z.ZhurTaaGoblin.class)); } @Override @@ -65,6 +318,10 @@ public final class RavnicaAllegiance extends ExpansionSet { if (maxCardNumberInBooster != Integer.MAX_VALUE) { savedCardsInfos.removeIf(next -> next.getCardNumberAsInt() > maxCardNumberInBooster); } + criteria = new CardCriteria(); + // Gateway Plaza is a normal common: https://twitter.com/EliShffrn/status/1043156989218414593s + criteria.setCodes(this.code).nameExact("Gateway Plaza"); + savedCardsInfos.addAll(CardRepository.instance.findCards(criteria)); savedCards.put(rarity, savedCardsInfos); } // Return a copy of the saved cards information, as not to modify the original. diff --git a/Mage.Stats/pom.xml b/Mage.Stats/pom.xml index 04ae3d81691..ae93dd043b6 100644 --- a/Mage.Stats/pom.xml +++ b/Mage.Stats/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-stats @@ -69,7 +69,7 @@ ch.qos.logback logback-classic - 1.1.2 + 1.2.3 @@ -87,7 +87,7 @@ commons-io commons-io - 2.4 + 2.6 diff --git a/Mage.Tests/CommanderOviya.dck b/Mage.Tests/CommanderOviya.dck new file mode 100644 index 00000000000..ffbcf0dbfdb --- /dev/null +++ b/Mage.Tests/CommanderOviya.dck @@ -0,0 +1,77 @@ +NAME:Oviya Test Deck +1 [C14:56] Loreseeker's Stone +1 [C14:54] Commander's Sphere +1 [C14:53] Assault Suit +1 [C14:52] Wolfcaller's Howl +1 [C14:51] Wave of Vitriol +1 [C14:50] Titania, Protector of Argoth +1 [C14:305] Oran-Rief, the Vastwood +1 [C14:227] Wren's Run Packmaster +1 [C14:226] Wood Elves +1 [C14:225] Wolfbriar Elemental +1 [C14:302] Jungle Basin +1 [C14:268] Skullclamp +1 [C14:224] Whirlwind +1 [C14:301] Havenwood Battleground +1 [C14:223] Wellwisher +1 [C14:267] Seer's Sundial +1 [C14:300] Haunted Fengraf +1 [C14:189] Drove of Elves +1 [C14:222] Tornado Elemental +1 [C14:221] Titania's Chosen +1 [C14:188] Desert Twister +1 [C14:220] Timberwatch Elf +1 [C14:187] Collective Unconscious +1 [C14:263] Predator, Flagship +1 [C14:186] Beastmaster Ascension +1 [C14:61] Myriad Landscape +1 [C14:316] Tranquil Thicket +1 [C14:315] Terramorphic Expanse +1 [C14:237] Emerald Medallion +1 [C14:311] Slippery Karst +1 [C14:199] Harrow +1 [C14:275] Swiftfoot Boots +1 [C14:198] Grim Flowering +1 [C14:197] Fresh Meat +1 [C14:196] Farhaven Elf +1 [C14:195] Ezuri, Renegade Leader +1 [C14:194] Essence Warden +1 [C14:193] Elvish Visionary +1 [C14:270] Sol Ring +1 [C14:192] Elvish Skysweeper +1 [C14:191] Elvish Mystic +1 [C14:190] Elvish Archdruid +1 [C14:209] Praetor's Counsel +1 [C14:208] Overwhelming Stampede +1 [C14:207] Overrun +1 [C14:206] Masked Admirers +1 [C14:205] Lys Alana Huntmaster +1 [C14:204] Llanowar Elves +1 [C14:203] Joraga Warcaller +1 [C14:202] Imperious Perfect +1 [C14:201] Immaculate Magistrate +1 [C14:289] Crystal Vein +1 [C14:200] Hunting Triad +1 [C14:45] Lifeblood Hydra +1 [C14:44] Grave Sifter +1 [C14:42] Creeperhulk +1 [C14:219] Thornweald Archer +1 [C14:49] Thunderfoot Baloth +1 [C14:218] Terastodon +1 [C14:217] Sylvan Safekeeper +1 [C14:48] Sylvan Offering +1 [C14:216] Sylvan Ranger +1 [C14:47] Song of the Dryads +1 [C14:215] Soul of the Harvest +1 [C14:46] Siege Behemoth +1 [C14:214] Silklash Spider +1 [C14:213] Reclamation Sage +25 [C14:334] Forest +1 [C14:212] Rampaging Baloths +1 [C14:211] Primordial Sage +1 [C14:210] Priest of Titania +1 [C14:298] Ghost Quarter +1 [C14:297] Gargoyle Castle +1 [C14:252] Moss Diamond +1 [C14:295] Evolving Wilds +SB: 1 [KLD:165] Oviya Pashiri, Sage Lifecrafter diff --git a/Mage.Tests/pom.xml b/Mage.Tests/pom.xml index 210ea3d16e4..06830c290ef 100644 --- a/Mage.Tests/pom.xml +++ b/Mage.Tests/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-tests diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java index b5e1ca8afd4..c25d6cad2d8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java @@ -1,56 +1,56 @@ - -package org.mage.test.cards.abilities.abilitywords; - -import mage.constants.PhaseStep; -import mage.constants.Zone; -import org.junit.Test; -import org.mage.test.serverside.base.CardTestPlayerBase; - -/** - * - * @author LevelX2 - */ -public class RevoltTest extends CardTestPlayerBase { - - /** - * In a duel commander match, I played a turn 1 Narnam Renegade off a basic - * forest, and it entered the battlefield with a +1/+1 counter (it shouldn't - * have). - */ - @Test - public void testFalseCondition() { - // Deathtouch - // Revolt — Narnam Renegade enters the battlefield with a +1/+1 counter on it if a permanent you controlled left this battlefield this turn. - addCard(Zone.HAND, playerA, "Narnam Renegade", 1); // Creature 1/2 {G} - addCard(Zone.HAND, playerA, "Forest", 1); - - playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Narnam Renegade"); - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertPowerToughness(playerA, "Narnam Renegade", 1, 2); - } - - @Test - public void testTrueCondition() { - // Deathtouch - // Revolt — Narnam Renegade enters the battlefield with a +1/+1 counter on it if a permanent you controlled left this battlefield this turn. - addCard(Zone.HAND, playerA, "Narnam Renegade", 1); // Creature 1/2 {G} - // {T}, Sacrifice Terramorphic Expanse: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library. - addCard(Zone.BATTLEFIELD, playerA, "Terramorphic Expanse", 1); - addCard(Zone.HAND, playerA, "Forest", 1); - - playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Narnam Renegade"); - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertGraveyardCount(playerA, "Terramorphic Expanse", 1); - assertPowerToughness(playerA, "Narnam Renegade", 2, 3); - } - -} + +package org.mage.test.cards.abilities.abilitywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class RevoltTest extends CardTestPlayerBase { + + /** + * In a duel commander match, I played a turn 1 Narnam Renegade off a basic + * forest, and it entered the battlefield with a +1/+1 counter (it shouldn't + * have). + */ + @Test + public void testFalseCondition() { + // Deathtouch + // Revolt — Narnam Renegade enters the battlefield with a +1/+1 counter on it if a permanent you controlled left this battlefield this turn. + addCard(Zone.HAND, playerA, "Narnam Renegade", 1); // Creature 1/2 {G} + addCard(Zone.HAND, playerA, "Forest", 1); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Narnam Renegade"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Narnam Renegade", 1, 2); + } + + @Test + public void testTrueCondition() { + // Deathtouch + // Revolt — Narnam Renegade enters the battlefield with a +1/+1 counter on it if a permanent you controlled left this battlefield this turn. + addCard(Zone.HAND, playerA, "Narnam Renegade", 1); // Creature 1/2 {G} + // {T}, Sacrifice Terramorphic Expanse: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library. + addCard(Zone.BATTLEFIELD, playerA, "Terramorphic Expanse", 1); + addCard(Zone.HAND, playerA, "Forest", 1); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Narnam Renegade"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Terramorphic Expanse", 1); + assertPowerToughness(playerA, "Narnam Renegade", 2, 3); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RiotTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RiotTest.java new file mode 100644 index 00000000000..41b7b56991e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RiotTest.java @@ -0,0 +1,116 @@ +package org.mage.test.cards.abilities.keywords; + +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.RiotAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class RiotTest extends CardTestPlayerBase { + + /** + * A creature with riot enters the battlefield with a +1/+1 counter on it or + * with haste, its controller's choice. This choice is made as the creature + * enters the battlefield, so no one can respond to the choice. + * + * The creature will have the chosen bonus the moment it enters the + * battlefield. If you choose to have the creature gain haste, it keeps + * haste even after the turn ends. This could matter if another player gains + * control of the creature later. + */ + @Test + public void RiotBoost() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + + // Riot (This creature enters the battleifled with your choice of a +1/+1 counter or haste.) + addCard(Zone.HAND, playerA, "Rampaging Rendhorn", 1); // Creature {4}{G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rampaging Rendhorn"); + setChoice(playerA, "Yes"); // yes - counter + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Rampaging Rendhorn", 1); + assertPowerToughness(playerA, "Rampaging Rendhorn", 5, 5); + assertAbility(playerA, "Rampaging Rendhorn", HasteAbility.getInstance(), false); + + } + + @Test + public void RiotHaste() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + + // Riot (This creature enters the battlefield with your choice of a +1/+1 counter or haste.) + addCard(Zone.HAND, playerA, "Rampaging Rendhorn", 1); // Creature {4}{G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rampaging Rendhorn"); + setChoice(playerA, "No"); // no - haste + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Rampaging Rendhorn", 1); + assertPowerToughness(playerA, "Rampaging Rendhorn", 4, 4); + assertAbility(playerA, "Rampaging Rendhorn", HasteAbility.getInstance(), true); + } + + @Test + public void RiotRhythmOfTheWildBoost() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + + // Creature spells you control can't be countered. + // Nontoken creatures you control have riot. + addCard(Zone.BATTLEFIELD, playerA, "Rhythm of the Wild", 1); + + // Riot (This creature enters the battleifled with your choice of a +1/+1 counter or haste.) + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); // Creature {1}{W} 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + setChoice(playerA, "Yes"); // yes - counter + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertPowerToughness(playerA, "Silvercoat Lion", 3, 3); + assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), false); + assertAbility(playerA, "Silvercoat Lion", new RiotAbility(), true); + } + + @Test + public void RiotRhythmOfTheWildHaste() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + + // Creature spells you control can't be countered. + // Nontoken creatures you control have riot. + addCard(Zone.BATTLEFIELD, playerA, "Rhythm of the Wild", 1); + + // Riot (This creature enters the battleifled with your choice of a +1/+1 counter or haste.) + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); // Creature {1}{W} 2/2 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + setChoice(playerA, "No"); // no - haste + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertPowerToughness(playerA, "Silvercoat Lion", 2, 2); + assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), true); + assertAbility(playerA, "Silvercoat Lion", new RiotAbility(), true); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java index 12b594c155b..ce9d973e1bb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.continuous; import mage.abilities.keyword.IndestructibleAbility; @@ -11,7 +10,6 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.permanent.Permanent; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -114,10 +112,6 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase { String bloodmoon = "Blood Moon"; String canopyvista = "Canopy Vista"; - /* - TODO: NOTE: this test is currently failing due to bug in code. See issue #3072 - */ - //@Ignore @Test public void testBloodMoonBeforeUrborg() { // Blood Moon 2R @@ -147,10 +141,6 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase { Assert.assertTrue("The mana the land can produce should be [{R}] but it's " + playerB.getManaAvailable(currentGame).toString(), playerB.getManaAvailable(currentGame).toString().equals("[{R}]")); } - /* - TODO: NOTE: this test is currently failing due to bug in code. See issue #3072 - */ - //@Ignore @Test public void testBloodMoonAfterUrborg() { // Blood Moon 2R @@ -186,6 +176,7 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase { In terms of time-stamp order, Urborg was down first, then Kormus Bell, then Quicksilver. When I put a flood counter on a basic swamp, it would become a 0/0 instead of a 1/1 and die. */ + @Test public void testCormusBellAfterUrborg() { // Land - Legendary @@ -250,19 +241,19 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Blood Sun"); // all lands lose all abilities except for mana-producing addCard(Zone.BATTLEFIELD, playerA, "Stormtide Leviathan"); // all lands are islands in addition to their other types addCard(Zone.BATTLEFIELD, playerA, "Darksteel Citadel"); // land has indestructible ability - + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); execute(); - + Permanent darksteel = getPermanent("Darksteel Citadel", playerA.getId()); Assert.assertNotNull(darksteel); Assert.assertFalse(darksteel.getAbilities().contains(IndestructibleAbility.getInstance())); // The ability is removed - + /* If a continuous effect has started applying in an earlier layer, it will continue to apply in later layers even if the ability that created that effect has been removed. Urborg ability is applied in the 4th layer. The Blood Sun works in the 6th. So the effect still applies to the lands. - */ + */ assertType(urborgtoy, CardType.LAND, SubType.SWAMP); assertType("Mountain", CardType.LAND, SubType.SWAMP); assertType(urborgtoy, CardType.LAND, SubType.ISLAND); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyCreatureCardToTokenImplTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyCreatureCardToTokenImplTest.java index 02341d56f57..c22fe6f299d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyCreatureCardToTokenImplTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyCreatureCardToTokenImplTest.java @@ -7,6 +7,7 @@ package org.mage.test.cards.copy; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -23,6 +24,7 @@ public class CopyCreatureCardToTokenImplTest extends CardTestPlayerBase { * either. */ @Test + @Ignore public void testTokenTriggeresETBEffect() { // Flying // Sphinx spells you cast cost {2} less to cast. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java index 7421496e7d8..bfbaef65bb8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java @@ -2,6 +2,7 @@ package org.mage.test.cards.single.avr; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -197,6 +198,7 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { * */ @Test + @Ignore public void testCastWithColorlessManaCanBeCountered() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); addCard(Zone.HAND, playerA, "Cavern of Souls"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java index 95d3140bdcc..f66f66b05c9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java @@ -1,15 +1,16 @@ package org.mage.test.cards.single.vis; -import java.util.UUID; import mage.game.permanent.Permanent; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import java.util.UUID; -import static mage.constants.Zone.*; import static mage.constants.PhaseStep.*; +import static mage.constants.Zone.BATTLEFIELD; +import static mage.constants.Zone.HAND; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; public class BroodOfCockroachesTest extends CardTestPlayerBase { @@ -20,7 +21,7 @@ public class BroodOfCockroachesTest extends CardTestPlayerBase { @Test public void should_display_correct_text() { - String expectedText = "When {this} dies, at the beginning of the next end step, you lose 1 life and return Brood of Cockroaches to your hand."; + String expectedText = "When {this} is put into your graveyard from the battlefield, at the beginning of the next end step, you lose 1 life and return {this} to your hand."; playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase(); @@ -29,7 +30,6 @@ public class BroodOfCockroachesTest extends CardTestPlayerBase { Permanent permanent = getPermanent(BROOD_OF_COCKROACHES, playerA); assertThat(permanent.getAbilities().get(1).toString(), is(expectedText)); - } @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/commander/CommanderColorIdentityTest.java b/Mage.Tests/src/test/java/org/mage/test/commander/CommanderColorIdentityTest.java index 293bde40aa0..7dcfa0c827f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/commander/CommanderColorIdentityTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/commander/CommanderColorIdentityTest.java @@ -1,11 +1,9 @@ - package org.mage.test.commander; import mage.cards.Card; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.filter.FilterMana; -import mage.util.CardUtil; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestCommander3PlayersFFA; diff --git a/Mage.Tests/src/test/java/org/mage/test/commander/duel/MythUnboundTest.java b/Mage.Tests/src/test/java/org/mage/test/commander/duel/MythUnboundTest.java new file mode 100644 index 00000000000..0388fbde92c --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/commander/duel/MythUnboundTest.java @@ -0,0 +1,51 @@ +package org.mage.test.commander.duel; + +import java.io.FileNotFoundException; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.GameException; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommanderDuelBase; + +/** + * + * @author LevelX2 + */ +public class MythUnboundTest extends CardTestCommanderDuelBase { + + @Override + protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + // Karador, Ghost Chieftain costs {1} less to cast for each creature card in your graveyard. + // During each of your turns, you may cast one creature card from your graveyard. + setDecknamePlayerA("CommanderOviya.dck"); // Commander = Oviya Pashiri, Sage Lifecrafter {G} + setDecknamePlayerB("CMDNorinTheWary.dck"); + + return super.createNewGameAndPlayers(); + } + + @Test + public void castCommanderTwice() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + // Your commander costs {1} less to cast for each time it's been cast from the command zone this game. + // Whenever your commander is put into the command zone from anywhere, draw a card. + addCard(Zone.BATTLEFIELD, playerA, "Myth Unbound", 1); // Enchantment {2}{G} + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2); + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oviya Pashiri, Sage Lifecrafter"); + + castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Lightning Bolt", "Oviya Pashiri, Sage Lifecrafter"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Oviya Pashiri, Sage Lifecrafter"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Myth Unbound", 1); + assertGraveyardCount(playerB, "Lightning Bolt", 1); + assertPermanentCount(playerA, "Oviya Pashiri, Sage Lifecrafter", 1); + assertHandCount(playerA, 1); + assertTappedCount("Forest", false, 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index afdbc2270e0..4842c49e6d2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -1159,7 +1159,7 @@ public class TestPlayer implements Player { findPermanent(firstFilter, groups[0], computerPlayer.getId(), game); // Second check to filter creature for combat - less strict to workaround issue in #3038 FilterCreatureForCombat secondFilter = new FilterCreatureForCombat(); - // secondFilter.add(Predicates.not(new AttackingPredicate())); + // secondFilter.add(Predicates.not(AttackingPredicate.instance)); secondFilter.add(Predicates.not(new SummoningSicknessPredicate())); // TODO: Cannot enforce legal attackers multiple times per combat. See issue #3038 Permanent attacker = findPermanent(secondFilter, groups[0], computerPlayer.getId(), game, false); @@ -2368,6 +2368,11 @@ public class TestPlayer implements Player { return computerPlayer.gainLife(amount, game, sourceId); } + @Override + public int damage(int damage, UUID sourceId, Game game) { + return computerPlayer.damage(damage, sourceId, game); + } + @Override public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) { return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable); @@ -2604,13 +2609,13 @@ public class TestPlayer implements Player { } @Override - public boolean flipCoin(Game game) { - return computerPlayer.flipCoin(game); + public boolean flipCoin(Ability source, Game game, boolean winnable) { + return computerPlayer.flipCoin(source, game, true); } @Override - public boolean flipCoin(Game game, ArrayList appliedEffects) { - return computerPlayer.flipCoin(game, appliedEffects); + public boolean flipCoin(Ability source, Game game, boolean winnable, ArrayList appliedEffects) { + return computerPlayer.flipCoin(source, game, true, appliedEffects); } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 4c18ad006f2..68a3ea860d7 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.cards.Card; import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; -import mage.cards.decks.importer.DeckImporterUtil; +import mage.cards.decks.importer.DeckImporter; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.cards.repository.CardScanner; @@ -189,7 +189,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement if (loadedDeckCardLists.containsKey(deckName)) { list = loadedDeckCardLists.get(deckName); } else { - list = DeckImporterUtil.importDeck(deckName); + list = DeckImporter.importDeckFromFile(deckName); loadedDeckCardLists.put(deckName, list); } Deck deck = Deck.load(list, false, false); diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java index 360bd942514..384d89c21f1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java +++ b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java @@ -138,6 +138,11 @@ public class PlayerStub implements Player { return 0; } + @Override + public int damage(int damage, UUID sourceId, Game game) { + return 0; + } + @Override public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) { return 0; @@ -598,7 +603,8 @@ public class PlayerStub implements Player { } @Override - public void lookAtAllLibraries(Ability source, Game game) {} + public void lookAtAllLibraries(Ability source, Game game) { + } @Override public boolean canPlayLand() { @@ -636,12 +642,12 @@ public class PlayerStub implements Player { } @Override - public boolean flipCoin(Game game) { + public boolean flipCoin(Ability source, Game game, boolean winnable) { return false; } @Override - public boolean flipCoin(Game game, ArrayList appliedEffects) { + public boolean flipCoin(Ability source, Game game, boolean winnable, ArrayList appliedEffects) { return false; } diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java new file mode 100644 index 00000000000..b076f71635e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java @@ -0,0 +1,137 @@ +package org.mage.test.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.Effect; +import mage.cards.*; +import mage.target.Target; +import org.apache.log4j.Logger; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author JayDi85 & ZeldaZach + */ +public class ExportJsonGameplayDataTest { + + private static final Logger logger = Logger.getLogger(ExportJsonGameplayDataTest.class); + + @Test + @Ignore + /** + * It's export code example for https://github.com/mtgjson/mtgjson4 + */ + public void exportTest() { + List cards = new ArrayList<>(); + Collection sets = Sets.getInstance().values(); + for (ExpansionSet set : sets) { + for (ExpansionSet.SetCardInfo setInfo : set.getSetCardInfo()) { + cards.add(CardImpl.createCard(setInfo.getCardClass(), new CardSetInfo(setInfo.getName(), set.getCode(), + setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo()))); + } + + JsonObject res = new JsonObject(); + + for (Card card : cards) { + try { + JsonObject resCard = new JsonObject(); + res.add(card.getName(), resCard); + + JsonArray resAbilities = new JsonArray(); + resCard.add("abilities", resAbilities); + for (Ability ability : card.getAbilities()) { + JsonObject resAbility = new JsonObject(); + resAbilities.add(resAbility); + + // basic + resAbility.addProperty("cost", ability.getManaCosts().getText()); + resAbility.addProperty("name", ability.toString()); + resAbility.addProperty("class", ability.getClass().getSimpleName()); + //resAbility.addProperty("rule", ability.getRule()); + + // modes + JsonArray resModes = new JsonArray(); + resAbility.add("modes", resModes); + for (Mode mode : ability.getModes().values()) { + JsonObject resMode = new JsonObject(); + resModes.add(resMode); + + // basic + //resMode.addProperty("name", mode.toString()); + + // effects + JsonArray resEffects = new JsonArray(); + resMode.add("effects", resEffects); + for (Effect effect : mode.getEffects()) { + JsonObject resEffect = new JsonObject(); + resEffects.add(resEffect); + + resEffect.addProperty("class", effect.getClass().getSimpleName()); + resEffect.addProperty("outcome", effect.getOutcome().toString()); + resEffect.addProperty("text", effect.getText(mode)); + } + if (resEffects.size() == 0) { + resMode.remove("effects"); + } + + // targets + JsonArray resTargets = new JsonArray(); + resMode.add("targets", resTargets); + for (Target target : mode.getTargets()) { + JsonObject resTarget = new JsonObject(); + resTargets.add(resTarget); + + resTarget.addProperty("name", target.getTargetName()); + resTarget.addProperty("class", target.getClass().getSimpleName()); + resTarget.addProperty("min", target.getMinNumberOfTargets()); + resTarget.addProperty("max", target.getMaxNumberOfTargets()); + } + if (resTargets.size() == 0) { + resMode.remove("targets"); + } + + if (resMode.get("effects") == null && resMode.get("targets") == null) { + resModes.remove(resMode); + } + } + if (resModes.size() == 0) { + resAbility.remove("modes"); + } + } + } catch (Throwable e) { + logger.error("Inner error for " + card.getName() + ": " + e.getMessage(), e); + break; + } + } + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + String filePath = System.getProperty("user.dir") + "/json/" + set.getCode() + ".json"; + File outputFile = new File(filePath); + final boolean mkdirs = outputFile.getParentFile().mkdirs(); + + try (Writer writer = + new BufferedWriter( + new OutputStreamWriter( + new FileOutputStream(outputFile, false), StandardCharsets.UTF_8 + ) + ) + ) { + writer.write(gson.toJson(res)); + System.out.println("Wrote " + set.getCode() + " to file"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/RandomTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/RandomTest.java index 2d20d3f909e..5735e12d601 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/RandomTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/RandomTest.java @@ -1,12 +1,27 @@ package org.mage.test.utils; +import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; +import mage.constants.MultiplayerAttackOption; +import mage.constants.PlanarDieRoll; +import mage.constants.RangeOfInfluence; +import mage.game.Game; +import mage.game.TwoPlayerDuel; +import mage.player.human.HumanPlayer; +import mage.players.Player; import mage.util.RandomUtil; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; /** @@ -56,5 +71,98 @@ public class RandomTest { Assert.assertNotEquals("different seed must have different deck", infoSameA, infoDifferent); } + @Test + @Ignore + public void test_GenerateRandomPng() throws IOException { + String dest = "f:/test/xmage/"; + int height = 512; + int weight = 512; + BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < weight; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, RandomUtil.nextBoolean() ? Color.white.getRGB() : Color.black.getRGB()); + } + } + ImageIO.write(image, "png", new File(dest + "xmage_random.png")); + } + @Test + @Ignore + public void test_GenerateRandomDicePng() throws IOException { + String dest = "f:/test/xmage/"; + //RandomUtil.setSeed(123); + Player player = new HumanPlayer("random", RangeOfInfluence.ALL, 1); + Game game = new TwoPlayerDuel(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 50); + + int height = 512; + int weight = 512; + BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < weight; x++) { + for (int y = 0; y < height; y++) { + // roll dice + int diceVal = player.rollDice(game, 12); + int colorMult = Math.floorDiv(255, 12); + + image.setRGB(x, y, new Color(colorMult * diceVal, colorMult * diceVal, colorMult * diceVal).getRGB()); + } + } + ImageIO.write(image, "png", new File(dest + "xmage_random_dice.png")); + } + + @Test + @Ignore + public void test_GenerateRandomPlanarDicePng() throws IOException { + String dest = "f:/test/xmage/"; + //RandomUtil.setSeed(123); + Player player = new HumanPlayer("random", RangeOfInfluence.ALL, 1); + Game game = new TwoPlayerDuel(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 50); + + int height = 512; + int weight = 512; + BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < weight; x++) { + for (int y = 0; y < height; y++) { + // roll planar dice + PlanarDieRoll res = player.rollPlanarDie(game); + image.setRGB(x, y, new Color( + res.equals(PlanarDieRoll.CHAOS_ROLL) ? 255 : 0, + res.equals(PlanarDieRoll.PLANAR_ROLL) ? 255 : 0, + res.equals(PlanarDieRoll.NIL_ROLL) ? 255 : 0 + ).getRGB()); + } + } + ImageIO.write(image, "png", new File(dest + "xmage_random_planar_dice.png")); + } + + @Test + @Ignore + public void test_GenerateRandomLibraryShufflePng() throws IOException { + String dest = "f:/test/xmage/"; + //RandomUtil.setSeed(123); + Player player = new HumanPlayer("random", RangeOfInfluence.ALL, 1); + Game game = new TwoPlayerDuel(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 50); + Deck deck = DeckTestUtils.buildRandomDeck("WGUBR", false, "GRN"); + player.getLibrary().addAll(deck.getCards(), game); + + // multiple cards analyze + for (int i = 0; i < player.getLibrary().size(); i++) { + UUID cardId = player.getLibrary().getCardList().get(i); + //int halfIndex = Math.floorDiv(player.getLibrary().size(), 2); + int colorMult = Math.floorDiv(255, player.getLibrary().size()); + + int height = 512; + int weight = 512; + BufferedImage image = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < weight; x++) { + for (int y = 0; y < height; y++) { + // shuffle, search card position and draw + player.getLibrary().shuffle(); + int cardPos = player.getLibrary().getCardPosition(cardId); + //image.setRGB(x, y, cardPos < halfIndex ? Color.white.getRGB() : Color.black.getRGB()); + image.setRGB(x, y, new Color(colorMult * cardPos, colorMult * cardPos, colorMult * cardPos).getRGB()); + } + } + ImageIO.write(image, "png", new File(dest + "xmage_random_shuffle_" + i + ".png")); + } + } } diff --git a/Mage.Updater/pom.xml b/Mage.Updater/pom.xml index 183b4f90e1e..f4d46c76553 100644 --- a/Mage.Updater/pom.xml +++ b/Mage.Updater/pom.xml @@ -5,7 +5,7 @@ mage-root org.mage - 1.4.32 + 1.4.33 4.0.0 diff --git a/Mage.Verify/pom.xml b/Mage.Verify/pom.xml index fb561bf2371..d4f35af8f7c 100644 --- a/Mage.Verify/pom.xml +++ b/Mage.Verify/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage-verify @@ -32,7 +32,7 @@ com.fasterxml.jackson.core jackson-databind - 2.9.7 + 2.9.8 @@ -49,7 +49,7 @@ org.mage mage-client - 1.4.32 + 1.4.33 diff --git a/Mage.Verify/src/main/java/mage/verify/JsonCard.java b/Mage.Verify/src/main/java/mage/verify/JsonCard.java index d01d9c8ba02..bb85a00e7d2 100644 --- a/Mage.Verify/src/main/java/mage/verify/JsonCard.java +++ b/Mage.Verify/src/main/java/mage/verify/JsonCard.java @@ -1,7 +1,12 @@ package mage.verify; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + import java.util.List; +import static mage.verify.MtgJson.MTGJSON_IGNORE_NEW_PROPERTIES; + +@JsonIgnoreProperties(ignoreUnknown = MTGJSON_IGNORE_NEW_PROPERTIES) class JsonCard { // docs: https://mtgjson.com/v4/docs.html diff --git a/Mage.Verify/src/main/java/mage/verify/JsonForeignData.java b/Mage.Verify/src/main/java/mage/verify/JsonForeignData.java index c6ca9353e46..5c85acd664a 100644 --- a/Mage.Verify/src/main/java/mage/verify/JsonForeignData.java +++ b/Mage.Verify/src/main/java/mage/verify/JsonForeignData.java @@ -1,5 +1,10 @@ package mage.verify; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import static mage.verify.MtgJson.MTGJSON_IGNORE_NEW_PROPERTIES; + +@JsonIgnoreProperties(ignoreUnknown = MTGJSON_IGNORE_NEW_PROPERTIES) public class JsonForeignData { public String flavorText; public String language; diff --git a/Mage.Verify/src/main/java/mage/verify/JsonSet.java b/Mage.Verify/src/main/java/mage/verify/JsonSet.java index 614d73123d2..d53d310d04f 100644 --- a/Mage.Verify/src/main/java/mage/verify/JsonSet.java +++ b/Mage.Verify/src/main/java/mage/verify/JsonSet.java @@ -1,7 +1,12 @@ package mage.verify; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + import java.util.List; +import static mage.verify.MtgJson.MTGJSON_IGNORE_NEW_PROPERTIES; + +@JsonIgnoreProperties(ignoreUnknown = MTGJSON_IGNORE_NEW_PROPERTIES) class JsonSet { public int baseSetSize; public String block; diff --git a/Mage.Verify/src/main/java/mage/verify/JsonToken.java b/Mage.Verify/src/main/java/mage/verify/JsonToken.java index 92237ae01f9..c3484856890 100644 --- a/Mage.Verify/src/main/java/mage/verify/JsonToken.java +++ b/Mage.Verify/src/main/java/mage/verify/JsonToken.java @@ -1,7 +1,12 @@ package mage.verify; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + import java.util.List; +import static mage.verify.MtgJson.MTGJSON_IGNORE_NEW_PROPERTIES; + +@JsonIgnoreProperties(ignoreUnknown = MTGJSON_IGNORE_NEW_PROPERTIES) public class JsonToken { public String artist; public String borderColor; diff --git a/Mage.Verify/src/main/java/mage/verify/MtgJson.java b/Mage.Verify/src/main/java/mage/verify/MtgJson.java index 11f147029a7..5eb355d472b 100644 --- a/Mage.Verify/src/main/java/mage/verify/MtgJson.java +++ b/Mage.Verify/src/main/java/mage/verify/MtgJson.java @@ -24,6 +24,8 @@ public final class MtgJson { public static Map mtgJsonToXMageCodes = new HashMap<>(); public static Map xMageToMtgJsonCodes = new HashMap<>(); + public static final boolean MTGJSON_IGNORE_NEW_PROPERTIES = true; // set it to false for full mtgjson checks and research (new fields finds or mtgjson updates) + static { mtgJsonToXMageCodes.put("pWCQ", "WMCQ"); mtgJsonToXMageCodes.put("pSUS", "SUS"); diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 6dc4d002136..6dc375d3b27 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -4,6 +4,7 @@ import mage.ObjectColor; import mage.abilities.keyword.MultikickerAbility; import mage.cards.*; import mage.cards.basiclands.BasicLand; +import mage.cards.repository.*; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.SubType; @@ -565,6 +566,7 @@ public class VerifyCardDataTest { //checkNumbers(card, ref); // TODO: load data from allsets.json and check it (allcards.json do not have card numbers) checkBasicLands(card, ref); checkMissingAbilities(card, ref); + //checkWrongCosts(card, ref); } private void checkColors(Card card, JsonCard ref) { @@ -656,6 +658,128 @@ public class VerifyCardDataTest { } } + private String prepareRule(String cardName, String rule) { + // remove and optimize rule text for analyze + String newRule = rule; + + // remove reminder text + newRule = newRule.replaceAll("(?i)\\(.+\\)", ""); + + // replace special text and symbols + newRule = newRule + .replace("{this}", cardName) + .replace("—", "—"); + + // remove html marks + newRule = newRule + .replace("", "") + .replace("", ""); + + return newRule; + } + + @Test + @Ignore + public void showCardInfo() throws Exception { + // debug only: show direct card info (takes it from class file, not from db repository) + String cardName = "Essence Capture"; + CardScanner.scan(); + CardSetInfo testSet = new CardSetInfo("test", "test", "123", Rarity.COMMON); + CardInfo cardInfo = CardRepository.instance.findCard(cardName); + Card card = CardImpl.createCard(cardInfo.getClassName(), testSet); + card.getRules().stream().forEach(System.out::println); + } + + private void checkWrongCosts(Card card, JsonCard ref) { + // checks missing or wrong cost + if (!card.getExpansionSetCode().equals("RNA")) { + return; + } + + String[] refRules = ref.text.split("[\\$\\\n]"); // ref card's abilities can be splited by \n or $ chars + for (int i = 0; i < refRules.length; i++) { + refRules[i] = prepareRule(card.getName(), refRules[i]); + } + + String[] cardRules = card.getRules().toArray(new String[0]); + for (int i = 0; i < cardRules.length; i++) { + cardRules[i] = prepareRule(card.getName(), cardRules[i]); + } + + for (String cardRule : cardRules) { + boolean isAbilityFounded = false; + boolean isCostOk = false; + for (String refRule : refRules) { + if (cardRule.equals(refRule)) { + isAbilityFounded = true; + isCostOk = true; + break; + } + } + + if (!isCostOk) { + fail(card, "abilities", "card ability have cost, but can't find in ref [" + "xxx" + ": " + card.getRules() + "]"); + } + } + } + + + /* + for(String rule : card.getRules()) { + rule = rule.replaceAll("(?i).+", ""); // Ignoring reminder text in italic + // TODO: add Equip {3} checks + // TODO: add Raid and other words checks + String[] sl = rule.split(":"); + if (sl.length == 2 && !sl[0].isEmpty()) { + String cardCost = sl[0] + .replace("{this}", card.getName()) + //.replace("", "") + //.replace("", "") + .replace("—", "—"); + String cardAbility = sl[1] + .trim() + .replace("{this}", card.getName()) + //.replace("", "") + //.replace("", "") + .replace("—", "—");; + + boolean found = false; + for (String refRule : refRules) { + refRule = refRule.replaceAll("(?i).+", ""); // Ignoring reminder text in italic + + // fix for ref mana: ref card have xxx instead {T}: Add {xxx}, example: W + if (refRule.length() == 1) { + refRule = "{T}: Add {" + refRule + "}"; + } + refRule = refRule + .trim() + //.replace("", "") + //.replace("", "") + .replace("—", "—"); + + // normal + if (refRule.startsWith(cardCost)) { + found = true; + break; + } + + // ref card have (xxx) instead xxx, example: ({T}: Add {G}.) + // ref card have (xxx) instead xxx, example: ({T}: Add {G}.) + // TODO: delete? + if (refRule.startsWith("(" + cardCost)) { + found = true; + break; + } + } + if (!found) { + fail(card, "abilities", "card ability have cost, but can't find in ref [" + cardCost + ": " + cardAbility + "]"); + } + } + + } + }*/ + + private void checkTypes(Card card, JsonCard ref) { if (skipListHaveName("TYPE", card.getExpansionSetCode(), card.getName())) { return; diff --git a/Mage/pom.xml b/Mage/pom.xml index ecb37107e1a..981365c3eea 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 mage diff --git a/Mage/src/main/java/mage/MageObjectReference.java b/Mage/src/main/java/mage/MageObjectReference.java index ff72668e405..44f63bebc66 100644 --- a/Mage/src/main/java/mage/MageObjectReference.java +++ b/Mage/src/main/java/mage/MageObjectReference.java @@ -1,7 +1,5 @@ package mage; -import java.io.Serializable; -import java.util.UUID; import mage.cards.Card; import mage.constants.Zone; import mage.game.Game; @@ -10,6 +8,9 @@ import mage.game.stack.Spell; import mage.game.stack.StackObject; import org.apache.log4j.Logger; +import java.io.Serializable; +import java.util.UUID; + /** * A object reference that takes zone changes into account. * @@ -145,4 +146,8 @@ public class MageObjectReference implements Comparable, Ser } return null; } + + public boolean zoneCounterIsCurrent(Game game) { + return game.getState().getZoneChangeCounter(sourceId) == zoneChangeCounter; + } } diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index 4ef44edad6f..e28354a1ba3 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -1,10 +1,8 @@ package mage.abilities; -import java.io.Serializable; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.abilities.costs.Cost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.Costs; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; @@ -24,6 +22,10 @@ import mage.target.Targets; import mage.target.targetadjustment.TargetAdjuster; import mage.watchers.Watcher; +import java.io.Serializable; +import java.util.List; +import java.util.UUID; + /** * Practically everything in the game is started from an Ability. This interface * describes what an Ability is composed of at the highest level. @@ -44,10 +46,8 @@ public interface Ability extends Controllable, Serializable { * * @see mage.players.PlayerImpl#playAbility(mage.abilities.ActivatedAbility, * mage.game.Game) - * @see - * mage.game.GameImpl#addTriggeredAbility(mage.abilities.TriggeredAbility) - * @see - * mage.game.GameImpl#addDelayedTriggeredAbility(mage.abilities.DelayedTriggeredAbility) + * @see mage.game.GameImpl#addTriggeredAbility(mage.abilities.TriggeredAbility) + * @see mage.game.GameImpl#addDelayedTriggeredAbility(mage.abilities.DelayedTriggeredAbility) */ void newId(); @@ -56,10 +56,8 @@ public interface Ability extends Controllable, Serializable { * * @see mage.players.PlayerImpl#playAbility(mage.abilities.ActivatedAbility, * mage.game.Game) - * @see - * mage.game.GameImpl#addTriggeredAbility(mage.abilities.TriggeredAbility) - * @see - * mage.game.GameImpl#addDelayedTriggeredAbility(mage.abilities.DelayedTriggeredAbility) + * @see mage.game.GameImpl#addTriggeredAbility(mage.abilities.TriggeredAbility) + * @see mage.game.GameImpl#addDelayedTriggeredAbility(mage.abilities.DelayedTriggeredAbility) */ void newOriginalId(); @@ -143,7 +141,7 @@ public interface Ability extends Controllable, Serializable { /** * TODO Method is unused, keep it around? - * + *

* Gets all costs that are optional to this ability. These costs can be paid * in addition to other costs to have other effects put into place. * @@ -208,7 +206,6 @@ public interface Ability extends Controllable, Serializable { * * @return The {@link java.util.UUID} of the first target within the targets * list. - * * @see mage.target.Target */ UUID getFirstTarget(); @@ -266,17 +263,15 @@ public interface Ability extends Controllable, Serializable { /** * Activates this ability prompting the controller to pay any mandatory * - * @param game A reference the {@link Game} for which this ability should be - * activated within. + * @param game A reference the {@link Game} for which this ability should be + * activated within. * @param noMana Whether or not {@link ManaCosts} have to be paid. * @return True if this ability was successfully activated. - * * @see mage.players.PlayerImpl#cast(mage.abilities.SpellAbility, * mage.game.Game, boolean) * @see mage.players.PlayerImpl#playAbility(mage.abilities.ActivatedAbility, * mage.game.Game) - * @see - * mage.players.PlayerImpl#triggerAbility(mage.abilities.TriggeredAbility, + * @see mage.players.PlayerImpl#triggerAbility(mage.abilities.TriggeredAbility, * mage.game.Game) */ boolean activate(Game game, boolean noMana); @@ -290,9 +285,7 @@ public interface Ability extends Controllable, Serializable { * * @param game The {@link Game} for which this ability resolves within. * @return Whether or not this ability successfully resolved. - * - * @see - * mage.players.PlayerImpl#playManaAbility(mage.abilities.mana.ManaAbility, + * @see mage.players.PlayerImpl#playManaAbility(mage.abilities.mana.ManaAbility, * mage.game.Game) * @see mage.players.PlayerImpl#specialAction(mage.abilities.SpecialAction, * mage.game.Game) @@ -380,7 +373,7 @@ public interface Ability extends Controllable, Serializable { /** * Sets the value for the ruleAtTheTop attribute - * + *

* true = show the rule at the top position of the rules * * @param ruleAtTheTop @@ -398,7 +391,7 @@ public interface Ability extends Controllable, Serializable { /** * Sets the value for the worksFaceDown flag - * + *

* true = the ability works also if the object is face down * * @param worksFaceDown @@ -414,7 +407,7 @@ public interface Ability extends Controllable, Serializable { /** * Sets the value for the ruleVisible attribute - * + *

* true = rule will be shown for the card / permanent false = rule won't be * shown * @@ -432,7 +425,7 @@ public interface Ability extends Controllable, Serializable { /** * Sets the value for the additional costs rule attribute - * + *

* true = rule will be shown for the card / permanent false = rule won't be * shown * @@ -451,7 +444,7 @@ public interface Ability extends Controllable, Serializable { * Sets the ability word for the given ability. An ability word is a word * that, in essence, groups, and reminds players of, cards that have a * common functionality and does not imply any particular rules. - * + *

* --- Not usable yet for rule text generation of triggered abilities --- * * @param abilityWord @@ -526,4 +519,10 @@ public interface Ability extends Controllable, Serializable { TargetAdjuster getTargetAdjuster(); void adjustTargets(Game game); + + void setCostAdjuster(CostAdjuster costAdjuster); + + CostAdjuster getCostAdjuster(); + + void adjustCosts(Game game); } diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 481658c5078..7a3053a1264 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -1,9 +1,5 @@ package mage.abilities; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.Mana; import mage.abilities.costs.*; @@ -37,6 +33,11 @@ import mage.util.ThreadLocalStringBuilder; import mage.watchers.Watcher; import org.apache.log4j.Logger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ @@ -71,6 +72,7 @@ public abstract class AbilityImpl implements Ability { protected List subAbilities = null; protected boolean canFizzle = true; protected TargetAdjuster targetAdjuster = null; + protected CostAdjuster costAdjuster = null; public AbilityImpl(AbilityType abilityType, Zone zone) { this.id = UUID.randomUUID(); @@ -117,6 +119,7 @@ public abstract class AbilityImpl implements Ability { this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter; this.canFizzle = ability.canFizzle; this.targetAdjuster = ability.targetAdjuster; + this.costAdjuster = ability.costAdjuster; } @Override @@ -1223,4 +1226,21 @@ public abstract class AbilityImpl implements Ability { targetAdjuster.adjustTargets(this, game); } } + + @Override + public void setCostAdjuster(CostAdjuster costAdjuster) { + this.costAdjuster = costAdjuster; + } + + @Override + public CostAdjuster getCostAdjuster() { + return costAdjuster; + } + + @Override + public void adjustCosts(Game game) { + if (costAdjuster != null) { + costAdjuster.adjustCosts(this, game); + } + } } diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 8ebc0a44a66..f0ba91bf64f 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -18,6 +18,7 @@ import mage.constants.TargetController; import mage.constants.TimingRule; import mage.constants.Zone; import mage.game.Game; +import mage.game.command.Commander; import mage.game.command.Emblem; import mage.game.command.Plane; import mage.game.permanent.Permanent; @@ -235,6 +236,8 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa return ((Emblem) mageObject).isControlledBy(playerId); } else if (mageObject instanceof Plane) { return ((Plane) mageObject).isControlledBy(playerId); + } else if (mageObject instanceof Commander) { + return ((Commander) mageObject).isControlledBy(playerId); } else if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) { return ((Card) mageObject).isOwnedBy(playerId); } diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index 712dba5b529..98def5bddb6 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -1,13 +1,6 @@ package mage.abilities; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.abilities.costs.OptionalAdditionalModeSourceCosts; import mage.cards.Card; import mage.constants.Outcome; @@ -18,8 +11,9 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponent; +import java.util.*; + /** - * * @author BetaSteward_at_googlemail.com */ public class Modes extends LinkedHashMap { @@ -340,7 +334,9 @@ public class Modes extends LinkedHashMap { StringBuilder sb = new StringBuilder(); if (this.getMaxModesFilter() != null) { sb.append("choose one or more. Each mode must target ").append(getMaxModesFilter().getMessage()); - } else if (this.getMinModes() == 1 && this.getMaxModes() == 3) { + } else if (this.getMinModes() == 0 && this.getMaxModes() == 1) { + sb.append("choose up to one "); + } else if (this.getMinModes() == 1 && this.getMaxModes() > 2) { sb.append("choose one or more "); } else if (this.getMinModes() == 1 && this.getMaxModes() == 2) { sb.append("choose one or both "); diff --git a/Mage/src/main/java/mage/abilities/SpellAbility.java b/Mage/src/main/java/mage/abilities/SpellAbility.java index 201d2deb349..d96699bf3bc 100644 --- a/Mage/src/main/java/mage/abilities/SpellAbility.java +++ b/Mage/src/main/java/mage/abilities/SpellAbility.java @@ -1,8 +1,5 @@ - package mage.abilities; -import java.util.Optional; -import java.util.UUID; import mage.MageObject; import mage.MageObjectReference; import mage.abilities.costs.Cost; @@ -12,17 +9,15 @@ import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.keyword.FlashAbility; import mage.cards.Card; import mage.cards.SplitCard; -import mage.constants.AbilityType; -import mage.constants.AsThoughEffectType; -import mage.constants.SpellAbilityCastMode; -import mage.constants.SpellAbilityType; -import mage.constants.TimingRule; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.players.Player; +import java.util.Optional; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ @@ -224,12 +219,16 @@ public class SpellAbility extends ActivatedAbilityImpl { if (event.getType() != GameEvent.EventType.CAST_SPELL) { return null; } + Card card = game.getCard(event.getSourceId()); - Optional ability = card.getAbilities(game).get(event.getTargetId()); - if (ability.isPresent() && ability.get() instanceof SpellAbility) { - return (SpellAbility) ability.get(); + if (card != null) { + Optional ability = card.getAbilities(game).get(event.getTargetId()); + if (ability.isPresent() && ability.get() instanceof SpellAbility) { + return (SpellAbility) ability.get(); + } + return card.getSpellAbility(); } - return card.getSpellAbility(); + return null; } public void setId(UUID idToUse) { diff --git a/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java index 8cef6957df4..6c0af59f42b 100644 --- a/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttacksFirstTimeTriggeredAbility.java @@ -35,7 +35,7 @@ public class AttacksFirstTimeTriggeredAbility extends TriggeredAbilityImpl { if (!event.getSourceId().equals(this.getSourceId())) { return false; } - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); if (watcher == null) { return false; } diff --git a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java index 671945e5f95..987c13eb7f1 100644 --- a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java @@ -30,7 +30,7 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { public DiesCreatureTriggeredAbility(Effect effect, boolean optional, boolean another, boolean setTargetPointer) { this(effect, optional, new FilterCreaturePermanent(another ? "another creature" : "a creature")); if (another) { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } this.setTargetPointer = setTargetPointer; } diff --git a/Mage/src/main/java/mage/abilities/common/OneOrMoreCountersAddedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/OneOrMoreCountersAddedTriggeredAbility.java new file mode 100644 index 00000000000..e00c6bf00da --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/OneOrMoreCountersAddedTriggeredAbility.java @@ -0,0 +1,53 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; + +public class OneOrMoreCountersAddedTriggeredAbility extends TriggeredAbilityImpl { + + private final CounterType counterType; + + public OneOrMoreCountersAddedTriggeredAbility(Effect effect) { + this(effect, false); + } + + public OneOrMoreCountersAddedTriggeredAbility(Effect effect, boolean optional) { + this(effect, optional, CounterType.P1P1); + } + + public OneOrMoreCountersAddedTriggeredAbility(Effect effect, boolean optional, CounterType counterType) { + super(Zone.BATTLEFIELD, effect, true); + this.counterType = counterType; + } + + private OneOrMoreCountersAddedTriggeredAbility(final OneOrMoreCountersAddedTriggeredAbility ability) { + super(ability); + this.counterType = ability.counterType; + } + + @Override + public OneOrMoreCountersAddedTriggeredAbility copy() { + return new OneOrMoreCountersAddedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTERS_ADDED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getData().equals(counterType.getName()) + && event.getAmount() > 0 + && event.getTargetId().equals(this.getSourceId()); + } + + @Override + public String getRule() { + return "Whenever one or more " + counterType.getName() + " counters are put on {this}, " + super.getRule(); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldSourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldSourceTriggeredAbility.java index 2c6fb1139ee..0f83feefa23 100644 --- a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldSourceTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldSourceTriggeredAbility.java @@ -13,17 +13,21 @@ import mage.game.permanent.Permanent; */ public class PutIntoGraveFromBattlefieldSourceTriggeredAbility extends TriggeredAbilityImpl { + private boolean onlyToControllerGraveyard; + public PutIntoGraveFromBattlefieldSourceTriggeredAbility(Effect effect) { - this(effect, false); + this(effect, false, false); } - public PutIntoGraveFromBattlefieldSourceTriggeredAbility(Effect effect, boolean optional) { + public PutIntoGraveFromBattlefieldSourceTriggeredAbility(Effect effect, boolean optional, boolean onlyToControllerGraveyard) { super(Zone.ALL, effect, optional); setLeavesTheBattlefieldTrigger(true); + this.onlyToControllerGraveyard = onlyToControllerGraveyard; } public PutIntoGraveFromBattlefieldSourceTriggeredAbility(final PutIntoGraveFromBattlefieldSourceTriggeredAbility ability) { super(ability); + this.onlyToControllerGraveyard = ability.onlyToControllerGraveyard; } @Override @@ -44,7 +48,7 @@ public class PutIntoGraveFromBattlefieldSourceTriggeredAbility extends Triggered if (permanent != null && zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; + return !onlyToControllerGraveyard || this.isControlledBy(game.getOwnerId(zEvent.getTargetId())); } } return false; @@ -52,6 +56,6 @@ public class PutIntoGraveFromBattlefieldSourceTriggeredAbility extends Triggered @Override public String getRule() { - return "When {this} is put into a graveyard from the battlefield, " + super.getRule(); + return "When {this} is put into " + (onlyToControllerGraveyard ? "your" : "a") + " graveyard from the battlefield, " + super.getRule(); } } diff --git a/Mage/src/main/java/mage/abilities/common/SimpleStaticAbility.java b/Mage/src/main/java/mage/abilities/common/SimpleStaticAbility.java index 3b608a9cdcb..b71bf85dae7 100644 --- a/Mage/src/main/java/mage/abilities/common/SimpleStaticAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SimpleStaticAbility.java @@ -2,16 +2,19 @@ package mage.abilities.common; -import mage.constants.Zone; import mage.abilities.StaticAbility; import mage.abilities.effects.Effect; +import mage.constants.Zone; /** - * * @author BetaSteward_at_googlemail.com */ public class SimpleStaticAbility extends StaticAbility { + public SimpleStaticAbility(Effect effect) { + this(Zone.BATTLEFIELD, effect); + } + public SimpleStaticAbility(Zone zone, Effect effect) { super(zone, effect); } diff --git a/Mage/src/main/java/mage/abilities/common/WinsCoinFlipTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/WinsCoinFlipTriggeredAbility.java index 704ff18af23..f80b41a544a 100644 --- a/Mage/src/main/java/mage/abilities/common/WinsCoinFlipTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/WinsCoinFlipTriggeredAbility.java @@ -5,10 +5,10 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.Zone; import mage.game.Game; +import mage.game.events.CoinFlippedEvent; import mage.game.events.GameEvent; /** - * * @author TheElk801 */ public class WinsCoinFlipTriggeredAbility extends TriggeredAbilityImpl { @@ -33,7 +33,8 @@ public class WinsCoinFlipTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getFlag(); + CoinFlippedEvent flipEvent = (CoinFlippedEvent) event; + return flipEvent.isWinnable() && (flipEvent.getChosen() == flipEvent.getResult()); } @Override diff --git a/Mage/src/main/java/mage/abilities/common/ZoneChangeAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/ZoneChangeAllTriggeredAbility.java index 77872721e3d..9d97496682c 100644 --- a/Mage/src/main/java/mage/abilities/common/ZoneChangeAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/ZoneChangeAllTriggeredAbility.java @@ -1,5 +1,3 @@ - - package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; @@ -50,8 +48,9 @@ public class ZoneChangeAllTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; - if ((fromZone == null || zEvent.getFromZone() == fromZone) && (toZone == null || zEvent.getToZone() == toZone)) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if ((fromZone == null || fromZone.match(zEvent.getFromZone())) + && (toZone == null || toZone.match(zEvent.getToZone()))) { Permanent perm; if (zEvent.getTarget() != null) { perm = zEvent.getTarget(); diff --git a/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java new file mode 100644 index 00000000000..4bc9f34d73a --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java @@ -0,0 +1,36 @@ + +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.constants.TurnPhase; +import mage.game.Game; +import mage.game.stack.Spell; + +import java.util.EnumSet; +import java.util.Set; + +/** + * @author LevelX2 + */ + +public enum AddendumCondition implements Condition { + + instance; + private static final Set turnPhases = EnumSet.of( + TurnPhase.PRECOMBAT_MAIN, TurnPhase.POSTCOMBAT_MAIN + ); + + @Override + public boolean apply(Game game, Ability source) { + if (!game.isActivePlayer(source.getControllerId()) || + !turnPhases.contains(game.getTurn().getPhase().getType())) { + return false; + } + if (CastFromEverywhereSourceCondition.instance.apply(game, source)) { + return true; + } + Spell spell = game.getSpell(source.getSourceId()); + return spell != null && !spell.isCopy(); + } +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/AfterCombatCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AfterCombatCondition.java new file mode 100644 index 00000000000..76bdc4be626 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/AfterCombatCondition.java @@ -0,0 +1,25 @@ + +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.constants.PhaseStep; +import mage.game.Game; + +/** + * @author L_J + */ +public enum AfterCombatCondition implements Condition { + + instance; + @Override + + public boolean apply(Game game, Ability source) { + return game.getStep().getType().isAfter(PhaseStep.END_COMBAT); + } + + @Override + public String toString() { + return "after combat"; + } +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java index ef4a90dc6cb..17ee4adf336 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/AttackedOrBlockedThisCombatSourceCondition.java @@ -24,7 +24,7 @@ public enum AttackedOrBlockedThisCombatSourceCondition implements Condition { public boolean apply(Game game, Ability source) { Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (sourceObject != null) { - AttackedOrBlockedThisCombatWatcher watcher = (AttackedOrBlockedThisCombatWatcher) game.getState().getWatchers().get(AttackedOrBlockedThisCombatWatcher.class.getSimpleName()); + AttackedOrBlockedThisCombatWatcher watcher = game.getState().getWatcher(AttackedOrBlockedThisCombatWatcher.class); if (watcher != null) { for (MageObjectReference mor : watcher.getAttackedThisTurnCreatures()) { if (mor.refersTo(sourceObject, game)) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/AttackedThisStepCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AttackedThisStepCondition.java index babbd9580c7..026ae5b498f 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/AttackedThisStepCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/AttackedThisStepCondition.java @@ -15,7 +15,7 @@ public enum AttackedThisStepCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerAttackedStepWatcher watcher = (PlayerAttackedStepWatcher) game.getState().getWatchers().get(PlayerAttackedStepWatcher.class.getSimpleName()); + PlayerAttackedStepWatcher watcher = game.getState().getWatcher(PlayerAttackedStepWatcher.class); return watcher != null && watcher.getNumberAttackingCurrentStep(source.getControllerId()) > 0; } diff --git a/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnCondition.java index 6341d527a84..5ee7dfb4a85 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnCondition.java @@ -19,7 +19,7 @@ public enum AttackedThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); - return !watcher.getAttackedThisTurnCreatures().isEmpty(); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); + return watcher != null && !watcher.getAttackedThisTurnCreatures().isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnSourceCondition.java index 58f3719ec75..0bf152ec768 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/AttackedThisTurnSourceCondition.java @@ -18,7 +18,7 @@ public enum AttackedThisTurnSourceCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); return sourcePermanent != null && watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(sourcePermanent, game)); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/BlockedThisTurnSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/BlockedThisTurnSourceCondition.java index d6578996f64..93f37e89a2f 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/BlockedThisTurnSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/BlockedThisTurnSourceCondition.java @@ -18,7 +18,7 @@ public enum BlockedThisTurnSourceCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - BlockedThisTurnWatcher watcher = (BlockedThisTurnWatcher) game.getState().getWatchers().get(BlockedThisTurnWatcher.class.getSimpleName()); + BlockedThisTurnWatcher watcher = game.getState().getWatcher(BlockedThisTurnWatcher.class); return sourcePermanent != null && watcher.getBlockedThisTurnCreatures().contains(new MageObjectReference(sourcePermanent, game)); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java index c8135244652..1a584533ecf 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/CastFromHandSourceCondition.java @@ -33,7 +33,7 @@ public enum CastFromHandSourceCondition implements Condition { return false; } } - CastFromHandWatcher watcher = (CastFromHandWatcher) game.getState().getWatchers().get(CastFromHandWatcher.class.getSimpleName()); + CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class); if (watcher != null && watcher.spellWasCastFromHand(source.getSourceId())) { return true; } diff --git a/Mage/src/main/java/mage/abilities/condition/common/ControllerAttackedThisTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ControllerAttackedThisTurnCondition.java index b327e6e2141..d7f732d11a5 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/ControllerAttackedThisTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/ControllerAttackedThisTurnCondition.java @@ -15,7 +15,7 @@ public enum ControllerAttackedThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); return source.isControlledBy(game.getActivePlayerId()) && watcher != null && !watcher.getAttackedThisTurnCreatures().isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/DealtDamageToAnOpponent.java b/Mage/src/main/java/mage/abilities/condition/common/DealtDamageToAnOpponent.java index 4e83de1baf2..57e48306403 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/DealtDamageToAnOpponent.java +++ b/Mage/src/main/java/mage/abilities/condition/common/DealtDamageToAnOpponent.java @@ -15,7 +15,7 @@ public class DealtDamageToAnOpponent implements Condition { @Override public boolean apply(Game game, Ability source) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { - PlayerDamagedBySourceWatcher watcher = (PlayerDamagedBySourceWatcher) game.getState().getWatchers().get(PlayerDamagedBySourceWatcher.class.getSimpleName(), opponentId); + PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, opponentId); if (watcher != null) { if (watcher.hasSourceDoneDamage(source.getSourceId(), game)) { return true; diff --git a/Mage/src/main/java/mage/abilities/condition/common/HateCondition.java b/Mage/src/main/java/mage/abilities/condition/common/HateCondition.java index 72216794d6d..1db22ed9f82 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/HateCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/HateCondition.java @@ -18,7 +18,7 @@ public enum HateCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - LifeLossOtherFromCombatWatcher watcher = (LifeLossOtherFromCombatWatcher) game.getState().getWatchers().get(LifeLossOtherFromCombatWatcher.class.getSimpleName()); + LifeLossOtherFromCombatWatcher watcher = game.getState().getWatcher(LifeLossOtherFromCombatWatcher.class); return watcher != null && watcher.opponentLostLifeOtherFromCombat(source.getControllerId(), game); } diff --git a/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java index 44686f489e0..2b6d991c540 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java @@ -13,7 +13,7 @@ public enum LandfallCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - LandfallWatcher watcher = (LandfallWatcher) game.getState().getWatchers().get(LandfallWatcher.class.getSimpleName()); + LandfallWatcher watcher = game.getState().getWatcher(LandfallWatcher.class); return watcher != null && watcher.landPlayed(source.getControllerId()); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java index 9832cc91098..7025aca0bcf 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java @@ -17,9 +17,9 @@ public enum LiveLostLastTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { - return watcher.getLiveLostLastTurn(source.getControllerId()) > 0; + return watcher.getLifeLostLastTurn(source.getControllerId()) > 0; } else { WatcherUtils.logMissingWatcher(game, source, PlayerLostLifeWatcher.class, this.getClass()); } diff --git a/Mage/src/main/java/mage/abilities/condition/common/ManaWasSpentCondition.java b/Mage/src/main/java/mage/abilities/condition/common/ManaWasSpentCondition.java index 5a0737d0a88..d512e91716a 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/ManaWasSpentCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/ManaWasSpentCondition.java @@ -30,7 +30,7 @@ public class ManaWasSpentCondition implements Condition { if (source.getAbilityType() == AbilityType.SPELL) { return (source.getManaCostsToPay().getPayment().getColor(coloredManaSymbol) > 0); } - ManaSpentToCastWatcher watcher = (ManaSpentToCastWatcher) game.getState().getWatchers().get(ManaSpentToCastWatcher.class.getSimpleName(), source.getSourceId()); + ManaSpentToCastWatcher watcher = game.getState().getWatcher(ManaSpentToCastWatcher.class, source.getSourceId()); if (watcher != null) { Mana payment = watcher.getAndResetLastPayment(); if (payment != null) { @@ -42,7 +42,7 @@ public class ManaWasSpentCondition implements Condition { @Override public String toString() { - return new StringBuilder("{").append(coloredManaSymbol.toString()).append("} was spent to cast it").toString(); + return "{" + coloredManaSymbol.toString() + "} was spent to cast it"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java index d095c2b0f5e..f6b939cc6ea 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MorbidCondition.java @@ -16,8 +16,8 @@ public enum MorbidCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Watcher watcher = game.getState().getWatchers().get(MorbidWatcher.class.getSimpleName()); - return watcher.conditionMet(); + MorbidWatcher watcher = game.getState().getWatcher(MorbidWatcher.class); + return watcher != null && watcher.conditionMet(); } @Override diff --git a/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java deleted file mode 100644 index ae960029b08..00000000000 --- a/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java +++ /dev/null @@ -1,26 +0,0 @@ - -package mage.abilities.condition.common; - -import java.util.EnumSet; -import java.util.Set; - -import mage.constants.TurnPhase; -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.game.Game; - -/** - * @author LevelX2 - */ - -public enum MyMainPhaseCondition implements Condition { - - instance; - private static final Set turnPhases = EnumSet.of(TurnPhase.PRECOMBAT_MAIN, TurnPhase.POSTCOMBAT_MAIN); - - @Override - public boolean apply(Game game, Ability source) { - return game.isActivePlayer(source.getControllerId()) && - turnPhases.contains(game.getTurn().getPhase().getType()); - } -} diff --git a/Mage/src/main/java/mage/abilities/condition/common/NoSpellsWereCastLastTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/NoSpellsWereCastLastTurnCondition.java index c43f09ba86c..ac1253311a0 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/NoSpellsWereCastLastTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/NoSpellsWereCastLastTurnCondition.java @@ -23,7 +23,10 @@ public enum NoSpellsWereCastLastTurnCondition implements Condition { return false; } - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); + if(watcher == null){ + return false; + } // if any player cast spell, return false for (Integer count : watcher.getAmountOfSpellsCastOnPrevTurn().values()) { if (count > 0) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/OpponentLostLifeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/OpponentLostLifeCondition.java index 75e9107f572..c509ebabc1c 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/OpponentLostLifeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/OpponentLostLifeCondition.java @@ -23,10 +23,10 @@ public class OpponentLostLifeCondition extends IntCompareCondition { @Override protected int getInputValue(Game game, Ability source) { int maxLostLive = 0; - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { - int lostLive = watcher.getLiveLost(opponentId); + int lostLive = watcher.getLifeLost(opponentId); if (lostLive > maxLostLive) { maxLostLive = lostLive; } diff --git a/Mage/src/main/java/mage/abilities/condition/common/PlayLandCondition.java b/Mage/src/main/java/mage/abilities/condition/common/PlayLandCondition.java index 121dfec8223..cab3b23a32b 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/PlayLandCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/PlayLandCondition.java @@ -13,7 +13,7 @@ public enum PlayLandCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayLandWatcher watcher = (PlayLandWatcher) game.getState().getWatchers().get(PlayLandWatcher.class.getSimpleName()); + PlayLandWatcher watcher = game.getState().getWatcher(PlayLandWatcher.class); return watcher != null && watcher.landPlayed(source.getControllerId()); } diff --git a/Mage/src/main/java/mage/abilities/condition/common/RaidCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RaidCondition.java index a821a30d305..85dcb3c2d9a 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RaidCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RaidCondition.java @@ -15,7 +15,7 @@ public enum RaidCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerAttackedWatcher watcher = (PlayerAttackedWatcher) game.getState().getWatchers().get(PlayerAttackedWatcher.class.getSimpleName()); + PlayerAttackedWatcher watcher = game.getState().getWatcher(PlayerAttackedWatcher.class); return watcher != null && watcher.getNumberOfAttackersCurrentTurn(source.getControllerId()) > 0; } diff --git a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java index 1c3feabc9e2..db68abf0285 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java @@ -15,7 +15,7 @@ public enum RevoltCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - RevoltWatcher watcher = (RevoltWatcher) game.getState().getWatchers().get(RevoltWatcher.class.getSimpleName()); + RevoltWatcher watcher = game.getState().getWatcher(RevoltWatcher.class); return watcher != null && watcher.revoltActive(source.getControllerId()); } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java index 38bb87a2c2f..7a9f111d229 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceDealtDamageCondition.java @@ -24,7 +24,7 @@ public class SourceDealtDamageCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - DamageDoneWatcher watcher = (DamageDoneWatcher) game.getState().getWatchers().get(DamageDoneWatcher.class.getSimpleName()); + DamageDoneWatcher watcher = game.getState().getWatcher(DamageDoneWatcher.class); return watcher != null && watcher.damageDoneBy(source.getSourceId(), source.getSourceObjectZoneChangeCounter(), game) >= value; } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceTargetsPermanentCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceTargetsPermanentCondition.java new file mode 100644 index 00000000000..b4e3697752e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceTargetsPermanentCondition.java @@ -0,0 +1,45 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.target.Target; + +import java.util.Iterator; + +/** + * @author TheElk801 + */ +public class SourceTargetsPermanentCondition implements Condition { + + private final FilterPermanent filter; + + public SourceTargetsPermanentCondition(FilterPermanent filter) { + this.filter = filter; + } + + @Override + public boolean apply(Game game, Ability source) { + StackObject sourceSpell = game.getStack().getStackObject(source.getSourceId()); + if (sourceSpell == null) { + return false; + } + Iterator targets = sourceSpell.getStackAbility().getTargets().iterator(); + while (targets.hasNext()) { + Permanent permanent = game.getPermanentOrLKIBattlefield(targets.next().getFirstTarget()); + if (permanent != null && filter.match(permanent, source.getSourceId(), source.getControllerId(), game)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "it targets " + filter.getMessage(); + } + +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/TargetAttackedThisTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TargetAttackedThisTurnCondition.java index f81afcc01e1..561a3afd294 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/TargetAttackedThisTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/TargetAttackedThisTurnCondition.java @@ -17,7 +17,7 @@ public enum TargetAttackedThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent creature = game.getPermanentOrLKIBattlefield(source.getTargets().getFirstTarget()); - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); return creature != null && watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(creature, game)); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java index 01f3decbd0c..1f905605a41 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java @@ -15,7 +15,10 @@ public enum TwoOrMoreSpellsWereCastLastTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); + if(watcher == null){ + return false; + } // if any player cast more than two spells, return true for (Integer count : watcher.getAmountOfSpellsCastOnPrevTurn().values()) { if (count >= 2) { diff --git a/Mage/src/main/java/mage/abilities/condition/common/WatcherCondition.java b/Mage/src/main/java/mage/abilities/condition/common/WatcherCondition.java deleted file mode 100644 index 94d6e45f034..00000000000 --- a/Mage/src/main/java/mage/abilities/condition/common/WatcherCondition.java +++ /dev/null @@ -1,51 +0,0 @@ -package mage.abilities.condition.common; - -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.watchers.Watcher; - -/** - * - * @author Quercitron - */ -public class WatcherCondition implements Condition { - - private final String watcherKey; - private final WatcherScope watcherScope; - private final String text; - - public WatcherCondition(String watcherKey, WatcherScope watcherScope) { - this(watcherKey, watcherScope, ""); - } - - public WatcherCondition(String watcherKey, WatcherScope watcherScope, String text) { - this.watcherKey = watcherKey; - this.watcherScope = watcherScope; - this.text = text; - } - - @Override - public boolean apply(Game game, Ability source) { - Watcher watcher = null; - switch (watcherScope) { - case GAME: - watcher = game.getState().getWatchers().get(watcherKey); - break; - case PLAYER: - watcher = game.getState().getWatchers().get(watcherKey, source.getControllerId()); - break; - case CARD: - watcher = game.getState().getWatchers().get(watcherKey, source.getSourceId()); - break; - } - return watcher != null && watcher.conditionMet(); - } - - @Override - public String toString() { - return text; - } - -} diff --git a/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java index a33a4d9bd03..d8ab4297193 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/YouGainedLifeCondition.java @@ -18,9 +18,9 @@ public class YouGainedLifeCondition extends IntCompareCondition { @Override protected int getInputValue(Game game, Ability source) { int gainedLife = 0; - PlayerGainedLifeWatcher watcher = (PlayerGainedLifeWatcher) game.getState().getWatchers().get(PlayerGainedLifeWatcher.class.getSimpleName()); + PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); if (watcher != null) { - gainedLife = watcher.getLiveGained(source.getControllerId()); + gainedLife = watcher.getLifeGained(source.getControllerId()); } return gainedLife; } diff --git a/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java b/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java new file mode 100644 index 00000000000..7ac35fe9791 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java @@ -0,0 +1,12 @@ +package mage.abilities.costs; + +import mage.abilities.Ability; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public interface CostAdjuster { + + void adjustCosts(Ability ability, Game game); +} diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java index 0e085bb1603..a2905ea8313 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/PayLifeCost.java @@ -1,18 +1,16 @@ - - package mage.abilities.costs.common; import mage.abilities.Ability; +import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.game.Game; +import mage.game.events.GameEvent; import java.util.UUID; -import mage.abilities.costs.Cost; /** - * * @author BetaSteward_at_googlemail.com */ public class PayLifeCost extends CostImpl { @@ -36,11 +34,12 @@ public class PayLifeCost extends CostImpl { @Override public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - //118.4. If a cost or effect allows a player to pay an amount of life greater than 0, + //118.4. If a cost or effect allows a player to pay an amount of life greater than 0, //the player may do so only if their life total is greater than or equal to the - //amount of the payment. If a player pays life, the payment is subtracted from his or + //amount of the payment. If a player pays life, the payment is subtracted from his or //her life total; in other words, the player loses that much life. (Players can always pay 0 life.) int lifeToPayAmount = amount.calculate(game, ability, null); + // Paying 0 life is not considered paying any life. if (lifeToPayAmount > 0 && !game.getPlayer(controllerId).canPayLifeCost()) { return false; } @@ -51,6 +50,9 @@ public class PayLifeCost extends CostImpl { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { int lifeToPayAmount = amount.calculate(game, ability, null); this.paid = game.getPlayer(controllerId).loseLife(lifeToPayAmount, game, false) == lifeToPayAmount; + if (paid) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIFE_PAID, controllerId, sourceId, controllerId, lifeToPayAmount)); + } return paid; } diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java index 47cc2a91fb0..4da6753e7e0 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/PayVariableLifeCost.java @@ -1,5 +1,3 @@ - - package mage.abilities.costs.common; import mage.abilities.Ability; @@ -12,7 +10,6 @@ import mage.players.Player; * * @author LevelX2 */ - public class PayVariableLifeCost extends VariableCostImpl { public PayVariableLifeCost() { @@ -21,7 +18,7 @@ public class PayVariableLifeCost extends VariableCostImpl { public PayVariableLifeCost(boolean additionalCostText) { super("life to pay"); - this.text = new StringBuilder(additionalCostText ? "as an additional cost to cast this spell, pay ":"Pay ") + this.text = new StringBuilder(additionalCostText ? "as an additional cost to cast this spell, pay " : "Pay ") .append(xText).append(' ').append("life").toString(); } @@ -44,7 +41,10 @@ public class PayVariableLifeCost extends VariableCostImpl { int maxValue = 0; Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - maxValue = controller.getLife(); + // Paying 0 life is not considered paying any life, so paying 0 is still allowed + if (game.getPlayer(source.getControllerId()).canPayLifeCost()) { + maxValue = controller.getLife(); + } } return maxValue; } diff --git a/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java b/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java index 44fa2a8a5e9..bd235979693 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java @@ -5,7 +5,6 @@ */ package mage.abilities.costs.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; @@ -16,8 +15,9 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author jeffwadsworth */ @@ -40,7 +40,7 @@ public class PutCardFromHandOnTopOfLibraryCost extends CostImpl { if (targetCardInHand.canChoose(controllerId, game) && controller.choose(Outcome.PreventDamage, targetCardInHand, sourceId, game)) { card = game.getCard(targetCardInHand.getFirstTarget()); - paid = controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.HAND, true, true); + paid = card != null && controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.HAND, true, true); } return paid; } diff --git a/Mage/src/main/java/mage/abilities/costs/common/SacrificeTargetCost.java b/Mage/src/main/java/mage/abilities/costs/common/SacrificeTargetCost.java index 050cb7959c0..9a5de3b0769 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/SacrificeTargetCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/SacrificeTargetCost.java @@ -1,9 +1,6 @@ package mage.abilities.costs.common; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.Cost; @@ -13,21 +10,31 @@ import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledPermanent; +import mage.util.CardUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public class SacrificeTargetCost extends CostImpl { - List permanents = new ArrayList<>(); + private final List permanents = new ArrayList<>(); public SacrificeTargetCost(TargetControlledPermanent target) { this.addTarget(target); target.setNotTarget(true); // sacrifice is never targeted this.text = "sacrifice " - + ((target.getNumberOfTargets() != 1 || (target.getTargetName().startsWith("an") || target.getTargetName().startsWith("a "))) - ? "" : (target.getTargetName().startsWith("artifact") ? "an " : "a ")) + target.getTargetName(); + + ((target.getNumberOfTargets() != 1 + || (target.getTargetName().startsWith("an") + || target.getTargetName().startsWith("a "))) + ? (target.getMinNumberOfTargets() == target.getMaxNumberOfTargets() + && target.getMinNumberOfTargets() > 1 + ? CardUtil.numberToText(target.getNumberOfTargets()) + " " : "") + : (target.getTargetName().startsWith("artifact") ? "an " : "a ")) + + target.getTargetName(); target.setTargetName(target.getTargetName() + " (to sacrifice)"); } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/MultipliedValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/MultipliedValue.java index 55822e15f67..94a8e78487a 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/MultipliedValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/MultipliedValue.java @@ -12,21 +12,21 @@ import mage.game.Game; public class MultipliedValue implements DynamicValue { private final DynamicValue value; - private final int multplier; // should be renamed to multiplier but don't want to break your stuff + private final int multiplier; public MultipliedValue(DynamicValue value, int multiplier) { this.value = value.copy(); - this.multplier = multiplier; + this.multiplier = multiplier; } MultipliedValue(final MultipliedValue dynamicValue) { this.value = dynamicValue.value.copy(); - this.multplier = dynamicValue.multplier; + this.multiplier = dynamicValue.multiplier; } @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - return multplier * value.calculate(game, sourceAbility, effect); + return multiplier * value.calculate(game, sourceAbility, effect); } @Override @@ -37,10 +37,10 @@ public class MultipliedValue implements DynamicValue { @Override public String toString() { StringBuilder sb = new StringBuilder(); - if (multplier == 2) { + if (multiplier == 2) { sb.append("twice "); } else { - sb.append(multplier).append(" * "); + sb.append(multiplier).append(" * "); } return sb.append(value.toString()).toString(); } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttachedPermanentToughnessValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttachedPermanentToughnessValue.java index 2dab3cdd799..43529161fe3 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttachedPermanentToughnessValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttachedPermanentToughnessValue.java @@ -12,29 +12,29 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author MTGfan */ -public class AttachedPermanentToughnessValue implements DynamicValue { - +public enum AttachedPermanentToughnessValue implements DynamicValue { + instance; + @Override public int calculate(Game game, Ability source, Effect effect) { Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); Permanent enchanted = game.getPermanentOrLKIBattlefield(enchantment.getAttachedTo()); return enchanted.getToughness().getValue(); } - + @Override - public AttachedPermanentToughnessValue copy(){ - return new AttachedPermanentToughnessValue(); + public AttachedPermanentToughnessValue copy() { + return AttachedPermanentToughnessValue.instance; } - + @Override public String toString() { return "equal to"; } - - @Override + + @Override public String getMessage() { return "that creature's toughness"; } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java index 69a12d8c92a..2435fda94a7 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java @@ -7,29 +7,24 @@ import mage.abilities.effects.Effect; import mage.game.Game; import mage.watchers.common.PlayersAttackedThisTurnWatcher; -import java.util.UUID; - /** * @author JayDi85 */ -public class AttackedThisTurnOpponentsCount implements DynamicValue { +public enum AttackedThisTurnOpponentsCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - return this.calculate(game, sourceAbility.getControllerId()); - } - - public int calculate(Game game, UUID controllerId) { - PlayersAttackedThisTurnWatcher watcher = (PlayersAttackedThisTurnWatcher) game.getState().getWatchers().get(PlayersAttackedThisTurnWatcher.class.getSimpleName()); + PlayersAttackedThisTurnWatcher watcher = game.getState().getWatcher(PlayersAttackedThisTurnWatcher.class); if (watcher != null) { - return watcher.getAttackedOpponentsCount(controllerId); + return watcher.getAttackedOpponentsCount(sourceAbility.getControllerId()); } return 0; } @Override public AttackedThisTurnOpponentsCount copy() { - return new AttackedThisTurnOpponentsCount(); + return AttackedThisTurnOpponentsCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInAllHandsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInAllHandsCount.java index 7220265e7bf..5910f57a6c9 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInAllHandsCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInAllHandsCount.java @@ -1,26 +1,26 @@ package mage.abilities.dynamicvalue.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author emerald000 */ -public class CardsInAllHandsCount implements DynamicValue { - +public enum CardsInAllHandsCount implements DynamicValue { + instance; + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { int count = 0; for (UUID playerId : game.getState().getPlayersInRange(sourceAbility.getControllerId(), game)) { Player player = game.getPlayer(playerId); - if (player != null) - { + if (player != null) { count += player.getHand().size(); } } @@ -29,7 +29,7 @@ public class CardsInAllHandsCount implements DynamicValue { @Override public CardsInAllHandsCount copy() { - return new CardsInAllHandsCount(); + return CardsInAllHandsCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInControllerHandCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInControllerHandCount.java index 476057003c4..ea8cde0572d 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInControllerHandCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInControllerHandCount.java @@ -6,7 +6,8 @@ import mage.abilities.effects.Effect; import mage.game.Game; import mage.players.Player; -public class CardsInControllerHandCount implements DynamicValue { +public enum CardsInControllerHandCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -21,7 +22,7 @@ public class CardsInControllerHandCount implements DynamicValue { @Override public CardsInControllerHandCount copy() { - return new CardsInControllerHandCount(); + return CardsInControllerHandCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetHandCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetHandCount.java index dd7ac467d9d..c5e63adb19c 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetHandCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetHandCount.java @@ -6,7 +6,8 @@ import mage.abilities.effects.Effect; import mage.game.Game; import mage.players.Player; -public class CardsInTargetHandCount implements DynamicValue { +public enum CardsInTargetHandCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -21,7 +22,7 @@ public class CardsInTargetHandCount implements DynamicValue { @Override public DynamicValue copy() { - return new CardsInTargetHandCount(); + return CardsInTargetHandCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetPlayerHandCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetPlayerHandCount.java index 393f45db14e..686f85b9596 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetPlayerHandCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CardsInTargetPlayerHandCount.java @@ -7,10 +7,10 @@ import mage.game.Game; import mage.players.Player; /** - * * @author cbrianhill */ -public class CardsInTargetPlayerHandCount implements DynamicValue { +public enum CardsInTargetPlayerHandCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -23,7 +23,7 @@ public class CardsInTargetPlayerHandCount implements DynamicValue { @Override public CardsInTargetPlayerHandCount copy() { - return new CardsInTargetPlayerHandCount(); + return CardsInTargetPlayerHandCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerGotLifeCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerGotLifeCount.java index 94107fb35c0..2663f6a0405 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerGotLifeCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerGotLifeCount.java @@ -33,9 +33,9 @@ public class ControllerGotLifeCount implements DynamicValue, MageSingleton { } public int calculate(Game game, UUID controllerId) { - PlayerGainedLifeWatcher watcher = (PlayerGainedLifeWatcher) game.getState().getWatchers().get(PlayerGainedLifeWatcher.class.getSimpleName()); + PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); if (watcher != null) { - return watcher.getLiveGained(controllerId); + return watcher.getLifeGained(controllerId); } return 0; } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerLifeCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerLifeCount.java index e756e77e3e4..512691fd8fe 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerLifeCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ControllerLifeCount.java @@ -6,7 +6,8 @@ import mage.abilities.effects.Effect; import mage.game.Game; import mage.players.Player; -public class ControllerLifeCount implements DynamicValue { +public enum ControllerLifeCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -19,7 +20,7 @@ public class ControllerLifeCount implements DynamicValue { @Override public ControllerLifeCount copy() { - return new ControllerLifeCount(); + return ControllerLifeCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CreaturesDiedThisTurnCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CreaturesDiedThisTurnCount.java index 806a27fd4cc..d5b3fb0b137 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CreaturesDiedThisTurnCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CreaturesDiedThisTurnCount.java @@ -10,11 +10,12 @@ import mage.watchers.common.CreaturesDiedWatcher; /** * @author LoneFox */ -public class CreaturesDiedThisTurnCount implements DynamicValue { +public enum CreaturesDiedThisTurnCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - CreaturesDiedWatcher watcher = (CreaturesDiedWatcher) game.getState().getWatchers().get(CreaturesDiedWatcher.class.getSimpleName()); + CreaturesDiedWatcher watcher = game.getState().getWatcher(CreaturesDiedWatcher.class); if (watcher != null) { return watcher.getAmountOfCreaturesDiedThisTurn(); } @@ -23,7 +24,7 @@ public class CreaturesDiedThisTurnCount implements DynamicValue { @Override public CreaturesDiedThisTurnCount copy() { - return new CreaturesDiedThisTurnCount(); + return CreaturesDiedThisTurnCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/DiscardCostCardConvertedMana.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/DiscardCostCardConvertedMana.java index 145cf7ddafd..03e750bcc39 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/DiscardCostCardConvertedMana.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/DiscardCostCardConvertedMana.java @@ -11,7 +11,8 @@ import mage.game.Game; /** * @author LevelX2 */ -public class DiscardCostCardConvertedMana implements DynamicValue { +public enum DiscardCostCardConvertedMana implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -26,7 +27,7 @@ public class DiscardCostCardConvertedMana implements DynamicValue { @Override public DiscardCostCardConvertedMana copy() { - return new DiscardCostCardConvertedMana(); + return DiscardCostCardConvertedMana.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ExileFromHandCostCardConvertedMana.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ExileFromHandCostCardConvertedMana.java index f13c39c2824..48bba827662 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ExileFromHandCostCardConvertedMana.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ExileFromHandCostCardConvertedMana.java @@ -14,10 +14,10 @@ import mage.game.Game; * cost. If no card was exiled the getManaCostsToPay().getX() will be used as * value. * - * * @author LevelX2 */ -public class ExileFromHandCostCardConvertedMana implements DynamicValue { +public enum ExileFromHandCostCardConvertedMana implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -35,7 +35,7 @@ public class ExileFromHandCostCardConvertedMana implements DynamicValue { @Override public ExileFromHandCostCardConvertedMana copy() { - return new ExileFromHandCostCardConvertedMana(); + return ExileFromHandCostCardConvertedMana.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GetXValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GetXValue.java index 07c5eefe0f3..84a0302bb46 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GetXValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GetXValue.java @@ -8,14 +8,15 @@ import mage.abilities.effects.Effect; import mage.game.Game; /** - * * @author BetaSteward_at_googlemail.com */ -public class GetXValue implements DynamicValue { +public enum GetXValue implements DynamicValue { + instance; + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { int amount = 0; - for (VariableCost cost: sourceAbility.getCosts().getVariableCosts()) { + for (VariableCost cost : sourceAbility.getCosts().getVariableCosts()) { amount += cost.getAmount(); } return amount; @@ -23,7 +24,7 @@ public class GetXValue implements DynamicValue { @Override public GetXValue copy() { - return new GetXValue(); + return GetXValue.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java index a668e5c3375..714cc80a631 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java @@ -10,10 +10,10 @@ import mage.game.permanent.Permanent; import mage.players.Player; /** - * * @author Styxo */ -public class GreatestPowerAmongControlledCreaturesValue implements DynamicValue { +public enum GreatestPowerAmongControlledCreaturesValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -32,7 +32,7 @@ public class GreatestPowerAmongControlledCreaturesValue implements DynamicValue @Override public GreatestPowerAmongControlledCreaturesValue copy() { - return new GreatestPowerAmongControlledCreaturesValue(); + return GreatestPowerAmongControlledCreaturesValue.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaSpentToCastCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaSpentToCastCount.java index 767c185e7a6..0ad7fed22b4 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaSpentToCastCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaSpentToCastCount.java @@ -10,13 +10,10 @@ import mage.game.Game; import mage.game.stack.Spell; /** - * * @author LevelX2 */ -public class ManaSpentToCastCount implements DynamicValue { - - public ManaSpentToCastCount() { - } +public enum ManaSpentToCastCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability source, Effect effect) { @@ -36,7 +33,7 @@ public class ManaSpentToCastCount implements DynamicValue { @Override public ManaSpentToCastCount copy() { - return new ManaSpentToCastCount(); + return ManaSpentToCastCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaTypeInManaPoolCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaTypeInManaPoolCount.java index 55dc44ddbc0..5a2fc332350 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaTypeInManaPoolCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaTypeInManaPoolCount.java @@ -1,5 +1,6 @@ package mage.abilities.dynamicvalue.common; +import mage.ConditionalMana; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; @@ -29,6 +30,9 @@ public class ManaTypeInManaPoolCount implements DynamicValue { Player player = game.getPlayer(sourceAbility.getControllerId()); if (player != null) { amount = player.getManaPool().get(manaType); + for (ConditionalMana mana : player.getManaPool().getConditionalMana()) { + amount += mana.get(manaType); + } } return amount; } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManacostVariableValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManacostVariableValue.java index e29a7a9a88f..bade65f5446 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManacostVariableValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManacostVariableValue.java @@ -5,7 +5,8 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.game.Game; -public class ManacostVariableValue implements DynamicValue { +public enum ManacostVariableValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -14,7 +15,7 @@ public class ManacostVariableValue implements DynamicValue { @Override public ManacostVariableValue copy() { - return new ManacostVariableValue(); + return ManacostVariableValue.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/MorphManacostVariableValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/MorphManacostVariableValue.java index b3f84b9a60f..bc137d87e22 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/MorphManacostVariableValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/MorphManacostVariableValue.java @@ -11,10 +11,10 @@ import mage.abilities.effects.Effect; import mage.game.Game; /** - * * @author LevelX2 */ -public class MorphManacostVariableValue implements DynamicValue { +public enum MorphManacostVariableValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -27,7 +27,7 @@ public class MorphManacostVariableValue implements DynamicValue { @Override public MorphManacostVariableValue copy() { - return new MorphManacostVariableValue(); + return MorphManacostVariableValue.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/MultikickerCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/MultikickerCount.java index 4d693677630..b4b583c1da6 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/MultikickerCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/MultikickerCount.java @@ -9,20 +9,17 @@ import mage.cards.Card; import mage.game.Game; /** - * * @author LevelX2 */ -public class MultikickerCount implements DynamicValue { - - public MultikickerCount() { - } +public enum MultikickerCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability source, Effect effect) { int count = 0; Card card = game.getCard(source.getSourceId()); if (card != null) { - for (Ability ability: card.getAbilities()) { + for (Ability ability : card.getAbilities()) { if (ability instanceof KickerAbility) { count += ((KickerAbility) ability).getKickedCounter(game, source); } @@ -33,7 +30,7 @@ public class MultikickerCount implements DynamicValue { @Override public MultikickerCount copy() { - return new MultikickerCount(); + return MultikickerCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java index 2435bb53add..d8eee3f6276 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java @@ -8,7 +8,8 @@ import mage.game.Game; /** * @author JayDi85 */ -public class OpponentsCount implements DynamicValue { +public enum OpponentsCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -17,7 +18,7 @@ public class OpponentsCount implements DynamicValue { @Override public OpponentsCount copy() { - return new OpponentsCount(); + return OpponentsCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsLostLifeCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsLostLifeCount.java index 1133be57bd7..0be9fa437aa 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsLostLifeCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsLostLifeCount.java @@ -20,7 +20,7 @@ public class OpponentsLostLifeCount implements DynamicValue { } public int calculate(Game game, UUID controllerId) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null) { return watcher.getAllOppLifeLost(controllerId, game); } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsPoisonCountersCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsPoisonCountersCount.java index 8851841caa2..76f16fe6ad9 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsPoisonCountersCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsPoisonCountersCount.java @@ -10,7 +10,8 @@ import mage.players.Player; import java.util.Set; import java.util.UUID; -public class OpponentsPoisonCountersCount implements DynamicValue { +public enum OpponentsPoisonCountersCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -27,7 +28,7 @@ public class OpponentsPoisonCountersCount implements DynamicValue { @Override public DynamicValue copy() { - return new OpponentsPoisonCountersCount(); + return OpponentsPoisonCountersCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouOwnThatOpponentsControlCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouOwnThatOpponentsControlCount.java index 66c49c96185..3a98ec1d655 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouOwnThatOpponentsControlCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouOwnThatOpponentsControlCount.java @@ -1,15 +1,17 @@ package mage.abilities.dynamicvalue.common; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.game.Game; import mage.game.permanent.Permanent; -public class PermanentsYouOwnThatOpponentsControlCount implements DynamicValue { +import java.util.Set; +import java.util.UUID; + +public enum PermanentsYouOwnThatOpponentsControlCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -28,7 +30,7 @@ public class PermanentsYouOwnThatOpponentsControlCount implements DynamicValue { @Override public PermanentsYouOwnThatOpponentsControlCount copy() { - return new PermanentsYouOwnThatOpponentsControlCount(); + return PermanentsYouOwnThatOpponentsControlCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/RemovedCountersForCostValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/RemovedCountersForCostValue.java index 26c45840993..2b8620a5611 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/RemovedCountersForCostValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/RemovedCountersForCostValue.java @@ -13,10 +13,10 @@ import mage.abilities.effects.Effect; import mage.game.Game; /** - * * @author LevelX2 */ -public class RemovedCountersForCostValue implements DynamicValue { +public enum RemovedCountersForCostValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -35,7 +35,7 @@ public class RemovedCountersForCostValue implements DynamicValue { @Override public RemovedCountersForCostValue copy() { - return new RemovedCountersForCostValue(); + return RemovedCountersForCostValue.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/RevealTargetFromHandCostCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/RevealTargetFromHandCostCount.java index b7574ac2f58..f9994726cc9 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/RevealTargetFromHandCostCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/RevealTargetFromHandCostCount.java @@ -13,10 +13,10 @@ import mage.abilities.effects.Effect; import mage.game.Game; /** - * * @author emerald000 */ -public class RevealTargetFromHandCostCount implements DynamicValue { +public enum RevealTargetFromHandCostCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -35,7 +35,7 @@ public class RevealTargetFromHandCostCount implements DynamicValue { @Override public RevealTargetFromHandCostCount copy() { - return new RevealTargetFromHandCostCount(); + return RevealTargetFromHandCostCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesPower.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesPower.java index 290a303c887..4cdaed1a82c 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesPower.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesPower.java @@ -10,8 +10,8 @@ import mage.game.Game; /** * @author LevelX2 */ -public class SacrificeCostCreaturesPower implements DynamicValue { - +public enum SacrificeCostCreaturesPower implements DynamicValue { +instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { for (Cost cost : sourceAbility.getCosts()) { @@ -26,7 +26,7 @@ public class SacrificeCostCreaturesPower implements DynamicValue { @Override public SacrificeCostCreaturesPower copy() { - return new SacrificeCostCreaturesPower(); + return SacrificeCostCreaturesPower.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java index bfc03a261ce..514b24f8a3f 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SacrificeCostCreaturesToughness.java @@ -10,7 +10,8 @@ import mage.game.Game; /** * @author LevelX2 */ -public class SacrificeCostCreaturesToughness implements DynamicValue { +public enum SacrificeCostCreaturesToughness implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -25,7 +26,7 @@ public class SacrificeCostCreaturesToughness implements DynamicValue { @Override public SacrificeCostCreaturesToughness copy() { - return new SacrificeCostCreaturesToughness(); + return SacrificeCostCreaturesToughness.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/StaticValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/StaticValue.java index 0297eec66af..f5a11f81362 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/StaticValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/StaticValue.java @@ -7,8 +7,9 @@ import mage.game.Game; public class StaticValue implements DynamicValue { - private int value = 0; - private String message; + private final int value; + private final String message; + private static final StaticValue zeroValue = new StaticValue(0); public StaticValue(int value) { this(value, ""); @@ -47,4 +48,8 @@ public class StaticValue implements DynamicValue { public int getValue() { return value; } + + public static StaticValue getZeroValue() { + return zeroValue; + } } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java index d42cc3f5281..6c49909cad5 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java @@ -10,14 +10,10 @@ import mage.game.stack.Spell; import mage.game.stack.StackObject; /** - * * @author Nicolas */ -public class SunburstCount implements DynamicValue { - - public SunburstCount() { - - } +public enum SunburstCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability source, Effect effect) { @@ -48,7 +44,7 @@ public class SunburstCount implements DynamicValue { @Override public SunburstCount copy() { - return new SunburstCount(); + return SunburstCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetConvertedManaCost.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetConvertedManaCost.java index 7be84e3585c..26fe5ed8f5a 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetConvertedManaCost.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetConvertedManaCost.java @@ -8,10 +8,10 @@ import mage.cards.Card; import mage.game.Game; /** - * * @author North */ -public class TargetConvertedManaCost implements DynamicValue { +public enum TargetConvertedManaCost implements DynamicValue { + instance; @Override public int calculate(Game game, Ability source, Effect effect) { @@ -24,7 +24,7 @@ public class TargetConvertedManaCost implements DynamicValue { @Override public TargetConvertedManaCost copy() { - return new TargetConvertedManaCost(); + return instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetPermanentPowerCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetPermanentPowerCount.java index 814eb19970d..ab7e13d4b97 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetPermanentPowerCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/TargetPermanentPowerCount.java @@ -9,10 +9,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author North */ -public class TargetPermanentPowerCount implements DynamicValue { +public enum TargetPermanentPowerCount implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { @@ -29,7 +29,7 @@ public class TargetPermanentPowerCount implements DynamicValue { @Override public TargetPermanentPowerCount copy() { - return new TargetPermanentPowerCount(); + return TargetPermanentPowerCount.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ZuberasDiedDynamicValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ZuberasDiedDynamicValue.java index 85a86a83751..c9310b63115 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ZuberasDiedDynamicValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ZuberasDiedDynamicValue.java @@ -9,17 +9,21 @@ import mage.watchers.common.ZuberasDiedWatcher; /** * Created by Eric on 9/24/2016. */ -public class ZuberasDiedDynamicValue implements DynamicValue { +public enum ZuberasDiedDynamicValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - ZuberasDiedWatcher watcher = (ZuberasDiedWatcher) game.getState().getWatchers().get(ZuberasDiedWatcher.class.getSimpleName()); - return watcher.zuberasDiedThisTurn; + ZuberasDiedWatcher watcher = game.getState().getWatcher(ZuberasDiedWatcher.class); + if (watcher == null) { + return 0; + } + return watcher.getZuberasDiedThisTurn(); } @Override public ZuberasDiedDynamicValue copy() { - return new ZuberasDiedDynamicValue(); + return ZuberasDiedDynamicValue.instance; } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java index dd050ce1729..790b95f3e61 100644 --- a/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java @@ -1,7 +1,5 @@ - package mage.abilities.effects; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -19,6 +17,8 @@ import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** * Cards with the Aura subtype don't change the zone they are in, if there is no * valid target on the battlefield. Also, when entering the battlefield and it @@ -60,6 +60,9 @@ public class AuraReplacementEffect extends ReplacementEffectImpl { Card card = game.getCard(event.getTargetId()); UUID sourceId = event.getSourceId(); UUID controllerId = event.getPlayerId(); + if (card == null) { + return false; + } if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null) { card = card.getSecondCardFace(); @@ -149,7 +152,6 @@ public class AuraReplacementEffect extends ReplacementEffectImpl { } Player targetPlayer = game.getPlayer(targetId); if (targetCard != null || targetPermanent != null || targetPlayer != null) { - card = game.getCard(event.getTargetId()); card.removeFromZone(game, fromZone, sourceId); PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game); ZoneChangeEvent zoneChangeEvent = new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD); @@ -184,14 +186,12 @@ public class AuraReplacementEffect extends ReplacementEffectImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD && (((ZoneChangeEvent) event).getFromZone() != Zone.STACK)) { Card card = game.getCard(event.getTargetId()); - if (card != null && (card.isEnchantment() && card.hasSubtype(SubType.AURA, game) + return card != null && (card.isEnchantment() && card.hasSubtype(SubType.AURA, game) || // in case of transformable enchantments (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null - && card.getSecondCardFace() != null - && card.getSecondCardFace().isEnchantment() - && card.getSecondCardFace().hasSubtype(SubType.AURA, game)))) { - return true; - } + && card.getSecondCardFace() != null + && card.getSecondCardFace().isEnchantment() + && card.getSecondCardFace().hasSubtype(SubType.AURA, game))); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java index ce14ca33b45..5f1bad6e5b9 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java @@ -494,7 +494,11 @@ public class ContinuousEffects implements Serializable { if (affectedAbility != null && affectedAbility.getSourceObject(game) instanceof SplitCardHalf) { idToCheck = ((SplitCardHalf) affectedAbility.getSourceObject(game)).getParentCard().getId(); } else { - idToCheck = objectId; + if (game.getObject(objectId) instanceof SplitCardHalf) { + idToCheck = ((SplitCardHalf) game.getObject(objectId)).getParentCard().getId(); + } else { + idToCheck = objectId; + } } for (AsThoughEffect effect : asThoughEffectsList) { Set abilities = asThoughEffectsMap.get(type).getAbility(effect.getId()); diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectsList.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectsList.java index 7b1c66c19c3..69837a16b71 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectsList.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectsList.java @@ -1,14 +1,13 @@ - package mage.abilities.effects; +import java.util.*; import mage.abilities.Ability; import mage.abilities.MageSingleton; import mage.constants.Duration; +import mage.constants.Zone; import mage.game.Game; import org.apache.log4j.Logger; -import java.util.*; - /** * @param * @author BetaSteward_at_googlemail.com @@ -42,7 +41,7 @@ public class ContinuousEffectsList extends ArrayList } public void removeEndOfTurnEffects() { - for (Iterator i = this.iterator(); i.hasNext(); ) { + for (Iterator i = this.iterator(); i.hasNext();) { T entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) { i.remove(); @@ -53,7 +52,7 @@ public class ContinuousEffectsList extends ArrayList public void removeEndOfCombatEffects() { - for (Iterator i = this.iterator(); i.hasNext(); ) { + for (Iterator i = this.iterator(); i.hasNext();) { T entry = i.next(); if (entry.getDuration() == Duration.EndOfCombat) { i.remove(); @@ -63,7 +62,7 @@ public class ContinuousEffectsList extends ArrayList } public void removeInactiveEffects(Game game) { - for (Iterator i = this.iterator(); i.hasNext(); ) { + for (Iterator i = this.iterator(); i.hasNext();) { T entry = i.next(); if (isInactive(entry, game)) { i.remove(); @@ -106,6 +105,11 @@ public class ContinuousEffectsList extends ArrayList if (effect.isInactive(ability, game)) { it.remove(); } + break; + case UntilSourceLeavesBattlefield: + if (Zone.BATTLEFIELD != game.getState().getZone(ability.getSourceId())) { + it.remove(); + } } } } @@ -147,7 +151,7 @@ public class ContinuousEffectsList extends ArrayList abilities.removeAll(abilitiesToRemove); } if (abilities == null || abilities.isEmpty()) { - for (Iterator iterator = this.iterator(); iterator.hasNext(); ) { + for (Iterator iterator = this.iterator(); iterator.hasNext();) { ContinuousEffect effect = iterator.next(); if (effect.getId().equals(effectIdToRemove)) { iterator.remove(); diff --git a/Mage/src/main/java/mage/abilities/effects/Effect.java b/Mage/src/main/java/mage/abilities/effects/Effect.java index f956b7bf7d3..07312ebdf1a 100644 --- a/Mage/src/main/java/mage/abilities/effects/Effect.java +++ b/Mage/src/main/java/mage/abilities/effects/Effect.java @@ -1,8 +1,5 @@ - package mage.abilities.effects; -import java.io.Serializable; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.constants.EffectType; @@ -10,8 +7,10 @@ import mage.constants.Outcome; import mage.game.Game; import mage.target.targetpointer.TargetPointer; +import java.io.Serializable; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public interface Effect extends Serializable { @@ -64,4 +63,7 @@ public interface Effect extends Serializable { Effect copy(); + Effect concatBy(String concatPrefix); + + String getConcatPrefix(); } diff --git a/Mage/src/main/java/mage/abilities/effects/EffectImpl.java b/Mage/src/main/java/mage/abilities/effects/EffectImpl.java index f640ec9aad8..65e0bbada81 100644 --- a/Mage/src/main/java/mage/abilities/effects/EffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/EffectImpl.java @@ -1,9 +1,5 @@ - package mage.abilities.effects; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.MageSingleton; import mage.abilities.Mode; import mage.constants.EffectType; @@ -11,8 +7,11 @@ import mage.constants.Outcome; import mage.target.targetpointer.FirstTargetPointer; import mage.target.targetpointer.TargetPointer; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public abstract class EffectImpl implements Effect { @@ -23,7 +22,7 @@ public abstract class EffectImpl implements Effect { protected TargetPointer targetPointer = FirstTargetPointer.getInstance(); protected String staticText = ""; protected Map values; - protected boolean applyEffectsAfter = false; + protected String concatPrefix = ""; // combines multiple effects in text rule public EffectImpl(Outcome outcome) { this.id = UUID.randomUUID(); @@ -36,6 +35,7 @@ public abstract class EffectImpl implements Effect { this.staticText = effect.staticText; this.effectType = effect.effectType; this.targetPointer = effect.targetPointer.copy(); + this.concatPrefix = effect.concatPrefix; if (effect.values != null) { values = new HashMap<>(); Map map = effect.values; @@ -43,7 +43,6 @@ public abstract class EffectImpl implements Effect { values.put(entry.getKey(), entry.getValue()); } } - this.applyEffectsAfter = effect.applyEffectsAfter; } @Override @@ -112,4 +111,15 @@ public abstract class EffectImpl implements Effect { } return values.get(key); } + + @Override + public Effect concatBy(String concatPrefix) { + this.concatPrefix = concatPrefix; + return this; + } + + @Override + public String getConcatPrefix() { + return this.concatPrefix; + } } diff --git a/Mage/src/main/java/mage/abilities/effects/Effects.java b/Mage/src/main/java/mage/abilities/effects/Effects.java index cb32b8471a2..df2661806be 100644 --- a/Mage/src/main/java/mage/abilities/effects/Effects.java +++ b/Mage/src/main/java/mage/abilities/effects/Effects.java @@ -1,16 +1,15 @@ - package mage.abilities.effects; +import mage.abilities.Mode; +import mage.constants.Outcome; +import mage.target.targetpointer.TargetPointer; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import mage.abilities.Mode; -import mage.constants.Outcome; -import mage.target.targetpointer.TargetPointer; /** - * * @author BetaSteward_at_googlemail.com */ public class Effects extends ArrayList { @@ -43,11 +42,25 @@ public class Effects extends ArrayList { public String getText(Mode mode) { StringBuilder sbText = new StringBuilder(); String lastRule = null; + int effectNum = 0; for (Effect effect : this) { String endString = ""; String nextRule = effect.getText(mode); + + // ignore empty rules + if (nextRule == null || nextRule.isEmpty()) { + continue; + } + effectNum++; + + // concat effects (default: each effect with a new sentence) + String concatPrefix = effect.getConcatPrefix(); + if (effectNum > 1 && !concatPrefix.isEmpty() && !concatPrefix.equals(".")) { + nextRule = concatPrefix + " " + nextRule; + } + if (nextRule != null) { - if (nextRule.startsWith("and ") || nextRule.startsWith("with ")) { + if (nextRule.startsWith("and ") || nextRule.startsWith("with ") || nextRule.startsWith("then ")) { endString = " "; } else if (nextRule.startsWith(",") || nextRule.startsWith(" ")) { endString = ""; @@ -63,6 +76,7 @@ public class Effects extends ArrayList { } lastRule = nextRule; } + if (lastRule != null && lastRule.length() > 3 && !lastRule.endsWith(".") && !lastRule.endsWith("\"") @@ -71,6 +85,7 @@ public class Effects extends ArrayList { && !lastRule.endsWith("")) { sbText.append('.'); } + return sbText.toString(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CipherEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CipherEffect.java index 9dd49c7ea60..72b22fc266e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CipherEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CipherEffect.java @@ -1,7 +1,6 @@ package mage.abilities.effects.common; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -20,11 +19,13 @@ import mage.players.Player; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** * FAQ 2013/01/11 - * + *

* 702.97. Cipher - * + *

* 702.97a Cipher appears on some instants and sorceries. It represents two * static abilities, one that functions while the spell is on the stack and one * that functions while the card with cipher is in the exile zone. "Cipher" @@ -33,17 +34,17 @@ import mage.target.targetpointer.FixedTarget; * that creature, that creature has 'Whenever this creature deals combat damage * to a player, you may copy this card and you may cast the copy without paying * its mana cost.'" - * + *

* 702.97b The term "encoded" describes the relationship between the card with * cipher while in the exile zone and the creature chosen when the spell * represented by that card resolves. - * + *

* 702.97c The card with cipher remains encoded on the chosen creature as long * as the card with cipher remains exiled and the creature remains on the * battlefield. The card remains encoded on that object even if it changes * controller or stops being a creature, as long as it remains on the * battlefield. - * + *

* TODO: Implement Cipher as two static abilities concerning the rules. * * @author LevelX2 @@ -114,20 +115,13 @@ class CipherStoreEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Card cipherCard = game.getCard(cipherCardId); - if (cipherCard != null) { + if (cipherCard != null && controller != null) { Card copyCard = game.copyCard(cipherCard, source, controller.getId()); SpellAbility ability = copyCard.getSpellAbility(); // remove the cipher effect from the copy - Effect cipherEffect = null; - for (Effect effect : ability.getEffects()) { - if (effect instanceof CipherEffect) { - cipherEffect = effect; - } - } - ability.getEffects().remove(cipherEffect); - if (ability instanceof SpellAbility) { - controller.cast(ability, game, true, new MageObjectReference(source.getSourceObject(game), game)); - } + ability.getEffects().removeIf(effect -> effect instanceof CipherEffect); + controller.cast(ability, game, true, new MageObjectReference(source.getSourceObject(game), game)); + } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyTargetSpellEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyTargetSpellEffect.java index 93c6712292a..c3a4879b4d5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyTargetSpellEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTargetSpellEffect.java @@ -2,6 +2,7 @@ package mage.abilities.effects.common; import mage.abilities.Ability; import mage.abilities.Mode; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.constants.Zone; @@ -17,6 +18,7 @@ public class CopyTargetSpellEffect extends OneShotEffect { private final boolean useController; private final boolean useLKI; + private String copyThatSpellName = "that spell"; public CopyTargetSpellEffect() { this(false); @@ -36,6 +38,12 @@ public class CopyTargetSpellEffect extends OneShotEffect { super(effect); this.useLKI = effect.useLKI; this.useController = effect.useController; + this.copyThatSpellName = effect.copyThatSpellName; + } + + public Effect withSpellName(String copyThatSpellName) { + this.copyThatSpellName = copyThatSpellName; + return this; } @Override @@ -81,7 +89,7 @@ public class CopyTargetSpellEffect extends OneShotEffect { if (!mode.getTargets().isEmpty()) { sb.append("target ").append(mode.getTargets().get(0).getTargetName()); } else { - sb.append("that spell"); + sb.append(copyThatSpellName); } sb.append(". You may choose new targets for the copy"); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java index 092c8ec92cb..8f90639c3bd 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java @@ -1,8 +1,5 @@ package mage.abilities.effects.common; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -14,11 +11,7 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.cards.Card; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.EmptyToken; @@ -27,8 +20,11 @@ import mage.util.CardUtil; import mage.util.functions.ApplyToPermanent; import mage.util.functions.EmptyApplyToPermanent; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author LevelX2 */ public class CreateTokenCopyTargetEffect extends OneShotEffect { @@ -73,12 +69,11 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { } /** - * - * @param playerId null the token is controlled/owned by the controller of - * the source ability + * @param playerId null the token is controlled/owned by the controller of + * the source ability * @param additionalCardType the token gains this card type in addition - * @param hasHaste the token gains haste - * @param number number of tokens to put into play + * @param hasHaste the token gains haste + * @param number number of tokens to put into play * @param tapped * @param attacking */ @@ -165,7 +160,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { copyFrom = game.getCard(getTargetPointer().getFirst(game, source)); } - if (permanent == null && copyFrom == null) { + if (copyFrom == null) { return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java index 2d37250007d..15bc8d25af4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenTargetEffect.java @@ -69,7 +69,14 @@ public class CreateTokenTargetEffect extends OneShotEffect { return staticText; } StringBuilder sb = new StringBuilder(); - sb.append("target ").append(mode.getTargets().get(0).getTargetName()); + + if (mode.getTargets().isEmpty()) { + sb.append("target player"); + } + else { + sb.append("target ").append(mode.getTargets().get(0).getTargetName()); + } + sb.append(" creates "); if (amount.toString().equals("1")) { sb.append("a "); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java index 5aa4b5c5b98..626b7225cbb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java @@ -1,7 +1,5 @@ - package mage.abilities.effects.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; @@ -14,8 +12,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com * @author North */ @@ -161,11 +160,15 @@ public class DamageTargetEffect extends OneShotEffect { if (!targetDescription.isEmpty()) { sb.append(targetDescription); } else { - String targetName = mode.getTargets().get(0).getTargetName(); - if (targetName.contains("any")) { - sb.append(targetName); + if (!mode.getTargets().isEmpty()) { + String targetName = mode.getTargets().get(0).getTargetName(); + if (targetName.contains("any")) { + sb.append(targetName); + } else { + sb.append("target ").append(targetName); + } } else { - sb.append("target ").append(targetName); + sb.append("that target"); } } if (!message.isEmpty()) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java index 6c86bed0a16..e1deaeef672 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DestroyTargetEffect.java @@ -1,7 +1,5 @@ - package mage.abilities.effects.common; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; @@ -13,8 +11,9 @@ import mage.target.targetpointer.FirstTargetPointer; import mage.target.targetpointer.SecondTargetPointer; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public class DestroyTargetEffect extends OneShotEffect { @@ -27,14 +26,18 @@ public class DestroyTargetEffect extends OneShotEffect { } public DestroyTargetEffect(String ruleText) { - this(false); - staticText = ruleText; + this(ruleText, false); } public DestroyTargetEffect(boolean noRegen) { this(noRegen, false); } + public DestroyTargetEffect(String ruleText, boolean noRegen) { + this(noRegen, false); + staticText = ruleText; + } + public DestroyTargetEffect(boolean noRegen, boolean multitargetHandling) { super(Outcome.DestroyPermanent); this.noRegen = noRegen; @@ -100,7 +103,12 @@ public class DestroyTargetEffect extends OneShotEffect { } sb.append(targetName); } else { - sb.append("Destroy ").append(CardUtil.numberToText(target.getNumberOfTargets())).append(" target ").append(target.getTargetName()); + if (target.getMaxNumberOfTargets() == target.getMinNumberOfTargets()) { + sb.append("destroy ").append(CardUtil.numberToText(target.getNumberOfTargets())); + } else { + sb.append("destroy up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets())); + } + sb.append(" target ").append(target.getTargetName()); } } if (noRegen) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java index 1bf91e308d6..2394b15275a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java @@ -41,7 +41,7 @@ public class DevourEffect extends ReplacementEffectImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creatures to devour"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } private final DevourFactor devourFactor; diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java index 49d5651cbf7..41200f26f0f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java @@ -32,7 +32,6 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR * Attention: This effect won't work with targets controlled by different * controllers If this is needed, the validForTurnNum has to be saved per * controller. - * */ public DontUntapInControllersNextUntapStepTargetEffect() { this(""); @@ -43,10 +42,9 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR } /** - * - * @param targetName used as target text for the generated rule text + * @param targetName used as target text for the generated rule text * @param onlyIfControlledByPlayer the effect only works if the permanent is - * controlled by that controller, null = it works for all players + * controlled by that controller, null = it works for all players */ public DontUntapInControllersNextUntapStepTargetEffect(String targetName, UUID onlyIfControlledByPlayer) { this(targetName, false, onlyIfControlledByPlayer); @@ -116,7 +114,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR } } } - + if (allHandled) { discard(); } @@ -149,8 +147,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR } else return targetName + " doesn't untap during its controller's next " + (twoSteps ? "two " : "") + "untap step" + (twoSteps ? "s" : ""); } else { - return "target " + (mode == null ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next " + (twoSteps ? "two " : "") + "untap step" + (twoSteps ? "s" : ""); + return "target " + (mode == null || mode.getTargets().isEmpty() ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next " + (twoSteps ? "two " : "") + "untap step" + (twoSteps ? "s" : ""); } } - -} +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java index ce8822a9d1e..c56a4f28b8b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java @@ -1,9 +1,7 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; @@ -18,20 +16,32 @@ import mage.util.CardUtil; public class DrawCardSourceControllerEffect extends OneShotEffect { protected DynamicValue amount; + protected String whoDrawCard = ""; public DrawCardSourceControllerEffect(int amount) { - this(new StaticValue(amount)); + this(amount, ""); + } + + public DrawCardSourceControllerEffect(int amount, String whoDrawCard) { + this(new StaticValue(amount), whoDrawCard); } public DrawCardSourceControllerEffect(DynamicValue amount) { + this(amount, ""); + } + + public DrawCardSourceControllerEffect(DynamicValue amount, String whoDrawCard) { super(Outcome.DrawCard); this.amount = amount.copy(); + this.whoDrawCard = whoDrawCard; setText(); } public DrawCardSourceControllerEffect(final DrawCardSourceControllerEffect effect) { super(effect); this.amount = effect.amount.copy(); + this.whoDrawCard = effect.whoDrawCard; + setText(); } @Override @@ -53,7 +63,7 @@ public class DrawCardSourceControllerEffect extends OneShotEffect { StringBuilder sb = new StringBuilder(); boolean oneCard = (amount instanceof StaticValue && amount.calculate(null, null, this) == 1) || amount instanceof PermanentsOnBattlefieldCount || amount.toString().equals("1") || amount.toString().equals("a"); - sb.append("draw ").append(oneCard ? "a" : CardUtil.numberToText(amount.toString())).append(" card"); + sb.append(whoDrawCard.isEmpty() ? "" : whoDrawCard + " ").append("draw ").append(oneCard ? "a" : CardUtil.numberToText(amount.toString())).append(" card"); if (!oneCard) { sb.append('s'); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/FlipCoinEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FlipCoinEffect.java index 6e7abd8d267..32b1b7940db 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/FlipCoinEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/FlipCoinEffect.java @@ -60,7 +60,7 @@ public class FlipCoinEffect extends OneShotEffect { MageObject mageObject = game.getObject(source.getSourceId()); if (controller != null && mageObject != null) { boolean result = true; - for (Effect effect : controller.flipCoin(game) ? executingEffectsWon : executingEffectsLost) { + for (Effect effect : controller.flipCoin(source, game, true) ? executingEffectsWon : executingEffectsLost) { effect.setTargetPointer(this.targetPointer); if (effect instanceof OneShotEffect) { result &= effect.apply(game, source); diff --git a/Mage/src/main/java/mage/abilities/effects/common/FlipUntilLoseEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FlipUntilLoseEffect.java index 365e6b3a6a1..6d1abe14fdd 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/FlipUntilLoseEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/FlipUntilLoseEffect.java @@ -34,7 +34,7 @@ public class FlipUntilLoseEffect extends OneShotEffect { return false; } while (true) { - if (!player.flipCoin(game)) { + if (!player.flipCoin(source, game, true)) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/GetEmblemTargetPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GetEmblemTargetPlayerEffect.java index 58fb0c2cf3b..a99b93a6f30 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/GetEmblemTargetPlayerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/GetEmblemTargetPlayerEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.MageObject; @@ -10,8 +9,9 @@ import mage.game.Game; import mage.game.command.Emblem; import mage.players.Player; +import java.util.stream.Collectors; + /** - * * @author LevelX2 */ public class GetEmblemTargetPlayerEffect extends OneShotEffect { @@ -53,6 +53,6 @@ public class GetEmblemTargetPlayerEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "Target " + mode.getTargets().get(0).getTargetName() + " gets an emblem with \"" + emblem.getAbilities().getRules(null) + '"'; + return "Target " + mode.getTargets().get(0).getTargetName() + " gets an emblem with \"" + emblem.getAbilities().getRules(null).stream().collect(Collectors.joining("; ")) + "\""; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/PopulateEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PopulateEffect.java index a74f8d79626..59b4cbdf407 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PopulateEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PopulateEffect.java @@ -34,7 +34,7 @@ public class PopulateEffect extends OneShotEffect { private static final FilterPermanent filter = new FilterPermanent("token for populate"); static { - filter.add(new TokenPredicate()); + filter.add(TokenPredicate.instance); filter.add(new ControllerPredicate(TargetController.YOU)); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java index 01aee794ef1..f1158cb434b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; @@ -13,7 +12,6 @@ import mage.players.Player; import mage.util.CardUtil; /** - * * @author BetaSteward_at_googlemail.com */ public class PutLibraryIntoGraveTargetEffect extends OneShotEffect { @@ -61,7 +59,12 @@ public class PutLibraryIntoGraveTargetEffect extends OneShotEffect { StringBuilder sb = new StringBuilder(); String message = amount.getMessage(); - sb.append("target ").append(mode.getTargets().get(0).getTargetName()); + if (!mode.getTargets().isEmpty()) { + sb.append("target ").append(mode.getTargets().get(0).getTargetName()); + } else { + sb.append("that target"); + } + sb.append(" puts the top "); if (message.isEmpty()) { if (amount.toString().equals("1")) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java index 9a1190329d1..363c97fc4a8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java @@ -65,19 +65,24 @@ public class ReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect return staticText; } StringBuilder sb = new StringBuilder(); - Target target = mode.getTargets().get(0); - sb.append("return "); - if (target.getMaxNumberOfTargets() > 1) { - if (target.getMaxNumberOfTargets() != target.getNumberOfTargets()) { - sb.append("up to "); + + if (mode.getTargets().isEmpty()) { + sb.append("return target creature to the battlefield"); + } else { + Target target = mode.getTargets().get(0); + sb.append("return "); + if (target.getMaxNumberOfTargets() > 1) { + if (target.getMaxNumberOfTargets() != target.getNumberOfTargets()) { + sb.append("up to "); + } + sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(' '); + } + sb.append("target ").append(mode.getTargets().get(0).getTargetName()).append(" to the battlefield"); + if (tapped) { + sb.append(" tapped"); } - sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(' '); - } - sb.append("target ").append(mode.getTargets().get(0).getTargetName()).append(" to the battlefield"); - if (tapped) { - sb.append(" tapped"); } sb.append(" under your control"); return sb.toString(); } -} +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java index 93647512202..cc531c79454 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java @@ -51,6 +51,9 @@ public class TapAllTargetPlayerControlsEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "tap all " + filter.toString() + " target " + mode.getTargets().get(0).getTargetName() + " controls"; + + return "tap all " + filter.toString() + " target " + + (mode.getTargets().size() == 0 ? "player" : mode.getTargets().get(0).getTargetName()) + + " controls"; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/TapEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TapEnchantedEffect.java index 40ea264ac52..462f09c412f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TapEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TapEnchantedEffect.java @@ -1,10 +1,8 @@ - - package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; @@ -15,17 +13,17 @@ import mage.game.permanent.Permanent; public class TapEnchantedEffect extends OneShotEffect { public TapEnchantedEffect() { - super(Outcome.Tap); - staticText = "tap enchanted creature"; - } + super(Outcome.Tap); + staticText = "tap enchanted creature"; + } public TapEnchantedEffect(final TapEnchantedEffect effect) { - super(effect); + super(effect); } @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) source.getSourceObject(game); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); if (permanent != null) { Permanent attach = game.getPermanent(permanent.getAttachedTo()); if (attach != null) { @@ -41,4 +39,4 @@ public class TapEnchantedEffect extends OneShotEffect { return new TapEnchantedEffect(this); } - } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/TapTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TapTargetEffect.java index 29d10627a73..e3aa5c5c56b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TapTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TapTargetEffect.java @@ -54,6 +54,10 @@ public class TapTargetEffect extends OneShotEffect { return "tap " + staticText; } + if (mode.getTargets().isEmpty()) { + return "tap target permanent"; + } + Target target = mode.getTargets().get(0); if (target.getMaxNumberOfTargets() > 1) { if (target.getMaxNumberOfTargets() == target.getNumberOfTargets()) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/UntapAllThatAttackedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/UntapAllThatAttackedEffect.java index 78834f82ae7..385ff814ec8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/UntapAllThatAttackedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/UntapAllThatAttackedEffect.java @@ -36,9 +36,9 @@ public class UntapAllThatAttackedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Watcher watcher = game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); - if (watcher instanceof AttackedThisTurnWatcher) { - Set attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures(); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); + if (watcher != null) { + Set attackedThisTurn = watcher.getAttackedThisTurnCreatures(); for (MageObjectReference mor : attackedThisTurn) { Permanent permanent = mor.getPermanent(game); if (permanent != null && permanent.isCreature()) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java index ccc695b67bb..05540aeb2c4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java @@ -20,7 +20,7 @@ public class UntapLandsEffect extends OneShotEffect { private static final FilterLandPermanent filter = new FilterLandPermanent("untapped lands"); static { - filter.add(new TappedPredicate()); + filter.add(TappedPredicate.instance); } private final int amount; private final boolean upTo; diff --git a/Mage/src/main/java/mage/abilities/effects/common/UntapTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/UntapTargetEffect.java index 838996d2b89..d474f15cc81 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/UntapTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/UntapTargetEffect.java @@ -65,8 +65,12 @@ public class UntapTargetEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - Target target = mode.getTargets().get(0); + if (mode.getTargets().isEmpty()) { + return "untap target permanent"; + } + + Target target = mode.getTargets().get(0); StringBuilder sb = new StringBuilder(); sb.append("untap "); if (target.getNumberOfTargets() == 0) { @@ -84,4 +88,4 @@ public class UntapTargetEffect extends OneShotEffect { return sb.toString(); } -} +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleAllEffect.java index b4c4ec8f1df..43e14562a26 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleAllEffect.java @@ -60,7 +60,7 @@ public class AttacksIfAbleAllEffect extends RequirementEffect { if (eachCombat) { return true; } - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game)); } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleSourceEffect.java index 44b4356b8e4..bf62c5c6429 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/AttacksIfAbleSourceEffect.java @@ -47,7 +47,7 @@ public class AttacksIfAbleSourceEffect extends RequirementEffect { if (eachCombat) { return true; } - AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game)); } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java index 0eef90ee664..ca59b004149 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java @@ -12,7 +12,6 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; /** - * * @author LevelX2 */ public class CantAttackYouUnlessPayManaAllEffect extends PayCostToAttackBlockEffectImpl { @@ -37,7 +36,7 @@ public class CantAttackYouUnlessPayManaAllEffect extends PayCostToAttackBlockEff + (payAlsoForAttackingPlaneswalker ? "or a planeswalker you control " : "") + "unless their controller pays " + (manaCosts == null ? "" : manaCosts.getText()) - + " for each creature he or she controls that's attacking you"; + + " for each creature they controls that's attacking you"; } public CantAttackYouUnlessPayManaAllEffect(final CantAttackYouUnlessPayManaAllEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesSourceEffect.java index 4c250916255..e06358e4874 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesSourceEffect.java @@ -9,7 +9,6 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author LevelX2 */ public class CantBeBlockedByCreaturesSourceEffect extends RestrictionEffect { @@ -19,8 +18,8 @@ public class CantBeBlockedByCreaturesSourceEffect extends RestrictionEffect { public CantBeBlockedByCreaturesSourceEffect(FilterCreaturePermanent filter, Duration duration) { super(duration); this.filter = filter; - staticText = new StringBuilder("{this} can't be blocked ") - .append(filter.getMessage().startsWith("except by") ? "" : "by ").append(filter.getMessage()).toString(); + staticText = "{this} can't be blocked " + (duration == Duration.EndOfTurn ? "this turn " : "") + + (filter.getMessage().startsWith("except by") ? "" : "by ") + filter.getMessage(); } public CantBeBlockedByCreaturesSourceEffect(final CantBeBlockedByCreaturesSourceEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java index 5c713db1f66..d8806469c3d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java @@ -19,9 +19,9 @@ public class MustBeBlockedByAllTargetEffect extends RequirementEffect { public MustBeBlockedByAllTargetEffect(Duration duration) { super(duration); - staticText = new StringBuilder("All creatures able to block target creature ") - .append(this.getDuration() == Duration.EndOfTurn ? "this turn ":"") - .append("do so").toString(); + staticText = "All creatures able to block target creature " + + (this.getDuration() == Duration.EndOfTurn ? "this turn " : "") + + "do so"; } public MustBeBlockedByAllTargetEffect(final MustBeBlockedByAllTargetEffect effect) { @@ -33,7 +33,7 @@ public class MustBeBlockedByAllTargetEffect extends RequirementEffect { Permanent attackingCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (attackingCreature != null && attackingCreature.isAttacking()) { if (source.getAbilityType() != AbilityType.STATIC) { - BlockedAttackerWatcher blockedAttackerWatcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher blockedAttackerWatcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attackingCreature, permanent, game)) { // has already blocked this turn, so no need to do again return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByTargetSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByTargetSourceEffect.java index 81fba0f3d3c..d56b0e8b0ec 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByTargetSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByTargetSourceEffect.java @@ -36,7 +36,7 @@ public class MustBeBlockedByTargetSourceEffect extends RequirementEffect { if (blocker != null && blocker.canBlock(source.getSourceId(), game)) { Permanent attacker = (Permanent) source.getSourceObjectIfItStillExists(game); if (attacker != null) { - BlockedAttackerWatcher blockedAttackerWatcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher blockedAttackerWatcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attacker, blocker, game)) { // has already blocked this turn, so no need to do again return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java index 59e56db5fbb..76c0e120248 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostTargetEffect.java @@ -1,8 +1,6 @@ package mage.abilities.effects.common.continuous; -import java.util.Locale; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; @@ -17,8 +15,10 @@ import mage.game.permanent.Permanent; import mage.target.Target; import mage.util.CardUtil; +import java.util.Locale; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public class BoostTargetEffect extends ContinuousEffectImpl { @@ -27,6 +27,10 @@ public class BoostTargetEffect extends ContinuousEffectImpl { private DynamicValue toughness; private boolean lockedIn; + public BoostTargetEffect(int power, int toughness) { + this(power, toughness, Duration.EndOfTurn); + } + public BoostTargetEffect(int power, int toughness, Duration duration) { this(new StaticValue(power), new StaticValue(toughness), duration, false); } @@ -39,8 +43,8 @@ public class BoostTargetEffect extends ContinuousEffectImpl { * @param power * @param toughness * @param duration - * @param lockedIn if true, power and toughness will be calculated only - * once, when the ability resolves + * @param lockedIn if true, power and toughness will be calculated only + * once, when the ability resolves */ public BoostTargetEffect(DynamicValue power, DynamicValue toughness, Duration duration, boolean lockedIn) { super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, isCanKill(toughness) ? Outcome.UnboostCreature : Outcome.BoostCreature); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantCastMoreThanOneSpellEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantCastMoreThanOneSpellEffect.java index e20ec587178..4901a687ec1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantCastMoreThanOneSpellEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantCastMoreThanOneSpellEffect.java @@ -69,7 +69,7 @@ public class CantCastMoreThanOneSpellEffect extends ContinuousRuleModifyingEffec return false; } } - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); return watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) > 0; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java index 034f7a273e7..fb52506093b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAttachedEffect.java @@ -70,7 +70,7 @@ public class GainAbilityAttachedEffect extends ContinuousEffectImpl { public void init(Ability source, Game game) { super.init(source, game); if (affectedObjectsSet) { - Permanent equipment = game.getPermanent(source.getSourceId()); + Permanent equipment = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { this.setTargetPointer(new FixedTarget(equipment.getAttachedTo(), game.getState().getZoneChangeCounter(equipment.getAttachedTo()))); } @@ -107,7 +107,7 @@ public class GainAbilityAttachedEffect extends ContinuousEffectImpl { } else { sb.append("gains "); } - sb.append(ability.getRule()); + sb.append('"' + ability.getRule("this creature") + '"'); if (!duration.toString().isEmpty()) { sb.append(' ').append(duration.toString()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java index 881e3190246..ba4747be4e1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityTargetEffect.java @@ -1,24 +1,18 @@ - package mage.abilities.effects.common.continuous; -import java.util.Locale; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.Card; -import mage.constants.DependencyType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.PhaseStep; -import mage.constants.SubLayer; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; +import java.util.Locale; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public class GainAbilityTargetEffect extends ContinuousEffectImpl { @@ -88,9 +82,7 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl { return true; } if (durationPhaseStep != null && durationPhaseStep == game.getPhase().getStep().getType()) { - if (!sameStep && game.isActivePlayer(durationPlayerId) || game.getPlayer(durationPlayerId).hasReachedNextTurnAfterLeaving()) { - return true; - } + return !sameStep && game.isActivePlayer(durationPlayerId) || game.getPlayer(durationPlayerId).hasReachedNextTurnAfterLeaving(); } else { sameStep = false; } @@ -137,21 +129,26 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl { return staticText; } StringBuilder sb = new StringBuilder(); - Target target = mode.getTargets().get(0); - if (target.getMaxNumberOfTargets() == Integer.MAX_VALUE) { - sb.append("any number of target ").append(target.getTargetName()).append(" gain "); - } else if (target.getMaxNumberOfTargets() > 1) { - if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { - sb.append("up to "); - } - sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" gain "); - } else { - if (!target.getTargetName().toUpperCase(Locale.ENGLISH).startsWith("ANOTHER")) { - sb.append("target "); - } - sb.append(target.getTargetName()).append(" gains "); + if (mode.getTargets().size() > 0) { + Target target = mode.getTargets().get(0); + if (target.getMaxNumberOfTargets() == Integer.MAX_VALUE) { + sb.append("any number of target ").append(target.getTargetName()).append(" gain "); + } else if (target.getMaxNumberOfTargets() > 1) { + if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) { + sb.append("up to "); + } + sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()).append(" gain "); + } else { + if (!target.getTargetName().toUpperCase(Locale.ENGLISH).startsWith("ANOTHER")) { + sb.append("target "); + } + sb.append(target.getTargetName()).append(" gains "); + } + } else { + sb.append("gains "); } + sb.append(ability.getRule()); if (durationPhaseStep != null) { sb.append(" until your next ").append(durationPhaseStep.toString().toLowerCase(Locale.ENGLISH)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java index 993134026fa..8e4d51164b1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java @@ -112,6 +112,11 @@ public class GainControlTargetEffect extends ContinuousEffectImpl { if (!staticText.isEmpty()) { return staticText; } + + if (mode.getTargets().isEmpty()) { + return "gain control of target permanent"; + } + Target target = mode.getTargets().get(0); StringBuilder sb = new StringBuilder("gain control of "); if (target.getMaxNumberOfTargets() > 1) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/CastWithoutPayingManaCostEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/CastWithoutPayingManaCostEffect.java index 91bb40fba53..90e19e1c133 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/CastWithoutPayingManaCostEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/CastWithoutPayingManaCostEffect.java @@ -3,10 +3,13 @@ package mage.abilities.effects.common.cost; import mage.MageObjectReference; import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.constants.ComparisonType; import mage.constants.Outcome; +import mage.filter.FilterCard; import mage.filter.common.FilterNonlandCard; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; @@ -25,23 +28,23 @@ import org.apache.log4j.Logger; */ public class CastWithoutPayingManaCostEffect extends OneShotEffect { - private final FilterNonlandCard filter; - private final int manaCost; + private final DynamicValue manaCost; /** * @param maxCost Maximum converted mana cost for this effect to apply to */ public CastWithoutPayingManaCostEffect(int maxCost) { + this(new StaticValue(maxCost)); + } + + public CastWithoutPayingManaCostEffect(DynamicValue maxCost) { super(Outcome.PlayForFree); - filter = new FilterNonlandCard("card with converted mana cost " + maxCost + " or less from your hand"); - filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, maxCost + 1)); this.manaCost = maxCost; this.staticText = "you may cast a card with converted mana cost " + maxCost + " or less from your hand without paying its mana cost"; } public CastWithoutPayingManaCostEffect(final CastWithoutPayingManaCostEffect effect) { super(effect); - this.filter = effect.filter.copy(); this.manaCost = effect.manaCost; } @@ -52,11 +55,14 @@ public class CastWithoutPayingManaCostEffect extends OneShotEffect { if (controller == null) { return false; } + int cmc = manaCost.calculate(game, source, this); + FilterCard filter = new FilterNonlandCard("card with converted mana cost " + cmc + " or less from your hand"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, cmc + 1)); Target target = new TargetCardInHand(filter); if (target.canChoose(source.getSourceId(), controller.getId(), game) - && controller.chooseUse(outcome, "Cast a card with converted mana cost " + manaCost - + " or less from your hand without paying its mana cost?", source, game)) { + && controller.chooseUse(outcome, "Cast a card with converted mana cost " + cmc + + " or less from your hand without paying its mana cost?", source, game)) { Card cardToCast = null; boolean cancel = false; while (controller.canRespond() && !cancel) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java index e50680a73c1..4c717eb6e49 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java @@ -1,8 +1,5 @@ - package mage.abilities.effects.common.counter; -import java.util.Locale; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; @@ -19,8 +16,10 @@ import mage.players.Player; import mage.target.Target; import mage.util.CardUtil; +import java.util.Locale; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public class AddCountersTargetEffect extends OneShotEffect { @@ -121,8 +120,8 @@ public class AddCountersTargetEffect extends OneShotEffect { } sb.append(" on "); - if (!mode.getTargets().isEmpty()) { - Target target = mode.getTargets().get(0); + Target target = mode.getTargets().getEffectTarget(this.targetPointer); + if (target != null) { if (target.getNumberOfTargets() == 0) { sb.append("up to "); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java index 5e8ddbdac5e..ad8a25bbdea 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java @@ -1,8 +1,5 @@ - package mage.abilities.effects.common.discard; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; @@ -20,8 +17,10 @@ import mage.target.TargetCard; import mage.target.common.TargetCardInHand; import mage.util.CardUtil; +import java.util.List; +import java.util.UUID; + /** - * * @author noxx */ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { @@ -98,7 +97,6 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - Card sourceCard = game.getCard(source.getSourceId()); if (player != null && controller != null) { if (revealAllCards) { this.numberCardsToReveal = new StaticValue(player.getHand().size()); @@ -125,6 +123,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect { revealedCards.addAll(player.getHand()); } + Card sourceCard = game.getCard(source.getSourceId()); player.revealCards(sourceCard != null ? sourceCard.getIdName() + " (" + sourceCard.getZoneChangeCounter(game) + ')' : "Discard", revealedCards, game); boolean result = true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java b/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java index 673acae8486..0c974f40213 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java +++ b/Mage/src/main/java/mage/abilities/effects/common/replacement/DealtDamageToCreatureBySourceDies.java @@ -63,7 +63,7 @@ public class DealtDamageToCreatureBySourceDies extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zce = (ZoneChangeEvent) event; if (zce.isDiesEvent()) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), source.getSourceId()); + DamagedByWatcher watcher = game.getState().getWatcher(DamagedByWatcher.class, source.getSourceId()); if (watcher != null) { return watcher.wasDamaged(zce.getTarget(), game); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyIfYouHaveCastAnotherSpellEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyIfYouHaveCastAnotherSpellEffect.java index 7126808c810..e3de9c3cf7e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyIfYouHaveCastAnotherSpellEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyIfYouHaveCastAnotherSpellEffect.java @@ -32,7 +32,7 @@ public class CastOnlyIfYouHaveCastAnotherSpellEffect extends ContinuousRuleModif @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getSourceId().equals(source.getSourceId())) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) == 0) { return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessEffect.java new file mode 100644 index 00000000000..3afcf0161f6 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessEffect.java @@ -0,0 +1,62 @@ + +package mage.abilities.effects.common.ruleModifying; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public class CombatDamageByToughnessEffect extends ContinuousEffectImpl { + + private final FilterCreaturePermanent filter; + private final boolean onlyControlled; + + public CombatDamageByToughnessEffect(FilterCreaturePermanent filter, boolean onlyControlled) { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + this.filter = filter; + this.onlyControlled = onlyControlled; + staticText = "Each " + filter.getMessage() + (onlyControlled ? " you control" : "") + + " assigns combat damage equal to its toughness rather than its power"; + } + + public CombatDamageByToughnessEffect(final CombatDamageByToughnessEffect effect) { + super(effect); + this.filter = effect.filter; + this.onlyControlled = effect.onlyControlled; + } + + @Override + public CombatDamageByToughnessEffect copy() { + return new CombatDamageByToughnessEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + // Change the rule + FilterCreaturePermanent filterPermanent = filter.copy(); + if (onlyControlled) { + filterPermanent.add(new ControllerIdPredicate(source.getControllerId())); + } + game.getCombat().setUseToughnessForDamage(true); + game.getCombat().addUseToughnessForDamageFilter(filterPermanent); + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.RulesEffects; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryGraveyardPutInHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryGraveyardPutInHandEffect.java index 7f1d990bb2f..4da00d454c9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryGraveyardPutInHandEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryGraveyardPutInHandEffect.java @@ -34,7 +34,7 @@ public class SearchLibraryGraveyardPutInHandEffect extends OneShotEffect { super(Outcome.Benefit); this.filter = filter; this.forceToSearchBoth = forceToSearchBoth; - staticText = (youMay ? "You may" : "") + "search your library and" + (forceToSearchBoth ? "" : "/or") + " graveyard for a card named " + filter.getMessage() + staticText = (youMay ? "You may" : "") + " search your library and" + (forceToSearchBoth ? "" : "/or") + " graveyard for a card named " + filter.getMessage() + ", reveal it, and put it into your hand. " + (forceToSearchBoth ? "Then shuffle your library" : "If you search your library this way, shuffle it"); } diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java index 0bbc9ebbb52..ed29b59aea6 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java @@ -5,6 +5,7 @@ import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.counters.CounterType; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.util.CardUtil; @@ -40,8 +41,15 @@ public class AdaptEffect extends OneShotEffect { if (permanent == null) { return false; } - if (permanent.getCounters(game).getCount(CounterType.P1P1) == 0) { - permanent.addCounters(CounterType.P1P1.createInstance(adaptNumber), source, game); + GameEvent event = new GameEvent( + GameEvent.EventType.ADAPT, source.getSourceId(), source.getSourceId(), + source.getControllerId(), adaptNumber, false + ); + if (game.replaceEvent(event)) { + return false; + } + if (permanent.getCounters(game).getCount(CounterType.P1P1) == 0 || event.getFlag()) { + permanent.addCounters(CounterType.P1P1.createInstance(event.getAmount()), source, game); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java index e2d20da03b4..15978c837b3 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java @@ -80,6 +80,12 @@ public class EchoEffect extends OneShotEffect { @Override public String getText(Mode mode) { StringBuilder sb = new StringBuilder("sacrifice {this} unless you "); + + if (cost == null) { + sb.append("pay this permanent's mana cost"); + return sb.toString(); + } + String costText = cost.getText(); if (costText.toLowerCase(Locale.ENGLISH).startsWith("discard")) { sb.append(costText.substring(0, 1).toLowerCase(Locale.ENGLISH)); diff --git a/Mage/src/main/java/mage/abilities/keyword/AdaptAbility.java b/Mage/src/main/java/mage/abilities/keyword/AdaptAbility.java new file mode 100644 index 00000000000..634c38bd4df --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/AdaptAbility.java @@ -0,0 +1,27 @@ + + +package mage.abilities.keyword; + +import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.keyword.AdaptEffect; +import mage.constants.Zone; + +/** + * @author TheElk801 + */ +public class AdaptAbility extends ActivatedAbilityImpl { + + public AdaptAbility(int adaptNumber, String manaCost) { + super(Zone.BATTLEFIELD, new AdaptEffect(adaptNumber), new ManaCostsImpl(manaCost)); + } + + public AdaptAbility(final AdaptAbility ability) { + super(ability); + } + + @Override + public AdaptAbility copy() { + return new AdaptAbility(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/AfterlifeAbility.java b/Mage/src/main/java/mage/abilities/keyword/AfterlifeAbility.java index ba71038869d..30569c053e1 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AfterlifeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AfterlifeAbility.java @@ -6,6 +6,7 @@ import mage.game.permanent.token.WhiteBlackSpiritToken; import mage.util.CardUtil; public class AfterlifeAbility extends DiesTriggeredAbility { + private final int tokenCount; public AfterlifeAbility(int tokenCount) { @@ -22,7 +23,7 @@ public class AfterlifeAbility extends DiesTriggeredAbility { public String getRule() { return "Afterlife " + tokenCount + " (When this creature dies, create " + CardUtil.numberToText(tokenCount, "a") - + " white and black Spirit creature token" + + " 1/1 white and black Spirit creature token" + (tokenCount > 1 ? "s" : "") + " with flying)"; } diff --git a/Mage/src/main/java/mage/abilities/keyword/BloodthirstAbility.java b/Mage/src/main/java/mage/abilities/keyword/BloodthirstAbility.java index 873e0c82c95..885301b7a59 100644 --- a/Mage/src/main/java/mage/abilities/keyword/BloodthirstAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/BloodthirstAbility.java @@ -69,15 +69,15 @@ class BloodthirstEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get(BloodthirstWatcher.class.getSimpleName(), source.getControllerId()); + BloodthirstWatcher watcher = game.getState().getWatcher(BloodthirstWatcher.class, source.getControllerId()); if (watcher != null && watcher.conditionMet()) { Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent != null) { ArrayList appliedEffects = (ArrayList) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game, appliedEffects); } + return true; } - return true; } return false; } diff --git a/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java b/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java index 3292aa3a364..b803f8e7c4a 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import mage.MageObjectReference; @@ -84,7 +83,11 @@ class CascadeEffect extends OneShotEffect { return false; } ExileZone exile = game.getExile().createZone(source.getSourceId(), controller.getName() + " Cascade"); - int sourceCost = game.getCard(source.getSourceId()).getConvertedManaCost(); + card = game.getCard(source.getSourceId()); + if (card == null) { + return false; + } + int sourceCost = card.getConvertedManaCost(); do { card = controller.getLibrary().getFromTop(game); if (card == null) { diff --git a/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java b/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java index 28331ab6929..b073f23f6fe 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java @@ -99,7 +99,7 @@ public class ChampionAbility extends StaticAbility { if (requiresCreature) { filter.add(new CardTypePredicate(CardType.CREATURE)); } - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); // When this permanent enters the battlefield, sacrifice it unless you exile another [object] you control. Ability ability1 = new EntersBattlefieldTriggeredAbility( diff --git a/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java b/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java index 30778d34e2f..98544656616 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java @@ -55,7 +55,7 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional protected static final String CONSPIRE_ACTIVATION_KEY = "ConspireActivation"; static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); filter.add(new SharesColorWithSourcePredicate()); filter.add(new CardTypePredicate(CardType.CREATURE)); } diff --git a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java index afba2dcd995..19a50c3e328 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java @@ -69,7 +69,7 @@ public class ConvokeAbility extends SimpleStaticAbility implements AlternateMana private static final FilterCreaturePermanent filterUntapped = new FilterCreaturePermanent(); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } public ConvokeAbility() { @@ -96,7 +96,7 @@ public class ConvokeAbility extends SimpleStaticAbility implements AlternateMana specialAction.setSourceId(source.getSourceId()); // create filter for possible creatures to tap FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); if (unpaid.getMana().getGeneric() == 0) { List colorPredicates = new ArrayList<>(); if (unpaid.getMana().getBlack() > 0) { diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java index c4d9502957f..f5a3c314dc0 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -54,7 +54,7 @@ class CrewCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); } private final int value; diff --git a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java index 6495c39ceca..ccb08800bba 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java @@ -1,17 +1,12 @@ package mage.abilities.keyword; -import java.util.UUID; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.EquipEffect; -import mage.abilities.effects.common.AttachEffect; import mage.constants.Outcome; -import mage.constants.SubType; import mage.constants.TimingRule; import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; @@ -45,7 +40,7 @@ public class EquipAbility extends ActivatedAbilityImpl { @Override public String getRule() { - return "Equip " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": Attach to target creature you control. Equip only as a sorcery.)"; + return "Equip " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": Attach to target creature you control. Equip only as a sorcery.)"; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java b/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java index 7dac00d4bd2..e926b1318d1 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ExertAbility.java @@ -109,7 +109,7 @@ class ExertReplacementEffect extends ReplacementEffectImpl { if (creature != null && controller != null) { if (exertOnlyOncePerTurn) { MageObjectReference creatureReference = new MageObjectReference(creature.getId(), creature.getZoneChangeCounter(game), game); - ExertedThisTurnWatcher watcher = (ExertedThisTurnWatcher) game.getState().getWatchers().get(ExertedThisTurnWatcher.class.getSimpleName()); + ExertedThisTurnWatcher watcher = game.getState().getWatcher(ExertedThisTurnWatcher.class); if (watcher != null && watcher.getExertedThisTurnCreatures().contains(creatureReference)) { return false; } diff --git a/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java b/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java index 9bc38f8a203..08f6943a423 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java @@ -23,12 +23,18 @@ public class FadingAbility extends EntersBattlefieldAbility { private String ruleText; public FadingAbility(int fadeCounter, Card card) { + this(fadeCounter, card, false); + } + + public FadingAbility(int fadeCounter, Card card, boolean shortRuleText) { super(new AddCountersSourceEffect(CounterType.FADE.createInstance(fadeCounter)), "with"); Ability ability = new BeginningOfUpkeepTriggeredAbility(new FadingEffect(), TargetController.YOU, false); ability.setRuleVisible(false); addSubAbility(ability); - ruleText = "Fading " + fadeCounter + " (This permanent enters the battlefield with " + fadeCounter + " fade counters on it." - + " At the beginning of your upkeep, remove a fade counter from this permanent. If you can't, sacrifice the permanent."; + ruleText = "Fading " + fadeCounter + + (shortRuleText ? "" + : " (This permanent enters the battlefield with " + fadeCounter + " fade counters on it." + + " At the beginning of your upkeep, remove a fade counter from this permanent. If you can't, sacrifice the permanent."); } public FadingAbility(final FadingAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/keyword/GravestormAbility.java b/Mage/src/main/java/mage/abilities/keyword/GravestormAbility.java index 01eb83de3be..ab4823303ef 100644 --- a/Mage/src/main/java/mage/abilities/keyword/GravestormAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/GravestormAbility.java @@ -74,20 +74,22 @@ class GravestormEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { MageObjectReference spellRef = (MageObjectReference) this.getValue("GravestormSpellRef"); if (spellRef != null) { - GravestormWatcher watcher = (GravestormWatcher) game.getState().getWatchers().get(GravestormWatcher.class.getSimpleName()); - int gravestormCount = watcher.getGravestormCount(); - if (gravestormCount > 0) { - Spell spell = (Spell) this.getValue("GravestormSpell"); - if (spell != null) { - if (!game.isSimulation()) { - game.informPlayers("Gravestorm: " + spell.getName() + " will be copied " + gravestormCount + " time" + (gravestormCount > 1 ? "s" : "")); - } - for (int i = 0; i < gravestormCount; i++) { - spell.createCopyOnStack(game, source, source.getControllerId(), true); + GravestormWatcher watcher = game.getState().getWatcher(GravestormWatcher.class); + if(watcher != null) { + int gravestormCount = watcher.getGravestormCount(); + if (gravestormCount > 0) { + Spell spell = (Spell) this.getValue("GravestormSpell"); + if (spell != null) { + if (!game.isSimulation()) { + game.informPlayers("Gravestorm: " + spell.getName() + " will be copied " + gravestormCount + " time" + (gravestormCount > 1 ? "s" : "")); + } + for (int i = 0; i < gravestormCount; i++) { + spell.createCopyOnStack(game, source, source.getControllerId(), true); + } } } + return true; } - return true; } return false; } diff --git a/Mage/src/main/java/mage/abilities/keyword/HexproofFromMonocoloredAbility.java b/Mage/src/main/java/mage/abilities/keyword/HexproofFromMonocoloredAbility.java new file mode 100644 index 00000000000..88fd558921d --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/HexproofFromMonocoloredAbility.java @@ -0,0 +1,44 @@ +package mage.abilities.keyword; + +import mage.abilities.MageSingleton; +import mage.abilities.common.SimpleStaticAbility; +import mage.constants.Zone; + +import java.io.ObjectStreamException; + +/** + * Hexproof from Monocolored (This creature or player can't be the target of monocolored + * spells or abilities your opponents control.) + * + * @author TheElk801 + */ +public class HexproofFromMonocoloredAbility extends SimpleStaticAbility implements MageSingleton { + + private static final HexproofFromMonocoloredAbility instance; + + static { + instance = new HexproofFromMonocoloredAbility(); + } + + private Object readResolve() throws ObjectStreamException { + return instance; + } + + public static HexproofFromMonocoloredAbility getInstance() { + return instance; + } + + private HexproofFromMonocoloredAbility() { + super(Zone.BATTLEFIELD, null); + } + + @Override + public HexproofFromMonocoloredAbility copy() { + return instance; + } + + @Override + public String getRule() { + return "hexproof from monocolored (This creature can't be the target of monocolored spells or abilities your opponents control.)"; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/ImproviseAbility.java b/Mage/src/main/java/mage/abilities/keyword/ImproviseAbility.java index f3a9f36d652..74181458175 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ImproviseAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ImproviseAbility.java @@ -37,7 +37,7 @@ public class ImproviseAbility extends SimpleStaticAbility implements AlternateMa private static final FilterArtifactPermanent filterUntapped = new FilterArtifactPermanent(); static { - filterUntapped.add(Predicates.not(new TappedPredicate())); + filterUntapped.add(Predicates.not(TappedPredicate.instance)); } public ImproviseAbility() { @@ -64,7 +64,7 @@ public class ImproviseAbility extends SimpleStaticAbility implements AlternateMa specialAction.setSourceId(source.getSourceId()); // create filter for possible artifacts to tap FilterControlledArtifactPermanent filter = new FilterControlledArtifactPermanent(); - filter.add(Predicates.not(new TappedPredicate())); + filter.add(Predicates.not(TappedPredicate.instance)); Target target = new TargetControlledPermanent(1, unpaid.getMana().getGeneric(), filter, true); target.setTargetName("artifact to Improvise"); specialAction.addTarget(target); diff --git a/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java b/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java index 0ca8676bbbf..aeb04bc04e9 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java @@ -88,7 +88,7 @@ class MeleeDynamicValue implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - MeleeWatcher watcher = (MeleeWatcher) game.getState().getWatchers().get(MeleeWatcher.class.getSimpleName()); + MeleeWatcher watcher = game.getState().getWatcher(MeleeWatcher.class); if (watcher != null) { if (!valueChecked) { this.lockedInValue = watcher.getNumberOfAttackedPlayers(sourceAbility.getControllerId()); diff --git a/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java b/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java index 85f700357ff..e7fbee0fb73 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java @@ -20,7 +20,7 @@ public class MentorAbility extends AttacksTriggeredAbility { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature with lesser power"); static { - filter.add(new AttackingPredicate()); + filter.add(AttackingPredicate.instance); filter.add(MentorAbilityPredicate.instance); } diff --git a/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java b/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java index ce728b1f75f..e63ae4d5a2d 100644 --- a/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java @@ -47,7 +47,7 @@ public class NinjutsuAbility extends ActivatedAbilityImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("unblocked attacker you control"); static { - filter.add(new UnblockedPredicate()); + filter.add(UnblockedPredicate.instance); } /** diff --git a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java index 6ce501563f3..c6c26c43cdd 100644 --- a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java @@ -1,7 +1,5 @@ - package mage.abilities.keyword; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -19,18 +17,19 @@ import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; import mage.util.CardUtil; +import java.util.UUID; + /** - * * 702.46. Offering # 702.46a Offering is a static ability of a card that * functions in any zone from which the card can be cast. "[Subtype] offering" * means "You may cast this card any time you could cast an instant by * sacrificing a [subtype] permanent. If you do, the total cost to cast this * card is reduced by the sacrificed permanent's mana cost." # - * + *

* 702.46b The permanent is sacrificed at the same time the spell is announced * (see rule 601.2a). The total cost of the spell is reduced by the sacrificed * permanent's mana cost (see rule 601.2e). # - * + *

* 702.46c Generic mana in the sacrificed permanent's mana cost reduces generic * mana in the total cost to cast the card with offering. Colored mana in the * sacrificed permanent's mana cost reduces mana of the same color in the total @@ -39,7 +38,6 @@ import mage.util.CardUtil; * cost of the card with offering, or is in excess of the card's colored mana * cost, reduces that much generic mana in the total cost. # * - * * @author LevelX2 */ public class OfferingAbility extends StaticAbility { @@ -47,7 +45,6 @@ public class OfferingAbility extends StaticAbility { private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); /** - * * @param subtype name of the subtype that can be offered */ public OfferingAbility(SubType subtype) { @@ -107,7 +104,7 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game, UUID playerId) { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(sourceId); - if (!card.isOwnedBy(source.getControllerId())) { + if (card == null || !card.isOwnedBy(source.getControllerId())) { return false; } // because can activate is always called twice, result from first call will be used @@ -129,6 +126,9 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl { } FilterControlledCreaturePermanent filter = ((OfferingAbility) source).getFilter(); Card spellToCast = game.getCard(source.getSourceId()); + if (spellToCast == null) { + return false; + } Player player = game.getPlayer(source.getControllerId()); if (player != null && !CardUtil.isCheckPlayableMode(affectedAbility) && player.chooseUse(Outcome.Benefit, "Offer a " + filter.getMessage() + " to cast " + spellToCast.getName() + '?', source, game)) { @@ -146,7 +146,6 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl { game.getState().setValue("offering_ok_" + card.getId(), true); game.getState().setValue("offering_Id_" + card.getId(), activationId); return true; - } } else { game.getState().setValue("offering_" + card.getId(), true); @@ -201,7 +200,7 @@ class OfferingCostReductionEffect extends CostModificationEffectImpl { Card card = game.getCard(source.getSourceId()); if (card != null) { Object object = game.getState().getValue("offering_Id_" + card.getId()); - if (object != null && ((UUID) object).equals(this.activationId) && offeredPermanent.getPermanent(game) != null) { + if (object != null && object.equals(this.activationId) && offeredPermanent.getPermanent(game) != null) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java b/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java index 3bc23ba84fa..3e3ff1ca3c5 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java @@ -92,7 +92,7 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost public boolean askToActivateAlternativeCosts(Ability ability, Game game) { if (ability instanceof SpellAbility) { Player player = game.getPlayer(controllerId); - ProwlWatcher prowlWatcher = (ProwlWatcher) game.getState().getWatchers().get(ProwlWatcher.class.getSimpleName()); + ProwlWatcher prowlWatcher = game.getState().getWatcher(ProwlWatcher.class); Card card = game.getCard(ability.getSourceId()); if (player == null || prowlWatcher == null || card == null) { throw new IllegalArgumentException("Params can't be null"); @@ -108,7 +108,7 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost this.resetProwl(); for (AlternativeCost2 prowlCost : prowlCosts) { if (prowlCost.canPay(ability, sourceId, controllerId, game) - && player.chooseUse(Outcome.Benefit, new StringBuilder("Cast for ").append(PROWL_KEYWORD).append(" cost ").append(prowlCost.getText(true)).append(" ?").toString(), ability, game)) { + && player.chooseUse(Outcome.Benefit, "Cast for " + PROWL_KEYWORD + " cost " + prowlCost.getText(true) + " ?", ability, game)) { prowlCost.activate(); ability.getManaCostsToPay().clear(); ability.getCosts().clear(); diff --git a/Mage/src/main/java/mage/abilities/keyword/RampageAbility.java b/Mage/src/main/java/mage/abilities/keyword/RampageAbility.java index 2359c92a3cc..00b7bf47bea 100644 --- a/Mage/src/main/java/mage/abilities/keyword/RampageAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/RampageAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import mage.abilities.Ability; @@ -19,9 +18,15 @@ public class RampageAbility extends BecomesBlockedTriggeredAbility { private final String rule; public RampageAbility(int amount) { + this(amount, false); + } + + public RampageAbility(int amount, boolean shortRuleText) { super(null, false); - rule = "rampage " + amount + " (Whenever this creature becomes blocked, it gets +" - + amount + "/+" + amount + " until end of turn for each creature blocking it beyond the first.)"; + rule = "rampage " + amount + + (shortRuleText ? "" + : " (Whenever this creature becomes blocked, it gets +" + + amount + "/+" + amount + " until end of turn for each creature blocking it beyond the first.)"); RampageValue rv = new RampageValue(amount); this.addEffect(new BoostSourceEffect(rv, rv, Duration.EndOfTurn, true)); } diff --git a/Mage/src/main/java/mage/abilities/keyword/RiotAbility.java b/Mage/src/main/java/mage/abilities/keyword/RiotAbility.java index 47ca943dcb7..8ce3e97bb51 100644 --- a/Mage/src/main/java/mage/abilities/keyword/RiotAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/RiotAbility.java @@ -71,7 +71,7 @@ class RiotReplacementEffect extends ReplacementEffectImpl { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); Player controller = game.getPlayer(source.getControllerId()); if (creature != null && controller != null) { - if (controller.chooseUse(outcome, "Have " + creature.getLogName() + " enter the battlefield with a +1/+1 counter on it? (If you don't it has haste)", source, game)) { + if (controller.chooseUse(outcome, "Have " + creature.getLogName() + " enter the battlefield with a +1/+1 counter on it or with haste?",null, "+1/+1 counter", "Haste", source, game)) { if (!game.isSimulation()) { game.informPlayers(controller.getLogName() + " choose to put a +1/+1 counter on " + creature.getName()); } diff --git a/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java b/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java index da422af6d8f..e2b3cba0b4e 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java @@ -112,7 +112,7 @@ class SoulboundEntersSelfEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.not(new PairedPredicate())); } @@ -173,7 +173,7 @@ class SoulbondEntersOtherAbility extends EntersBattlefieldAllTriggeredAbility { static { soulbondFilter.add(Predicates.not(new PairedPredicate())); soulbondFilter.add(new ControllerPredicate(TargetController.YOU)); - soulbondFilter.add(new AnotherPredicate()); + soulbondFilter.add(AnotherPredicate.instance); } public SoulbondEntersOtherAbility() { @@ -214,7 +214,7 @@ class SoulboundEntersOtherEffect extends OneShotEffect { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control"); static { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.add(Predicates.not(new PairedPredicate())); } diff --git a/Mage/src/main/java/mage/abilities/keyword/SpectacleAbility.java b/Mage/src/main/java/mage/abilities/keyword/SpectacleAbility.java index e646742d6ab..8f3d172b239 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SpectacleAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SpectacleAbility.java @@ -40,7 +40,7 @@ public class SpectacleAbility extends SpellAbility { @Override public ActivationStatus canActivate(UUID playerId, Game game) { - PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); + PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); if (watcher != null && watcher.getAllOppLifeLost(playerId, game) > 0) { return super.canActivate(playerId, game); } diff --git a/Mage/src/main/java/mage/abilities/keyword/StormAbility.java b/Mage/src/main/java/mage/abilities/keyword/StormAbility.java index 45b99a4ab62..4e1b33d6769 100644 --- a/Mage/src/main/java/mage/abilities/keyword/StormAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/StormAbility.java @@ -74,7 +74,7 @@ class StormEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { MageObjectReference spellRef = (MageObjectReference) this.getValue("StormSpellRef"); if (spellRef != null) { - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { int stormCount = watcher.getSpellOrder(spellRef, game) - 1; if (stormCount > 0) { diff --git a/Mage/src/main/java/mage/abilities/keyword/SunburstAbility.java b/Mage/src/main/java/mage/abilities/keyword/SunburstAbility.java index e5aabcfe010..434b57f96a2 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SunburstAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SunburstAbility.java @@ -50,7 +50,7 @@ public class SunburstAbility extends EntersBattlefieldAbility { class SunburstEffect extends OneShotEffect { - private static final DynamicValue amount = new SunburstCount(); + private static final DynamicValue amount = SunburstCount.instance; public SunburstEffect() { super(Outcome.Benefit); diff --git a/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java b/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java index 9e74163a2f7..4b4d591f888 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java @@ -24,7 +24,7 @@ public class SupportAbility extends EntersBattlefieldTriggeredAbility { if (!card.isInstant() && !card.isSorcery()) { FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures"); if (card.isCreature()) { - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); filter.setMessage("other target creatures"); } addTarget(new TargetCreaturePermanent(0, amount, filter, false)); diff --git a/Mage/src/main/java/mage/abilities/keyword/SurgeAbility.java b/Mage/src/main/java/mage/abilities/keyword/SurgeAbility.java index a94231fb4b8..0e4c28b5406 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SurgeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SurgeAbility.java @@ -42,7 +42,7 @@ public class SurgeAbility extends SpellAbility { @Override public ActivationStatus canActivate(UUID playerId, Game game) { // check if controller or teammate has already cast a spell this turn - CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); if (watcher != null) { Player player = game.getPlayer(playerId); if (player != null) { diff --git a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java index 086a90ff431..288e48b1952 100644 --- a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java @@ -1,8 +1,6 @@ package mage.abilities.mana; -import java.util.ArrayList; -import java.util.List; import mage.Mana; import mage.abilities.Abilities; import mage.abilities.Ability; @@ -20,8 +18,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.ArrayList; +import java.util.List; + /** - * * @author LevelX2 */ public class AnyColorLandsProduceManaAbility extends ActivatedManaAbilityImpl { @@ -31,7 +31,11 @@ public class AnyColorLandsProduceManaAbility extends ActivatedManaAbilityImpl { } public AnyColorLandsProduceManaAbility(TargetController targetController, boolean onlyColors) { - super(Zone.BATTLEFIELD, new AnyColorLandsProduceManaEffect(targetController, onlyColors), new TapSourceCost()); + this(targetController, onlyColors, null); + } + + public AnyColorLandsProduceManaAbility(TargetController targetController, boolean onlyColors, FilterPermanent filter) { + super(Zone.BATTLEFIELD, new AnyColorLandsProduceManaEffect(targetController, onlyColors, filter), new TapSourceCost()); } public AnyColorLandsProduceManaAbility(final AnyColorLandsProduceManaAbility ability) { @@ -62,16 +66,21 @@ class AnyColorLandsProduceManaEffect extends ManaEffect { private boolean inManaTypeCalculation = false; - public AnyColorLandsProduceManaEffect(TargetController targetController, boolean onlyColors) { + AnyColorLandsProduceManaEffect(TargetController targetController, boolean onlyColors, FilterPermanent filter) { super(); - filter = new FilterLandPermanent(); + if (filter == null) { + this.filter = new FilterLandPermanent(); + } else { + this.filter = filter.copy(); + } this.onlyColors = onlyColors; - filter.add(new ControllerPredicate(targetController)); + this.filter.add(new ControllerPredicate(targetController)); String text = targetController == TargetController.OPPONENT ? "an opponent controls" : "you control"; - staticText = "Add one mana of any " + (this.onlyColors ? "color" : "type") + " that a land " + text + " could produce"; + staticText = "Add one mana of any " + (this.onlyColors ? "color" : "type") + " that a " + + (filter == null ? "land " : filter.getMessage() + " ") + text + " could produce"; } - public AnyColorLandsProduceManaEffect(final AnyColorLandsProduceManaEffect effect) { + private AnyColorLandsProduceManaEffect(final AnyColorLandsProduceManaEffect effect) { super(effect); this.filter = effect.filter.copy(); this.onlyColors = effect.onlyColors; diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index 56cad1816ca..9a473048df1 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -327,9 +327,11 @@ public abstract class CardImpl extends MageObjectImpl implements Card { return spellAbility; } - // @Override -// public void adjustCosts(Ability ability, Game game) { -// } + @Override + public void adjustCosts(Ability ability, Game game) { + ability.adjustCosts(game); + } + @Override public void adjustTargets(Ability ability, Game game) { ability.adjustTargets(game); @@ -360,9 +362,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { public List getMana() { List mana = new ArrayList<>(); for (ActivatedManaAbilityImpl ability : this.abilities.getActivatedManaAbilities(Zone.BATTLEFIELD)) { - for (Mana netMana : ability.getNetMana(null)) { - mana.add(netMana); - } + mana.addAll(ability.getNetMana(null)); } return mana; } diff --git a/Mage/src/main/java/mage/cards/decks/Constructed.java b/Mage/src/main/java/mage/cards/decks/Constructed.java index 23410c32b5d..4773b3972f4 100644 --- a/Mage/src/main/java/mage/cards/decks/Constructed.java +++ b/Mage/src/main/java/mage/cards/decks/Constructed.java @@ -1,26 +1,29 @@ package mage.cards.decks; -import java.util.*; -import java.util.Map.Entry; import mage.cards.Card; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.Rarity; import org.apache.log4j.Logger; +import java.util.*; +import java.util.Map.Entry; + /** - * * @author BetaSteward_at_googlemail.com */ public class Constructed extends DeckValidator { private static final Logger logger = Logger.getLogger(DeckValidator.class); - protected static final List anyNumberCardsAllowed = new ArrayList<>(Arrays.asList("Relentless Rats", "Shadowborn Apostle", "Rat Colony")); - protected static final List basicLandNames = new ArrayList<>( - Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes", "Snow-Covered Forest", - "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); + protected static final List anyNumberCardsAllowed = Arrays.asList( + "Relentless Rats", "Shadowborn Apostle", "Rat Colony", "Persistent Petitioners" + ); + protected static final List basicLandNames = Arrays.asList( + "Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes", "Snow-Covered Forest", + "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains" + ); protected List banned = new ArrayList<>(); protected List restricted = new ArrayList<>(); protected List setCodes = new ArrayList<>(); diff --git a/Mage/src/main/java/mage/cards/decks/importer/CardLookup.java b/Mage/src/main/java/mage/cards/decks/importer/CardLookup.java new file mode 100644 index 00000000000..2a7aa1ae3e1 --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/importer/CardLookup.java @@ -0,0 +1,22 @@ +package mage.cards.decks.importer; + +import java.util.List; +import java.util.Optional; + +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; + +public class CardLookup { + + public static final CardLookup instance = new CardLookup(); + + public Optional lookupCardInfo(String name) { + return Optional.ofNullable(CardRepository.instance.findPreferedCoreExpansionCard(name, true)); + } + + public List lookupCardInfo(CardCriteria criteria) { + return CardRepository.instance.findCards(criteria); + } + +} diff --git a/Mage/src/main/java/mage/cards/decks/importer/CodDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/CodDeckImporter.java new file mode 100644 index 00000000000..a79a6beeb5b --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/importer/CodDeckImporter.java @@ -0,0 +1,74 @@ +package mage.cards.decks.importer; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLists; +import mage.cards.repository.CardInfo; + +public class CodDeckImporter extends XmlDeckImporter { + + @Override + public DeckCardLists importDeck(String filename, StringBuilder errorMessages) { + try { + Document doc = getXmlDocument(filename); + DeckCardLists decklist = new DeckCardLists(); + + List mainCards = getNodes(doc, "/cockatrice_deck/zone[@name='main']/card"); + decklist.setCards(mainCards.stream() + .flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) + .collect(Collectors.toList())); + + List sideboardCards = getNodes(doc, "/cockatrice_deck/zone[@name='side']/card"); + decklist.setSideboard(sideboardCards.stream() + .flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) + .collect(Collectors.toList())); + + getNodes(doc, "/cockatrice_deck/deckname") + .forEach(n -> decklist.setName(n.getTextContent().trim())); + + return decklist; + } catch (Exception e) { + logger.error("Error loading deck", e); + errorMessages.append("There was an error loading the deck."); + return new DeckCardLists(); + } + } + + private static int getQuantityFromNode(Node node) { + Node numberNode = node.getAttributes().getNamedItem("number"); + if (numberNode == null) { + return 1; + } + try { + return Math.min(100, Math.max(1, Integer.parseInt(numberNode.getNodeValue()))); + } catch (NumberFormatException e) { + return 1; + } + } + + private static Function> toDeckCardInfo(CardLookup lookup, StringBuilder errors) { + return node -> { + String name = node.getAttributes().getNamedItem("name").getNodeValue().trim(); + Optional cardInfo = lookup.lookupCardInfo(name); + if (cardInfo.isPresent()) { + CardInfo info = cardInfo.get(); + return Collections.nCopies( + getQuantityFromNode(node), + new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream(); + } else { + errors.append("Could not find card: '").append(name).append("'\n"); + return Stream.empty(); + } + }; + } + +} diff --git a/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java index fee59b3b4d6..787e3cfe5ac 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java @@ -15,7 +15,7 @@ import mage.cards.repository.CardRepository; * * @author North */ -public class DckDeckImporter extends DeckImporter { +public class DckDeckImporter extends PlainTextDeckImporter { private static final Pattern pattern = Pattern.compile("(SB:)?\\s*(\\d*)\\s*\\[([^]:]+):([^]:]+)\\]\\s*(.*)\\s*$"); diff --git a/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java index cf2c83a0c55..5ab07af1de4 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java @@ -1,6 +1,8 @@ package mage.cards.decks.importer; +import java.util.Optional; + import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardInfo; @@ -10,7 +12,7 @@ import mage.cards.repository.CardRepository; * * @author BetaSteward_at_googlemail.com */ -public class DecDeckImporter extends DeckImporter { +public class DecDeckImporter extends PlainTextDeckImporter { @Override protected void readLine(String line, DeckCardLists deckList) { @@ -29,10 +31,11 @@ public class DecDeckImporter extends DeckImporter { String lineName = line.substring(delim).trim(); try { int num = Integer.parseInt(lineNum); - CardInfo cardInfo = CardRepository.instance.findPreferedCoreExpansionCard(lineName, true); - if (cardInfo == null) { + Optional cardLookup = getCardLookup().lookupCardInfo(lineName); + if (!cardLookup.isPresent()) { sbMessage.append("Could not find card: '").append(lineName).append("' at line ").append(lineCount).append('\n'); } else { + CardInfo cardInfo = cardLookup.get(); for (int i = 0; i < num; i++) { if (!sideboard) { deckList.getCards().add(new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode())); diff --git a/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java index 1957cd7058e..2e20ded6412 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java @@ -1,74 +1,89 @@ - - package mage.cards.decks.importer; -import mage.cards.decks.DeckCardLists; import org.apache.log4j.Logger; - import java.io.File; +import java.util.Locale; +import java.util.Optional; import java.util.Scanner; -/** - * - * @author BetaSteward_at_googlemail.com - */ + +import mage.cards.decks.DeckCardLists; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; + public abstract class DeckImporter { - private static final Logger logger = Logger.getLogger(DeckImporter.class); + protected static final Logger logger = Logger.getLogger(DeckImporter.class); - protected StringBuilder sbMessage = new StringBuilder(); //TODO we should stop using this not garbage collectable StringBuilder. It just bloats - protected int lineCount; + private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "}; + public static DeckImporter getDeckImporter(String file) { + if (file == null) { + return null; + } if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) { + return new DecDeckImporter(); + } else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) { + return new MWSDeckImporter(); + } else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) { + return new TxtDeckImporter(haveSideboardSection(file)); + } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dck")) { + return new DckDeckImporter(); + } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dek")) { + return new DekDeckImporter(); + } else if (file.toLowerCase(Locale.ENGLISH).endsWith("cod")) { + return new CodDeckImporter(); + } else if (file.toLowerCase(Locale.ENGLISH).endsWith("o8d")) { + return new O8dDeckImporter(); + } else { + return null; + } + } - /** - * - * @param file file to import - * @param errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0) - * @return decks list - */ - public DeckCardLists importDeck(String file, StringBuilder errorMessages) { - File f = new File(file); - DeckCardLists deckList = new DeckCardLists(); - if (!f.exists()) { - logger.warn("Deckfile " + file + " not found."); - return deckList; + public static DeckCardLists importDeckFromFile(String file) { + return importDeckFromFile(file, new StringBuilder()); + } + + public static DeckCardLists importDeckFromFile(String file, StringBuilder errorMessages) { + DeckImporter deckImporter = getDeckImporter(file); + if (deckImporter != null) { + return deckImporter.importDeck(file, errorMessages); + } else { + return new DeckCardLists(); + } + } + + public abstract DeckCardLists importDeck(String file, StringBuilder errorMessages); + + public DeckCardLists importDeck(String file) { + return importDeck(file, new StringBuilder()); + } + + public CardLookup getCardLookup() { + return CardLookup.instance; + } + + private static boolean haveSideboardSection(String file) { + // search for sideboard section: + // or //sideboard + // or SB: 1 card name -- special deckstats.net + + File f = new File(file); + try (Scanner scanner = new Scanner(f)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim().toLowerCase(Locale.ENGLISH); + + for (String mark : SIDEBOARD_MARKS) { + if (line.startsWith(mark)) { + return true; + } } - lineCount = 0; - - sbMessage.setLength(0); - try { - try (Scanner scanner = new Scanner(f)) { - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - lineCount++; - readLine(line, deckList); - } - - if (sbMessage.length() > 0) { - if(errorMessages != null) { - // normal output for user - errorMessages.append(sbMessage); - }else{ - // fatal error - logger.fatal(sbMessage); - } - } - } catch (Exception ex) { - logger.fatal(null, ex); - } - } catch (Exception ex) { - logger.fatal(null, ex); - } - return deckList; + } + } catch (Exception e) { + // ignore error, deckimporter will process it } - public DeckCardLists importDeck(String file) { - return importDeck(file, null); - } + // not found + return false; + } - public String getErrors(){ - return sbMessage.toString(); - } - - protected abstract void readLine(String line, DeckCardLists deckList); } diff --git a/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java b/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java deleted file mode 100644 index 0384a17f44c..00000000000 --- a/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java +++ /dev/null @@ -1,71 +0,0 @@ - -package mage.cards.decks.importer; - -import java.io.File; -import java.util.Locale; -import java.util.Scanner; -import mage.cards.decks.DeckCardLists; - -/** - * - * @author North - */ -public final class DeckImporterUtil { - - private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "}; - - public static boolean haveSideboardSection(String file) { - // search for sideboard section: - // or //sideboard - // or SB: 1 card name -- special deckstats.net - - File f = new File(file); - try (Scanner scanner = new Scanner(f)) { - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim().toLowerCase(Locale.ENGLISH); - - for (String mark : SIDEBOARD_MARKS) { - if (line.startsWith(mark)) { - return true; - } - } - } - } catch (Exception e) { - // ignore error, deckimporter will process it - } - - // not found - return false; - } - - public static DeckImporter getDeckImporter(String file) { - if (file == null) { - return null; - } if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) { - return new DecDeckImporter(); - } else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) { - return new MWSDeckImporter(); - } else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) { - return new TxtDeckImporter(haveSideboardSection(file)); - } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dck")) { - return new DckDeckImporter(); - } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dek")) { - return new DekDeckImporter(); - } else { - return null; - } - } - - public static DeckCardLists importDeck(String file, StringBuilder errorMessages) { - DeckImporter deckImporter = getDeckImporter(file); - if (deckImporter != null) { - return deckImporter.importDeck(file, errorMessages); - } else { - return new DeckCardLists(); - } - } - - public static DeckCardLists importDeck(String file) { - return importDeck(file, null); - } -} diff --git a/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java index 7e6efc577a6..2672ff9d3ef 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java @@ -8,7 +8,7 @@ import mage.cards.repository.CardRepository; /** * Created by royk on 11-Sep-16. */ -public class DekDeckImporter extends DeckImporter { +public class DekDeckImporter extends PlainTextDeckImporter { @Override protected void readLine(String line, DeckCardLists deckList) { diff --git a/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java index bb5c0662186..7c23d28c60b 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java @@ -14,7 +14,7 @@ import mage.util.RandomUtil; * * @author BetaSteward_at_googlemail.com */ -public class MWSDeckImporter extends DeckImporter { +public class MWSDeckImporter extends PlainTextDeckImporter { @Override protected void readLine(String line, DeckCardLists deckList) { @@ -43,13 +43,13 @@ public class MWSDeckImporter extends DeckImporter { CardCriteria criteria = new CardCriteria(); criteria.name(lineName); criteria.setCodes(setCode); - List cards = CardRepository.instance.findCards(criteria); + List cards = getCardLookup().lookupCardInfo(criteria); if (!cards.isEmpty()) { cardInfo = cards.get(RandomUtil.nextInt(cards.size())); } } if (cardInfo == null) { - cardInfo = CardRepository.instance.findPreferedCoreExpansionCard(lineName, true); + cardInfo = getCardLookup().lookupCardInfo(lineName).orElse(null); } if (cardInfo == null) { diff --git a/Mage/src/main/java/mage/cards/decks/importer/O8dDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/O8dDeckImporter.java new file mode 100644 index 00000000000..cefc64e9616 --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/importer/O8dDeckImporter.java @@ -0,0 +1,71 @@ +package mage.cards.decks.importer; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLists; +import mage.cards.repository.CardInfo; + +public class O8dDeckImporter extends XmlDeckImporter { + + @Override + public DeckCardLists importDeck(String filename, StringBuilder errorMessages) { + try { + Document doc = getXmlDocument(filename); + DeckCardLists decklist = new DeckCardLists(); + + List mainCards = getNodes(doc, "/deck/section[@name='Main']/card"); + decklist.setCards(mainCards.stream() + .flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) + .collect(Collectors.toList())); + + List sideboardCards = getNodes(doc, "/deck/section[@name='Sideboard']/card"); + decklist.setSideboard(sideboardCards.stream() + .flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) + .collect(Collectors.toList())); + + return decklist; + } catch (Exception e) { + logger.error("Error loading deck", e); + errorMessages.append("There was an error loading the deck."); + return new DeckCardLists(); + } + } + + private static int getQuantityFromNode(Node node) { + Node numberNode = node.getAttributes().getNamedItem("qty"); + if (numberNode == null) { + return 1; + } + try { + return Math.min(100, Math.max(1, Integer.parseInt(numberNode.getNodeValue()))); + } catch (NumberFormatException e) { + return 1; + } + } + + private static Function> toDeckCardInfo(CardLookup lookup, StringBuilder errors) { + return node -> { + String name = node.getTextContent(); + Optional cardInfo = lookup.lookupCardInfo(name); + if (cardInfo.isPresent()) { + CardInfo info = cardInfo.get(); + return Collections.nCopies( + getQuantityFromNode(node), + new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream(); + } else { + errors.append("Could not find card: '").append(name).append("'\n"); + return Stream.empty(); + } + }; + } + +} diff --git a/Mage/src/main/java/mage/cards/decks/importer/PlainTextDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/PlainTextDeckImporter.java new file mode 100644 index 00000000000..c9d99d3aaee --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/importer/PlainTextDeckImporter.java @@ -0,0 +1,67 @@ + + +package mage.cards.decks.importer; + +import java.io.File; +import java.util.Scanner; + +import mage.cards.decks.DeckCardLists; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public abstract class PlainTextDeckImporter extends DeckImporter { + + protected StringBuilder sbMessage = new StringBuilder(); //TODO we should stop using this not garbage collectable StringBuilder. It just bloats + protected int lineCount; + + + /** + * + * @param file file to import + * @param errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0) + * @return decks list + */ + public DeckCardLists importDeck(String file, StringBuilder errorMessages) { + File f = new File(file); + DeckCardLists deckList = new DeckCardLists(); + if (!f.exists()) { + logger.warn("Deckfile " + file + " not found."); + return deckList; + } + lineCount = 0; + + sbMessage.setLength(0); + try { + try (Scanner scanner = new Scanner(f)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + lineCount++; + readLine(line, deckList); + } + + if (sbMessage.length() > 0) { + if(errorMessages != null) { + // normal output for user + errorMessages.append(sbMessage); + }else{ + // fatal error + logger.fatal(sbMessage); + } + } + } catch (Exception ex) { + logger.fatal(null, ex); + } + } catch (Exception ex) { + logger.fatal(null, ex); + } + return deckList; + } + + public DeckCardLists importDeck(String file) { + return importDeck(file, null); + } + + protected abstract void readLine(String line, DeckCardLists deckList); +} diff --git a/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java index 4d593610ff5..a2b5706eb8b 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java @@ -14,7 +14,7 @@ import mage.cards.repository.CardRepository; * * @author BetaSteward_at_googlemail.com */ -public class TxtDeckImporter extends DeckImporter { +public class TxtDeckImporter extends PlainTextDeckImporter { private static final String[] SET_VALUES = new String[]{"lands", "creatures", "planeswalkers", "other spells", "sideboard cards", "Instant", "Land", "Enchantment", "Artifact", "Sorcery", "Planeswalker", "Creature"}; diff --git a/Mage/src/main/java/mage/cards/decks/importer/XmlDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/XmlDeckImporter.java new file mode 100644 index 00000000000..8a88799656f --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/importer/XmlDeckImporter.java @@ -0,0 +1,52 @@ +package mage.cards.decks.importer; + +import static javax.xml.xpath.XPathConstants.NODESET; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +public abstract class XmlDeckImporter extends DeckImporter { + + private XPathFactory xpathFactory = XPathFactory.newInstance(); + private DocumentBuilder builder = getDocumentBuilder(); + + protected List getNodes(Document doc, String xpathExpression) throws XPathExpressionException { + NodeList nodes = (NodeList) xpathFactory.newXPath().evaluate(xpathExpression, doc, NODESET); + ArrayList list = new ArrayList<>(); + for (int i = 0; i < nodes.getLength(); i++) { + list.add(nodes.item(i)); + } + return list; + } + + private DocumentBuilder getDocumentBuilder() { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + return factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new RuntimeException(); + } + } + + protected Document getXmlDocument(String filename) throws IOException { + try { + return builder.parse(new File(filename)); + } catch (SAXException e) { + throw new IOException(e); + } + } + +} diff --git a/Mage/src/main/java/mage/cards/repository/CardCriteria.java b/Mage/src/main/java/mage/cards/repository/CardCriteria.java index 6e72fcde256..85882512b24 100644 --- a/Mage/src/main/java/mage/cards/repository/CardCriteria.java +++ b/Mage/src/main/java/mage/cards/repository/CardCriteria.java @@ -309,4 +309,97 @@ public class CardCriteria { qb.orderBy(sortBy, true); } } + + public String getName() { + return name; + } + + public String getNameExact() { + return nameExact; + } + + public String getRules() { + return rules; + } + + public List getSetCodes() { + return setCodes; + } + + public List getTypes() { + return types; + } + + public List getNotTypes() { + return notTypes; + } + + public List getSupertypes() { + return supertypes; + } + + public List getNotSupertypes() { + return notSupertypes; + } + + public List getSubtypes() { + return subtypes; + } + + public List getRarities() { + return rarities; + } + + public Boolean getDoubleFaced() { + return doubleFaced; + } + + public boolean isBlack() { + return black; + } + + public boolean isBlue() { + return blue; + } + + public boolean isGreen() { + return green; + } + + public boolean isRed() { + return red; + } + + public boolean isWhite() { + return white; + } + + public boolean isColorless() { + return colorless; + } + + public Integer getConvertedManaCost() { + return convertedManaCost; + } + + public String getSortBy() { + return sortBy; + } + + public Long getStart() { + return start; + } + + public Long getCount() { + return count; + } + + public int getMinCardNumber() { + return minCardNumber; + } + + public int getMaxCardNumber() { + return maxCardNumber; + } + } diff --git a/Mage/src/main/java/mage/cards/repository/CardInfo.java b/Mage/src/main/java/mage/cards/repository/CardInfo.java index 2563d4e3077..e33bafe158b 100644 --- a/Mage/src/main/java/mage/cards/repository/CardInfo.java +++ b/Mage/src/main/java/mage/cards/repository/CardInfo.java @@ -301,7 +301,7 @@ public class CardInfo { return sl; } for (String s : subtypes.split(SEPARATOR)) { - sl.add(s); + sl.add(SubType.fromString(s)); } return sl; } diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 93363d0a30a..379cfd1e9ce 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -14,6 +14,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetType; import mage.constants.SuperType; +import mage.game.events.Listener; import mage.util.RandomUtil; import org.apache.log4j.Logger; @@ -22,20 +23,23 @@ import java.sql.SQLException; import java.util.*; /** - * @author North + * @author North, JayDi85 */ public enum CardRepository { instance; + private static final Logger logger = Logger.getLogger(CardRepository.class); + private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "card"; // raise this if db structure was changed private static final long CARD_DB_VERSION = 51; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 123; + private static final long CARD_CONTENT_VERSION = 214; private Dao cardDao; private Set classNames; + private RepositoryEventSource eventSource = new RepositoryEventSource(); CardRepository() { File file = new File("db"); @@ -48,32 +52,50 @@ public enum CardRepository { boolean isObsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, CARD_DB_VERSION); boolean isNewBuild = RepositoryUtil.isNewBuildRun(connectionSource, VERSION_ENTITY_NAME, CardRepository.class); // recreate db on new build if (isObsolete || isNewBuild) { + //System.out.println("Local cards db is outdated, cleaning..."); TableUtils.dropTable(connectionSource, CardInfo.class, true); } TableUtils.createTableIfNotExists(connectionSource, CardInfo.class); cardDao = DaoManager.createDao(connectionSource, CardInfo.class); + + eventSource.fireRepositoryDbLoaded(); } catch (SQLException ex) { Logger.getLogger(CardRepository.class).error("Error creating card repository - ", ex); } } - public void addCards(final List cards) { + public void subscribe(Listener listener) { + eventSource.addListener(listener); + } + + public void saveCards(final List newCards, long newContentVersion) { try { cardDao.callBatchTasks(() -> { - try { - for (CardInfo card : cards) { - cardDao.create(card); - if (classNames != null) { - classNames.add(card.getClassName()); + // add + if (newCards != null && newCards.size() > 0) { + logger.info("DB: need to add " + newCards.size() + " new cards"); + try { + for (CardInfo card : newCards) { + cardDao.create(card); + if (classNames != null) { + classNames.add(card.getClassName()); + } } + } catch (SQLException ex) { + Logger.getLogger(CardRepository.class).error("Error adding cards to DB - ", ex); } - } catch (SQLException ex) { - Logger.getLogger(CardRepository.class).error("Error adding cards to DB - ", ex); } + + // no card updates + return null; }); + + setContentVersion(newContentVersion); + eventSource.fireRepositoryDbUpdated(); } catch (Exception ex) { + // } } diff --git a/Mage/src/main/java/mage/cards/repository/CardScanner.java b/Mage/src/main/java/mage/cards/repository/CardScanner.java index 8a551411398..9939dd49ace 100644 --- a/Mage/src/main/java/mage/cards/repository/CardScanner.java +++ b/Mage/src/main/java/mage/cards/repository/CardScanner.java @@ -1,13 +1,12 @@ - package mage.cards.repository; -import java.util.ArrayList; -import java.util.List; import mage.cards.*; import org.apache.log4j.Logger; +import java.util.ArrayList; +import java.util.List; + /** - * * @author North */ public final class CardScanner { @@ -27,14 +26,15 @@ public final class CardScanner { scanned = true; List cardsToAdd = new ArrayList<>(); - int setsUpdatedCount = 0; - int setsAddedCount = 0; + List setsToAdd = new ArrayList<>(); + List setsToUpdate = new ArrayList<>(); + // check sets for (ExpansionSet set : Sets.getInstance().values()) { ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(set.getCode()); if (expansionInfo == null) { - setsAddedCount += 1; - ExpansionRepository.instance.add(new ExpansionInfo(set)); + // need add + setsToAdd.add(new ExpansionInfo(set)); } else if (!expansionInfo.name.equals(set.getName()) || !expansionInfo.code.equals(set.getCode()) || (expansionInfo.blockName == null ? set.getBlockName() != null : !expansionInfo.blockName.equals(set.getBlockName())) @@ -42,22 +42,17 @@ public final class CardScanner { || expansionInfo.type != set.getSetType() || expansionInfo.boosters != set.hasBoosters() || expansionInfo.basicLands != set.hasBasicLands()) { - setsUpdatedCount += 1; - ExpansionRepository.instance.update(expansionInfo); + // need update + setsToUpdate.add(expansionInfo); } } - ExpansionRepository.instance.setContentVersion(ExpansionRepository.instance.getContentVersionConstant()); - - if (setsAddedCount > 0) { - logger.info("DB: need to add " + setsAddedCount + " new sets"); - } - if (setsUpdatedCount > 0) { - logger.info("DB: need to update " + setsUpdatedCount + " sets"); - } + ExpansionRepository.instance.saveSets(setsToAdd, setsToUpdate, ExpansionRepository.instance.getContentVersionConstant()); + // check cards (only add mode, without updates) for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet.SetCardInfo setInfo : set.getSetCardInfo()) { if (CardRepository.instance.findCard(set.getCode(), setInfo.getCardNumber()) == null) { + // need add Card card = CardImpl.createCard( setInfo.getCardClass(), new CardSetInfo(setInfo.getName(), set.getCode(), setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo()), @@ -73,11 +68,6 @@ public final class CardScanner { } } } - - if (!cardsToAdd.isEmpty()) { - logger.info("DB: need to add " + cardsToAdd.size() + " new cards"); - CardRepository.instance.addCards(cardsToAdd); - } - CardRepository.instance.setContentVersion(CardRepository.instance.getContentVersionConstant()); + CardRepository.instance.saveCards(cardsToAdd, CardRepository.instance.getContentVersionConstant()); } } diff --git a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java index fe53c4c32cc..c0bfded7684 100644 --- a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java +++ b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java @@ -8,6 +8,7 @@ import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.stmt.SelectArg; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; +import mage.game.events.Listener; import org.apache.log4j.Logger; import java.io.File; @@ -18,7 +19,7 @@ import java.util.LinkedList; import java.util.List; /** - * @author North + * @author North, JayDi85 */ public enum ExpansionRepository { @@ -32,7 +33,7 @@ public enum ExpansionRepository { private static final long EXPANSION_CONTENT_VERSION = 17; private Dao expansionDao; - + private RepositoryEventSource eventSource = new RepositoryEventSource(); public boolean instanceInitialized = false; ExpansionRepository() { @@ -46,31 +47,59 @@ public enum ExpansionRepository { boolean isObsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, EXPANSION_DB_VERSION); boolean isNewBuild = RepositoryUtil.isNewBuildRun(connectionSource, VERSION_ENTITY_NAME, ExpansionRepository.class); // recreate db on new build if (isObsolete || isNewBuild) { + //System.out.println("Local sets db is outdated, cleaning..."); TableUtils.dropTable(connectionSource, ExpansionInfo.class, true); } TableUtils.createTableIfNotExists(connectionSource, ExpansionInfo.class); expansionDao = DaoManager.createDao(connectionSource, ExpansionInfo.class); instanceInitialized = true; + + eventSource.fireRepositoryDbLoaded(); } catch (SQLException ex) { ex.printStackTrace(); } } - public void add(ExpansionInfo expansion) { - try { - expansionDao.create(expansion); - } catch (SQLException ex) { - logger.error(ex); - } + public void subscribe(Listener listener) { + eventSource.addListener(listener); } - public void update(ExpansionInfo expansion) { + public void saveSets(final List newSets, final List updatedSets, long newContentVersion) { try { - expansionDao.update(expansion); - } catch (SQLException ex) { - logger.error(ex); + expansionDao.callBatchTasks(() -> { + // add + if (newSets != null && newSets.size() > 0) { + logger.info("DB: need to add " + newSets.size() + " new sets"); + try { + for (ExpansionInfo exp : newSets) { + expansionDao.create(exp); + } + } catch (SQLException ex) { + Logger.getLogger(CardRepository.class).error("Error adding expansions to DB - ", ex); + } + } + + // update + if (updatedSets != null && updatedSets.size() > 0) { + logger.info("DB: need to update " + updatedSets.size() + " sets"); + try { + for (ExpansionInfo exp : updatedSets) { + expansionDao.update(exp); + } + } catch (SQLException ex) { + Logger.getLogger(CardRepository.class).error("Error adding expansions to DB - ", ex); + } + } + + return null; + }); + + setContentVersion(newContentVersion); + eventSource.fireRepositoryDbUpdated(); + } catch (Exception ex) { + // } } diff --git a/Mage/src/main/java/mage/cards/repository/RepositoryEvent.java b/Mage/src/main/java/mage/cards/repository/RepositoryEvent.java new file mode 100644 index 00000000000..2056f747199 --- /dev/null +++ b/Mage/src/main/java/mage/cards/repository/RepositoryEvent.java @@ -0,0 +1,27 @@ +package mage.cards.repository; + +import mage.game.events.ExternalEvent; + +import java.io.Serializable; +import java.util.EventObject; + +/** + * @author JayDi85 + */ +public class RepositoryEvent extends EventObject implements ExternalEvent, Serializable { + + public enum RepositoryEventType { + DB_LOADED, DB_UPDATED + } + + private RepositoryEventType eventType; + + public RepositoryEvent(RepositoryEventType eventType) { + super(eventType); + this.eventType = eventType; + } + + public RepositoryEventType getEventType() { + return eventType; + } +} diff --git a/Mage/src/main/java/mage/cards/repository/RepositoryEventSource.java b/Mage/src/main/java/mage/cards/repository/RepositoryEventSource.java new file mode 100644 index 00000000000..33dda83d60f --- /dev/null +++ b/Mage/src/main/java/mage/cards/repository/RepositoryEventSource.java @@ -0,0 +1,34 @@ +package mage.cards.repository; + +import mage.game.events.EventDispatcher; +import mage.game.events.EventSource; +import mage.game.events.Listener; + +import java.io.Serializable; + +/** + * @author JayDi85 + */ +public class RepositoryEventSource implements EventSource, Serializable { + + protected final EventDispatcher dispatcher = new EventDispatcher() { + }; + + @Override + public void addListener(Listener listener) { + dispatcher.addListener(listener); + } + + @Override + public void removeAllListener() { + dispatcher.removeAllListener(); + } + + public void fireRepositoryDbLoaded() { + dispatcher.fireEvent(new RepositoryEvent(RepositoryEvent.RepositoryEventType.DB_LOADED)); + } + + public void fireRepositoryDbUpdated() { + dispatcher.fireEvent(new RepositoryEvent(RepositoryEvent.RepositoryEventType.DB_UPDATED)); + } +} diff --git a/Mage/src/main/java/mage/cards/repository/RepositoryUtil.java b/Mage/src/main/java/mage/cards/repository/RepositoryUtil.java index b794e8a4e79..cf39f4c8b05 100644 --- a/Mage/src/main/java/mage/cards/repository/RepositoryUtil.java +++ b/Mage/src/main/java/mage/cards/repository/RepositoryUtil.java @@ -8,16 +8,25 @@ import com.j256.ormlite.stmt.SelectArg; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; import mage.util.JarVersion; +import org.apache.log4j.Logger; import java.sql.SQLException; import java.util.List; /** - * - * @author North + * @author North, JayDi85 */ public final class RepositoryUtil { + private static final Logger logger = Logger.getLogger(RepositoryUtil.class); + + public static void bootstrapLocalDb() { + // call local db to init all sets and cards repository (need for correct updates cycle, not on random request) + logger.info("Loading database..."); + ExpansionRepository.instance.getContentVersionConstant(); + CardRepository.instance.getContentVersionConstant(); + } + public static boolean isDatabaseObsolete(ConnectionSource connectionSource, String entityName, long version) throws SQLException { TableUtils.createTableIfNotExists(connectionSource, DatabaseVersion.class); Dao dbVersionDao = DaoManager.createDao(connectionSource, DatabaseVersion.class); @@ -37,6 +46,7 @@ public final class RepositoryUtil { public static boolean isNewBuildRun(ConnectionSource connectionSource, String entityName, Class clazz) throws SQLException { // build time checks only for releases, not runtime (e.g. IDE debug) + // that's check uses for cards db cleanup on new version/build String currentBuild = JarVersion.getBuildTime(clazz); if (!JarVersion.isBuildTimeOk(currentBuild)) { return false; diff --git a/Mage/src/main/java/mage/constants/Duration.java b/Mage/src/main/java/mage/constants/Duration.java index e23951b8e12..1c462cbb3df 100644 --- a/Mage/src/main/java/mage/constants/Duration.java +++ b/Mage/src/main/java/mage/constants/Duration.java @@ -12,6 +12,7 @@ public enum Duration { WhileInGraveyard("", false), EndOfTurn("until end of turn", true), UntilYourNextTurn("until your next turn", true), + UntilSourceLeavesBattlefield("until {source} leaves the battlefield", true), // supported for continuous layered effects EndOfCombat("until end of combat", true), EndOfStep("until end of phase step", true), Custom("", true); diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 98e2cd259ff..d1b5522ecec 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -52,6 +52,7 @@ public enum CounterType { FUSE("fuse"), GEM("gem"), GLOBE("globe"), + GLYPH("glyph"), GOLD("gold"), GROWTH("growth"), HATCHLING("hatchling"), @@ -74,12 +75,14 @@ public enum CounterType { LOYALTY("loyalty"), MANIFESTATION("manifestation"), MANNEQUIN("mannequin"), + MATRIX("matrix"), M1M1(new BoostCounter(-1, -1).name), M2M1(new BoostCounter(-2, -1).name), M2M2(new BoostCounter(-2, -2).name), MINE("mine"), MINING("mining"), MIRE("mire"), + MUSIC("music"), MUSTER("muster"), NET("net"), OMEN("omen"), @@ -95,12 +98,14 @@ public enum CounterType { PETAL("petal"), PETRIFICATION("petrification"), PHYLACTERY("phylactery"), + PIN("pin"), PLAGUE("plague"), PLOT("plot"), POLYP("polyp"), POISON("poison"), PRESSURE("pressure"), PREY("prey"), + PUPA("pupa"), REPAIR("repair"), RUST("rust"), QUEST("quest"), @@ -109,6 +114,7 @@ public enum CounterType { SHELL("shell"), SHIELD("shield"), SHRED("shred"), + SLEEP("sleep"), SLIME("slime"), SLUMBER("slumber"), SOOT("soot"), diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 4226afe8767..a21da63a26b 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -297,7 +297,7 @@ public final class StaticFilters { public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_ANOTHER_CREATURE = new FilterControlledCreaturePermanent("another creature"); static { - FILTER_CONTROLLED_ANOTHER_CREATURE.add(new AnotherPredicate()); + FILTER_CONTROLLED_ANOTHER_CREATURE.add(AnotherPredicate.instance); FILTER_CONTROLLED_ANOTHER_CREATURE.setLockedFilter(true); } @@ -405,13 +405,13 @@ public final class StaticFilters { FILTER_PERMANENT_PLANESWALKER.setLockedFilter(true); } - public static final FilterPermanent FILTER_PERMANENT_NON_LAND = new FilterNonlandPermanent(); + public static final FilterNonlandPermanent FILTER_PERMANENT_NON_LAND = new FilterNonlandPermanent(); static { FILTER_PERMANENT_NON_LAND.setLockedFilter(true); } - public static final FilterPermanent FILTER_PERMANENTS_NON_LAND = new FilterNonlandPermanent("nonland permanents"); + public static final FilterNonlandPermanent FILTER_PERMANENTS_NON_LAND = new FilterNonlandPermanent("nonland permanents"); static { FILTER_PERMANENTS_NON_LAND.setLockedFilter(true); @@ -463,7 +463,7 @@ public final class StaticFilters { public static final FilterSpell FILTER_SPELL_A_MULTICOLORED = new FilterSpell("a multicolored spell"); static { - FILTER_SPELL_A_MULTICOLORED.add(new MulticoloredPredicate()); + FILTER_SPELL_A_MULTICOLORED.add(MulticoloredPredicate.instance); FILTER_SPELL_A_MULTICOLORED.setLockedFilter(true); } @@ -500,14 +500,14 @@ public final class StaticFilters { public static final FilterCreaturePermanent FILTER_CREATURE_TOKENS = new FilterCreaturePermanent("creature tokens"); static { - FILTER_CREATURE_TOKENS.add(new TokenPredicate()); + FILTER_CREATURE_TOKENS.add(TokenPredicate.instance); FILTER_CREATURE_TOKENS.setLockedFilter(true); } public static final FilterCreaturePermanent FILTER_ATTACKING_CREATURES = new FilterCreaturePermanent("attacking creatures"); static { - FILTER_ATTACKING_CREATURES.add(new AttackingPredicate()); + FILTER_ATTACKING_CREATURES.add(AttackingPredicate.instance); FILTER_ATTACKING_CREATURES.setLockedFilter(true); } diff --git a/Mage/src/main/java/mage/filter/common/FilterAttackingCreature.java b/Mage/src/main/java/mage/filter/common/FilterAttackingCreature.java index 90d1271aecb..ac3564f19ff 100644 --- a/Mage/src/main/java/mage/filter/common/FilterAttackingCreature.java +++ b/Mage/src/main/java/mage/filter/common/FilterAttackingCreature.java @@ -16,7 +16,7 @@ public class FilterAttackingCreature extends FilterCreaturePermanent { public FilterAttackingCreature(String name) { super(name); - this.add(new AttackingPredicate()); + this.add(AttackingPredicate.instance); } public FilterAttackingCreature(final FilterAttackingCreature filter) { diff --git a/Mage/src/main/java/mage/filter/common/FilterAttackingOrBlockingCreature.java b/Mage/src/main/java/mage/filter/common/FilterAttackingOrBlockingCreature.java index aaaa446e1cb..2cb8bbfe23d 100644 --- a/Mage/src/main/java/mage/filter/common/FilterAttackingOrBlockingCreature.java +++ b/Mage/src/main/java/mage/filter/common/FilterAttackingOrBlockingCreature.java @@ -19,8 +19,8 @@ public class FilterAttackingOrBlockingCreature extends FilterCreaturePermanent { public FilterAttackingOrBlockingCreature(String name) { super(name); this.add(Predicates.or( - new AttackingPredicate(), - new BlockingPredicate())); + AttackingPredicate.instance, + BlockingPredicate.instance)); } public FilterAttackingOrBlockingCreature(final FilterAttackingOrBlockingCreature filter) { diff --git a/Mage/src/main/java/mage/filter/common/FilterBlockingCreature.java b/Mage/src/main/java/mage/filter/common/FilterBlockingCreature.java index 9a285ba6c68..660b9abf15e 100644 --- a/Mage/src/main/java/mage/filter/common/FilterBlockingCreature.java +++ b/Mage/src/main/java/mage/filter/common/FilterBlockingCreature.java @@ -15,7 +15,7 @@ public class FilterBlockingCreature extends FilterCreaturePermanent { public FilterBlockingCreature(String name) { super(name); - this.add(new BlockingPredicate()); + this.add(BlockingPredicate.instance); } public FilterBlockingCreature(final FilterBlockingCreature filter) { diff --git a/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java b/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java index 9cbee3044f3..ef474acf326 100644 --- a/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java @@ -6,7 +6,6 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; /** - * * @author LevelX2 */ public class FilterControlledPlaneswalkerPermanent extends FilterControlledPermanent { @@ -15,6 +14,10 @@ public class FilterControlledPlaneswalkerPermanent extends FilterControlledPerma this("planeswalker you control"); } + public FilterControlledPlaneswalkerPermanent(SubType subType) { + this(subType, "a " + subType + " planeswalker"); + } + public FilterControlledPlaneswalkerPermanent(SubType subType, String name) { super(name); this.add(new CardTypePredicate(CardType.PLANESWALKER)); diff --git a/Mage/src/main/java/mage/filter/common/FilterCreatureForAttack.java b/Mage/src/main/java/mage/filter/common/FilterCreatureForAttack.java index 112685b0dd6..68b75d79265 100644 --- a/Mage/src/main/java/mage/filter/common/FilterCreatureForAttack.java +++ b/Mage/src/main/java/mage/filter/common/FilterCreatureForAttack.java @@ -25,9 +25,9 @@ public class FilterCreatureForAttack extends FilterCreaturePermanent { public FilterCreatureForAttack(String name) { super(name); - this.add(Predicates.not(new AttackingPredicate())); - this.add(Predicates.not(new BlockingPredicate())); - this.add(Predicates.not(new TappedPredicate())); + this.add(Predicates.not(AttackingPredicate.instance)); + this.add(Predicates.not(BlockingPredicate.instance)); + this.add(Predicates.not(TappedPredicate.instance)); this.add(Predicates.not(new AbilityPredicate(DefenderAbility.class))); this.add(new CanTapPredicate()); } diff --git a/Mage/src/main/java/mage/filter/common/FilterCreatureForCombat.java b/Mage/src/main/java/mage/filter/common/FilterCreatureForCombat.java index 5b418ce182d..dc94c1fa324 100644 --- a/Mage/src/main/java/mage/filter/common/FilterCreatureForCombat.java +++ b/Mage/src/main/java/mage/filter/common/FilterCreatureForCombat.java @@ -18,7 +18,7 @@ public class FilterCreatureForCombat extends FilterCreatureForCombatBase { public FilterCreatureForCombat(String name) { super(name); - this.add(Predicates.not(new TappedPredicate())); + this.add(Predicates.not(TappedPredicate.instance)); } public FilterCreatureForCombat(final FilterCreatureForCombat filter) { diff --git a/Mage/src/main/java/mage/filter/common/FilterCreatureForCombatBase.java b/Mage/src/main/java/mage/filter/common/FilterCreatureForCombatBase.java index 195d4cefcb4..a5daa73e32f 100644 --- a/Mage/src/main/java/mage/filter/common/FilterCreatureForCombatBase.java +++ b/Mage/src/main/java/mage/filter/common/FilterCreatureForCombatBase.java @@ -22,7 +22,7 @@ public class FilterCreatureForCombatBase extends FilterCreaturePermanent { public FilterCreatureForCombatBase(String name) { super(name); - this.add(Predicates.not(new AttackingPredicate())); + this.add(Predicates.not(AttackingPredicate.instance)); this.add(new PhasedInPredicate()); this.add(new CanBlockPredicate()); } diff --git a/Mage/src/main/java/mage/filter/common/FilterHistoricCard.java b/Mage/src/main/java/mage/filter/common/FilterHistoricCard.java index fc843f163cf..eb3f7cf1c1f 100644 --- a/Mage/src/main/java/mage/filter/common/FilterHistoricCard.java +++ b/Mage/src/main/java/mage/filter/common/FilterHistoricCard.java @@ -20,7 +20,7 @@ public class FilterHistoricCard extends FilterCard { public FilterHistoricCard(String name) { super(name); - this.add(new HistoricPredicate()); + this.add(HistoricPredicate.instance); } public FilterHistoricCard(final FilterHistoricCard filter) { diff --git a/Mage/src/main/java/mage/filter/common/FilterHistoricSpell.java b/Mage/src/main/java/mage/filter/common/FilterHistoricSpell.java index d6b59a6cc74..13ccb99ea17 100644 --- a/Mage/src/main/java/mage/filter/common/FilterHistoricSpell.java +++ b/Mage/src/main/java/mage/filter/common/FilterHistoricSpell.java @@ -16,7 +16,7 @@ public class FilterHistoricSpell extends FilterSpell { public FilterHistoricSpell(String name) { super(name); - this.add(new HistoricPredicate()); + this.add(HistoricPredicate.instance); } public FilterHistoricSpell(final FilterHistoricSpell filter) { diff --git a/Mage/src/main/java/mage/filter/common/FilterUntappedCreature.java b/Mage/src/main/java/mage/filter/common/FilterUntappedCreature.java index 13f1ee652ae..ebf7c43da1d 100644 --- a/Mage/src/main/java/mage/filter/common/FilterUntappedCreature.java +++ b/Mage/src/main/java/mage/filter/common/FilterUntappedCreature.java @@ -17,7 +17,7 @@ public class FilterUntappedCreature extends FilterCreaturePermanent { public FilterUntappedCreature(String name) { super(name); - this.add(Predicates.not(new TappedPredicate())); + this.add(Predicates.not(TappedPredicate.instance)); } public FilterUntappedCreature(final FilterUntappedCreature filter) { diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ColorlessPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ColorlessPredicate.java index 3dcf34b34d8..0eee39d8823 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/ColorlessPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ColorlessPredicate.java @@ -6,10 +6,10 @@ import mage.filter.predicate.Predicate; import mage.game.Game; /** - * * @author North */ -public class ColorlessPredicate implements Predicate { +public enum ColorlessPredicate implements Predicate { + instance; @Override public boolean apply(MageObject input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/HistoricPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/HistoricPredicate.java index fa862b16b89..39d0a7c15f8 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/HistoricPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/HistoricPredicate.java @@ -10,10 +10,10 @@ import mage.filter.predicate.Predicate; import mage.game.Game; /** - * * @author LevelX2 */ -public class HistoricPredicate implements Predicate { +public enum HistoricPredicate implements Predicate { + instance; @Override public boolean apply(MageObject input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/MonocoloredPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/MonocoloredPredicate.java index 66d98053ece..50172d93ad9 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/MonocoloredPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/MonocoloredPredicate.java @@ -6,10 +6,10 @@ import mage.filter.predicate.Predicate; import mage.game.Game; /** - * * @author LevelX2 */ -public class MonocoloredPredicate implements Predicate { +public enum MonocoloredPredicate implements Predicate { + instance; @Override public boolean apply(MageObject input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/MulticoloredPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/MulticoloredPredicate.java index f1598666111..58a5937d744 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/MulticoloredPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/MulticoloredPredicate.java @@ -8,10 +8,10 @@ import mage.filter.predicate.Predicate; import mage.game.Game; /** - * * @author jeffwadsworth */ -public class MulticoloredPredicate implements Predicate { +public enum MulticoloredPredicate implements Predicate { + instance; @Override public boolean apply(MageObject input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/other/FaceDownPredicate.java b/Mage/src/main/java/mage/filter/predicate/other/FaceDownPredicate.java index 1253e4fb1e8..c6079cf9d48 100644 --- a/Mage/src/main/java/mage/filter/predicate/other/FaceDownPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/other/FaceDownPredicate.java @@ -6,10 +6,10 @@ import mage.filter.predicate.Predicate; import mage.game.Game; /** - * * @author North */ -public class FaceDownPredicate implements Predicate { +public enum FaceDownPredicate implements Predicate { + instance; @Override public boolean apply(Card input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/AnotherPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/AnotherPredicate.java index 19d9bdd2a47..c8d9671388d 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/AnotherPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/AnotherPredicate.java @@ -7,10 +7,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author North */ -public class AnotherPredicate implements ObjectSourcePlayerPredicate> { +public enum AnotherPredicate implements ObjectSourcePlayerPredicate> { + instance; @Override public boolean apply(ObjectSourcePlayer input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/AttackingPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/AttackingPredicate.java index 871661f0bc0..899967ab453 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/AttackingPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/AttackingPredicate.java @@ -6,10 +6,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author North */ -public class AttackingPredicate implements Predicate { +public enum AttackingPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/BlockedByIdPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/BlockedByIdPredicate.java index b1ba27d4005..135281a0e14 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/BlockedByIdPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/BlockedByIdPredicate.java @@ -28,7 +28,7 @@ public class BlockedByIdPredicate implements Predicate { } // Check if the blockerId was blocked before, if it does no longer exists now but so the target attacking is still valid Permanent blocker = game.getPermanentOrLKIBattlefield(blockerId); if (blocker != null) { - BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + BlockedAttackerWatcher watcher = game.getState().getWatcher(BlockedAttackerWatcher.class); if (watcher != null) { return watcher.creatureHasBlockedAttacker(input, blocker, game); } diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/BlockedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/BlockedPredicate.java index 1e0ef1f468e..97fd2a2f543 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/BlockedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/BlockedPredicate.java @@ -6,10 +6,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author North */ -public class BlockedPredicate implements Predicate { +public enum BlockedPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/BlockingPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/BlockingPredicate.java index 33601091112..cf2c3f7c55c 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/BlockingPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/BlockingPredicate.java @@ -6,10 +6,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author North */ -public class BlockingPredicate implements Predicate { +public enum BlockingPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/CommanderPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/CommanderPredicate.java index 8be4989a9fd..58bc4269b22 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/CommanderPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/CommanderPredicate.java @@ -11,10 +11,10 @@ import mage.game.permanent.Permanent; import mage.players.Player; /** - * * @author LevelX2 */ -public class CommanderPredicate implements Predicate { +public enum CommanderPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/CounterAnyPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/CounterAnyPredicate.java index 71065e54e3a..228f1dd6285 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/CounterAnyPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/CounterAnyPredicate.java @@ -1,19 +1,15 @@ package mage.filter.predicate.permanent; -import mage.counters.Counter; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author LevelX2 */ -public class CounterAnyPredicate implements Predicate { - - public CounterAnyPredicate() { - } +public enum CounterAnyPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java index 17807a0ea3b..191e58133ac 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate.java @@ -28,14 +28,14 @@ public class DamagedPlayerThisTurnPredicate implements ObjectPlayerPredicate> { +public enum DefendingPlayerControlsPredicate implements ObjectSourcePlayerPredicate> { + instance; @Override public boolean apply(ObjectSourcePlayer input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/EnchantedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/EnchantedPredicate.java index c548735dc50..71491195df6 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/EnchantedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/EnchantedPredicate.java @@ -1,19 +1,18 @@ package mage.filter.predicate.permanent; -import java.util.Objects; -import java.util.UUID; - import mage.MageObject; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.Objects; + /** - * * @author LevelX2 */ -public class EnchantedPredicate implements Predicate { +public enum EnchantedPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { @@ -26,6 +25,6 @@ public class EnchantedPredicate implements Predicate { @Override public String toString() { - return "Enchanted" ; + return "Enchanted"; } } diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java index cb0b266d9e8..c92c4145943 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java @@ -15,7 +15,8 @@ import java.util.Objects; /** * @author LevelX2 */ -public class EquippedPredicate implements Predicate { +public enum EquippedPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/TappedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/TappedPredicate.java index fb3319ac463..2b4d720d9c9 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/TappedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/TappedPredicate.java @@ -6,10 +6,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author North */ -public class TappedPredicate implements Predicate { +public enum TappedPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/TokenPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/TokenPredicate.java index 61afd03d769..97e8f49f5e4 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/TokenPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/TokenPredicate.java @@ -7,10 +7,10 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; /** - * * @author North */ -public class TokenPredicate implements Predicate { +public enum TokenPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/TransformedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/TransformedPredicate.java index 8cbcf132be9..9479bcf8145 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/TransformedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/TransformedPredicate.java @@ -6,10 +6,10 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * * @author Saga */ -public class TransformedPredicate implements Predicate { +public enum TransformedPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { @@ -18,6 +18,6 @@ public class TransformedPredicate implements Predicate { @Override public String toString() { - return "Transformed" ; + return "Transformed"; } } \ No newline at end of file diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/UnblockedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/UnblockedPredicate.java index 4b164bc4ae6..2bcff6037f8 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/UnblockedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/UnblockedPredicate.java @@ -13,7 +13,8 @@ import mage.game.turn.Step; * * @author LevelX2 */ -public class UnblockedPredicate implements Predicate { +public enum UnblockedPredicate implements Predicate { + instance; @Override public boolean apply(Permanent input, Game game) { diff --git a/Mage/src/main/java/mage/game/GameCommanderImpl.java b/Mage/src/main/java/mage/game/GameCommanderImpl.java index f6c2e6779de..e5f06d560a1 100644 --- a/Mage/src/main/java/mage/game/GameCommanderImpl.java +++ b/Mage/src/main/java/mage/game/GameCommanderImpl.java @@ -54,7 +54,7 @@ public abstract class GameCommanderImpl extends GameImpl { ability.addEffect(new CommanderCostModification(commander.getId())); getState().setValue(commander.getId() + "_castCount", 0); CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), checkCommanderDamage); - getState().getWatchers().add(watcher); + getState().addWatcher(watcher); watcher.addCardInfoToCommander(this); } } @@ -155,7 +155,7 @@ public abstract class GameCommanderImpl extends GameImpl { protected boolean checkStateBasedActions() { for (Player player : getPlayers().values()) { for (UUID commanderId : player.getCommandersIds()) { - CommanderInfoWatcher damageWatcher = (CommanderInfoWatcher) getState().getWatchers().get(CommanderInfoWatcher.class.getSimpleName(), commanderId); + CommanderInfoWatcher damageWatcher = getState().getWatcher(CommanderInfoWatcher.class, commanderId); if (damageWatcher == null) { continue; } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index a6eb99e1415..25ec612248d 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1,9 +1,5 @@ package mage.game; -import java.io.IOException; -import java.io.Serializable; -import java.util.*; -import java.util.Map.Entry; import mage.MageException; import mage.MageObject; import mage.abilities.*; @@ -65,10 +61,14 @@ import mage.util.GameLog; import mage.util.MessageToClient; import mage.util.RandomUtil; import mage.util.functions.ApplyToPermanent; -import mage.watchers.Watchers; import mage.watchers.common.*; import org.apache.log4j.Logger; +import java.io.IOException; +import java.io.Serializable; +import java.util.*; +import java.util.Map.Entry; + public abstract class GameImpl implements Game, Serializable { private static final int ROLLBACK_TURNS_MAX = 4; @@ -150,6 +150,7 @@ public abstract class GameImpl implements Game, Serializable { this.state = new GameState(); this.startLife = startLife; this.executingRollback = false; + initGameDefaultWatchers(); } public GameImpl(final GameImpl game) { @@ -259,6 +260,7 @@ public abstract class GameImpl implements Game, Serializable { public void addPlayer(Player player, Deck deck) { player.useDeck(deck, this); state.addPlayer(player); + initPlayerDefaultWatchers(player.getId()); } @Override @@ -504,7 +506,7 @@ public abstract class GameImpl implements Game, Serializable { return Optional.empty(); } -// @Override + // @Override // public Zone getZone(UUID objectId) { // return state.getZone(objectId); // } @@ -532,7 +534,7 @@ public abstract class GameImpl implements Game, Serializable { } } -// /** + // /** // * Starts check if game is over or if playerId is given let the player // * concede. // * @@ -1011,22 +1013,7 @@ public abstract class GameImpl implements Game, Serializable { } } getState().setChoosingPlayerId(null); - state.getWatchers().reset(); // watcher objects from cards are reused during match so reset all card watchers already added - Watchers watchers = state.getWatchers(); - // add default watchers - for (UUID playerId : state.getPlayerList(startingPlayerId)) { - watchers.add(new PlayerDamagedBySourceWatcher(playerId)); - watchers.add(new BloodthirstWatcher(playerId)); - } - watchers.add(new MorbidWatcher()); - watchers.add(new CastSpellLastTurnWatcher()); - watchers.add(new CastSpellYourLastTurnWatcher()); - watchers.add(new PlayerLostLifeWatcher()); - watchers.add(new PlayerLostLifeNonCombatWatcher()); - watchers.add(new BlockedAttackerWatcher()); - watchers.add(new DamageDoneWatcher()); - watchers.add(new PlanarRollWatcher()); - watchers.add(new PlayersAttackedThisTurnWatcher()); + state.resetWatchers(); // watcher objects from cards are reused during match so reset all card watchers already added //20100716 - 103.5 for (UUID playerId : state.getPlayerList(startingPlayerId)) { @@ -1075,6 +1062,24 @@ public abstract class GameImpl implements Game, Serializable { } } + + public void initGameDefaultWatchers() { + getState().addWatcher(new MorbidWatcher()); + getState().addWatcher(new CastSpellLastTurnWatcher()); + getState().addWatcher(new CastSpellYourLastTurnWatcher()); + getState().addWatcher(new PlayerLostLifeWatcher()); + getState().addWatcher(new PlayerLostLifeNonCombatWatcher()); + getState().addWatcher(new BlockedAttackerWatcher()); + getState().addWatcher(new DamageDoneWatcher()); + getState().addWatcher(new PlanarRollWatcher()); + getState().addWatcher(new PlayersAttackedThisTurnWatcher()); + } + + public void initPlayerDefaultWatchers(UUID playerId) { + getState().addWatcher(new PlayerDamagedBySourceWatcher(playerId)); + getState().addWatcher(new BloodthirstWatcher(playerId)); + } + protected void sendStartMessage(Player choosingPlayer, Player startingPlayer) { StringBuilder message = new StringBuilder(); if (choosingPlayer != null) { @@ -1117,7 +1122,7 @@ public abstract class GameImpl implements Game, Serializable { for (Player player : getPlayers().values()) { player.endOfTurn(this); } - state.getWatchers().reset(); + state.resetWatchers(); } protected UUID pickChoosingPlayer() { @@ -1206,7 +1211,7 @@ public abstract class GameImpl implements Game, Serializable { fireInformEvent(new StringBuilder(player.getLogName()) .append(" mulligans") .append(deduction == 0 ? " for free and draws " : " down to ") - .append(Integer.toString(numCards - deduction)) + .append((numCards - deduction)) .append(numCards - deduction == 1 ? " card" : " cards").toString()); player.drawCards(numCards - deduction, this); } @@ -1543,10 +1548,9 @@ public abstract class GameImpl implements Game, Serializable { } /** - * * @param emblem * @param sourceObject - * @param toPlayerId controller and owner of the emblem + * @param toPlayerId controller and owner of the emblem */ @Override public void addEmblem(Emblem emblem, MageObject sourceObject, UUID toPlayerId) { @@ -1562,11 +1566,10 @@ public abstract class GameImpl implements Game, Serializable { } /** - * * @param plane * @param sourceObject - * @param toPlayerId controller and owner of the plane (may only be one per - * game..) + * @param toPlayerId controller and owner of the plane (may only be one per + * game..) * @return boolean - whether the plane was added successfully or not */ @Override @@ -1795,7 +1798,7 @@ public abstract class GameImpl implements Game, Serializable { break; } // triggered abilities that don't use the stack have to be executed first (e.g. Banisher Priest Return exiled creature - for (Iterator it = abilities.iterator(); it.hasNext();) { + for (Iterator it = abilities.iterator(); it.hasNext(); ) { TriggeredAbility triggeredAbility = it.next(); if (!triggeredAbility.isUsesStack()) { state.removeTriggeredAbility(triggeredAbility); @@ -1980,7 +1983,7 @@ public abstract class GameImpl implements Game, Serializable { if ((ability instanceof SpellAbility) && SpellAbilityType.BASE_ALTERNATE == ((SpellAbility) ability).getSpellAbilityType() && !ability.getTargets().isEmpty()) { - spellAbility = (SpellAbility) ability; + spellAbility = ability; break; } } @@ -2530,7 +2533,7 @@ public abstract class GameImpl implements Game, Serializable { } //20100423 - 800.4a Set toOutside = new HashSet<>(); - for (Iterator it = getBattlefield().getAllPermanents().iterator(); it.hasNext();) { + for (Iterator it = getBattlefield().getAllPermanents().iterator(); it.hasNext(); ) { Permanent perm = it.next(); if (perm.isOwnedBy(playerId)) { if (perm.getAttachedTo() != null) { @@ -2573,7 +2576,7 @@ public abstract class GameImpl implements Game, Serializable { player.moveCards(toOutside, Zone.OUTSIDE, null, this); // triggered abilities that don't use the stack have to be executed List abilities = state.getTriggered(player.getId()); - for (Iterator it = abilities.iterator(); it.hasNext();) { + for (Iterator it = abilities.iterator(); it.hasNext(); ) { TriggeredAbility triggeredAbility = it.next(); if (!triggeredAbility.isUsesStack()) { state.removeTriggeredAbility(triggeredAbility); @@ -2593,7 +2596,7 @@ public abstract class GameImpl implements Game, Serializable { // Remove cards from the player in all exile zones for (ExileZone exile : this.getExile().getExileZones()) { - for (Iterator it = exile.iterator(); it.hasNext();) { + for (Iterator it = exile.iterator(); it.hasNext(); ) { Card card = this.getCard(it.next()); if (card != null && card.isOwnedBy(playerId)) { it.remove(); @@ -2603,7 +2606,7 @@ public abstract class GameImpl implements Game, Serializable { //Remove all commander/emblems/plane the player controls boolean addPlaneAgain = false; - for (Iterator it = this.getState().getCommand().iterator(); it.hasNext();) { + for (Iterator it = this.getState().getCommand().iterator(); it.hasNext(); ) { CommandObject obj = it.next(); if (obj.isControlledBy(playerId)) { if (obj instanceof Emblem) { @@ -2739,7 +2742,7 @@ public abstract class GameImpl implements Game, Serializable { } if (!game.isSimulation()) { StringBuilder message = new StringBuilder(preventionSource.getLogName()).append(": Prevented "); - message.append(Integer.toString(result.getPreventedDamage())).append(" damage from ").append(damageSource.getLogName()); + message.append(result.getPreventedDamage()).append(" damage from ").append(damageSource.getLogName()); if (!targetName.isEmpty()) { message.append(" to ").append(targetName); } @@ -2774,7 +2777,7 @@ public abstract class GameImpl implements Game, Serializable { * Gets last known information about object in the zone. At the moment * doesn't take into account zone (it is expected that it doesn't really * matter, if not, then Map> should be used instead). - * + *

* Can return null. * * @param objectId @@ -3129,7 +3132,7 @@ public abstract class GameImpl implements Game, Serializable { public void saveRollBackGameState() { if (gameOptions.rollbackTurnsAllowed) { int toDelete = getTurnNum() - ROLLBACK_TURNS_MAX; - if (toDelete > 0 && gameStatesRollBack.containsKey(toDelete)) { + if (toDelete > 0) { gameStatesRollBack.remove(toDelete); } gameStatesRollBack.put(getTurnNum(), state.copy()); @@ -3181,9 +3184,7 @@ public abstract class GameImpl implements Game, Serializable { @Override public void setEnterWithCounters(UUID sourceId, Counters counters) { if (counters == null) { - if (enterWithCounters.containsKey(sourceId)) { - enterWithCounters.remove(sourceId); - } + enterWithCounters.remove(sourceId); return; } enterWithCounters.put(sourceId, counters); diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index b98810d1794..3caa16a21af 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -531,10 +531,23 @@ public class GameState implements Serializable, Copyable { return this.turnMods; } + @Deprecated public Watchers getWatchers() { return this.watchers; } + public T getWatcher(Class watcherClass) { + return watcherClass.cast(watchers.get(watcherClass.getSimpleName())); + } + + public T getWatcher(Class watcherClass, UUID uuid) { + return watcherClass.cast(watchers.get(watcherClass.getSimpleName(), uuid.toString())); + } + + public T getWatcher(Class watcherClass, String prefix) { + return watcherClass.cast(watchers.get(watcherClass.getSimpleName(), prefix)); + } + public SpecialActions getSpecialActions() { return this.specialActions; } @@ -763,7 +776,9 @@ public class GameState implements Serializable, Copyable { ZoneChangeEvent castEvent = (ZoneChangeEvent) event; UUID targetId = castEvent.getTargetId(); Card card = game.getCard(targetId); - movedCards.add(card); + if (card != null) { + movedCards.add(card); + } } ZoneChangeData eventData = entry.getKey(); if (!movedCards.isEmpty()) { @@ -1104,6 +1119,10 @@ public class GameState implements Serializable, Copyable { this.watchers.add(watcher); } + public void resetWatchers() { + this.watchers.reset(); + } + public int getZoneChangeCounter(UUID objectId) { return zoneChangeCounter.getOrDefault(objectId, 1); } diff --git a/Mage/src/main/java/mage/game/Table.java b/Mage/src/main/java/mage/game/Table.java index 5b6f223021a..eba4df35c6b 100644 --- a/Mage/src/main/java/mage/game/Table.java +++ b/Mage/src/main/java/mage/game/Table.java @@ -298,8 +298,8 @@ public class Table implements Serializable { .setGameType(this.getGameType()) .setDeckType(this.getDeckType()) .setControllerName(this.getControllerName()) - .setStartTimeMs(this.getStartTime().getTime()) - .setEndTimeMs(this.getEndTime().getTime()) + .setStartTimeMs(this.getStartTime() != null ? this.getStartTime().getTime() : 0L) + .setEndTimeMs(this.getEndTime() != null ? this.getEndTime().getTime() : 0L) .build(); } } diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index 08157890e1f..c7ab29f73c8 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -275,7 +275,7 @@ public class Combat implements Serializable, Copyable { Permanent attackingPermanent = game.getPermanent(attacker); if (attackingPermanent != null) { attackingPermanent.setTapped(false); - attackingPermanent.tap(game); // to tap with event finally here is needed to prevent abusing of Vampire Envoy like cards + attackingPermanent.tap(true,game); // to tap with event finally here is needed to prevent abusing of Vampire Envoy like cards } } handleBanding(attacker, game); @@ -463,7 +463,7 @@ public class Combat implements Serializable, Copyable { target.setRequired(true); target.setTargetName("planeswalker or player for " + creature.getLogName() + " to attack"); if (player.chooseTarget(Outcome.Damage, target, null, game)) { - System.out.println("The player " + player.getName() + " declares an attacker here. " + creature.getName()); + //System.out.println("The player " + player.getName() + " declares an attacker here. " + creature.getName()); player.declareAttacker(creature.getId(), target.getFirstTarget(), game, false); } } diff --git a/Mage/src/main/java/mage/game/command/emblems/AurraSingBaneOfJediEmblem.java b/Mage/src/main/java/mage/game/command/emblems/AurraSingBaneOfJediEmblem.java index 8917e9a01f0..30763b68c2d 100644 --- a/Mage/src/main/java/mage/game/command/emblems/AurraSingBaneOfJediEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/AurraSingBaneOfJediEmblem.java @@ -18,7 +18,7 @@ public final class AurraSingBaneOfJediEmblem extends Emblem { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a nontoken creature you control"); static { - filter.add(Predicates.not(new TokenPredicate())); + filter.add(Predicates.not(TokenPredicate.instance)); } // Whenever a nontoken creature you control leaves the battlefied, discard a card. diff --git a/Mage/src/main/java/mage/game/command/emblems/DomriChaosBringerEmblem.java b/Mage/src/main/java/mage/game/command/emblems/DomriChaosBringerEmblem.java new file mode 100644 index 00000000000..fc35e32c1a2 --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/DomriChaosBringerEmblem.java @@ -0,0 +1,24 @@ +package mage.game.command.emblems; + +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.command.Emblem; +import mage.game.permanent.token.RedGreenBeastToken; + +/** + * @author TheElk801 + */ +public final class DomriChaosBringerEmblem extends Emblem { + + // -8: You get an emblem with "At the beginning of each end step, create a 4/4 red and green Beast creature token with trample." + public DomriChaosBringerEmblem() { + this.setName("Emblem Domri"); + this.setExpansionSetCodeForImage("RNA"); + this.getAbilities().add(new BeginningOfEndStepTriggeredAbility( + Zone.COMMAND, new CreateTokenEffect(new RedGreenBeastToken()), + TargetController.ANY, null, false + )); + } +} diff --git a/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java b/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java index 63bae300ec3..da013f91215 100644 --- a/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java @@ -1,4 +1,3 @@ - package mage.game.command.emblems; import mage.abilities.Ability; @@ -13,7 +12,6 @@ import mage.constants.Zone; import mage.game.command.Emblem; /** - * * @author spjspj */ public final class GarrukApexPredatorEmblem extends Emblem { @@ -25,12 +23,12 @@ public final class GarrukApexPredatorEmblem extends Emblem { public GarrukApexPredatorEmblem() { setName("Emblem Garruk"); - Effect effect = new BoostTargetEffect(5, 5, Duration.EndOfTurn); - effect.setText("it gets +5/+5"); + + Effect effect = new BoostTargetEffect(-1, 0, Duration.EndOfTurn); + effect.setText("it gets -1/-0"); Ability ability = new AttackedByCreatureTriggeredAbility(Zone.COMMAND, effect, false, SetTargetPointer.PERMANENT); - effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, - "and gains trample until end of turn"); - ability.addEffect(effect); + effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); + ability.addEffect(effect.concatBy("and")); this.getAbilities().add(ability); } } diff --git a/Mage/src/main/java/mage/game/command/emblems/JaceUnravelerOfSecretsEmblem.java b/Mage/src/main/java/mage/game/command/emblems/JaceUnravelerOfSecretsEmblem.java index 0ae65c40435..4c5cec028cd 100644 --- a/Mage/src/main/java/mage/game/command/emblems/JaceUnravelerOfSecretsEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/JaceUnravelerOfSecretsEmblem.java @@ -51,7 +51,7 @@ class JaceUnravelerOfSecretsTriggeredAbility extends SpellCastOpponentTriggeredA @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName()); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); if (watcher != null) { List spells = watcher.getSpellsCastThisTurn(event.getPlayerId()); if (spells != null && spells.size() == 1) { diff --git a/Mage/src/main/java/mage/game/command/emblems/JayaBallardEmblem.java b/Mage/src/main/java/mage/game/command/emblems/JayaBallardEmblem.java index 45f0b291d7b..1984d36f53a 100644 --- a/Mage/src/main/java/mage/game/command/emblems/JayaBallardEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/JayaBallardEmblem.java @@ -119,7 +119,7 @@ class JayaBallardReplacementEffect extends ReplacementEffectImpl { if (card != null && (card.isInstant() || card.isSorcery())) { // TODO: Find a way to check, that the spell from graveyard was really cast by the ability of the emblem. // currently every spell cast from graveyard will be exiled. - CastFromGraveyardWatcher watcher = (CastFromGraveyardWatcher) game.getState().getWatchers().get(CastFromGraveyardWatcher.class.getSimpleName()); + CastFromGraveyardWatcher watcher = game.getState().getWatcher(CastFromGraveyardWatcher.class); return watcher != null && watcher.spellWasCastFromGraveyard(event.getTargetId(), game.getState().getZoneChangeCounter(event.getTargetId())); } } diff --git a/Mage/src/main/java/mage/game/command/emblems/ObNixilisOfTheBlackOathEmblem.java b/Mage/src/main/java/mage/game/command/emblems/ObNixilisOfTheBlackOathEmblem.java index c324972d068..4131d1b3237 100644 --- a/Mage/src/main/java/mage/game/command/emblems/ObNixilisOfTheBlackOathEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/ObNixilisOfTheBlackOathEmblem.java @@ -24,7 +24,7 @@ public final class ObNixilisOfTheBlackOathEmblem extends Emblem { // You get an emblem with "{1}{B}, Sacrifice a creature: You gain X life and draw X cards, where X is the sacrificed creature's power." public ObNixilisOfTheBlackOathEmblem() { this.setName("Emblem Nixilis"); - DynamicValue xValue = new SacrificeCostCreaturesPower(); + DynamicValue xValue = SacrificeCostCreaturesPower.instance; Effect effect = new GainLifeEffect(xValue); effect.setText("You gain X life"); Ability ability = new SimpleActivatedAbility(Zone.COMMAND, effect, new ManaCostsImpl("{1}{B}")); diff --git a/Mage/src/main/java/mage/game/command/emblems/WillKenrithEmblem.java b/Mage/src/main/java/mage/game/command/emblems/WillKenrithEmblem.java index 9a0f1bbbe68..9e171194f28 100644 --- a/Mage/src/main/java/mage/game/command/emblems/WillKenrithEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/WillKenrithEmblem.java @@ -1,4 +1,3 @@ - package mage.game.command.emblems; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -8,7 +7,6 @@ import mage.filter.StaticFilters; import mage.game.command.Emblem; /** - * * @author TheElk801 */ public final class WillKenrithEmblem extends Emblem { @@ -18,9 +16,8 @@ public final class WillKenrithEmblem extends Emblem { this.setName("Emblem Will Kenrith"); this.getAbilities().add(new SpellCastControllerTriggeredAbility( Zone.COMMAND, - new CopyTargetSpellEffect(true) - .setText("copy that spell. You may choose new targets for the copy"), - StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, + new CopyTargetSpellEffect(true).withSpellName("it"), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false, true )); diff --git a/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java b/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java index 784207f8c17..0b5da1d1e49 100644 --- a/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java @@ -35,7 +35,7 @@ public class AkoumPlane extends Plane { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that isn't enchanted"); static { - filter.add(Predicates.not(new EnchantedPredicate())); + filter.add(Predicates.not(EnchantedPredicate.instance)); filterCard.add(new CardTypePredicate(CardType.ENCHANTMENT)); } diff --git a/Mage/src/main/java/mage/game/command/planes/BantPlane.java b/Mage/src/main/java/mage/game/command/planes/BantPlane.java index a1187a748f8..5ea0fc27e6d 100644 --- a/Mage/src/main/java/mage/game/command/planes/BantPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/BantPlane.java @@ -107,7 +107,7 @@ class PlanarDieRollCostIncreasingEffect extends CostModificationEffectImpl { public boolean apply(Game game, Ability source, Ability abilityToModify) { Player activePlayer = game.getPlayer(game.getActivePlayerId()); if (activePlayer != null) { - PlanarRollWatcher watcher = (PlanarRollWatcher) game.getState().getWatchers().get(PlanarRollWatcher.class.getSimpleName()); + PlanarRollWatcher watcher = game.getState().getWatcher(PlanarRollWatcher.class); int rolledCounter = 0; if (watcher != null) { rolledCounter = watcher.getNumberTimesPlanarDieRolled(activePlayer.getId()); diff --git a/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java b/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java index bf125dadf41..04fb098a1fb 100644 --- a/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java @@ -53,7 +53,7 @@ public class FeedingGroundsPlane extends Plane { this.getAbilities().add(ability); // Active player can roll the planar die: Whenever you roll {CHAOS}, target red or green creature gets X +1/+1 counters - Effect chaosEffect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), new TargetConvertedManaCost()); + Effect chaosEffect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), TargetConvertedManaCost.instance); Target chaosTarget = new TargetCreaturePermanent(1, 1, filter, false); List chaosEffects = new ArrayList(); diff --git a/Mage/src/main/java/mage/game/events/CoinFlippedEvent.java b/Mage/src/main/java/mage/game/events/CoinFlippedEvent.java new file mode 100644 index 00000000000..b7dad082256 --- /dev/null +++ b/Mage/src/main/java/mage/game/events/CoinFlippedEvent.java @@ -0,0 +1,41 @@ +package mage.game.events; + +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + **/ +public class CoinFlippedEvent extends GameEvent { + private final boolean result; + private final boolean chosen; + private final boolean winnable; + + CoinFlippedEvent(UUID playerId, UUID sourceId, boolean result, boolean chosen, boolean winnable) { + super(EventType.COIN_FLIPPED, playerId, sourceId, playerId); + this.result = result; + this.chosen = chosen; + this.winnable = winnable; + } + + public boolean getResult() { + return result; + } + + public String getResultName() { + return CardUtil.booleanToFlipName(result); + } + + public boolean getChosen() { + return chosen; + } + + public String getChosenName() { + return CardUtil.booleanToFlipName(chosen); + } + + public boolean isWinnable() { + return winnable; + } +} diff --git a/Mage/src/main/java/mage/game/events/FlipCoinEvent.java b/Mage/src/main/java/mage/game/events/FlipCoinEvent.java new file mode 100644 index 00000000000..c2dceaa73e9 --- /dev/null +++ b/Mage/src/main/java/mage/game/events/FlipCoinEvent.java @@ -0,0 +1,49 @@ +package mage.game.events; + +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + **/ +public class FlipCoinEvent extends GameEvent { + private boolean result; + private final boolean chosen; + private final boolean winnable; + + public FlipCoinEvent(UUID playerId, UUID sourceId, boolean result, boolean chosen, boolean winnable) { + super(EventType.FLIP_COIN, playerId, sourceId, playerId); + this.result = result; + this.chosen = chosen; + this.winnable = winnable; + } + + public boolean getResult() { + return result; + } + + public String getResultName() { + return CardUtil.booleanToFlipName(result); + } + + public void setResult(boolean result) { + this.result = result; + } + + public boolean getChosen() { + return chosen; + } + + public String getChosenName() { + return CardUtil.booleanToFlipName(chosen); + } + + public boolean isWinnable() { + return winnable; + } + + public CoinFlippedEvent getFlippedEvent() { + return new CoinFlippedEvent(playerId, sourceId, result, chosen, winnable); + } +} diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index eeb746ce952..edff7314ab5 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -1,14 +1,14 @@ package mage.game.events; +import mage.MageObjectReference; +import mage.constants.Zone; + import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import mage.MageObjectReference; -import mage.constants.Zone; /** - * * @author BetaSteward_at_googlemail.com */ public class GameEvent implements Serializable { @@ -221,6 +221,7 @@ public class GameEvent implements Serializable { PLANESWALK, PLANESWALKED, PAID_CUMULATIVE_UPKEEP, DIDNT_PAY_CUMULATIVE_UPKEEP, + LIFE_PAID, //permanent events ENTERS_THE_BATTLEFIELD_SELF, /* 616.1a If any of the replacement and/or prevention effects are self-replacement effects (see rule 614.15), one of them must be chosen. If not, proceed to rule 616.1b. */ @@ -232,6 +233,7 @@ public class GameEvent implements Serializable { FLIP, FLIPPED, UNFLIP, UNFLIPPED, TRANSFORM, TRANSFORMED, + ADAPT, BECOMES_MONSTROUS, BECOMES_EXERTED, /* BECOMES_EXERTED @@ -383,12 +385,12 @@ public class GameEvent implements Serializable { } private GameEvent(EventType type, UUID customEventType, - UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag) { + UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag) { this(type, customEventType, targetId, sourceId, playerId, amount, flag, null); } private GameEvent(EventType type, UUID customEventType, - UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag, MageObjectReference reference) { + UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag, MageObjectReference reference) { this.type = type; this.customEventType = customEventType; this.targetId = targetId; @@ -466,7 +468,7 @@ public class GameEvent implements Serializable { /** * used to store which replacement effects were already applied to an event * or or any modified events that may replace it - * + *

* 614.5. A replacement effect doesn't invoke itself repeatedly; it gets * only one opportunity to affect an event or any modified events that may * replace it. Example: A player controls two permanents, each with an diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index 1e17d0e8a9a..8ebdc1f6481 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -1,9 +1,6 @@ package mage.game.permanent; -import java.util.List; -import java.util.Set; -import java.util.UUID; import mage.MageObject; import mage.MageObjectReference; import mage.abilities.Ability; @@ -14,6 +11,10 @@ import mage.game.Controllable; import mage.game.Game; import mage.game.GameState; +import java.util.List; +import java.util.Set; +import java.util.UUID; + public interface Permanent extends Card, Controllable { void setControllerId(UUID controllerId); @@ -24,6 +25,8 @@ public interface Permanent extends Card, Controllable { boolean tap(Game game); + boolean tap(boolean forCombat, Game game); + /** * use tap(game) *

@@ -106,6 +109,8 @@ public interface Permanent extends Card, Controllable { int getDamage(); + int damage(int damage, UUID sourceId, Game game); + int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable); int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, List appliedEffects); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 800ccba21d0..0b646f11dc8 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -43,7 +43,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { private static final Logger logger = Logger.getLogger(PermanentImpl.class); - public class MarkedDamageInfo { + static class MarkedDamageInfo { public MarkedDamageInfo(Counter counter, MageObject sourceObject) { this.counter = counter; @@ -390,11 +390,16 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public boolean tap(Game game) { + return tap(false, game); + } + + @Override + public boolean tap(boolean forCombat, Game game) { //20091005 - 701.15a if (!tapped) { if (!replaceEvent(EventType.TAP, game)) { this.tapped = true; - fireEvent(EventType.TAPPED, game); + game.fireEvent(new GameEvent(EventType.TAPPED, objectId, ownerId, controllerId, 0, forCombat)); return true; } } @@ -711,6 +716,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { return this.damage; } + @Override + public int damage(int damage, UUID sourceId, Game game) { + return damage(damage, sourceId, game, true, false, false, null); + } + @Override public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable) { return damage(damage, sourceId, game, preventable, combat, false, null); @@ -946,6 +956,14 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } } + if (abilities.containsKey(HexproofFromMonocoloredAbility.getInstance().getId())) { + if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game) + && null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) + && !source.getColor(game).isColorless() && !source.getColor(game).isMulticolored()) { + return false; + } + } + if (hasProtectionFrom(source, game)) { return false; } diff --git a/Mage/src/main/java/mage/game/permanent/token/BelzenlokDemonToken.java b/Mage/src/main/java/mage/game/permanent/token/BelzenlokDemonToken.java index 81883c03a14..4f1f815b654 100644 --- a/Mage/src/main/java/mage/game/permanent/token/BelzenlokDemonToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/BelzenlokDemonToken.java @@ -72,7 +72,7 @@ class BelzenlokDemonTokenEffect extends OneShotEffect { static { filter.add(new CardTypePredicate(CardType.CREATURE)); - filter.add(new AnotherPredicate()); + filter.add(AnotherPredicate.instance); } BelzenlokDemonTokenEffect() { diff --git a/Mage/src/main/java/mage/game/permanent/token/BiogenicOozeToken.java b/Mage/src/main/java/mage/game/permanent/token/BiogenicOozeToken.java new file mode 100644 index 00000000000..3f25f1635e7 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/BiogenicOozeToken.java @@ -0,0 +1,26 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +public final class BiogenicOozeToken extends TokenImpl { + + public BiogenicOozeToken() { + super("Ooze", "2/2 green Ooze creature token"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.OOZE); + color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + setOriginalExpansionSetCode("RNA"); + } + + public BiogenicOozeToken(final BiogenicOozeToken token) { + super(token); + } + + public BiogenicOozeToken copy() { + return new BiogenicOozeToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java b/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java index a9984358dfd..593a757c1cb 100644 --- a/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java @@ -1,17 +1,15 @@ - - package mage.game.permanent.token; +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.util.RandomUtil; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.MageInt; -import mage.util.RandomUtil; /** - * * @author LevelX2 */ public final class CentaurToken extends TokenImpl { @@ -19,13 +17,16 @@ public final class CentaurToken extends TokenImpl { final static private List tokenImageSets = new ArrayList<>(); static { - tokenImageSets.addAll(Arrays.asList("RTR", "MM3")); + tokenImageSets.addAll(Arrays.asList("RTR", "MM3", "RNA")); } public CentaurToken() { super("Centaur", "3/3 green Centaur creature token"); cardType.add(CardType.CREATURE); - setTokenType(RandomUtil.nextInt(2) +1); // randomly take image 1 or 2 + availableImageSetCodes = tokenImageSets; + if (getOriginalExpansionSetCode() != null && getOriginalExpansionSetCode().equals("RNA")) { + setTokenType(RandomUtil.nextInt(2) + 1); // randomly take image 1 or 2 + } color.setGreen(true); subtype.add(SubType.CENTAUR); power = new MageInt(3); diff --git a/Mage/src/main/java/mage/game/permanent/token/FrogLizardToken.java b/Mage/src/main/java/mage/game/permanent/token/FrogLizardToken.java index bf46efa927b..5a11a156333 100644 --- a/Mage/src/main/java/mage/game/permanent/token/FrogLizardToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/FrogLizardToken.java @@ -1,19 +1,16 @@ - - package mage.game.permanent.token; + +import mage.MageInt; import mage.constants.CardType; import mage.constants.SubType; -import mage.MageInt; /** - * * @author spjspj */ public final class FrogLizardToken extends TokenImpl { public FrogLizardToken() { super("Frog Lizard", "3/3 green Frog Lizard creature token"); - this.setOriginalExpansionSetCode("GTC"); cardType.add(CardType.CREATURE); color.setGreen(true); diff --git a/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java b/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java index 79a3a2236db..19a6571f9d4 100644 --- a/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java @@ -1,16 +1,15 @@ - package mage.game.permanent.token; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import mage.MageInt; import mage.abilities.keyword.HasteAbility; import mage.constants.CardType; import mage.constants.SubType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * * @author North */ public final class GoblinToken extends TokenImpl { @@ -20,7 +19,7 @@ public final class GoblinToken extends TokenImpl { static { tokenImageSets.addAll(Arrays.asList("10E", "ALA", "SOM", "M10", "NPH", "M13", "RTR", "MMA", "M15", "C14", "KTK", "EVG", "DTK", "ORI", "DDG", "DDN", "DD3EVG", "MM2", - "MM3", "EMA", "C16", "DOM", "ANA")); + "MM3", "EMA", "C16", "DOM", "ANA", "RNA")); } public GoblinToken(boolean withHaste) { diff --git a/Mage/src/main/java/mage/game/permanent/token/HumanToken.java b/Mage/src/main/java/mage/game/permanent/token/HumanToken.java index 83524c1f95a..b1509f116b5 100644 --- a/Mage/src/main/java/mage/game/permanent/token/HumanToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/HumanToken.java @@ -1,14 +1,12 @@ - - package mage.game.permanent.token; -import java.util.Arrays; +import mage.MageInt; import mage.constants.CardType; import mage.constants.SubType; -import mage.MageInt; + +import java.util.Arrays; /** - * * @author LoneFox */ public final class HumanToken extends TokenImpl { @@ -20,7 +18,7 @@ public final class HumanToken extends TokenImpl { subtype.add(SubType.HUMAN); power = new MageInt(1); toughness = new MageInt(1); - availableImageSetCodes.addAll(Arrays.asList("DKA", "AVR", "FNMP")); + availableImageSetCodes.addAll(Arrays.asList("DKA", "AVR", "FNMP", "RNA")); } public HumanToken(final HumanToken token) { @@ -28,7 +26,7 @@ public final class HumanToken extends TokenImpl { } @Override - public HumanToken copy() { + public HumanToken copy() { return new HumanToken(this); } diff --git a/Mage/src/main/java/mage/game/permanent/token/MesmerizingBenthidToken.java b/Mage/src/main/java/mage/game/permanent/token/MesmerizingBenthidToken.java new file mode 100644 index 00000000000..c2d50814b81 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/MesmerizingBenthidToken.java @@ -0,0 +1,36 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.common.BlocksTriggeredAbility; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author TheElk801 + */ +public final class MesmerizingBenthidToken extends TokenImpl { + + public MesmerizingBenthidToken() { + super("Illusion", "0/2 blue Illusion creature token with \"Whenever this creature blocks a creature, that creature doesn't untap during its controller's next untap step.\""); + cardType.add(CardType.CREATURE); + color.setBlue(true); + setOriginalExpansionSetCode("RNA"); + + subtype.add(SubType.ILLUSION); + power = new MageInt(0); + toughness = new MageInt(2); + this.addAbility(new BlocksTriggeredAbility( + new DontUntapInControllersNextUntapStepTargetEffect("that creature"), + false, true + )); + } + + private MesmerizingBenthidToken(final MesmerizingBenthidToken token) { + super(token); + } + + public MesmerizingBenthidToken copy() { + return new MesmerizingBenthidToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/RedGreenBeastToken.java b/Mage/src/main/java/mage/game/permanent/token/RedGreenBeastToken.java new file mode 100644 index 00000000000..55a29a38b31 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/RedGreenBeastToken.java @@ -0,0 +1,33 @@ + +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.keyword.TrampleAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author TheElk801 + */ +public final class RedGreenBeastToken extends TokenImpl { + + public RedGreenBeastToken() { + super("Beast", "4/4 red and green Beast creature token with trample"); + cardType.add(CardType.CREATURE); + color.setRed(true); + color.setGreen(true); + subtype.add(SubType.BEAST); + power = new MageInt(4); + toughness = new MageInt(4); + + this.addAbility(TrampleAbility.getInstance()); + } + + private RedGreenBeastToken(final RedGreenBeastToken token) { + super(token); + } + + public RedGreenBeastToken copy() { + return new RedGreenBeastToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java b/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java index 64668eb42a2..b3bc59eeba4 100644 --- a/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java @@ -1,14 +1,14 @@ - package mage.game.permanent.token; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import mage.MageInt; import mage.abilities.keyword.FlyingAbility; import mage.constants.CardType; import mage.constants.SubType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * @author nantuko */ @@ -17,7 +17,8 @@ public final class SpiritWhiteToken extends TokenImpl { final static private List tokenImageSets = new ArrayList<>(); static { - tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3", "CMA", "E01", "ANA")); + tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", + "SOI", "EMA", "C16", "MM3", "CMA", "E01", "ANA", "RNA")); } public SpiritWhiteToken() { diff --git a/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java b/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java index 86ba65c2c7d..222b063c816 100644 --- a/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java +++ b/Mage/src/main/java/mage/game/permanent/token/TokenImpl.java @@ -1,9 +1,5 @@ package mage.game.permanent.token; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.UUID; import mage.MageObject; import mage.MageObjectImpl; import mage.abilities.Ability; @@ -18,6 +14,11 @@ import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.util.RandomUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.UUID; + public abstract class TokenImpl extends MageObjectImpl implements Token { protected String description; @@ -241,6 +242,8 @@ public abstract class TokenImpl extends MageObjectImpl implements Token { @Override public void setOriginalExpansionSetCode(String originalExpansionSetCode) { + // TODO: remove original set code at all... token image must be takes by card source or by latest set (on null source) + // TODO: if set have same tokens then selects it by random this.originalExpansionSetCode = originalExpansionSetCode; setTokenDescriptor(); } diff --git a/Mage/src/main/java/mage/game/permanent/token/TreasureToken.java b/Mage/src/main/java/mage/game/permanent/token/TreasureToken.java index aba3940cb60..6325461b403 100644 --- a/Mage/src/main/java/mage/game/permanent/token/TreasureToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/TreasureToken.java @@ -1,9 +1,5 @@ - package mage.game.permanent.token; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; @@ -13,8 +9,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * * @author TheElk801 */ public final class TreasureToken extends TokenImpl { @@ -22,7 +21,7 @@ public final class TreasureToken extends TokenImpl { final static private List tokenImageSets = new ArrayList<>(); static { - tokenImageSets.addAll(Arrays.asList("XLN")); + tokenImageSets.addAll(Arrays.asList("XLN", "RNA")); } public TreasureToken() { diff --git a/Mage/src/main/java/mage/game/permanent/token/WardenSphinxToken.java b/Mage/src/main/java/mage/game/permanent/token/WardenSphinxToken.java new file mode 100644 index 00000000000..45542d6ae06 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/WardenSphinxToken.java @@ -0,0 +1,34 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author JayDi85 + */ +public final class WardenSphinxToken extends TokenImpl { + + public WardenSphinxToken() { + super("Sphinx", "4/4 white and blue Sphinx creature token with flying and vigilance"); + this.setOriginalExpansionSetCode("RNA"); + color.setWhite(true); + color.setBlue(true); + cardType.add(CardType.CREATURE); + subtype.add(SubType.SPHINX); + power = new MageInt(4); + toughness = new MageInt(4); + this.addAbility(FlyingAbility.getInstance()); + this.addAbility(VigilanceAbility.getInstance()); + } + + public WardenSphinxToken(final WardenSphinxToken token) { + super(token); + } + + public WardenSphinxToken copy() { + return new WardenSphinxToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java b/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java index d0080034f4b..432de3e57c0 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java @@ -1,17 +1,15 @@ - package mage.game.permanent.token; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import mage.MageInt; import mage.constants.CardType; import mage.constants.SubType; import mage.util.RandomUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * * @author BetaSteward_at_googlemail.com */ public final class ZombieToken extends TokenImpl { @@ -20,7 +18,7 @@ public final class ZombieToken extends TokenImpl { static { tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "C15", "C16", "C17", "CNS", - "MMA", "BNG", "KTK", "DTK", "ORI", "OGW", "SOI", "EMN", "EMA", "MM3", "AKH", "CMA", "E01")); + "MMA", "BNG", "KTK", "DTK", "ORI", "OGW", "SOI", "EMN", "EMA", "MM3", "AKH", "CMA", "E01", "RNA")); } public ZombieToken() { diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 2fcadf1147b..6d1afef06cc 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -5,6 +5,7 @@ import mage.MageObject; import mage.ObjectColor; import mage.abilities.*; import mage.abilities.costs.Cost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.ManaCost; @@ -52,6 +53,7 @@ public class StackAbility extends StackObjImpl implements Ability { private String name; private String expansionSetCode; private TargetAdjuster targetAdjuster = null; + private CostAdjuster costAdjuster = null; public StackAbility(Ability ability, UUID controllerId) { this.ability = ability; @@ -68,6 +70,7 @@ public class StackAbility extends StackObjImpl implements Ability { this.expansionSetCode = stackAbility.expansionSetCode; this.targetAdjuster = stackAbility.targetAdjuster; this.targetChanged = stackAbility.targetChanged; + this.costAdjuster = stackAbility.costAdjuster; } @Override @@ -627,4 +630,21 @@ public class StackAbility extends StackObjImpl implements Ability { targetAdjuster.adjustTargets(this, game); } } + + @Override + public void setCostAdjuster(CostAdjuster costAdjuster) { + this.costAdjuster = costAdjuster; + } + + @Override + public CostAdjuster getCostAdjuster() { + return costAdjuster; + } + + @Override + public void adjustCosts(Game game) { + if (costAdjuster != null) { + costAdjuster.adjustCosts(this, game); + } + } } diff --git a/Mage/src/main/java/mage/players/Library.java b/Mage/src/main/java/mage/players/Library.java index 3c896d5b837..3f930f781fa 100644 --- a/Mage/src/main/java/mage/players/Library.java +++ b/Mage/src/main/java/mage/players/Library.java @@ -1,15 +1,15 @@ - package mage.players; -import java.io.Serializable; -import java.util.*; -import java.util.stream.Collectors; import mage.cards.Card; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.util.RandomUtil; +import java.io.Serializable; +import java.util.*; +import java.util.stream.Collectors; + /** * @author BetaSteward_at_googlemail.com */ @@ -186,7 +186,9 @@ public class Library implements Serializable { Map cards = new HashMap<>(); for (UUID cardId : library) { Card card = game.getCard(cardId); - cards.putIfAbsent(card.getName(), card); + if (card != null) { + cards.putIfAbsent(card.getName(), card); + } } return cards.values(); } @@ -234,4 +236,17 @@ public class Library implements Serializable { public void reset() { this.emptyDraw = false; } + + /** + * Tests only -- find card position in library + */ + public int getCardPosition(UUID cardId) { + UUID[] list = library.toArray(new UUID[0]); + for (int i = 0; i < list.length; i++) { + if (list[i].equals(cardId)) { + return i; + } + } + return -1; + } } diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index dab98647ec4..0686edb5f4d 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -1,7 +1,5 @@ package mage.players; -import java.io.Serializable; -import java.util.*; import mage.MageItem; import mage.MageObject; import mage.MageObjectReference; @@ -39,6 +37,9 @@ import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; import mage.util.Copyable; +import java.io.Serializable; +import java.util.*; + /** * @author BetaSteward_at_googlemail.com */ @@ -84,6 +85,8 @@ public interface Player extends MageItem, Copyable { int gainLife(int amount, Game game, UUID sourceId); + int damage(int damage, UUID sourceId, Game game); + int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable); int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List appliedEffects); @@ -392,9 +395,9 @@ public interface Player extends MageItem, Copyable { boolean hasProtectionFrom(MageObject source, Game game); - boolean flipCoin(Game game); + boolean flipCoin(Ability source, Game game, boolean winnable); - boolean flipCoin(Game game, ArrayList appliedEffects); + boolean flipCoin(Ability source, Game game, boolean winnable, ArrayList appliedEffects); int rollDice(Game game, int numSides); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 5f0d1fe40bb..abf0db8c5bc 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -42,11 +42,8 @@ import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.*; import mage.game.combat.CombatGroup; import mage.game.command.CommandObject; -import mage.game.events.DamagePlayerEvent; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; +import mage.game.events.*; import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; import mage.game.match.MatchPlayer; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; @@ -619,9 +616,7 @@ public abstract class PlayerImpl implements Player, Serializable { return false; } } - if (hasProtectionFrom(source, game)) { - return false; - } + return !hasProtectionFrom(source, game); } return true; @@ -1122,6 +1117,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean playLand(Card card, Game game, boolean ignoreTiming) { // Check for alternate casting possibilities: e.g. land with Morph + if (card == null) { + return false; + } ActivatedAbility playLandAbility = null; boolean found = false; for (Ability ability : card.getAbilities()) { @@ -1342,7 +1340,7 @@ public abstract class PlayerImpl implements Player, Serializable { switch (((SpellAbility) ability).getSpellAbilityType()) { case SPLIT_FUSED: if (zone == Zone.HAND) { - if (((SpellAbility) ability).canChooseTarget(game)) { + if (ability.canChooseTarget(game)) { useable.put(ability.getId(), (SpellAbility) ability); } } @@ -1456,37 +1454,39 @@ public abstract class PlayerImpl implements Player, Serializable { for (ActivatedAbility ability : otherAbilities) { if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) { Card card = game.getCard(ability.getSourceId()); - if (card.isSplitCard() && ability instanceof FlashbackAbility) { - FlashbackAbility flashbackAbility; - // Left Half - if (card.isInstant()) { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.INSTANT); - } else { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.SORCERY); - } - flashbackAbility.setSourceId(card.getId()); - flashbackAbility.setControllerId(card.getOwnerId()); - flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_LEFT); - flashbackAbility.setAbilityName(((SplitCard) card).getLeftHalfCard().getName()); - if (flashbackAbility.canActivate(playerId, game).canActivate()) { - useable.put(flashbackAbility.getId(), flashbackAbility); - } - // Right Half - if (card.isInstant()) { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.INSTANT); - } else { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.SORCERY); - } - flashbackAbility.setSourceId(card.getId()); - flashbackAbility.setControllerId(card.getOwnerId()); - flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_RIGHT); - flashbackAbility.setAbilityName(((SplitCard) card).getRightHalfCard().getName()); - if (flashbackAbility.canActivate(playerId, game).canActivate()) { - useable.put(flashbackAbility.getId(), flashbackAbility); - } + if (card != null) { + if (card.isSplitCard() && ability instanceof FlashbackAbility) { + FlashbackAbility flashbackAbility; + // Left Half + if (card.isInstant()) { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.INSTANT); + } else { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.SORCERY); + } + flashbackAbility.setSourceId(card.getId()); + flashbackAbility.setControllerId(card.getOwnerId()); + flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_LEFT); + flashbackAbility.setAbilityName(((SplitCard) card).getLeftHalfCard().getName()); + if (flashbackAbility.canActivate(playerId, game).canActivate()) { + useable.put(flashbackAbility.getId(), flashbackAbility); + } + // Right Half + if (card.isInstant()) { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.INSTANT); + } else { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.SORCERY); + } + flashbackAbility.setSourceId(card.getId()); + flashbackAbility.setControllerId(card.getOwnerId()); + flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_RIGHT); + flashbackAbility.setAbilityName(((SplitCard) card).getRightHalfCard().getName()); + if (flashbackAbility.canActivate(playerId, game).canActivate()) { + useable.put(flashbackAbility.getId(), flashbackAbility); + } - } else { - useable.put(ability.getId(), ability); + } else { + useable.put(ability.getId(), ability); + } } } } @@ -1690,9 +1690,7 @@ public abstract class PlayerImpl implements Player, Serializable { leftForUntap = getPermanentsThatCanBeUntapped(game, canBeUntapped, handledEntry.getKey().getKey(), notMoreThanEffectsUsage); // remove already selected permanents for (Permanent permanent : selectedToUntap) { - if (leftForUntap.contains(permanent)) { - leftForUntap.remove(permanent); - } + leftForUntap.remove(permanent); } } else { @@ -1919,6 +1917,11 @@ public abstract class PlayerImpl implements Player, Serializable { return 0; } + @Override + public int damage(int damage, UUID sourceId, Game game) { + return doDamage(damage, sourceId, game, true, false, null); + } + @Override public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) { return doDamage(damage, sourceId, game, combatDamage, preventable, null); @@ -1956,7 +1959,7 @@ public abstract class PlayerImpl implements Player, Serializable { sourceControllerId = ((Card) source).getOwnerId(); } else if (source instanceof CommandObject) { sourceControllerId = ((CommandObject) source).getControllerId(); - sourceAbilities = ((CommandObject) source).getAbilities(); + sourceAbilities = source.getAbilities(); } } else { sourceAbilities = ((Permanent) source).getAbilities(game); @@ -2491,7 +2494,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void lookAtAllLibraries(Ability source, Game game) { - for(UUID playerId : game.getState().getPlayersInRange(this.getId(), game)){ + for (UUID playerId : game.getState().getPlayersInRange(this.getId(), game)) { Player player = game.getPlayer(playerId); String playerName = this.getName().equals(player.getName()) ? "Your " : player.getName() + "'s "; playerName += "library"; @@ -2554,27 +2557,38 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public boolean flipCoin(Game game) { - return this.flipCoin(game, null); + public boolean flipCoin(Ability source, Game game, boolean winnable) { + return this.flipCoin(source, game, winnable, null); } /** + * @param source * @param game + * @param winnable * @param appliedEffects - * @return true if player won the toss + * @return if winnable, true if player won the toss, if not winnable, true for heads and false for tails */ @Override - public boolean flipCoin(Game game, ArrayList appliedEffects) { + public boolean flipCoin(Ability source, Game game, boolean winnable, ArrayList appliedEffects) { + boolean chosen = false; + if (winnable) { + chosen = this.chooseUse(Outcome.Benefit, "Heads or tails?", "", "Heads", "Tails", source, game); + game.informPlayers(getLogName() + " chose " + (chosen ? "heads." : "tails.")); + } boolean result = RandomUtil.nextBoolean(); - if (!game.isSimulation()) { - game.informPlayers("[Flip a coin] " + getLogName() + (result ? " won (head)." : " lost (tail).")); + FlipCoinEvent event = new FlipCoinEvent(playerId, source.getSourceId(), result, chosen, winnable); + event.addAppliedEffects(appliedEffects); + game.replaceEvent(event); + game.informPlayers(getLogName() + " got " + (event.getResult() ? "heads" : "tails")); + if (event.isWinnable()) { + game.informPlayers(getLogName() + " " + (event.getResult() == event.getChosen() ? "won" : "lost") + " the flip"); } - GameEvent event = new GameEvent(GameEvent.EventType.FLIP_COIN, playerId, null, playerId, 0, result); event.setAppliedEffects(appliedEffects); - if (!game.replaceEvent(event)) { - game.fireEvent(new GameEvent(GameEvent.EventType.COIN_FLIPPED, playerId, null, playerId, 0, event.getFlag())); + game.fireEvent(event.getFlippedEvent()); + if (event.isWinnable()) { + return event.getResult() == event.getChosen(); } - return event.getFlag(); + return event.getResult(); } @Override @@ -2592,7 +2606,7 @@ public abstract class PlayerImpl implements Player, Serializable { public int rollDice(Game game, ArrayList appliedEffects, int numSides) { int result = RandomUtil.nextInt(numSides) + 1; if (!game.isSimulation()) { - game.informPlayers("[Roll a die] " + getLogName() + " rolled a " + result + " on a " + numSides + " sided dice"); + game.informPlayers("[Roll a die] " + getLogName() + " rolled a " + result + " on a " + numSides + " sided die"); } GameEvent event = new GameEvent(GameEvent.EventType.ROLL_DICE, playerId, null, playerId, result, true); event.setAppliedEffects(appliedEffects); @@ -2842,9 +2856,7 @@ public abstract class PlayerImpl implements Player, Serializable { } } } - if (canPlayCardByAlternateCost(card, available, ability, game)) { - return true; - } + return canPlayCardByAlternateCost(card, available, ability, game); } return false; } @@ -3577,7 +3589,7 @@ public abstract class PlayerImpl implements Player, Serializable { case OUTSIDE: for (Card card : cards) { if (card instanceof Permanent) { - game.getBattlefield().removePermanent(((Permanent) card).getId()); + game.getBattlefield().removePermanent(card.getId()); ZoneChangeEvent event = new ZoneChangeEvent(card.getId(), (source == null ? null : source.getSourceId()), byOwner ? card.getOwnerId() : getId(), Zone.BATTLEFIELD, Zone.OUTSIDE, appliedEffects); game.fireEvent(event); @@ -3726,7 +3738,7 @@ public abstract class PlayerImpl implements Player, Serializable { } boolean result = false; // Zone fromZone = game.getState().getZone(card.getId()); - if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null ? fromZone == Zone.BATTLEFIELD : false)) { + if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null && fromZone == Zone.BATTLEFIELD)) { if (!game.isSimulation()) { if (card instanceof PermanentCard && game.getCard(card.getId()) != null) { card = game.getCard(card.getId()); diff --git a/Mage/src/main/java/mage/target/Targets.java b/Mage/src/main/java/mage/target/Targets.java index a1645e12d44..112a4093165 100644 --- a/Mage/src/main/java/mage/target/Targets.java +++ b/Mage/src/main/java/mage/target/Targets.java @@ -1,10 +1,14 @@ - package mage.target; import mage.abilities.Ability; import mage.constants.Outcome; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.targetpointer.FirstTargetPointer; +import mage.target.targetpointer.SecondTargetPointer; +import mage.target.targetpointer.TargetPointer; +import mage.target.targetpointer.ThirdTargetPointer; +import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.List; @@ -12,11 +16,12 @@ import java.util.UUID; import java.util.stream.Collectors; /** - * * @author BetaSteward_at_googlemail.com */ public class Targets extends ArrayList { + private static final Logger logger = Logger.getLogger(Targets.class); + public Targets() { } @@ -101,7 +106,7 @@ public class Targets extends ArrayList { * Checks if there are enough targets that can be chosen. Should only be * used for Ability targets since this checks for protection, shroud etc. * - * @param sourceId - the target event source + * @param sourceId - the target event source * @param sourceControllerId - controller of the target event source * @param game * @return - true if enough valid targets exist @@ -130,6 +135,38 @@ public class Targets extends ArrayList { return null; } + public Target getEffectTarget(TargetPointer targetPointer) { + boolean proccessed = false; + + if (targetPointer instanceof FirstTargetPointer) { + proccessed = true; + if (this.size() > 0) { + return this.get(0); + } + } + + if (targetPointer instanceof SecondTargetPointer) { + proccessed = true; + if (this.size() > 1) { + return this.get(1); + } + } + + if (targetPointer instanceof ThirdTargetPointer) { + proccessed = true; + if (this.size() > 2) { + return this.get(2); + } + } + + if (!proccessed) { + logger.error("Unknown target pointer " + (targetPointer != null ? targetPointer : "null"), new Throwable()); + // TODO: add other target types? + } + + return null; + } + public Targets copy() { return new Targets(this); } diff --git a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java index d5d490816dd..f9c867c1e3f 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java +++ b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java @@ -1,21 +1,29 @@ package mage.target.common; -import java.util.UUID; import mage.abilities.Ability; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.game.Game; import mage.players.Player; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public class TargetCreatureOrPlaneswalker extends TargetPermanent { public TargetCreatureOrPlaneswalker() { - this(1, 1, new FilterCreatureOrPlaneswalkerPermanent(), false); + this(1); + } + + public TargetCreatureOrPlaneswalker(int numTargets) { + this(numTargets, numTargets); + } + + public TargetCreatureOrPlaneswalker(int minNumTargets, int maxNumTargets) { + this(minNumTargets, maxNumTargets, new FilterCreatureOrPlaneswalkerPermanent(), false); } public TargetCreatureOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterCreatureOrPlaneswalkerPermanent filter, boolean notTarget) { diff --git a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java index ac4156a25c5..70dab46b02e 100644 --- a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java +++ b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java @@ -1,4 +1,3 @@ - package mage.target.common; import java.util.HashSet; @@ -99,7 +98,8 @@ public class TargetPermanentOrPlayer extends TargetImpl { } if (player != null) { if (!isNotTarget()) { - if (!player.canBeTargetedBy(targetSource, source.getControllerId(), game)) { + if (!player.canBeTargetedBy(targetSource, source.getControllerId(), game) + || !filter.match(player, source.getSourceId(), source.getControllerId(), game)) { return false; } } @@ -130,7 +130,7 @@ public class TargetPermanentOrPlayer extends TargetImpl { MageObject targetSource = game.getObject(sourceId); for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); - if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) { + if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { return true; @@ -163,7 +163,7 @@ public class TargetPermanentOrPlayer extends TargetImpl { int count = 0; for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); - if (player != null && filter.match(player, game)) { + if (player != null && filter.getPlayerFilter().match(player, game)) { count++; if (count >= this.minNumberOfTargets) { return true; @@ -187,7 +187,7 @@ public class TargetPermanentOrPlayer extends TargetImpl { MageObject targetSource = game.getObject(sourceId); for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); - if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(player, game)) { + if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) { possibleTargets.add(playerId); } } @@ -204,7 +204,7 @@ public class TargetPermanentOrPlayer extends TargetImpl { Set possibleTargets = new HashSet<>(); for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); - if (player != null && filter.match(player, game)) { + if (player != null && filter.getPlayerFilter().match(player, game)) { possibleTargets.add(playerId); } } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 9b3cfe75ca1..c81981296e7 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -354,6 +354,13 @@ public final class CardUtil { return message; } + public static String booleanToFlipName(boolean flip) { + if (flip) { + return "Heads"; + } + return "Tails"; + } + public static boolean checkNumeric(String s) { return s.chars().allMatch(Character::isDigit); diff --git a/Mage/src/main/java/mage/util/JarVersion.java b/Mage/src/main/java/mage/util/JarVersion.java index e79adbbc2f9..5c494ed13b7 100644 --- a/Mage/src/main/java/mage/util/JarVersion.java +++ b/Mage/src/main/java/mage/util/JarVersion.java @@ -3,9 +3,9 @@ package mage.util; import org.apache.log4j.Logger; import java.net.URL; -import java.time.Instant; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -20,6 +20,7 @@ public class JarVersion { public static String getBuildTime(Class clazz) { // build time info inserted by maven on jar build phase (see root pom.xml) + String resultFormat = "uuuu-MM-dd HH:mm"; String className = clazz.getSimpleName() + ".class"; String classPath = clazz.getResource(className).toString(); @@ -39,9 +40,11 @@ public class JarVersion { Manifest manifest = new Manifest(new URL(manifestPath).openStream()); Attributes attr = manifest.getMainAttributes(); String buildTime = attr.getValue("Build-Time"); - Instant instant = Instant.parse(buildTime); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneOffset.UTC); - return formatter.format(instant); + // default maven format: yyyy-MM-dd'T'HH:mm:ss'Z' or see maven.build.timestamp.format in pom file + DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss'Z'").withZone(ZoneOffset.UTC); + TemporalAccessor ta = sourceFormatter.parse(buildTime); + DateTimeFormatter resultFormatter = DateTimeFormatter.ofPattern(resultFormat).withZone(ZoneOffset.UTC); + return resultFormatter.format(ta); } catch (Throwable e) { logger.error("Can't read build time in jar manifest for class " + clazz.getName() + " and path " + manifestPath, e); return JAR_BUILD_TIME_ERROR; diff --git a/Mage/src/main/java/mage/util/SubTypeList.java b/Mage/src/main/java/mage/util/SubTypeList.java index 84b4fa74912..2dc37f16d51 100644 --- a/Mage/src/main/java/mage/util/SubTypeList.java +++ b/Mage/src/main/java/mage/util/SubTypeList.java @@ -20,20 +20,6 @@ public class SubTypeList extends ArrayList { Collections.addAll(this, subTypesList); } - @Deprecated - public boolean addAll(List subtypes) { - return addAll(subtypes.stream() - .map(SubType::byDescription) - .collect(Collectors.toList())); - } - - @Deprecated - public boolean removeAll(List subtypes) { - return removeAll(subtypes.stream() - .map(SubType::byDescription) - .collect(Collectors.toList())); - } - public boolean add(SubType... subTypes) { return Collections.addAll(this, subTypes); } @@ -42,18 +28,4 @@ public class SubTypeList extends ArrayList { return super.removeAll(Arrays.stream(subTypes) .collect(Collectors.toList())); } - - @Deprecated - public boolean add(String s) { - SubType subType = SubType.byDescription(s); - if (subType != null) { - return add(subType); - } - return false; - } - - @Deprecated - public boolean contains(String s) { - return contains(SubType.byDescription(s)); - } } diff --git a/Mage/src/main/java/mage/watchers/Watcher.java b/Mage/src/main/java/mage/watchers/Watcher.java index 07092b7c89a..9a941c01432 100644 --- a/Mage/src/main/java/mage/watchers/Watcher.java +++ b/Mage/src/main/java/mage/watchers/Watcher.java @@ -21,6 +21,10 @@ public abstract class Watcher implements Serializable { protected boolean condition; protected final WatcherScope scope; + public Watcher(Class watcherClass, WatcherScope scope){ + this(watcherClass.getSimpleName(), scope); + } + public Watcher(String basicKey, WatcherScope scope) { this.basicKey = basicKey; this.scope = scope; diff --git a/Mage/src/main/java/mage/watchers/Watchers.java b/Mage/src/main/java/mage/watchers/Watchers.java index af9bf034c85..7fba3a54deb 100644 --- a/Mage/src/main/java/mage/watchers/Watchers.java +++ b/Mage/src/main/java/mage/watchers/Watchers.java @@ -1,22 +1,24 @@ - package mage.watchers; -import java.util.HashMap; -import java.util.UUID; import mage.game.Game; import mage.game.events.GameEvent; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + +import java.util.HashMap; /** - * * @author BetaSteward_at_googlemail.com */ public class Watchers extends HashMap { + private static Logger logger = LogManager.getLogger(Watcher.class.getSimpleName()); + public Watchers() { } - public Watchers(final Watchers watchers) { - watchers.entrySet().forEach((entry) -> this.put(entry.getKey(), entry.getValue().copy())); + private Watchers(final Watchers watchers) { + watchers.forEach((key, value) -> this.put(key, value.copy())); } public Watchers copy() { @@ -37,7 +39,16 @@ public class Watchers extends HashMap { this.values().forEach(Watcher::reset); } - public Watcher get(String key, UUID id) { - return this.get(id + key); + public Watcher get(String key, String id) { + return get(id + key); + } + + @Override + public Watcher get(Object key) { + if (containsKey(key)) { + return super.get(key); + } + logger.error(key + " not found in watchers", new Throwable()); + return null; } } diff --git a/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java index 3254f72abe9..f470a6e06ac 100644 --- a/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/AttackedThisTurnWatcher.java @@ -1,15 +1,17 @@ package mage.watchers.common; +import mage.MageObjectReference; +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import mage.MageObjectReference; -import mage.constants.WatcherScope; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.watchers.Watcher; /** * @author magenoxx_at_gmail.com @@ -47,6 +49,15 @@ public class AttackedThisTurnWatcher extends Watcher { return this.attackedThisTurnCreaturesCounts; } + public boolean checkIfAttacked(Permanent permanent, Game game) { + for (MageObjectReference mor : attackedThisTurnCreatures) { + if (mor.refersTo(permanent, game)) { + return true; + } + } + return false; + } + @Override public AttackedThisTurnWatcher copy() { return new AttackedThisTurnWatcher(this); diff --git a/Mage/src/main/java/mage/watchers/common/BlockedThisTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/BlockedThisTurnWatcher.java index 263f24b8bb8..4a7d6133c7d 100644 --- a/Mage/src/main/java/mage/watchers/common/BlockedThisTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/BlockedThisTurnWatcher.java @@ -1,17 +1,17 @@ package mage.watchers.common; -import java.util.HashSet; -import java.util.Set; - import mage.MageObjectReference; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; + /** - * * @author Quercitron */ public class BlockedThisTurnWatcher extends Watcher { @@ -44,6 +44,15 @@ public class BlockedThisTurnWatcher extends Watcher { return this.blockedThisTurnCreatures; } + public boolean checkIfBlocked(Permanent permanent, Game game) { + for (MageObjectReference mor : blockedThisTurnCreatures) { + if (mor.refersTo(permanent, game)) { + return true; + } + } + return false; + } + @Override public void reset() { super.reset(); diff --git a/Mage/src/main/java/mage/watchers/common/PlayerGainedLifeWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerGainedLifeWatcher.java index fe9ceb02c0b..b9a9cba116e 100644 --- a/Mage/src/main/java/mage/watchers/common/PlayerGainedLifeWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/PlayerGainedLifeWatcher.java @@ -24,7 +24,7 @@ public class PlayerGainedLifeWatcher extends Watcher { super(PlayerGainedLifeWatcher.class.getSimpleName(), WatcherScope.GAME); } - public PlayerGainedLifeWatcher(final PlayerGainedLifeWatcher watcher) { + private PlayerGainedLifeWatcher(final PlayerGainedLifeWatcher watcher) { super(watcher); for (Entry entry : watcher.amountOfLifeGainedThisTurn.entrySet()) { amountOfLifeGainedThisTurn.put(entry.getKey(), entry.getValue()); @@ -45,7 +45,7 @@ public class PlayerGainedLifeWatcher extends Watcher { } } - public int getLiveGained(UUID playerId) { + public int getLifeGained(UUID playerId) { return amountOfLifeGainedThisTurn.getOrDefault(playerId, 0); } diff --git a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java index bcc4182fd97..70c389b01d2 100644 --- a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeWatcher.java @@ -49,7 +49,7 @@ public class PlayerLostLifeWatcher extends Watcher { } } - public int getLiveLost(UUID playerId) { + public int getLifeLost(UUID playerId) { return amountOfLifeLostThisTurn.getOrDefault(playerId, 0); } @@ -64,7 +64,7 @@ public class PlayerLostLifeWatcher extends Watcher { return amount; } - public int getLiveLostLastTurn(UUID playerId) { + public int getLifeLostLastTurn(UUID playerId) { return amountOfLifeLostLastTurn.getOrDefault(playerId, 0); } diff --git a/Mage/src/main/java/mage/watchers/common/ZuberasDiedWatcher.java b/Mage/src/main/java/mage/watchers/common/ZuberasDiedWatcher.java index d176bdd186d..12625b4c17c 100644 --- a/Mage/src/main/java/mage/watchers/common/ZuberasDiedWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ZuberasDiedWatcher.java @@ -14,7 +14,11 @@ import mage.watchers.Watcher; */ public class ZuberasDiedWatcher extends Watcher { - public int zuberasDiedThisTurn = 0; + public int getZuberasDiedThisTurn() { + return zuberasDiedThisTurn; + } + + private int zuberasDiedThisTurn = 0; public ZuberasDiedWatcher() { super(ZuberasDiedWatcher.class.getSimpleName(), WatcherScope.GAME); diff --git a/Mage/src/test/java/mage/cards/decks/importer/CodDeckImportTest.java b/Mage/src/test/java/mage/cards/decks/importer/CodDeckImportTest.java new file mode 100644 index 00000000000..9dd94dfdb88 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/CodDeckImportTest.java @@ -0,0 +1,40 @@ +package mage.cards.decks.importer; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import mage.cards.decks.DeckCardLists; + +public class CodDeckImportTest { + + private static final FakeCardLookup LOOKUP = new FakeCardLookup(false) + .addCard("Forest") + .addCard("Razorverge Thicket") + .addCard("Avacyn's Pilgrim") + .addCard("War Priest of Thune"); + + @Test + public void testImport() { + CodDeckImporter importer = new CodDeckImporter() { + @Override + public CardLookup getCardLookup() { + return LOOKUP; + } + }; + StringBuilder errors = new StringBuilder(); + DeckCardLists deck = importer.importDeck( + "src/test/java/mage/cards/decks/importer/samples/testdeck.cod", errors); + assertEquals("Deck Name", deck.getName()); + + TestDeckChecker.checker() + .addMain("Forest", 12) + .addMain("Razorverge Thicket", 100) + .addMain("Avacyn's Pilgrim", 1) + .addSide("War Priest of Thune", 3) + .verify(deck, 113, 3); + + assertEquals("Could not find card: '@#$NOT A REAL CARD NAME@#$'\n", errors.toString()); + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/importer/DecDeckImportTest.java b/Mage/src/test/java/mage/cards/decks/importer/DecDeckImportTest.java new file mode 100644 index 00000000000..65803c884b4 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/DecDeckImportTest.java @@ -0,0 +1,52 @@ +package mage.cards.decks.importer; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import mage.cards.decks.DeckCardLists; + +public class DecDeckImportTest { + + private static final FakeCardLookup LOOKUP = new FakeCardLookup(); + + @Test + public void testImport() { + StringBuilder errors = new StringBuilder(); + DecDeckImporter importer = new DecDeckImporter() { + @Override + public CardLookup getCardLookup() { + return LOOKUP; + } + }; + DeckCardLists deck = importer.importDeck( + "src/test/java/mage/cards/decks/importer/samples/testdeck.dec", errors); + + TestDeckChecker.checker() + .addMain("Masticore", 4) + .addMain("Metalworker", 4) + .addMain("Phyrexian Colossus", 1) + .addMain("Crumbling Sanctuary", 1) + .addMain("Grim Monolith", 4) + .addMain("Mishra's Helix", 1) + .addMain("Phyrexian Processor", 4) + .addMain("Tangle Wire", 4) + .addMain("Thran Dynamo", 4) + .addMain("Voltaic Key", 4) + .addMain("Tinker", 4) + .addMain("Brainstorm", 4) + .addMain("Crystal Vein", 4) + .addMain("Island", 9) + .addMain("Rishadan Port", 4) + .addMain("Saprazzan Skerry", 4) + .addSide("Annul", 4) + .addSide("Chill", 4) + .addSide("Miscalculation", 4) + .addSide("Mishra's Helix", 1) + .addSide("Rising Waters", 2) + .verify(deck, 60, 15); + + assertEquals("", errors.toString()); + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/importer/FakeCardLookup.java b/Mage/src/test/java/mage/cards/decks/importer/FakeCardLookup.java new file mode 100644 index 00000000000..105f0707853 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/FakeCardLookup.java @@ -0,0 +1,54 @@ +package mage.cards.decks.importer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; + +public class FakeCardLookup extends CardLookup { + + private final Map lookup = new HashMap<>(); + private final boolean alwaysMatches; + + public FakeCardLookup() { + this(true); + } + + public FakeCardLookup(boolean alwaysMatches) { + this.alwaysMatches = alwaysMatches; + } + + public FakeCardLookup addCard(String cardName) { + lookup.put(cardName, new CardInfo() {{ + name = cardName; + }}); + return this; + } + + public Optional lookupCardInfo(String cardName) { + CardInfo card = lookup.get(cardName); + if (card != null) { + return Optional.of(card); + } + + if (alwaysMatches) { + return Optional.of(new CardInfo() {{ + name = cardName; + }}); + } + + return Optional.empty(); + } + + @Override + public List lookupCardInfo(CardCriteria criteria) { + return lookupCardInfo(criteria.getName()) + .map(Collections::singletonList) + .orElse(Collections.emptyList()); + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/importer/MwsDeckImportTest.java b/Mage/src/test/java/mage/cards/decks/importer/MwsDeckImportTest.java new file mode 100644 index 00000000000..cf364d81080 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/MwsDeckImportTest.java @@ -0,0 +1,57 @@ +package mage.cards.decks.importer; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import java.util.List; + +import org.junit.Test; + +import mage.cards.decks.DeckCardLists; +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; + +public class MwsDeckImportTest { + + private static final FakeCardLookup LOOKUP = new FakeCardLookup(); + + @Test + public void testImport() { + MWSDeckImporter importer = new MWSDeckImporter() { + @Override + public CardLookup getCardLookup() { + return LOOKUP; + } + }; + StringBuilder errors = new StringBuilder(); + DeckCardLists deck = importer.importDeck( + "src/test/java/mage/cards/decks/importer/samples/testdeck.mwDeck", errors); + + TestDeckChecker.checker() + .addMain("Mutavault", 4) + .addMain("Plains", 18) + .addMain("Daring Skyjek", 2) + .addMain("Azorius Arrester", 4) + .addMain("Banisher Priest", 4) + .addMain("Boros Elite", 4) + .addMain("Dryad Militant", 4) + .addMain("Imposing Sovereign", 4) + .addMain("Precinct Captain", 4) + .addMain("Soldier of the Pantheon", 4) + .addMain("Spear of Heliod", 3) + .addMain("Rootborn Defenses", 1) + .addMain("Brave the Elements", 4) + + .addSide("Wear/Tear", 1) + .addSide("Glare of Heresy", 2) + .addSide("Fiendslayer Paladin", 3) + .addSide("Riot Control", 3) + .addSide("Ajani, Caller of the Pride", 3) + .addSide("Rootborn Defenses", 3) + + .verify(deck, 60, 15); + + assertEquals("", errors.toString()); + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/importer/O8dDeckImportTest.java b/Mage/src/test/java/mage/cards/decks/importer/O8dDeckImportTest.java new file mode 100644 index 00000000000..4eade3abd73 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/O8dDeckImportTest.java @@ -0,0 +1,33 @@ +package mage.cards.decks.importer; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import mage.cards.decks.DeckCardLists; + +public class O8dDeckImportTest { + + private static final FakeCardLookup LOOKUP = new FakeCardLookup(); + + @Test + public void testImport() { + O8dDeckImporter importer = new O8dDeckImporter() { + @Override + public CardLookup getCardLookup() { + return LOOKUP; + } + }; + StringBuilder errors = new StringBuilder(); + DeckCardLists deck = importer.importDeck( + "src/test/java/mage/cards/decks/importer/samples/testdeck.o8d", errors); + + TestDeckChecker.checker() + .addMain("Forest", 1) + .addSide("Island", 2) + .verify(deck, 1, 2); + + assertEquals("", errors.toString()); + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/importer/TestDeckChecker.java b/Mage/src/test/java/mage/cards/decks/importer/TestDeckChecker.java new file mode 100644 index 00000000000..e4f25432391 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/TestDeckChecker.java @@ -0,0 +1,54 @@ +package mage.cards.decks.importer; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; + +import mage.cards.decks.DeckCardLists; + +public class TestDeckChecker { + + private final List main = new ArrayList<>(); + private final List side = new ArrayList<>(); + + public TestDeckChecker addMain(String name) { + return addMain(name, 1); + } + + public TestDeckChecker addMain(String name, int quantity) { + main.addAll(Collections.nCopies(quantity, name)); + return this; + } + + public TestDeckChecker addSide(String name) { + return addSide(name, 1); + } + + public TestDeckChecker addSide(String name, int quantity) { + side.addAll(Collections.nCopies(quantity, name)); + return this; + } + + public void verify(DeckCardLists deck, int nMain, int nSide) { + assertEquals(nMain, main.size()); + assertEquals(nSide, side.size()); + assertEquals(nMain, deck.getCards().size()); + assertEquals(nSide, deck.getSideboard().size()); + + for (int i = 0; i < main.size(); i++) { + String expected = main.get(i); + String actual = deck.getCards().get(i).getCardName(); + assertEquals(String.format("Expected: '%s' Actual: '%s' at index: %s", + expected, actual, i), expected, actual); + } + } + + public static TestDeckChecker checker() { + return new TestDeckChecker(); + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.cod b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.cod new file mode 100644 index 00000000000..c90d63f6767 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.cod @@ -0,0 +1,14 @@ + + + Deck Name + Some comments in here. + + + + + + + + + + \ No newline at end of file diff --git a/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.dec b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.dec new file mode 100644 index 00000000000..80abb81381d --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.dec @@ -0,0 +1,28 @@ +// Name: Mono-Blue Tinker from MTGSalvation.com via mtgtrice mtg-decks +// Creatures + 4 Masticore + 4 Metalworker + 1 Phyrexian Colossus +// Artifacts + 1 Crumbling Sanctuary + 4 Grim Monolith + 1 Mishra's Helix + 4 Phyrexian Processor + 4 Tangle Wire + 4 Thran Dynamo + 4 Voltaic Key +// Sorceries + 4 Tinker +// Instants + 4 Brainstorm +// Lands + 4 Crystal Vein + 9 Island + 4 Rishadan Port + 4 Saprazzan Skerry +// Sideboard +SB: 4 Annul +SB: 4 Chill +SB: 4 Miscalculation +SB: 1 Mishra's Helix +SB: 2 Rising Waters \ No newline at end of file diff --git a/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.mwDeck b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.mwDeck new file mode 100644 index 00000000000..527f58f60d4 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.mwDeck @@ -0,0 +1,23 @@ +// Deck file for Magic Workstation (http://www.magicworkstation.com) +// NAME : WW Human +// CREATOR : meltiin (magic-ville.com) +// FORMAT : Standard + 4 [M14] Mutavault + 18 [UNH] Plains + 2 [GTC] Daring Skyjek + 4 [RTR] Azorius Arrester + 4 [M14] Banisher Priest + 4 [GTC] Boros Elite + 4 [RTR] Dryad Militant + 4 [M14] Imposing Sovereign + 4 [RTR] Precinct Captain + 4 [THS] Soldier of the Pantheon + 3 [THS] Spear of Heliod + 1 [RTR] Rootborn Defenses + 4 [M14] Brave the Elements +SB: 1 [DGM] Wear/Tear +SB: 2 [THS] Glare of Heresy +SB: 3 [M14] Fiendslayer Paladin +SB: 3 [DGM] Riot Control +SB: 3 [M14] Ajani, Caller of the Pride +SB: 3 [RTR] Rootborn Defenses \ No newline at end of file diff --git a/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.o8d b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.o8d new file mode 100644 index 00000000000..556671d0f4a --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/importer/samples/testdeck.o8d @@ -0,0 +1,8 @@ + +

+ Forest +
+
+ Island +
+ diff --git a/Utils/cardClass.tmpl b/Utils/cardClass.tmpl index c78080f860f..9d165a4cd2d 100644 --- a/Utils/cardClass.tmpl +++ b/Utils/cardClass.tmpl @@ -3,7 +3,7 @@ package mage.cards.[=$cardNameFirstLetter=]; import java.util.UUID;[= if ($power || $power eq 0) { if ($planeswalker eq 'true') { - $OUT .= "\nimport mage.abilities.common.PlaneswalkerEntersWithLoyalityCountersAbility;" + $OUT .= "\nimport mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;" }else { $OUT .= "\nimport mage.MageInt;" } @@ -30,7 +30,7 @@ public final class [=$className=] extends CardImpl { [=$subType=][=$colors=][= if ($power || $power eq 0) { if ($planeswalker eq 'true') { - $OUT .= "\n this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility($power));"; + $OUT .= "\n this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility($power));"; } else { $OUT .= "\n this.power = new MageInt($power);"; $OUT .= "\n this.toughness = new MageInt($toughness);"; diff --git a/Utils/find_new_cards.pl b/Utils/find_new_cards.pl index db6a7db5f3f..79d50ff9581 100644 --- a/Utils/find_new_cards.pl +++ b/Utils/find_new_cards.pl @@ -5,7 +5,7 @@ use strict; my $addedCards; -my $GIT_CMD = "C:\\Program Files (x86)\\Git\\bin\\git.exe"; +my $GIT_CMD = "git.exe"; my $text = `\"$GIT_CMD\" tag`; print "Assuming the tag command is on: \"$GIT_CMD\" tag\n"; diff --git a/Utils/gen-list-unimplemented-cards-for-set.pl b/Utils/gen-list-unimplemented-cards-for-set.pl index 98a8da096ef..3d8d2849a3c 100755 --- a/Utils/gen-list-unimplemented-cards-for-set.pl +++ b/Utils/gen-list-unimplemented-cards-for-set.pl @@ -89,6 +89,7 @@ sub toCamelCase { # TODO: check for basic lands with ending 1,2,3,4,5 ... my %cardNames; my $toPrint = ''; +my $setAbbr = $sets{$setName}; foreach my $card (sort cardSort @setCards) { my $className = toCamelCase(@{$card}[0]); @@ -102,7 +103,7 @@ foreach my $card (sort cardSort @setCards) { } my $cardName = @{$card}[0]; $cardName =~ s/ /+/g; - $toPrint .= "@{$card}[2]|[@{$card}[0]](https://magiccards.info/query?q=!$cardName)"; + $toPrint .= "@{$card}[2]|[@{$card}[0]](https://scryfall.com/search?q=!\"$cardName\" e:$setAbbr)"; } } @@ -127,7 +128,7 @@ foreach $cn (sort keys (%cardNames)) } my $cn2 = $cn; $cn2 =~ s/ /+/g; - print ISSUE_TRACKER "- $x_or_not [$cn](https://magiccards.info/query?q=!$cn2)\n"; + print ISSUE_TRACKER "- $x_or_not [$cn](https://scryfall.com/search?q=!\"$cn2\" e:$setAbbr)\n"; } close ISSUE_TRACKER; -print ("Tracking Issue text for a new Github issue (similar to https://github.com/magefree/mage/issues/2215): " . lc($sets{$setName}) ."_issue_tracker.txt\n"); +print ("Tracking Issue text for a new Github issue (similar to https://github.com/magefree/mage/issues/2215): " . lc($setAbbr) ."_issue_tracker.txt\n"); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 9d04bad1c03..89ec7fa76ca 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -34576,25 +34576,276 @@ Kraul Raider|Guilds of Ravnica|270|C|{2}{B}|Creature - Insect Warrior|2|3|Menace Attendant of Vraska|Guilds of Ravnica|271|U|{1}{B}{G}|Creature - Zombie Soldier|3|3|When Attendant of Vraska dies, if you control a Vraska planeswalker, you gain life equal to Attendant of Vraska's power.| Vraska's Stoneglare|Guilds of Ravnica|272|R|{4}{B}{G}|Sorcery|||Destroy target creature. You gain life equal to its toughness. You may search your library and/or graveyard for a card named Vraska, Regal Gorgon, reveal it, and put it into your hand. If you search your library this way, shuffle it.| Impervious Greatwurm|Guilds of Ravnica|273|M|{7}{G}{G}{G}|Creature - Wurm|16|16|Convoke$Indestructible| +Angel of Grace|Ravnica Allegiance|1|M|{3}{W}{W}|Creature - Angel|5|4|Flash$Flying$When Angel of Grace enters the battlefield, until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead.${4}{W}{W}, Exile Angel of Grace from your graveyard: Your life total becomes 10.| +Angelic Exaltation|Ravnica Allegiance|2|U|{3}{W}|Enchantment|||Whenever a creature you control attacks alone, it gets +X/+X until end of turn, where X is the number of creatures you control.| +Archway Angel|Ravnica Allegiance|3|U|{5}{W}|Creature - Angel|3|4|Flying$When Archway Angel enters the battlefield, you gain 2 life for each Gate you control.| +Arrester's Zeal|Ravnica Allegiance|4|C|{W}|Instant|||Target creature gets +2/+2 until end of turn.$Addendum — If you cast this spell during your main phase, that creature gains flying until end of turn.| +Bring to Trial|Ravnica Allegiance|5|C|{2}{W}|Sorcery|||Exile target creature with power 4 or greater.| +Civic Stalwart|Ravnica Allegiance|6|C|{3}{W}|Creature - Elephant Soldier|3|3|When Civic Stalwart enters the battlefield, creatures you control get +1/+1 until end of turn.| +Concordia Pegasus|Ravnica Allegiance|7|C|{1}{W}|Creature - Pegasus|1|3|Flying| +Expose to Daylight|Ravnica Allegiance|8|C|{2}{W}|Instant|||Destroy target artifact or enchantment. Scry 1.| +Forbidding Spirit|Ravnica Allegiance|9|U|{1}{W}{W}|Creature - Spirit Cleric|3|3|When Forbidding Spirit enters the battlefield, until your next turn, creatures can't attack you or a planeswalker you control unless their controller pays {2} for each of those creatures.| +Haazda Officer|Ravnica Allegiance|10|C|{2}{W}|Creature - Human Soldier|3|2|When Haazda Officer enters the battlefield, target creature you control gets +1/+1 until end of turn.| +Hero of Precinct One|Ravnica Allegiance|11|R|{1}{W}|Creature - Human Warrior|2|2|Whenever you cast a multicolored spell, create a 1/1 white Human creature token.| +Impassioned Orator|Ravnica Allegiance|12|C|{1}{W}|Creature - Human Cleric|2|2|Whenever another creature enters the battlefield under your control, you gain 1 life.| +Justiciar's Portal|Ravnica Allegiance|13|C|{1}{W}|Instant|||Exile target creature you control, then return that card to the battlefield under its owner's control. It gains first strike until end of turn.| +Knight of Sorrows|Ravnica Allegiance|14|C|{4}{W}|Creature - Human Knight|3|3|Knight of Sorrows can block an additional creature each combat.$Afterlife 1| +Lumbering Battlement|Ravnica Allegiance|15|R|{4}{W}|Creature - Beast|4|5|Vigilance$When Lumbering Battlement enters the battlefield, exile any number of other nontoken creatures you control until it leaves the battlefield.$Lumbering Battlement gets +2/+2 for each card exiled with it.| +Ministrant of Obligation|Ravnica Allegiance|16|U|{2}{W}|Creature - Human Cleric|2|1|Afterlife 2| +Prowling Caracal|Ravnica Allegiance|17|C|{1}{W}|Creature - Cat|3|1|| +Rally to Battle|Ravnica Allegiance|18|U|{3}{W}|Instant|||Creatures you control get +1/+3 until end of turn. Untap them.| +Resolute Watchdog|Ravnica Allegiance|19|U|{W}|Creature - Hound|1|3|Defender${1}, Sacrifice Resolute Watchdog: Target creature you control gains indestructible until end of turn.| +Sentinel's Mark|Ravnica Allegiance|20|U|{1}{W}|Enchantment - Aura|||Flash$Enchant creature$Enchanted creature gets +1/+2 and has vigilance.$Addendum — When Sentinel's Mark enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn.| +Sky Tether|Ravnica Allegiance|21|U|{W}|Enchantment - Aura|||Enchant creature$Enchanted creature has defender and loses flying.| +Smothering Tithe|Ravnica Allegiance|22|R|{3}{W}|Enchantment|||Whenever an opponent draws a card, that player may pay {2}. If the player doesn't, you create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color."| +Spirit of the Spires|Ravnica Allegiance|23|U|{3}{W}|Creature - Spirit|2|4|Flying$Other creatures you control with flying get +0/+1.| +Summary Judgment|Ravnica Allegiance|24|C|{1}{W}|Instant|||Summary Judgment deals 3 damage to target tapped creature.$Addendum — If you cast this spell during your main phase, it deals 5 damage to that creature instead.| +Syndicate Messenger|Ravnica Allegiance|25|C|{3}{W}|Creature - Bird|2|3|Flying$Afterlife 1| +Tenth District Veteran|Ravnica Allegiance|26|C|{2}{W}|Creature - Human Soldier|2|3|Vigilance$Whenever Tenth District Veteran attacks, untap another target creature you control.| Tithe Taker|Ravnica Allegiance|27|R|{1}{W}|Creature - Human Soldier|2|1|During your turn, spells your opponents cast cost {1} more to cast and abilities your opponents activate cost {1} more to activate unless they're mana abilities.$Afterlife 1| +Twilight Panther|Ravnica Allegiance|28|C|{W}|Creature - Cat Spirit|1|2|{B}: Twilight Panther gains deathtouch until end of turn.| +Unbreakable Formation|Ravnica Allegiance|29|R|{2}{W}|Instant|||Creatures you control gain indestructible until end of turn.$Addendum — If you cast this spell during your main phase, put a +1/+1 counter on each of those creatures, and they also gain vigilance until end of turn.| +Watchful Giant|Ravnica Allegiance|30|C|{5}{W}|Creature - Giant Soldier|3|6|When Watchful Giant enters the battlefield, create a 1/1 white Human creature token.| +Arrester's Admonition|Ravnica Allegiance|31|C|{2}{U}|Instant|||Return target creature to its owner's hand.$Addendum — If you cast this spell during your main phase, draw a card.| +Benthic Biomancer|Ravnica Allegiance|32|R|{U}|Creature - Merfolk Wizard Mutant|1|1|{1}{U}: Adapt 1.$Whenever one or more +1/+1 counters are put on Benthic Biomancer, draw a card, then discard a card.| +Chillbringer|Ravnica Allegiance|33|C|{4}{U}|Creature - Elemental|3|3|Flying$When Chillbringer enters the battlefield, tap target creature an opponent controls. It doesn't untap during its controller's next untap step.| +Clear the Mind|Ravnica Allegiance|34|C|{2}{U}|Sorcery|||Target player shuffles their graveyard into their library.$Draw a card.| +Code of Constraint|Ravnica Allegiance|35|U|{2}{U}|Instant|||Target creature gets -4/-0 until end of turn.$Draw a card.$Addendum — If you cast this spell during your main phase, tap that creature and it doesn't untap during its controller's next untap step.| +Coral Commando|Ravnica Allegiance|36|C|{2}{U}|Creature - Merfolk Warrior|3|2|| +Essence Capture|Ravnica Allegiance|37|U|{U}{U}|Instant|||Counter target creature spell. Put a +1/+1 counter on up to one target creature you control.| +Eyes Everywhere|Ravnica Allegiance|38|U|{2}{U}|Enchantment|||At the beginning of your upkeep, scry 1.${5}{U}: Exchange control of Eyes Everywhere and target nonland permanent. Activate this ability only any time you could cast a sorcery.| +Faerie Duelist|Ravnica Allegiance|39|C|{1}{U}|Creature - Faerie Rogue|1|2|Flash$Flying$When Faerie Duelist enters the battlefield, target creature an opponent controls gets -2/-0 until end of turn.| +Gateway Sneak|Ravnica Allegiance|40|U|{2}{U}|Creature - Vedalken Rogue|1|3|Whenever a Gate enters the battlefield under your control, Gateway Sneak can't be blocked this turn.$Whenever Gateway Sneak deals combat damage to a player, draw a card.| +Humongulus|Ravnica Allegiance|41|C|{4}{U}|Creature - Homunculus|2|5|Hexproof| +Mass Manipulation|Ravnica Allegiance|42|R|{X}{X}{U}{U}{U}{U}|Sorcery|||Gain control of X target creatures and/or planeswalkers.| +Mesmerizing Benthid|Ravnica Allegiance|43|M|{3}{U}{U}|Creature - Octopus|4|5|When Mesmerizing Benthid enters the battlefield, create two 0/2 blue Illusion creature tokens with "Whenever this creature blocks a creature, that creature doesn't untap during its controller's next untap step."$Mesmerizing Benthid has hexproof as long as you control an Illusion.| +Persistent Petitioners|Ravnica Allegiance|44|C|{1}{U}|Creature - Human Advisor|1|3|{1}, {T}: Target player puts the top card of their library into their graveyard.$Tap four untapped Advisors you control: Target player puts the top twelve cards of their library into their graveyard.$A deck can have any number of cards named Persistent Petitioners.| +Precognitive Perception|Ravnica Allegiance|45|R|{3}{U}{U}|Instant|||Draw three cards.$Addendum — If you cast this spell during your main phase, instead scry 3, then draw three cards.| +Prying Eyes|Ravnica Allegiance|46|C|{4}{U}{U}|Instant|||Draw four cards, then discard two cards.| +Pteramander|Ravnica Allegiance|47|U|{U}|Creature - Salamander Drake|1|1|Flying${7}{U}: Adapt 4. This ability costs {1} less to activate for each instant and sorcery card in your graveyard.| +Quench|Ravnica Allegiance|48|C|{1}{U}|Instant|||Counter target spell unless its controller pays {2}.| +Sage's Row Savant|Ravnica Allegiance|49|C|{1}{U}|Creature - Vedalken Wizard|2|1|When Sage's Row Savant enters the battlefield, scry 2.| +Senate Courier|Ravnica Allegiance|50|C|{2}{U}|Creature - Bird|1|4|Flying${1}{W}: Senate Courier gains vigilance until end of turn.| +Shimmer of Possibility|Ravnica Allegiance|51|C|{1}{U}|Sorcery|||Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order.| +Skatewing Spy|Ravnica Allegiance|52|U|{3}{U}|Creature - Vedalken Rogue Mutant|2|3|{5}{U}: Adapt 2.$Each creature you control with a +1/+1 counter on it has flying.| +Skitter Eel|Ravnica Allegiance|53|C|{3}{U}|Creature - Fish Crab|3|3|{2}{U}: Adapt 2.| +Slimebind|Ravnica Allegiance|54|C|{1}{U}|Enchantment - Aura|||Flash$Enchant creature$Enchanted creature gets -4/-0.| +Sphinx of Foresight|Ravnica Allegiance|55|R|{2}{U}{U}|Creature - Sphinx|4|4|You may reveal this card from your opening hand. If you do, scry 3 at the beginning of your first upkeep.$Flying$At the beginning of your upkeep, scry 1.| +Swirling Torrent|Ravnica Allegiance|56|U|{5}{U}|Sorcery|||Choose one or both —$• Put target creature on top of its owner's library.$• Return target creature to its owner's hand.| +Thought Collapse|Ravnica Allegiance|57|C|{1}{U}{U}|Instant|||Counter target spell. Its controller puts the top three cards of their library into their graveyard.| +Verity Circle|Ravnica Allegiance|58|R|{2}{U}|Enchantment|||Whenever a creature an opponent controls becomes tapped, if it isn't being declared as an attacker, you may draw a card.${4}{U}: Tap target creature without flying.| +Wall of Lost Thoughts|Ravnica Allegiance|59|U|{1}{U}|Creature - Wall|0|4|Defender$When Wall of Lost Thoughts enters the battlefield, target player puts the top four cards of their library into their graveyard.| +Windstorm Drake|Ravnica Allegiance|60|U|{4}{U}|Creature - Drake|3|3|Flying$Other creatures you control with flying get +1/+0.| +Awaken the Erstwhile|Ravnica Allegiance|61|R|{3}{B}{B}|Sorcery|||Each player discards all the cards in their hand, then creates that many 2/2 black Zombie creature tokens.| +Bankrupt in Blood|Ravnica Allegiance|62|U|{1}{B}|Sorcery|||As an additional cost to cast this spell, sacrifice two creatures.$Draw three cards.| +Blade Juggler|Ravnica Allegiance|63|C|{4}{B}|Creature - Human Rogue|3|2|Spectacle {2}{B}$When Blade Juggler enters the battlefield, it deals 1 damage to you and you draw a card.| +Bladebrand|Ravnica Allegiance|64|C|{1}{B}|Instant|||Target creature gains deathtouch until end of turn.$Draw a card.| +Bloodmist Infiltrator|Ravnica Allegiance|65|U|{2}{B}|Creature - Vampire|3|1|Whenever Bloodmist Infiltrator attacks, you may sacrifice another creature. If you do, Bloodmist Infiltrator can't be blocked this turn.| +Carrion Imp|Ravnica Allegiance|66|C|{3}{B}|Creature - Imp|2|3|Flying$When Carrion Imp enters the battlefield, you may exile target creature card from a graveyard. If you do, you gain 2 life.| +Catacomb Crocodile|Ravnica Allegiance|67|C|{4}{B}|Creature - Crocodile|3|7|| +Clear the Stage|Ravnica Allegiance|68|U|{4}{B}|Instant|||Target creature gets -3/-3 until end of turn. If you control a creature with power 4 or greater, you may return up to one target creature card from your graveyard to your hand.| +Consign to the Pit|Ravnica Allegiance|69|C|{5}{B}|Sorcery|||Destroy target creature. Consign to the Pit deals 2 damage to that creature's controller.| +Cry of the Carnarium|Ravnica Allegiance|70|U|{1}{B}{B}|Sorcery|||All creatures get -2/-2 until end of turn. Exile all creature cards in all graveyards that were put there from the battlefield this turn. If a creature would die this turn, exile it instead.| +Dead Revels|Ravnica Allegiance|71|C|{3}{B}|Sorcery|||Spectacle {1}{B}$Return up to two target creature cards from your graveyard to your hand.| +Debtors' Transport|Ravnica Allegiance|72|C|{5}{B}|Creature - Thrull|5|3|Afterlife 2| +Drill Bit|Ravnica Allegiance|73|U|{2}{B}|Sorcery|||Spectacle {B}$Target player reveals their hand. You choose a nonland card from it. That player discards that card.| +Font of Agonies|Ravnica Allegiance|74|R|{B}|Enchantment|||Whenever you pay life, put that many blood counters on Font of Agonies.${1}{B}, Remove four blood counters from Font of Agonies: Destroy target creature.| +Grotesque Demise|Ravnica Allegiance|75|C|{2}{B}|Instant|||Exile target creature with power 3 or less.| +Gutterbones|Ravnica Allegiance|76|R|{B}|Creature - Skeleton Warrior|2|1|Gutterbones enters the battlefield tapped.${1}{B}: Return Gutterbones from your graveyard to your hand. Activate this ability only during your turn and only if an opponent lost life this turn.| +Ill-Gotten Inheritance|Ravnica Allegiance|77|C|{3}{B}|Enchantment|||At the beginning of your upkeep, Ill-Gotten Inheritance deals 1 damage to each opponent and you gain 1 life.${5}{B}, Sacrifice Ill-Gotten Inheritance: It deals 4 damage to target opponent and you gain 4 life.| +Noxious Groodion|Ravnica Allegiance|78|C|{2}{B}|Creature - Beast|2|2|Deathtouch| +Orzhov Enforcer|Ravnica Allegiance|79|U|{1}{B}|Creature - Human Rogue|1|2|Deathtouch$Afterlife 1| +Orzhov Racketeers|Ravnica Allegiance|80|U|{4}{B}|Creature - Human Rogue|3|2|Whenever Orzhov Racketeers deals combat damage to a player, that player discards a card.$Afterlife 2| +Pestilent Spirit|Ravnica Allegiance|81|R|{2}{B}|Creature - Spirit|3|2|Menace, deathtouch$Instant and sorcery spells you control have deathtouch.| +Plague Wight|Ravnica Allegiance|82|C|{1}{B}|Creature - Zombie|2|1|Whenever Plague Wight becomes blocked, each creature blocking it gets -1/-1 until end of turn.| +Priest of Forgotten Gods|Ravnica Allegiance|83|R|{1}{B}|Creature - Human Cleric|1|2|{T}, Sacrifice two other creatures: Any number of target players each lose 2 life and sacrifice a creature. You add {B}{B} and draw a card.| +Rakdos Trumpeter|Ravnica Allegiance|84|C|{1}{B}|Creature - Human Shaman|1|3|Menace${3}{R}: Rakdos Trumpeter gets +2/+0 until end of turn.| +Spawn of Mayhem|Ravnica Allegiance|85|M|{2}{B}{B}|Creature - Demon|4|4|Spectacle {1}{B}{B}$Flying, trample$At the beginning of your upkeep, Spawn of Mayhem deals 1 damage to each player. Then if you have 10 or less life, put a +1/+1 counter on Spawn of Mayhem.| +Spire Mangler|Ravnica Allegiance|86|U|{2}{B}|Creature - Insect|2|1|Flash$Flying$When Spire Mangler enters the battlefield, target creature with flying you control gets +2/+0 until end of turn.| +Thirsting Shade|Ravnica Allegiance|87|C|{B}|Creature - Shade|1|1|Lifelink${2}{B}: Thirsting Shade gets +1/+1 until end of turn.| +Undercity Scavenger|Ravnica Allegiance|88|C|{3}{B}|Creature - Ogre Warrior|3|3|When Undercity Scavenger enters the battlefield, you may sacrifice another creature. If you do, put two +1/+1 counters on Undercity Scavenger, then scry 2.| +Undercity's Embrace|Ravnica Allegiance|89|C|{2}{B}|Instant|||Target opponent sacrifices a creature. If you control a creature with power 4 or greater, you gain 4 life.| +Vindictive Vampire|Ravnica Allegiance|90|U|{3}{B}|Creature - Vampire|2|3|Whenever another creature you control dies, Vindictive Vampire deals 1 damage to each opponent and you gain 1 life.| +Act of Treason|Ravnica Allegiance|91|C|{2}{R}|Sorcery|||Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.| +Amplifire|Ravnica Allegiance|92|R|{2}{R}{R}|Creature - Elemental|1|1|At the beginning of your upkeep, reveal cards from the top of your library until you reveal a creature card. Until your next turn, Amplifire's base power becomes twice that card's power and its base toughness becomes twice that card's toughness. Put the revealed cards on the bottom of your library in a random order.| +Burn Bright|Ravnica Allegiance|93|C|{2}{R}|Instant|||Creatures you control get +2/+0 until end of turn.| +Burning-Tree Vandal|Ravnica Allegiance|94|C|{2}{R}|Creature - Human Rogue|2|1|Riot$Whenever Burning-Tree Vandal attacks, you may discard a card. If you do, draw a card.| +Cavalcade of Calamity|Ravnica Allegiance|95|U|{1}{R}|Enchantment|||Whenever a creature you control with power 1 or less attacks, Cavalcade of Calamity deals 1 damage to the player or planeswalker that creature is attacking.| +Clamor Shaman|Ravnica Allegiance|96|U|{2}{R}|Creature - Goblin Shaman|1|1|Riot$Whenever Clamor Shaman attacks, target creature an opponent controls can't block this turn.| +Dagger Caster|Ravnica Allegiance|97|U|{3}{R}|Creature - Viashino Rogue|2|3|When Dagger Caster enters the battlefield, it deals 1 damage to each opponent and 1 damage to each creature your opponents control.| +Deface|Ravnica Allegiance|98|C|{R}|Sorcery|||Choose one —$• Destroy target artifact.$• Destroy target creature with defender.| +Electrodominance|Ravnica Allegiance|99|R|{X}{R}{R}|Instant|||Electrodominance deals X damage to any target. You may cast a card with converted mana cost X or less from your hand without paying its mana cost.| +Feral Maaka|Ravnica Allegiance|100|C|{1}{R}|Creature - Cat|2|2|| +Flames of the Raze-Boar|Ravnica Allegiance|101|U|{5}{R}|Instant|||Flames of the Raze-Boar deals 4 damage to target creature an opponent controls. Then Flames of the Raze-Boar deals 2 damage to each other creature that player controls if you control a creature with power 4 or greater.| +Gates Ablaze|Ravnica Allegiance|102|U|{2}{R}|Sorcery|||Gates Ablaze deals X damage to each creature, where X is the number of Gates you control.| +Ghor-Clan Wrecker|Ravnica Allegiance|103|C|{3}{R}|Creature - Human Warrior|2|2|Riot$Menace| +Goblin Gathering|Ravnica Allegiance|104|C|{2}{R}|Sorcery|||Create a number of 1/1 red Goblin creature tokens equal to two plus the number of cards named Goblin Gathering in your graveyard.| +Gravel-Hide Goblin|Ravnica Allegiance|105|C|{1}{R}|Creature - Goblin Shaman|2|1|{3}{G}: Gravel-Hide Goblin gets +2/+2 until end of turn.| +Immolation Shaman|Ravnica Allegiance|106|R|{1}{R}|Creature - Viashino Shaman|1|3|Whenever an opponent activates an ability of an artifact, creature, or land that isn't a mana ability, Immolation Shaman deals 1 damage to that player.${3}{R}{R}: Immolation Shaman gets +3/+3 and gains menace until end of turn.| Light Up the Stage|Ravnica Allegiance|107|U|{2}{R}|Sorcery|||Spectacle {R}$Exile the top two cards of your library. Until the end of your next turn, you may play those cards.| +Mirror March|Ravnica Allegiance|108|R|{5}{R}|Enchantment|||Whenever a nontoken creature enters the battlefield under your control, flip a coin until you lose a flip. For each flip you won, create a token that's a copy of that creature. Those tokens gain haste. Exile them at the beginning of the next end step.| Rix Maadi Reveler|Ravnica Allegiance|109|R|{1}{R}|Creature - Human Shaman|2|2|Spectacle {2}{B}{R}$When Rix Maadi Reveler enters the battlefield, discard a card, then draw a card. If Rix Maadi Reveler's spectacle cost was paid, instead discard your hand, then draw three cards.| +Rubble Reading|Ravnica Allegiance|110|C|{3}{R}|Sorcery|||Destroy target land. Scry 2.| +Rubblebelt Recluse|Ravnica Allegiance|111|C|{4}{R}|Creature - Ogre Berserker|6|5|Rubblebelt Recluse attacks each combat if able.| +Rumbling Ruin|Ravnica Allegiance|112|U|{5}{R}|Creature - Elemental|6|6|When Rumbling Ruin enters the battlefield, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn.| +Scorchmark|Ravnica Allegiance|113|C|{1}{R}|Instant|||Scorchmark deals 2 damage to target creature. If that creature would die this turn, exile it instead.| +Skarrgan Hellkite|Ravnica Allegiance|114|M|{3}{R}{R}|Creature - Dragon|4|4|Riot$Flying${3}{R}: Skarrgan Hellkite deals 2 damage divided as you choose among one or two targets. Activate this ability only if Skarrgan Hellkite has a +1/+1 counter on it.| +Skewer the Critics|Ravnica Allegiance|115|C|{2}{R}|Sorcery|||Spectacle {R}$Skewer the Critics deals 3 damage to any target.| +Smelt-Ward Ignus|Ravnica Allegiance|116|U|{1}{R}|Creature - Elemental|2|1|{2}{R}, Sacrifice Smelt-Ward Ignus: Gain control of target creature with power 3 or less until end of turn. Untap that creature. It gains haste until end of turn. Activate this ability only any time you could cast a sorcery.| +Spear Spewer|Ravnica Allegiance|117|C|{R}|Creature - Goblin Warrior|0|2|Defender${T}: Spear Spewer deals 1 damage to each player.| +Spikewheel Acrobat|Ravnica Allegiance|118|C|{3}{R}|Creature - Human Rogue|5|2|Spectacle {2}{R}| +Storm Strike|Ravnica Allegiance|119|C|{R}|Instant|||Target creature gets +1/+0 and gains first strike until end of turn. Scry 1.| +Tin Street Dodger|Ravnica Allegiance|120|U|{R}|Creature - Goblin Rogue|1|1|Haste${R}: Tin Street Dodger can't be blocked this turn except by creatures with defender.| +Axebane Beast|Ravnica Allegiance|121|C|{3}{G}|Creature - Beast|3|4|| +Biogenic Ooze|Ravnica Allegiance|122|M|{3}{G}{G}|Creature - Ooze|2|2|When Biogenic Ooze enters the battlefield, create a 2/2 green Ooze creature token.$At the beginning of your end step, put a +1/+1 counter on each Ooze you control.${1}{G}{G}{G}: Create a 2/2 green Ooze creature token.| +Biogenic Upgrade|Ravnica Allegiance|123|U|{4}{G}{G}|Sorcery|||Distribute three +1/+1 counters among one, two, or three target creatures, then double the number of +1/+1 counters on each of those creatures.| +End-Raze Forerunners|Ravnica Allegiance|124|R|{5}{G}{G}{G}|Creature - Boar|7|7|Vigilance, trample, haste$When End-Raze Forerunners enters the battlefield, other creatures you control get +2/+2 and gain vigilance and trample until end of turn.| +Enraged Ceratok|Ravnica Allegiance|125|U|{2}{G}{G}|Creature - Rhino|4|4|Enraged Ceratok can't be blocked by creatures with power 2 or less.| +Gatebreaker Ram|Ravnica Allegiance|126|U|{2}{G}|Creature - Sheep|2|2|Gatebreaker Ram gets +1/+1 for each Gate you control.$As long as you control two or more Gates, Gatebreaker Ram has vigilance and trample.| +Gift of Strength|Ravnica Allegiance|127|C|{1}{G}|Instant|||Target creature gets +3/+3 and gains reach until end of turn.| +Growth-Chamber Guardian|Ravnica Allegiance|128|R|{1}{G}|Creature - Elf Crab Warrior|2|2|{2}{G}: Adapt 2.$Whenever one or more +1/+1 counters are put on Growth-Chamber Guardian, you may search your library for a card named Growth-Chamber Guardian, reveal it, put it into your hand, then shuffle your library.| +Gruul Beastmaster|Ravnica Allegiance|129|U|{3}{G}|Creature - Human Shaman|2|2|Riot$Whenever Gruul Beastmaster attacks, another target creature you control gets +X/+0 until end of turn, where X is Gruul Beastmaster's power.| +Guardian Project|Ravnica Allegiance|130|R|{3}{G}|Enchantment|||Whenever a nontoken creature enters the battlefield under your control, if that creature does not have the same name as another creature you control or a creature card in your graveyard, draw a card.| +Incubation Druid|Ravnica Allegiance|131|R|{1}{G}|Creature - Elf Druid|0|2|{T}: Add one mana of any type that a land you control could produce. If Incubation Druid has a +1/+1 counter on it, add three mana of that type instead.${3}{G}{G}: Adapt 3.| +Mammoth Spider|Ravnica Allegiance|132|C|{4}{G}|Creature - Spider|3|5|Reach| +Open the Gates|Ravnica Allegiance|133|C|{G}|Sorcery|||Search your library for a basic land card or a Gate card, reveal it, put it into your hand, then shuffle your library.| +Rampage of the Clans|Ravnica Allegiance|134|R|{3}{G}|Instant|||Destroy all artifacts and enchantments. For each permanent destroyed this way, its controller creates a 3/3 green Centaur creature token.| +Rampaging Rendhorn|Ravnica Allegiance|135|C|{4}{G}|Creature - Beast|4|4|Riot| +Regenesis|Ravnica Allegiance|136|U|{3}{G}{G}|Instant|||Return up to two target permanent cards from your graveyard to your hand.| +Root Snare|Ravnica Allegiance|137|C|{1}{G}|Instant|||Prevent all combat damage that would be dealt this turn.| +Sagittars' Volley|Ravnica Allegiance|138|C|{2}{G}|Instant|||Destroy target creature with flying. Sagittars' Volley deals 1 damage to each creature with flying your opponents control.| +Saruli Caretaker|Ravnica Allegiance|139|C|{G}|Creature - Dryad|0|3|Defender${T}, Tap an untapped creature you control: Add one mana of any color.| +Sauroform Hybrid|Ravnica Allegiance|140|C|{1}{G}|Creature - Human Lizard Warrior|2|2|{4}{G}{G}: Adapt 4.| +Silhana Wayfinder|Ravnica Allegiance|141|U|{1}{G}|Creature - Elf Scout|2|1|When Silhana Wayfinder enters the battlefield, look at the top four cards of your library. You may reveal a creature or land card from among them and put it on top of your library. Put the rest on the bottom of your library in a random order.| +Steeple Creeper|Ravnica Allegiance|142|C|{2}{G}|Creature - Frog Snake|4|2|{3}{U}: Steeple Creeper gains flying until end of turn.| +Stony Strength|Ravnica Allegiance|143|C|{G}|Instant|||Put a +1/+1 counter on target creature you control. Untap that creature.| +Sylvan Brushstrider|Ravnica Allegiance|144|C|{2}{G}|Creature - Beast|3|2|When Sylvan Brushstrider enters the battlefield, you gain 2 life.| +Territorial Boar|Ravnica Allegiance|145|C|{1}{G}|Creature - Boar|2|2|Whenever a creature with power 4 or greater enters the battlefield under your control, Territorial Boar gets +1/+1 and gains vigilance until end of turn.| +Titanic Brawl|Ravnica Allegiance|146|C|{1}{G}|Instant|||This spell costs {1} less to cast if it targets a creature you control with a +1/+1 counter on it.$Target creature you control fights target creature you don't control.| +Tower Defense|Ravnica Allegiance|147|U|{1}{G}|Instant|||Creatures you control get +0/+5 and gain reach until end of turn.| +Trollbred Guardian|Ravnica Allegiance|148|U|{4}{G}|Creature - Troll Frog Warrior|5|5|{2}{G}: Adapt 2.$Each creature you control with a +1/+1 counter on it has trample.| +Wilderness Reclamation|Ravnica Allegiance|149|U|{3}{G}|Enchantment|||At the beginning of your end step, untap all lands you control.| +Wrecking Beast|Ravnica Allegiance|150|C|{5}{G}{G}|Creature - Beast|6|6|Riot$Trample| Absorb|Ravnica Allegiance|151|R|{W}{U}{U}|Instant|||Counter target spell. You gain 3 life.| Aeromunculus|Ravnica Allegiance|152|C|{1}{G}{U}|Creature - Homunculus Mutant|2|3|Flying${2}{G}{U}: Adapt 1.| +Applied Biomancy|Ravnica Allegiance|153|C|{G}{U}|Instant|||Choose one or both —$• Target creature gets +1/+1 until end of turn.$• Return target creature to its owner's hand.| +Azorius Knight-Arbiter|Ravnica Allegiance|154|C|{3}{W}{U}|Creature - Human Knight|2|5|Vigilance$Azorius Knight-Arbiter can't be blocked.| +Azorius Skyguard|Ravnica Allegiance|155|U|{4}{W}{U}|Creature - Human Knight|3|3|Flying, first strike$Creatures your opponents control get -1/-0.| +Basilica Bell-Haunt|Ravnica Allegiance|156|U|{W}{W}{B}{B}|Creature - Spirit|3|4|When Basilica Bell-Haunt enters the battlefield, each opponent discards a card and you gain 3 life.| Bedevil|Ravnica Allegiance|157|R|{B}{B}{R}|Instant|||Destroy target artifact, creature, or planeswalker.| +Biomancer's Familiar|Ravnica Allegiance|158|R|{G}{U}|Creature - Mutant|2|2|Activated abilities of creatures you control cost {2} less to activate. This effect can't reduce the amount of mana an ability costs to activate to less than one mana.${T}: The next time target creature adapts this turn, it adapts as though it had no +1/+1 counters on it.| +Bolrac-Clan Crusher|Ravnica Allegiance|159|U|{3}{R}{G}|Creature - Ogre Warrior|4|4|{T}, Remove a +1/+1 counter from a creature you control: Bolrac-Clan Crusher deals 2 damage to any target.| +Captive Audience|Ravnica Allegiance|160|M|{5}{B}{R}|Enchantment|||Captive Audience enters the battlefield under the control of an opponent of your choice.$At the beginning of your upkeep, choose one that hasn't been chosen —$• Your life total becomes 4.$• Discard your hand.$• Each opponent creates five 2/2 black Zombie creature tokens.| +Cindervines|Ravnica Allegiance|161|R|{R}{G}|Enchantment|||Whenever an opponent casts a noncreature spell, Cindervines deals 1 damage to that player.${1}, Sacrifice Cindervines: Destroy target artifact or enchantment. Cindervines deals 2 damage to that permanent's controller.| +Clan Guildmage|Ravnica Allegiance|162|U|{R}{G}|Creature - Human Shaman|2|2|{1}{R}, {T}: Target creature can't block this turn.${2}{G}, {T}: Target land you control becomes a 4/4 Elemental creature with haste until end of turn. It's still a land.| +Combine Guildmage|Ravnica Allegiance|163|U|{G}{U}|Creature - Merfolk Wizard|2|2|{1}{G}, {T}: This turn, each creature you control enters the battlefield with an additional +1/+1 counter on it.${1}{U}, {T}: Move a +1/+1 counter from target creature you control onto another target creature you control.| +Cult Guildmage|Ravnica Allegiance|164|U|{B}{R}|Creature - Human Shaman|2|2|{3}{B}, {T}: Target player discards a card. Activate this ability only any time you could cast a sorcery.${R}, {T}: Cult Guildmage deals 1 damage to target opponent or planeswalker.| +Deputy of Detention|Ravnica Allegiance|165|R|{1}{W}{U}|Creature - Vedalken Wizard|1|3|When Deputy of Detention enters the battlefield, exile target nonland permanent an opponent controls and all other nonland permanents that player controls with the same name as that permanent until Deputy of Detention leaves the battlefield.| +Domri, Chaos Bringer|Ravnica Allegiance|166|M|{2}{R}{G}|Legendary Planeswalker - Domri|5|+1: Add {R} or {G}. If that mana is spent on a creature spell, it gains riot.$−3: Look at the top four cards of your library. You may reveal up to two creature cards from among them and put them into your hand. Put the rest on the bottom of your library in a random order.$−8: You get an emblem with "At the beginning of each end step, create a 4/4 red and green Beast creature token with trample."| +Dovin, Grand Arbiter|Ravnica Allegiance|167|M|{1}{W}{U}|Legendary Planeswalker - Dovin|3|+1: Until end of turn, whenever a creature you control deals combat damage to a player, put a loyalty counter on Dovin, Grand Arbiter.$-1: Create a 1/1 colorless Thopter artifact creature token with flying. You gain 1 life.$-7: Look at the top ten cards of your library. Put three of them into your hand and the rest on the bottom of your library in a random order.| +Dovin's Acuity|Ravnica Allegiance|168|U|{1}{W}{U}|Enchantment|||When Dovin's Acuity enters the battlefield, you gain 2 life and draw a card.$Whenever you cast an instant spell during your main phase, you may return Dovin's Acuity to its owner's hand.| Emergency Powers|Ravnica Allegiance|169|M|{5}{W}{U}|Instant|||Each player shuffles their hand and graveyard into their library, then draws seven cards. Exile Emergency Powers.$Addendum — If you cast this spell during your main phase, you may put a permanent card with converted mana cost 7 or less from your hand onto the battlefield.| +Ethereal Absolution|Ravnica Allegiance|170|R|{4}{W}{B}|Enchantment|||Creatures you control get +1/+1.$Creatures your opponents control get -1/-1.${2}{W}{B}: Exile target card from an opponent's graveyard. If it was a creature card, you create a 1/1 white and black Spirit creature token with flying.| +Final Payment|Ravnica Allegiance|171|C|{W}{B}|Instant|||As an additional cost to cast this spell, pay 5 life or sacrifice a creature or enchantment.$Destroy target creature.| +Fireblade Artist|Ravnica Allegiance|172|U|{B}{R}|Creature - Human Shaman|2|2|Haste$At the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker.| Frenzied Arynx|Ravnica Allegiance|173|C|{2}{R}{G}|Creature - Cat Beast|3|3|Riot$Trample${4}{R}{G}: Frenzied Arynx gets +3/+0 until end of turn.| +Frilled Mystic|Ravnica Allegiance|174|U|{G}{G}{U}{U}|Creature - Elf Lizard Wizard|3|2|Flash$When Frilled Mystic enters the battlefield, you may counter target spell.| +Galloping Lizrog|Ravnica Allegiance|175|U|{3}{G}{U}|Creature - Frog Lizard|3|3|Trample$When Galloping Lizrog enters the battlefield, you may remove any number of +1/+1 counters from among creatures you control. If you do, put twice that many +1/+1 counters on Galloping Lizrog.| +Get the Point|Ravnica Allegiance|176|C|{3}{B}{R}|Instant|||Destroy target creature. Scry 1.| +Grasping Thrull|Ravnica Allegiance|177|C|{3}{W}{B}|Creature - Thrull|3|3|Flying$When Grasping Thrull enters the battlefield, it deals 2 damage to each opponent and you gain 2 life.| Growth Spiral|Ravnica Allegiance|178|C|{G}{U}|Instant|||Draw a card. You may put a land card from your hand onto the battlefield.| Gruul Spellbreaker|Ravnica Allegiance|179|R|{1}{R}{G}|Creature - Ogre Warrior|3|3|Riot$Trample$As long as it's your turn, you and Gruul Spellbreaker have hexproof.| +Gyre Engineer|Ravnica Allegiance|180|U|{1}{G}{U}|Creature - Vedalken Wizard|1|1|{T}: Add {G}{U}.| +Hackrobat|Ravnica Allegiance|181|U|{1}{B}{R}|Creature - Human Rogue|2|3|Spectacle {B}{R}${B}: Hackrobat gains deathtouch until end of turn.${R}: Hackrobat gets +2/-2 until end of turn.| +High Alert|Ravnica Allegiance|182|U|{1}{W}{U}|Enchantment|||Each creature you control assigns combat damage equal to its toughness rather than its power.$Creatures you control can attack as though they didn't have defender.${2}{W}{U}: Untap target creature.| +Hydroid Krasis|Ravnica Allegiance|183|M|{X}{G}{U}|Creature - Jellyfish Hydra Beast|0|0|When you cast this spell, you gain half X life and draw half X cards. Round down each time.$Flying, trample$Hydroid Krasis enters the battlefield with X +1/+1 counters on it.| Imperious Oligarch|Ravnica Allegiance|184|C|{W}{B}|Creature - Human Cleric|2|1|Vigilance$Afterlife 1| +Judith, the Scourge Diva|Ravnica Allegiance|185|R|{1}{B}{R}|Legendary Creature - Human Shaman|2|2|Other creatures you control get +1/+0.$Whenever a nontoken creature you control dies, Judith, the Scourge Diva deals 1 damage to any target.| +Kaya, Orzhov Usurper|Ravnica Allegiance|186|M|{1}{W}{B}|Legendary Planeswalker - Kaya|3|+1: Exile up to two target cards from a single graveyard. You gain 2 life if at least one creature card was exiled this way.$-1: Exile target nonland permanent with converted mana cost 1 or less.$-5: Kaya, Orzhov Usurper deals damage to target player equal to the number of cards that player owns in exile and you gain that much life.| +Kaya's Wrath|Ravnica Allegiance|187|R|{W}{W}{B}{B}|Sorcery|||Destroy all creatures. You gain life equal to the number of creatures you controlled that were destroyed this way.| +Knight of the Last Breath|Ravnica Allegiance|188|U|{5}{W}{B}|Creature - Giant Knight|4|4|{3}, Sacrifice another nontoken creature: Create a 1/1 white and black Spirit creature token with flying.$Afterlife 3| Lavinia, Azorius Renegade|Ravnica Allegiance|189|R|{W}{U}|Legendary Creature - Human Soldier|2|2|Each opponent can't cast noncreature spells with converted mana cost greater than the number of lands that player controls.$Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell.| +Lawmage's Binding|Ravnica Allegiance|190|C|{1}{W}{U}|Enchantment - Aura|||Flash$Enchant creature$Enchanted creature can't attack or block, and its activated abilities can't be activated.| +Macabre Mockery|Ravnica Allegiance|191|U|{2}{B}{R}|Instant|||Put target creature card from an opponent's graveyard onto the battlefield under your control. It gets +2/+0 and gains haste until end of turn. Sacrifice it at the beginning of the next end step.| Mortify|Ravnica Allegiance|192|U|{1}{W}{B}|Instant|||Destroy target creature or enchantment.| +Nikya of the Old Ways|Ravnica Allegiance|193|R|{3}{R}{G}|Legendary Creature - Centaur Druid|5|5|You can't cast noncreature spells.$Whenever you tap a land for mana, add one mana of any type that land produced.| +Pitiless Pontiff|Ravnica Allegiance|194|U|{W}{B}|Creature - Vampire Cleric|2|2|{1}, Sacrifice another creature: Pitiless Pontiff gains deathtouch and indestructible until end of turn.| +Prime Speaker Vannifar|Ravnica Allegiance|195|M|{2}{G}{U}|Legendary Creature - Elf Ooze Wizard|2|4|{T}, Sacrifice another creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost, put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery.| Rafter Demon|Ravnica Allegiance|196|C|{2}{B}{R}|Creature - Demon|4|2|Spectacle {3}{B}{R}$When Rafter Demon enters the battlefield, if its spectacle cost was paid, each opponent discards a card.| Rakdos Firewheeler|Ravnica Allegiance|197|U|{B}{B}{R}{R}|Creature - Human Rogue|4|3|When Rakdos Firewheeler enters the battlefield, it deals 2 damage to target opponent and 2 damage to up to one target creature or planeswalker.| +Rakdos Roustabout|Ravnica Allegiance|198|C|{1}{B}{R}|Creature - Ogre Warrior|3|2|Whenever Rakdos Roustabout becomes blocked, it deals 1 damage to the player or planeswalker it's attacking.| +Rakdos, the Showstopper|Ravnica Allegiance|199|M|{4}{B}{R}|Legendary Creature - Demon|6|6|Flying, trample$When Rakdos, the Showstopper enters the battlefield, flip a coin for each creature that isn't a Demon, Devil, or Imp. Destroy each creature whose coin comes up tails.| +Ravager Wurm|Ravnica Allegiance|200|M|{3}{R}{G}{G}|Creature - Wurm|4|5|Riot$When Ravager Wurm enters the battlefield, choose up to one —$• Ravager Wurm fights target creature you don't control.$• Destroy target land with an activated ability that isn't a mana ability.| +Rhythm of the Wild|Ravnica Allegiance|201|U|{1}{R}{G}|Enchantment|||Creature spells you control can't be countered.$Nontoken creatures you control have riot.| +Rubblebelt Runner|Ravnica Allegiance|202|C|{1}{R}{G}|Creature - Viashino Warrior|3|3|Rubblebelt Runner can't be blocked by creature tokens.| +Savage Smash|Ravnica Allegiance|203|C|{1}{R}{G}|Sorcery|||Target creature you control gets +2/+2 until end of turn. It fights target creature you don't control.| +Senate Guildmage|Ravnica Allegiance|204|U|{W}{U}|Creature - Human Wizard|2|2|{W}, {T}: You gain 2 life.${U}, {T}: Draw a card, then discard a card.| +Seraph of the Scales|Ravnica Allegiance|205|M|{2}{W}{B}|Creature - Angel|4|3|Flying${W}: Seraph of the Scales gains vigilance until end of turn.${B}: Seraph of the Scales gains deathtouch until end of turn.$Afterlife 2| +Sharktocrab|Ravnica Allegiance|206|U|{2}{G}{U}|Creature - Fish Octopus Crab|4|4|{2}{G}{U}: Adapt 1.$Whenever one or more +1/+1 counter are put on Sharktocrab, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step.| Simic Ascendancy|Ravnica Allegiance|207|R|{G}{U}|Enchantment|||{1}{G}{U}: Put a +1/+1 counter on target creature you control.$Whenever one or more +1/+1 counters are put on a creature you control, put that many growth counters on Simic Ascendancy.$At the beginning of your upkeep, if Simic Ascendancy has twenty or more growth counters on it, you win the game.| +Sphinx of New Prahv|Ravnica Allegiance|208|U|{W}{W}{U}{U}|Creature - Sphinx|4|3|Flying, vigilance$Spells your opponents cast that target Sphinx of New Prahv cost {2} more to cast.| Sphinx's Insight|Ravnica Allegiance|209|C|{2}{W}{U}|Instant|||Draw two cards.$Addendum — If you cast this spell during your main phase, you gain 2 life.| +Sunder Shaman|Ravnica Allegiance|210|U|{R}{R}{G}{G}|Creature - Giant Shaman|5|5|Sunder Shaman can't be blocked by more than one creature.$Whenever Sunder Shaman deals combat damage to a player, destroy target artifact or enchantment that player controls.| +Syndicate Guildmage|Ravnica Allegiance|211|U|{W}{B}|Creature - Human Cleric|2|2|{1}{W}, {T}: Tap target creature with power 4 or greater.${4}{B}, {T}: Syndicate Guildmage deals 2 damage to target opponent or planeswalker.| +Teysa Karlov|Ravnica Allegiance|212|R|{2}{W}{B}|Legendary Creature - Human Advisor|2|4|If a creature dying causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.$Creature tokens you control have vigilance and lifelink.| +Theater of Horrors|Ravnica Allegiance|213|R|{1}{B}{R}|Enchantment|||At the beginning of your upkeep, exile the top card of your library.$During your turn, if an opponent lost life this turn, you may play cards exiled with Theater of Horrors.${3}{R}: Theater of Horrors deals 1 damage to target opponent or planeswalker.| Zegana, Utopian Speaker|Ravnica Allegiance|214|R|{2}{G}{U}|Legendary Creature - Merfolk Wizard|4|4|When Zegana, Utopian Speaker enters the battlefield, if you control another creature with a +1/+1 counter on it, draw a card.${4}{G}{U}: Adapt 4.$Each creature you control with a +1/+1 counter on it has trample.| +Zhur-Taa Goblin|Ravnica Allegiance|215|U|{R}{G}|Creature - Goblin Berserker|2|2|Riot| +Footlight Fiend|Ravnica Allegiance|216|C|{B/R}|Creature - Devil|1|1|When Footlight Fiend dies, it deals 1 damage to any target.| +Rubble Slinger|Ravnica Allegiance|217|C|{2}{R/G}|Creature - Human Warrior|2|3|Reach| +Scuttlegator|Ravnica Allegiance|218|C|{4}{G/U}{G/U}|Creature - Crab Turtle Crocodile|6|6|Defender${6}{G/U}{G/U}: Adapt 3.$As long as Scuttlegator has a +1/+1 counter on it, it can attack as though it didn't have defender.| +Senate Griffin|Ravnica Allegiance|219|C|{2}{W/U}{W/U}|Creature - Griffin|3|2|Flying$When Senate Griffin enters the battlefield, scry 1.| +Vizkopa Vampire|Ravnica Allegiance|220|C|{2}{W/B}|Creature - Vampire|3|1|Lifelink| +Bedazzle|Ravnica Allegiance|221|R|{4}{B}{R}|Instant|||Destroy target nonbasic land. Bedazzle deals 2 damage to target opponent or planeswalker.| +Bedeck|Ravnica Allegiance|221|R|{B/R}{B/R}|Instant|||Target creature gets +3/-3 until end of turn.| +Carnage|Ravnica Allegiance|222|U|{2}{B}{R}|Sorcery|||Carnage deals 3 damage to target opponent. That player discards two cards.| +Carnival|Ravnica Allegiance|222|U|{B/R}|Instant|||Carnival deals 1 damage to target creature or planeswalker and 1 damage to that permanent's controller.| +Collision|Ravnica Allegiance|223|U|{1}{R/G}|Instant|||Collision deals 6 damage to target creature with flying.| +Colossus|Ravnica Allegiance|223|U|{R}{G}|Instant|||Target creature gets +4/+2 and gains trample until end of turn.| +Consecrate|Ravnica Allegiance|224|U|{1}{W/B}|Instant|||Exile target card from a graveyard.$Draw a card.| +Consume|Ravnica Allegiance|224|U|{2}{W}{B}|Sorcery|||Target player sacrifices a creature with the greatest power among creatures they control. You gain life equal to its power.| +Deploy|Ravnica Allegiance|225|U|{2}{W}{U}|Instant|||Create two 1/1 colorless Thopter artifact creature tokens with flying, then you gain 1 life for each creature you control.| +Depose|Ravnica Allegiance|225|U|{1}{W/U}|Instant|||Tap target creature.$Draw a card.| Incongruity|Ravnica Allegiance|226|U|{1}{G}{U}|Instant|||Exile target creature. That creature's controller creates a 3/3 green Frog Lizard creature token.| Incubation|Ravnica Allegiance|226|U|{G/U}|Sorcery|||Look at the top five cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Replicate|Ravnica Allegiance|227|R|{1}{G}{U}|Sorcery|||Create a token that's a copy of target creature you control.| +Repudiate|Ravnica Allegiance|227|R|{G/U}{G/U}|Instant|||Counter target activated or triggered ability.| +Revenge|Ravnica Allegiance|228|R|{4}{W}{B}|Sorcery|||Double your life total. Target opponent loses half their life, rounded up.| +Revival|Ravnica Allegiance|228|R|{W/B}{W/B}|Sorcery|||Return target creature card with converted mana cost 3 or less from your graveyard to the battlefield.| +Thrash|Ravnica Allegiance|229|R|{R/G}{R/G}|Instant|||Target creature you control deals damage equal to its power to target creature or planeswalker you don't control.| +Threat|Ravnica Allegiance|229|R|{2}{R}{G}|Sorcery|||Create a 4/4 red and green Beast creature token with trample.| +Warden|Ravnica Allegiance|230|R|{3}{W}{U}|Sorcery|||Create a 4/4 white and blue Sphinx creature token with flying and vigilance.| +Warrant|Ravnica Allegiance|230|R|{W/U}{W/U}|Instant|||Put target attacking or blocking creature on top of its owner's library.| +Azorius Locket|Ravnica Allegiance|231|C|{3}|Artifact|||{T}: Add {W} or {U}.${W/U}{W/U}{W/U}{W/U}, {T}, Sacrifice Azorius Locket: Draw two cards.| Gate Colossus|Ravnica Allegiance|232|U|{8}|Artifact Creature - Construct|8|8|This spell costs {1} less to cast for each Gate you control.$Gate Colossus can't be blocked by creatures with power 2 or less.$Whenever a Gate enters the battlefield under your control, you may put Gate Colossus from your graveyard on top of your library.| +Glass of the Guildpact|Ravnica Allegiance|233|R|{2}|Artifact|||Multicolored creatures you control get +1/+1.| +Gruul Locket|Ravnica Allegiance|234|C|{3}|Artifact|||{T}: Add {R} or {G}.${R/G}{R/G}{R/G}{R/G}, {T}, Sacrifice Gruul Locket: Draw two cards.| +Junktroller|Ravnica Allegiance|235|U|{4}|Artifact Creature - Golem|0|6|Defender${T}: Put target card from a graveyard on the bottom of its owner's library.| +Orzhov Locket|Ravnica Allegiance|236|C|{3}|Artifact|||{T}: Add {W} or {B}.${W/B}{W/B}{W/B}{W/B}, {T}, Sacrifice Orzhov Locket: Draw two cards.| +Rakdos Locket|Ravnica Allegiance|237|C|{3}|Artifact|||{T}: Add {B} or {R}.${B/R}{B/R}{B/R}{B/R}, {T}, Sacrifice Rakdos Locket: Draw two cards.| +Scrabbling Claws|Ravnica Allegiance|238|U|{1}|Artifact|||{T}: Target player exiles a card from their graveyard.${1}, Sacrifice Scrabbling Claws: Exile target card from a graveyard. Draw a card.| +Screaming Shield|Ravnica Allegiance|239|U|{1}|Artifact - Equipment|||Equipped creature gets +0/+3 and has "{2}, {T}: Target player puts the top three cards of their library into their graveyard."$Equip {3}| +Simic Locket|Ravnica Allegiance|240|C|{3}|Artifact|||{T}: Add {G} or {U}.${G/U}{G/U}{G/U}{G/U}, {T}, Sacrifice Simic Locket: Draw two cards.| +Sphinx of the Guildpact|Ravnica Allegiance|241|U|{7}|Artifact Creature - Sphinx|5|5|Sphinx of the Guildpact is all colors.$Flying$Hexproof from monocolored| +Tome of the Guildpact|Ravnica Allegiance|242|R|{5}|Artifact|||Whenever you cast a multicolored spell, draw a card.${T}: Add one mana of any color.| +Azorius Guildgate|Ravnica Allegiance|243|C||Land - Gate|||Azorius Guildgate enters the battlefield tapped.${T}: Add {W} or {U}.| +Blood Crypt|Ravnica Allegiance|245|R||Land - Swamp Mountain|||({T}: Add {B} or {R}.)$As Blood Crypt enters the battlefield, you may pay 2 life. If you don't, it enters the battlefield tapped.| +Breeding Pool|Ravnica Allegiance|246|R||Land - Forest Island|||({T}: Add {G} or {U}.)$As Breeding Pool enters the battlefield, you may pay 2 life. If you don't, it enters the battlefield tapped.| +Gateway Plaza|Ravnica Allegiance|247|C||Land - Gate|||Gateway Plaza enters the battlefield tapped.$When Gateway Plaza enters the battlefield, sacrifice it unless you pay {1}.${T}: Add one mana of any color.| +Godless Shrine|Ravnica Allegiance|248|R||Land - Plains Swamp|||({T}: Add {W} or {B}.)$As Godless Shrine enters the battlefield, you may pay 2 life. If you don't, it enters the battlefield tapped.| +Gruul Guildgate|Ravnica Allegiance|249|C||Land - Gate|||Gruul Guildgate enters the battlefield tapped.${T}: Add {R} or {G}.| +Hallowed Fountain|Ravnica Allegiance|251|R||Land - Plains Island|||({T}: Add {W} or {U}.)$As Hallowed Fountain enters the battlefield, you may pay 2 life. If you don't, it enters the battlefield tapped.| +Orzhov Guildgate|Ravnica Allegiance|252|C||Land - Gate|||Orzhov Guildgate enters the battlefield tapped.${T}: Add {W} or {B}.| +Plaza of Harmony|Ravnica Allegiance|254|R||Land|||When Plaza of Harmony enters the battlefield, if you control two or more Gates, you gain 3 life.${T}: Add {C}.${T}: Add one mana of any type a Gate you control could produce.| +Rakdos Guildgate|Ravnica Allegiance|255|C||Land - Gate|||Rakdos Guildgate enters the battlefield tapped.${T}: Add {B} or {R}.| +Simic Guildgate|Ravnica Allegiance|257|C||Land - Gate|||Simic Guildgate enters the battlefield tapped.${T}: Add {G} or {U}.| +Stomping Ground|Ravnica Allegiance|259|R||Land - Mountain Forest|||({T}: Add {R} or {G}.)$As Stomping Ground enters the battlefield, you may pay 2 life. If you don't, it enters the battlefield tapped.| +Dovin, Architect of Law|Ravnica Allegiance|265|M|{4}{W}{U}|Legendary Planeswalker - Dovin|5|+1: You gain 2 life and draw a card.$-1: Tap target creature. It doesn't untap during its controller's next untap step.$-9: Tap all permanents target opponent controls. That player skips their next untap step.| +Elite Arrester|Ravnica Allegiance|266|C|{W}|Creature - Human Soldier|0|3|{1}{U}, {T}: Tap target creature.| +Dovin's Dismissal|Ravnica Allegiance|267|R|{2}{W}{U}|Instant|||Put up to one target tapped creature on top of its owner's library. You may search your library and/or graveyard for a card named Dovin, Architect of Law, reveal it, and put it into your hand. If you search your library this way, shuffle it.| +Dovin's Automaton|Ravnica Allegiance|268|U|{4}|Artifact Creature - Homunculus|3|3|As long as you control a Dovin planeswalker, Dovin's Automaton gets +2/+2 and has vigilance.| +Domri, City Smasher|Ravnica Allegiance|269|M|{4}{R}{G}|Legendary Planeswalker - Domri|4|+2: Creatures you control get +1/+1 and gain haste until end of turn.$-3: Domri, City Smasher deals 3 damage to any target.$-8: Put three +1/+1 counters on each creature you control. Those creatures gain trample until end of turn.| +Ragefire|Ravnica Allegiance|270|C|{1}{R}|Sorcery|||Ragefire deals 3 damage to target creature.| +Charging War Boar|Ravnica Allegiance|271|U|{1}{R}{G}|Creature - Boar|3|1|Haste$As long as you control a Domri planeswalker, Charging War Boar gets +1/+1 and has trample.| +Domri's Nodorog|Ravnica Allegiance|272|R|{3}{R}{G}|Creature - Beast|5|2|Trample$When Domri's Nodorog enters the battlefield, you may search your library and/or graveyard for a card named Domri, City Smasher, reveal it, and put it into your hand. If you search your library this way, shuffle it.| The Haunt of Hightower|Ravnica Allegiance|273|M|{4}{B}{B}|Legendary Creature - Vampire|3|3|Flying, lifelink$Whenever The Haunt of Hightower attacks, defending player discards a card.$Whenever a card is put into an opponent's graveyard from anywhere, put a +1/+1 counter on The Haunt of Hightower.| \ No newline at end of file diff --git a/mageadmin.log b/mageadmin.log deleted file mode 100644 index 90f899eed0c..00000000000 --- a/mageadmin.log +++ /dev/null @@ -1,1478 +0,0 @@ -DEBUG 2017-05-12 00:41:30,044 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,049 Logging level: null =>[main] MageTestPlayerBase.init -FATAL 2017-05-12 00:41:30,841 ConfigSettings error =>[main] ConfigSettings. -javax.xml.bind.UnmarshalException - - with linked exception: -[java.io.FileNotFoundException: C:\dev\mage\config\config.xml (The system cannot find the path specified)] - at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:220) - at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:189) - at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) - at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162) - at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171) - at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189) - at mage.server.util.ConfigSettings.(ConfigSettings.java:53) - at mage.server.util.ConfigSettings.(ConfigSettings.java:44) - at org.mage.test.serverside.base.MageTestPlayerBase.init(MageTestPlayerBase.java:99) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) - at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) - at org.junit.runners.ParentRunner.run(ParentRunner.java:363) - at org.junit.runners.Suite.runChild(Suite.java:128) - at org.junit.runners.Suite.runChild(Suite.java:27) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) - at org.junit.runners.ParentRunner.run(ParentRunner.java:363) - at org.junit.runner.JUnitCore.run(JUnitCore.java:137) - at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) - at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) - at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) - at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:498) - at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) -Caused by: java.io.FileNotFoundException: C:\dev\mage\config\config.xml (The system cannot find the path specified) - at java.io.FileInputStream.open0(Native Method) - at java.io.FileInputStream.open(FileInputStream.java:195) - at java.io.FileInputStream.(FileInputStream.java:138) - at java.io.FileInputStream.(FileInputStream.java:93) - at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90) - at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188) - at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:623) - at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:148) - at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:805) - at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770) - at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) - at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) - at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643) - at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:217) - ... 35 more -DEBUG 2017-05-12 00:41:30,850 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,850 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,852 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,853 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,854 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,854 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,855 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,855 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,857 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,857 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,859 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,859 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,861 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,862 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,864 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,865 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,867 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,867 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,868 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,869 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,870 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,870 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,871 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,872 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,873 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,873 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,874 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,875 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,876 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,876 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,878 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,878 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,880 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,880 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,882 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,882 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,883 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,884 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,885 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,885 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,891 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,892 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,893 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,893 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,894 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,895 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,896 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,896 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,898 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,898 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,899 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,899 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,900 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,901 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,902 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,902 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,903 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,903 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,904 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,904 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,905 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,905 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,906 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,907 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,908 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,908 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,909 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,909 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,910 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,910 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,911 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,913 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,913 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,914 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,915 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,915 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,916 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,917 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,918 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,918 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,919 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,920 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,920 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,921 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,923 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,923 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,924 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,924 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,928 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,928 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,929 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,930 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,933 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,933 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,934 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,935 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,936 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,936 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,937 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,938 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,939 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,939 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,941 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,941 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,943 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,943 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,945 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,945 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,946 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,947 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,948 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,948 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,949 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,949 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,950 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,950 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,952 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,952 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,953 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,953 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,954 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,954 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,955 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,955 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,956 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,956 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,957 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,957 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,958 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,958 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,958 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,959 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,960 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,961 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,962 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,962 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,964 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,964 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,965 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,965 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,966 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,966 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,966 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,966 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,967 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,967 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,968 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,968 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,969 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,969 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,971 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,971 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,972 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,972 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,973 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,973 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,974 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,974 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,975 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,975 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,976 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,976 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,977 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,977 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,978 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,978 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,979 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,979 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,982 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,982 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,983 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,984 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,985 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,985 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,986 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,987 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,988 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,988 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,989 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,990 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,991 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,991 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,992 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,993 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,994 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,994 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,995 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,995 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,997 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,997 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,998 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,998 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:30,999 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,000 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,001 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,001 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,008 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,008 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,009 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,010 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,013 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,014 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,014 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,015 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,016 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,017 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,019 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,019 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,020 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,020 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,020 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,021 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,021 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,021 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,022 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,022 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,023 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,023 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,024 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,024 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,025 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,025 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,025 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,025 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,026 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,026 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,027 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,027 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,027 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,028 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,028 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,028 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,029 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,029 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,030 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,030 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,031 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,031 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,032 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,032 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,033 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,033 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,033 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,034 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,034 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,034 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,035 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,035 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,036 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,036 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,036 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,037 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,038 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,038 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,039 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,039 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,040 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,040 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,041 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,041 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,042 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,042 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,043 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,043 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,043 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,043 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,044 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,044 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,045 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,045 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,046 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,046 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,047 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,047 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,048 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,048 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,049 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,049 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,050 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,050 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,050 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,050 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,051 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,051 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,052 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,052 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,052 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,053 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,053 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,053 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,054 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,054 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,055 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,055 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,056 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,056 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,057 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,057 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,057 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,058 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,058 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,058 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,059 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,059 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,059 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,059 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,060 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,060 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,061 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,061 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,061 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,062 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,062 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,063 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,063 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,063 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,064 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,064 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,065 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,065 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,066 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,066 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,067 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,067 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,068 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,068 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,069 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,069 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,070 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,070 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,071 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,071 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,072 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,072 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,073 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,073 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,074 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,074 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,075 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,075 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,076 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,076 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,077 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,077 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,078 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,078 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,078 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,078 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,079 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,079 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,080 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,080 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,081 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,081 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,081 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,081 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,082 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,082 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,083 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,083 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,083 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,084 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,084 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,084 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,086 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,086 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,087 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,087 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,088 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,088 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,089 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,089 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,089 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,090 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,090 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,090 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,091 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,092 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,093 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,093 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,096 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,099 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,100 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,101 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,102 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,102 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,103 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,103 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,105 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,105 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,105 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,106 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,107 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,107 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,108 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,108 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,108 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,109 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,110 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,110 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,111 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,111 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,114 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,114 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,115 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,115 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,116 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,116 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,117 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,117 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,118 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,118 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,119 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,119 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,120 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,120 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,122 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,122 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,127 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,127 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,128 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,128 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,130 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,130 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,131 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,131 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,164 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,165 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,165 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,166 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,166 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,166 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,167 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,167 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,167 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,167 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,168 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,168 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,168 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,168 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,169 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,169 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,170 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,170 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,171 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,171 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,171 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,171 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,172 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,172 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,173 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,173 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,173 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,173 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,174 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,174 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,175 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,175 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,176 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,177 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,178 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,178 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,179 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,179 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,180 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,180 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,182 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,182 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,183 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,183 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,187 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,187 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,188 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,188 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,204 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,204 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,205 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,205 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,220 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,220 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,221 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,221 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,229 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,229 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,230 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,230 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,242 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,242 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,243 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,243 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,243 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,243 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,244 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,244 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,245 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,245 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,246 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,246 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,247 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,247 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,248 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,248 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,248 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,249 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,249 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,249 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,250 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,250 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,251 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,251 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,252 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,252 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,253 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,253 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,253 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,254 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,254 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,254 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,255 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,255 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,255 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,255 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,260 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,260 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,261 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,261 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,262 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,263 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,263 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,263 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,264 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,264 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,264 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,265 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,265 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,266 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,266 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,266 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,267 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,267 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,268 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,268 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,269 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,269 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,270 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,270 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,271 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,271 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,272 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,272 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,273 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,273 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,274 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,274 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,275 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,275 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,275 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,275 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,276 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,276 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,277 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,277 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,278 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,278 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,279 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,279 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,280 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,280 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,281 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,281 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,282 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,282 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,283 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,283 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,284 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,284 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,284 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,284 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,285 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,285 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,290 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,290 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,291 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,291 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,292 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,292 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,293 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,293 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,293 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,293 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,295 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,295 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,295 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,295 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,296 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,297 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,297 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,297 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,298 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,298 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,301 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,302 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,302 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,302 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,303 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,303 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,303 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,304 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,304 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,305 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,305 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,305 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,306 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,306 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,306 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,306 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,307 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,308 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,308 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,308 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,309 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,310 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,310 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,310 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,311 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,311 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,312 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,312 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,313 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,313 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,314 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,314 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,315 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,315 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,315 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,315 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,316 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,317 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,318 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,318 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,319 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,319 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,319 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,319 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,320 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,321 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,321 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,321 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,322 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,322 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,323 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,323 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,324 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,324 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,324 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,325 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,328 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,328 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,329 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,329 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,330 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,330 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,330 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,330 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,331 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,331 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,331 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,332 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,332 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,333 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,333 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,333 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,334 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,334 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,335 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,335 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,335 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,335 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,336 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,336 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,337 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,337 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,338 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,338 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,339 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,339 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,339 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,339 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,340 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,340 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,341 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,341 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,342 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,342 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,343 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,343 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,344 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,344 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,345 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,345 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,345 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,345 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,346 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,347 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,348 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,348 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,348 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,348 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,349 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,349 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,350 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,350 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,351 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,351 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,351 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,351 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,352 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,352 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,353 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,353 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,354 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,354 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,355 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,355 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,355 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,355 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,357 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,357 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,358 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,359 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,359 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,359 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,360 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,360 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,361 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,361 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,362 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,362 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,363 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,363 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,364 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,364 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,365 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,365 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,366 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,366 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,367 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,367 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,368 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,369 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,369 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,369 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,371 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,372 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,373 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,373 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,376 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,376 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,377 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,377 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,379 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,380 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,382 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,383 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,391 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,392 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,403 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,403 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,405 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,405 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,406 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,406 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,407 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,408 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,408 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,408 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,409 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,409 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,412 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,412 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,417 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,441 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,442 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,442 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,450 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,450 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,451 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,466 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,467 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,467 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,691 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,691 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,692 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,692 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,693 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,693 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,694 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,694 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,752 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,752 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,752 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,753 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,753 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,754 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,754 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,754 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,755 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,755 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,756 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,756 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,766 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,766 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,766 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,767 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,774 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,774 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,775 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,775 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,780 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,780 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,780 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,780 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,781 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,781 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,782 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,782 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,784 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,784 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,785 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,785 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,786 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,786 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,787 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,787 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,793 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,793 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,793 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,793 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,797 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,797 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,799 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,801 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,802 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:31,803 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,051 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,051 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,052 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,052 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,069 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,069 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,070 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,070 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,082 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,082 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,083 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,083 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,087 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,087 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,088 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,089 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,094 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,094 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,095 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,095 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,105 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,144 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,145 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,145 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,149 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,149 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,150 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,150 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,150 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,150 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,151 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,151 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,151 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,152 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,152 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,152 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,153 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,153 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,154 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,154 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,155 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,155 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,156 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,156 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,156 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,156 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,157 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,157 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,159 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,159 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,159 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,160 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,161 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,161 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,162 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,162 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,166 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,167 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,167 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,167 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,169 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,169 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,170 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,170 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,171 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,171 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,172 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,172 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,173 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,173 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,174 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,175 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,176 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,177 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,189 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,190 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,191 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,191 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,233 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,233 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,234 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,234 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,235 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,235 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,236 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,236 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,237 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,237 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,237 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,237 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,239 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,240 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,240 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,240 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,244 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,244 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,245 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,245 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,246 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,246 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,247 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,247 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,252 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,253 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,253 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,253 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,254 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,254 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,254 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,255 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,256 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,256 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,256 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,256 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,257 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,257 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,258 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,258 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,258 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,259 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,259 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,259 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,260 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,260 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,261 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,261 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,262 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,262 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,263 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,263 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,264 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,265 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,265 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,265 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,266 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,266 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,267 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,267 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,268 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,268 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,271 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,271 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,272 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,272 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,273 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,273 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,275 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,275 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,276 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,276 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,281 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,281 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,282 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,282 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,282 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,283 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,283 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,283 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,285 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,285 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,285 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,286 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,287 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,287 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,288 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,288 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,289 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,289 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,299 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,300 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,300 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,301 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,307 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,307 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,308 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,308 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,314 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,314 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,315 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,315 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,316 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,316 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,317 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,317 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,318 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,318 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,319 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,319 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,320 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,320 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,325 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,325 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,326 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,326 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,327 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,327 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,328 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,328 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,328 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,329 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,330 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,330 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,330 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,330 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,332 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,332 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,332 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,332 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,333 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,333 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,334 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,334 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,335 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,335 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,336 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,336 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,337 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,337 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,338 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,338 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,339 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,339 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,340 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,340 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,341 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,341 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,342 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,342 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,343 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,343 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,344 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,344 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,344 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,344 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,345 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,345 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,346 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,346 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,347 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,348 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,349 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,349 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,350 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,350 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,350 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,350 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,351 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,351 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,352 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,352 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,353 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,353 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,354 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,354 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,354 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,355 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,356 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,356 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,357 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,357 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,358 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,358 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,358 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,359 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,359 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,359 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,360 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,360 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,360 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,360 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,361 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,361 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,362 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,362 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,362 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,363 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,363 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,363 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,364 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,364 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,364 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,364 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,365 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,365 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,366 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,366 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,367 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,367 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,368 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,368 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,369 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,369 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,370 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,370 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,371 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,371 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,372 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,372 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,374 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,374 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,383 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,383 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,384 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,384 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,384 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,384 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,385 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,385 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,386 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,386 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,387 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,387 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,388 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,388 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,388 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,389 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,389 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,389 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,390 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,390 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,391 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,391 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,392 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,392 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,393 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,393 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,395 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,395 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,396 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,397 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,398 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,398 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,399 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,399 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,400 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,401 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,401 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,401 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,402 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,402 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,403 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,403 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,405 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,405 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,406 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,406 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,406 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,407 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,407 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,407 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,408 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,408 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,409 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,409 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,410 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,410 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,411 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,411 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,433 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,433 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,434 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,434 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,435 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,435 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,436 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,436 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,437 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,437 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,438 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,438 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,439 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,439 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,440 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,440 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,441 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,441 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,442 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,442 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,443 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,443 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,444 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,444 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,445 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,445 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,446 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,446 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,447 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,447 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,447 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,447 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,449 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,450 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,450 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,451 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,454 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,454 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,455 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,455 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,456 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,456 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,457 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,458 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,458 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,458 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,459 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,460 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,460 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,460 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,461 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,461 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,462 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,462 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,463 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,463 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,463 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,464 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,464 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,465 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,465 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,465 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,466 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,467 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,479 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,479 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,499 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,500 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,500 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,501 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,506 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,507 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,507 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,507 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,508 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,508 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,509 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,509 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,510 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,510 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,511 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,511 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,512 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,512 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,512 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,512 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,513 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,513 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,513 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,514 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,515 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,515 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,516 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,516 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,517 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,517 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,518 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,518 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,519 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,519 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,520 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,520 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,520 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,520 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,521 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,521 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,522 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,522 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,528 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,528 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,529 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,530 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,541 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,541 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,541 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,541 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,542 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,542 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,543 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,544 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,546 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,546 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,547 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,547 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,547 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,547 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,548 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,548 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,548 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,549 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:32,665 created dao for class class mage.cards.repository.DatabaseVersion with reflection =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:32,666 creating table 'version' =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:32,986 opened connection to jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE got #1201466784 =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:32,988 executed create table statement changed 0 rows: CREATE TABLE IF NOT EXISTS `version` (`entity` VARCHAR(255) , `version` BIGINT ) =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:32,997 built statement SELECT * FROM `version` WHERE (`entity` = ? AND `version` = 51 ) =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,006 prepared statement 'SELECT * FROM `version` WHERE (`entity` = ? AND `version` = 51 ) ' with 1 args =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,016 starting iterator @1943634922 for 'SELECT * FROM `version` WHERE (`entity` = ? AND `version` = 51 ) ' =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,016 closed iterator @1943634922 after 0 rows =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,017 query of 'SELECT * FROM `version` WHERE (`entity` = ? AND `version` = 51 ) ' returned 0 results =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,021 insert data with statement 'INSERT INTO `version` (`entity` ,`version` ) VALUES (?,?)' and 2 args, changed 1 rows =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,026 created dao for class class mage.cards.repository.CardInfo with reflection =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,027 dropping table 'card' =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,027 dropping index 'className_index' for table 'card =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,027 dropping index 'name_index' for table 'card =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,027 dropping index 'setCode_cardNumber_index' for table 'card =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,032 ignoring drop error 'org.h2.jdbc.JdbcSQLException: Index "CLASSNAME_INDEX" not found; SQL statement: -DROP INDEX `className_index` [42112-187]' for statement: DROP INDEX `className_index` =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,033 ignoring drop error 'org.h2.jdbc.JdbcSQLException: Index "NAME_INDEX" not found; SQL statement: -DROP INDEX `name_index` [42112-187]' for statement: DROP INDEX `name_index` =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,034 ignoring drop error 'org.h2.jdbc.JdbcSQLException: Index "SETCODE_CARDNUMBER_INDEX" not found; SQL statement: -DROP INDEX `setCode_cardNumber_index` [42112-187]' for statement: DROP INDEX `setCode_cardNumber_index` =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,035 ignoring drop error 'org.h2.jdbc.JdbcSQLException: Table "CARD" not found; SQL statement: -DROP TABLE `card` [42102-187]' for statement: DROP TABLE `card` =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,035 creating table 'card' =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,036 creating index 'className_index' for table 'card =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,036 creating index 'name_index' for table 'card =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,036 creating index 'setCode_cardNumber_index' for table 'card =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,038 executed create table statement changed 0 rows: CREATE TABLE IF NOT EXISTS `card` (`name` VARCHAR(255) , `cardNumber` VARCHAR(255) , `setCode` VARCHAR(255) , `className` VARCHAR(255) , `power` VARCHAR(255) , `toughness` VARCHAR(255) , `startingLoyalty` VARCHAR(255) , `convertedManaCost` INTEGER , `rarity` VARCHAR(100) , `types` VARCHAR(255) , `subtypes` VARCHAR(255) , `supertypes` VARCHAR(255) , `manaCosts` VARCHAR(255) , `rules` VARCHAR(700) , `black` TINYINT(1) , `blue` TINYINT(1) , `green` TINYINT(1) , `red` TINYINT(1) , `white` TINYINT(1) , `frameColor` VARCHAR(255) , `frameStyle` VARCHAR(255) , `variousArt` TINYINT(1) , `splitCard` TINYINT(1) , `splitCardFuse` TINYINT(1) , `splitCardAftermath` TINYINT(1) , `splitCardHalf` TINYINT(1) , `flipCard` TINYINT(1) , `doubleFaced` TINYINT(1) , `nightCard` TINYINT(1) , `flipCardName` VARCHAR(255) , `secondSideName` VARCHAR(255) ) =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,043 executed create table statement changed 0 rows: CREATE INDEX IF NOT EXISTS `className_index` ON `card` ( `className` ) =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,044 executed create table statement changed 0 rows: CREATE INDEX IF NOT EXISTS `name_index` ON `card` ( `name`, `nightCard` ) =>[main] Slf4jLoggingLog.log -INFO 2017-05-12 00:41:33,045 executed create table statement changed 0 rows: CREATE INDEX IF NOT EXISTS `setCode_cardNumber_index` ON `card` ( `cardNumber`, `setCode` ) =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,046 executing raw query for: select * from card where lower(name) = 'plains' =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,049 starting iterator @26757919 for 'select * from card where lower(name) = 'plains'' =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,049 closed iterator @26757919 after 0 rows =>[main] Slf4jLoggingLog.log -DEBUG 2017-05-12 00:41:33,051 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,052 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,054 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,055 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,058 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,060 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,061 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,061 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,062 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,062 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,062 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,063 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,065 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,065 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,066 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,066 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,067 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,067 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,067 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,068 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,069 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,070 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,070 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,071 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,071 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,071 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,072 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,072 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,073 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,074 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,074 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,074 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,075 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,076 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,076 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,077 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,078 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,078 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,078 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,079 Logging level: null =>[main] MageTestPlayerBase.init -INFO 2017-05-12 00:41:33,672 Starting MAGE tests =>[main] MageTestBase.init -INFO 2017-05-12 00:41:33,672 Logging level: null =>[main] MageTestBase.init -DEBUG 2017-05-12 00:41:33,674 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,674 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,675 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,675 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,675 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,675 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,676 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,676 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,739 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,739 Logging level: null =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,740 Starting MAGE tests =>[main] MageTestPlayerBase.init -DEBUG 2017-05-12 00:41:33,740 Logging level: null =>[main] MageTestPlayerBase.init diff --git a/pom.xml b/pom.xml index e4f8e8f1ee1..bc1f3ad553c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.32 + 1.4.33 pom Mage Root Mage Root POM @@ -88,8 +88,9 @@ - 1.4.32 + 1.4.33 UTF-8 + yyyy-MM-dd'T'HH:mm:ss'Z' diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 00000000000..9b5b43fcd3b --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,2 @@ +sonar.projectName=XMage +sonar.projectVersion=1.4.332V0