diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml index 78daaf61891..7a5a733b2c1 100644 --- a/Mage.Client/pom.xml +++ b/Mage.Client/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 org.mage diff --git a/Mage.Client/release/sample-decks/Commander/Commander 2018/Adaptive Enchantment.dck b/Mage.Client/release/sample-decks/Commander/Commander 2018/Adaptive Enchantment.dck new file mode 100644 index 00000000000..58cdece1e0b --- /dev/null +++ b/Mage.Client/release/sample-decks/Commander/Commander 2018/Adaptive Enchantment.dck @@ -0,0 +1,86 @@ +1 [C18:61] Ajani's Chosen +1 [C18:81] Archetype of Imagination +1 [C18:38] Arixmethes, Slumbering Isle +1 [C18:128] Aura Gnarlid +1 [C18:233] Azorius Chancery +1 [C18:169] Bant Charm +1 [C18:131] Bear Umbra +1 [C18:237] Blossoming Sands +1 [C18:132] Boon Satyr +1 [C18:170] Bruna, Light of Alabaster +1 [C18:64] Celestial Archon +1 [C18:172] Cold-Eyed Selkie +1 [C18:240] Command Tower +1 [C18:137] Creeping Renaissance +1 [C18:139] Dawn's Reflection +1 [C18:173] Daxos of Meletis +1 [C18:86] Dictate of Kruphix +1 [C18:66] Dismantling Blow +1 [C18:89] Eel Umbra +1 [C18:140] Eidolon of Blossoms +1 [C18:177] Elderwood Scion +1 [C18:2] Empyrial Storm +1 [C18:141] Enchantress's Presence +1 [C18:142] Epic Proportions +1 [C18:8] Estrid's Invocation +1 [C18:9] Ever-Watching Threshold +1 [C18:245] Evolving Wilds +1 [C18:147] Fertile Ground +1 [C18:180] Finest Hour +1 [C18:58] Forge of Heroes +1 [C18:30] Genesis Storm +1 [C18:149] Ground Seal +1 [C18:3] Heavenly Blademaster +1 [C18:151] Herald of the Pantheon +1 [C18:153] Hydra Omnivore +1 [C18:42] Kestia, the Cultivator +1 [C18:263] Krosan Verge +1 [C18:155] Kruphix's Insight +1 [C18:10] Loyal Drake +1 [C18:31] Loyal Guardian +1 [C18:4] Loyal Unicorn +1 [C18:69] Martial Coup +1 [C18:265] Meandering River +1 [C18:267] Mosswort Bridge +1 [C18:32] Myth Unbound +1 [C18:33] Nylea's Colossus +1 [C18:11] Octopus Umbra +1 [C18:157] Overgrowth +1 [C18:70] Phyrexian Rebirth +1 [C18:34] Ravenous Slime +1 [C18:159] Reclamation Sage +1 [C18:188] Righteous Authority +1 [C18:72] Sage's Reverie +1 [C18:277] Seaside Citadel +1 [C18:281] Selesnya Sanctuary +1 [C18:74] Sigil of the Empty Throne +1 [C18:75] Silent Sentinel +1 [C18:282] Simic Growth Chamber +1 [C18:162] Snake Umbra +1 [C18:222] Sol Ring +1 [C18:76] Soul Snare +1 [C18:163] Spawning Grounds +1 [C18:286] Terramorphic Expanse +1 [C18:287] Thornwood Falls +1 [C18:288] Tranquil Cove +1 [C18:289] Tranquil Expanse +1 [C18:47] Tuvasa the Sunlit +1 [C18:192] Unflinching Courage +1 [C18:78] Unquestioned Authority +1 [C18:110] Vow of Flight +1 [C18:164] Vow of Wildness +1 [C18:112] Whitewater Naiads +1 [C18:165] Wild Growth +1 [C18:79] Winds of Rath +1 [C18:292] Woodland Stream +1 [C18:167] Yavimaya Enchantress +2 [C18:307] Forest +2 [C18:296] Island +2 [C18:297] Island +2 [C18:298] Island +3 [C18:305] Forest +3 [C18:306] Forest +3 [C18:293] Plains +3 [C18:294] Plains +3 [C18:295] Plains +SB:1 [C18:40] Estrid, the Masked diff --git a/Mage.Client/release/sample-decks/Commander/Commander 2018/Exquisite Invention.dck b/Mage.Client/release/sample-decks/Commander/Commander 2018/Exquisite Invention.dck new file mode 100644 index 00000000000..655ed6ea71c --- /dev/null +++ b/Mage.Client/release/sample-decks/Commander/Commander 2018/Exquisite Invention.dck @@ -0,0 +1,79 @@ +1 [C18:197] Blinkmoth Urn +1 [C18:92] Into the Roil +1 [C18:230] Worn Powerstone +1 [C18:91] Inkwell Leviathan +1 [C18:199] Chief of the Foundry +1 [C18:90] Etherium Sculptor +1 [C18:111] Whirler Rogue +1 [C18:198] Bosh, Iron Golem +1 [C18:278] Seat of the Synod +1 [C18:58] Forge of Heroes +1 [C18:57] Retrofitter Foundry +1 [C18:13] Vedalken Humiliator +1 [C18:56] Geode Golem +1 [C18:55] Endless Atlas +1 [C18:99] Reverse Engineer +1 [C18:54] Coveted Jewel +1 [C18:10] Loyal Drake +1 [C18:53] Ancient Stone Idol +1 [C18:239] Buried Ruin +1 [C18:185] Maverick Thopterist +1 [C18:100] Saheeli's Artistry +1 [C18:223] Soul of New Phyrexia +1 [C18:27] Treasure Nabber +1 [C18:26] Saheeli's Directive +1 [C18:101] Sharding Sphinx +1 [C18:222] Sol Ring +1 [C18:225] Swiftfoot Boots +4 [C18:302] Mountain +1 [C18:224] Steel Hellkite +1 [C18:23] Loyal Apprentice +1 [C18:106] Thirst for Knowledge +1 [C18:227] Unstable Obelisk +4 [C18:304] Mountain +1 [C18:226] Thopter Assembly +4 [C18:303] Mountain +1 [C18:21] Enchanter's Bane +1 [C18:108] Tidings +1 [C18:229] Vessel of Endless Rest +1 [C18:107] Thopter Spy Network +1 [C18:228] Unwinding Clock +1 [C18:28] Varchild, Betrayer of Kjeldor +1 [C18:250] Great Furnace +5 [C18:296] Island +1 [C18:210] Mind Stone +5 [C18:298] Island +5 [C18:297] Island +1 [C18:256] Izzet Boilerworks +1 [C18:212] Myr Battlesphere +1 [C18:255] Highland Lake +1 [C18:211] Mirrorworks +1 [C18:214] Pilgrim's Eye +1 [C18:257] Izzet Guildgate +1 [C18:216] Prototype Portal +1 [C18:215] Prismatic Lens +1 [C18:218] Scrabbling Claws +1 [C18:217] Psychosis Crawler +1 [C18:219] Scuttling Doom Engine +1 [C18:7] Echo Storm +1 [C18:39] Brudiclad, Telchor Engineer +1 [C18:120] Blasphemous Act +1 [C18:241] Darksteel Citadel +1 [C18:80] Aether Gale +1 [C18:240] Command Tower +1 [C18:284] Swiftwater Cliffs +1 [C18:122] Chaos Warp +1 [C18:124] Hellkite Igniter +1 [C18:200] Commander's Sphere +1 [C18:126] Thopter Engineer +1 [C18:202] Darksteel Juggernaut +1 [C18:125] Magmaquake +1 [C18:205] Duplicant +1 [C18:45] Tawnos, Urza's Apprentice +1 [C18:204] Dreamstone Hedron +1 [C18:248] Foundry of the Consuls +1 [C18:207] Izzet Signet +1 [C18:206] Hedron Archive +1 [C18:209] Mimic Vat +1 [C18:208] Magnifying Glass +SB: 1 [C18:44] Saheeli, the Gifted diff --git a/Mage.Client/release/sample-decks/Commander/Commander 2018/Nature's Vengeance.dck b/Mage.Client/release/sample-decks/Commander/Commander 2018/Nature's Vengeance.dck new file mode 100644 index 00000000000..84bec7b4493 --- /dev/null +++ b/Mage.Client/release/sample-decks/Commander/Commander 2018/Nature's Vengeance.dck @@ -0,0 +1,91 @@ +1 [C18:114] Moonlight Bargain +1 [C18:116] Retreat to Hagra +1 [C18:117] Ruinous Path +1 [C18:118] Soul of Innistrad +1 [C18:119] Stitch Together +1 [C18:121] Chain Reaction +1 [C18:123] Flameblast Dragon +1 [C18:127] Acidic Slime +1 [C18:129] Avenger of Zendikar +1 [C18:130] Baloth Woodcrasher +1 [C18:133] Borderland Explorer +1 [C18:134] Budoka Gardener +1 [C18:135] Centaur Vinecrasher +1 [C18:136] Consign to Dust +1 [C18:138] Cultivate +1 [C18:143] Explore +1 [C18:144] Explosive Vegetation +1 [C18:145] Far Wanderings +1 [C18:146] Farhaven Elf +1 [C18:148] Grapple with the Past +1 [C18:14] Bloodtracker +1 [C18:150] Harrow +1 [C18:152] Hunting Wilds +1 [C18:154] Khalni Heart Expedition +1 [C18:156] Moldgraf Monstrosity +1 [C18:158] Rampaging Baloths +1 [C18:160] Sakura-Tribe Elder +1 [C18:161] Scute Mob +1 [C18:166] Yavimaya Elder +1 [C18:16] Loyal Subordinate +1 [C18:171] Charnelhoard Wurm +1 [C18:174] Deathreap Ritual +1 [C18:175] Decimate +1 [C18:181] Gaze of Granite +1 [C18:182] Grisly Salvage +1 [C18:184] Lavalanche +1 [C18:187] Putrefy +1 [C18:189] Rubblehulk +1 [C18:190] Savage Twister +1 [C18:194] Worm Harvest +1 [C18:195] Zendikar Incarnate +1 [C18:221] Seer's Sundial +1 [C18:222] Sol Ring +1 [C18:22] Fury Storm +1 [C18:231] Akoum Refuge +1 [C18:235] Barren Moor +1 [C18:236] Blighted Woodland +1 [C18:238] Bojuka Bog +1 [C18:23] Loyal Apprentice +1 [C18:240] Command Tower +1 [C18:245] Evolving Wilds +1 [C18:246] Forgotten Cave +1 [C18:249] Golgari Rot Farm +1 [C18:24] Nesting Dragon +1 [C18:251] Grim Backwoods +1 [C18:252] Gruul Turf +1 [C18:254] Haunted Fengraf +1 [C18:258] Jund Panorama +1 [C18:259] Jungle Hollow +1 [C18:25] Reality Scramble +1 [C18:261] Kazandu Refuge +1 [C18:262] Khalni Garden +1 [C18:268] Mountain Valley +1 [C18:269] Myriad Landscape +1 [C18:273] Rakdos Carnarium +1 [C18:274] Rocky Tar Pit +1 [C18:275] Savage Lands +1 [C18:285] Temple of the False God +1 [C18:286] Terramorphic Expanse +1 [C18:290] Tranquil Thicket +1 [C18:29] Crash of Rhino Beetles +1 [C18:31] Loyal Guardian +1 [C18:35] Turntimber Sower +1 [C18:36] Whiptongue Hydra +1 [C18:41] Gyrus, Waker of Corpses +1 [C18:49] Windgrace's Judgment +1 [C18:58] Forge of Heroes +1 [C18:20] Emissary of Grudges +1 [C18:46] Thantis, the Warweaver +1 [C18:291] Warped Landscape +1 [C18:50] Xantcha, Sleeper Agent +2 [C18:299] Swamp +2 [C18:300] Swamp +2 [C18:301] Swamp +2 [C18:302] Mountain +2 [C18:303] Mountain +1 [C18:304] Mountain +2 [C18:306] Forest +2 [C18:307] Forest +3 [C18:305] Forest +SB: 1 [C18:43] Lord Windgrace diff --git a/Mage.Client/release/sample-decks/Commander/Commander 2018/Subjective Reality.dck b/Mage.Client/release/sample-decks/Commander/Commander 2018/Subjective Reality.dck new file mode 100644 index 00000000000..49462f68623 --- /dev/null +++ b/Mage.Client/release/sample-decks/Commander/Commander 2018/Subjective Reality.dck @@ -0,0 +1,93 @@ +1 [C18:102] Sigiled Starfish +1 [C18:103] Sphinx of Jwar Isle +1 [C18:104] Sphinx of Uthuun +1 [C18:105] Telling Time +1 [C18:109] Treasure Hunt +1 [C18:113] Army of the Damned +1 [C18:115] Phyrexian Delver +1 [C18:12] Primordial Mist +1 [C18:15] Entreat the Dead +1 [C18:168] Aethermage's Touch +1 [C18:16] Loyal Subordinate +1 [C18:176] Duskmantle Seer +1 [C18:178] Enigma Sphinx +1 [C18:179] Esper Charm +1 [C18:17] Night Incarnate +1 [C18:183] High Priest of Penance +1 [C18:186] Mortify +1 [C18:18] Skull Storm +1 [C18:191] Silent-Blade Oni +1 [C18:193] Utter End +1 [C18:196] Azorius Signet +1 [C18:19] Sower of Discord +1 [C18:1] Boreas Charger +1 [C18:200] Commander's Sphere +1 [C18:201] Crystal Ball +1 [C18:203] Dimir Signet +1 [C18:210] Mind Stone +1 [C18:213] Orzhov Signet +1 [C18:214] Pilgrim's Eye +1 [C18:220] Seer's Lantern +1 [C18:222] Sol Ring +1 [C18:232] Arcane Sanctum +1 [C18:233] Azorius Chancery +1 [C18:234] Azorius Guildgate +1 [C18:235] Barren Moor +1 [C18:240] Command Tower +1 [C18:242] Dimir Aqueduct +1 [C18:243] Dimir Guildgate +1 [C18:244] Dismal Backwater +1 [C18:247] Forsaken Sanctuary +1 [C18:253] Halimar Depths +1 [C18:260] Jwar Isle Refuge +1 [C18:264] Lonely Sandbar +1 [C18:265] Meandering River +1 [C18:266] Mortuary Mire +1 [C18:270] New Benalia +1 [C18:271] Orzhov Basilica +1 [C18:272] Orzhov Guildgate +1 [C18:276] Scoured Barrens +1 [C18:279] Secluded Steppe +1 [C18:280] Sejiri Refuge +1 [C18:283] Submerged Boneyard +1 [C18:48] Varina, Lich Queen +1 [C18:4] Loyal Unicorn +1 [C18:56] Geode Golem +1 [C18:58] Forge of Heroes +1 [C18:59] Isolated Watchtower +1 [C18:5] Magus of the Balance +1 [C18:60] Adarkar Valkyrie +1 [C18:62] Akroma's Vengeance +1 [C18:63] Banishing Stroke +1 [C18:65] Crib Swap +1 [C18:67] Entreat the Angels +1 [C18:68] Lightform +1 [C18:71] Return to Dust +1 [C18:73] Serra Avatar +1 [C18:77] Terminus +1 [C18:82] Brainstorm +1 [C18:83] Cloudform +1 [C18:84] Conundrum Sphinx +1 [C18:85] Devastation Tide +1 [C18:87] Djinn of Wishes +1 [C18:88] Dream Cache +1 [C18:93] Jeskai Infiltrator +1 [C18:94] Mulldrifter +1 [C18:95] Ninja of the Deep Hours +1 [C18:96] Ponder +1 [C18:97] Portent +1 [C18:98] Predict +1 [C18:298] Island +1 [C18:299] Swamp +1 [C18:300] Swamp +1 [C18:301] Swamp +1 [C18:006] Aminatou's Augury +1 [C18:288] Tranquil Cove +1 [C18:51] Yennett, Cryptic Sovereign +1 [C18:52] Yuriko, the Tiger's Shadow +2 [C18:296] Island +2 [C18:297] Island +2 [C18:295] Plains +3 [C18:293] Plains +3 [C18:294] Plains +SB: 1 [C18:37] Aminatou, the Fateshifter diff --git a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java index af83e6775bd..7ca2057605b 100644 --- a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java +++ b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java @@ -1083,10 +1083,10 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg } repaint(); } - + private void chooseMatching() { Collection toMatch = dragCardList(); - + for (DragCardGridListener l : listeners) { for (CardView card : allCards) { for (CardView aMatch : toMatch) { @@ -1337,6 +1337,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg public void analyseDeck() { HashMap qtys = new HashMap<>(); HashMap pips = new HashMap<>(); + HashMap pips_at_cmcs = new HashMap<>(); HashMap sourcePips = new HashMap<>(); HashMap manaCounts = new HashMap<>(); pips.put("#w}", 0); @@ -1396,11 +1397,40 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg } mc = mc.replaceAll("\\{([WUBRG]).([WUBRG])\\}", "{$1}{$2}"); mc = mc.replaceAll("\\{", "#"); + mc = mc.replaceAll("#2\\/", "#"); + mc = mc.replaceAll("p}", "}"); mc = mc.toLowerCase(Locale.ENGLISH); + int cmc = card.getConvertedManaCost(); + + // Do colorless mana pips + Pattern regex = Pattern.compile("#([0-9]+)}"); + Matcher regexMatcher = regex.matcher(mc); + while (regexMatcher.find()) { + String val = regexMatcher.group(1); + int colorless_val = Integer.parseInt(val); + + int total_c_pip = 0; + if (pips.get("#c}") != null) { + total_c_pip = pips.get("#c}"); + } + pips.put("#c}", colorless_val + total_c_pip); + + int cmc_pip_value = 0; + if (pips_at_cmcs.get(cmc + "##c}") != null) { + cmc_pip_value = pips_at_cmcs.get(cmc + "##c}"); + } + pips_at_cmcs.put(cmc + "##c}", colorless_val + cmc_pip_value); + } + for (String pip : pips.keySet()) { int value = pips.get(pip); while (mc.toLowerCase(Locale.ENGLISH).contains(pip)) { pips.put(pip, ++value); + int pip_value = 0; + if (pips_at_cmcs.get(cmc + "#" + pip) != null) { + pip_value = pips_at_cmcs.get(cmc + "#" + pip); + } + pips_at_cmcs.put(cmc + "#" + pip, ++pip_value); mc = mc.replaceFirst(pip, ""); } } @@ -1448,9 +1478,17 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg panel4.add(new JLabel("Mana sources found:")); panel4.add(chart3); + JPanel panel5 = new JPanel(); + panel5.setLayout(new BoxLayout(panel5, BoxLayout.Y_AXIS)); + ManaBarChart chart4 = new ManaBarChart(pips_at_cmcs); + chart4.setMinimumSize(new Dimension(200, 200)); + panel5.add(new JLabel("Mana distribution:")); + panel5.add(chart4); + panel.add(panel2); panel.add(panel3); panel.add(panel4); + panel.add(panel5); JFrame frame = new JFrame("JOptionPane showMessageDialog component example"); JOptionPane.showMessageDialog(frame, panel, "This is the distribution of colors found", JOptionPane.INFORMATION_MESSAGE); @@ -1719,7 +1757,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg JMenuItem invertSelection = new JMenuItem("Invert Selection"); invertSelection.addActionListener(e2 -> invertSelection()); menu.add(invertSelection); - + JMenuItem chooseMatching = new JMenuItem("Choose Matching"); chooseMatching.addActionListener(e2 -> chooseMatching()); menu.add(chooseMatching); diff --git a/Mage.Client/src/main/java/mage/client/cards/ManaBarChart.java b/Mage.Client/src/main/java/mage/client/cards/ManaBarChart.java new file mode 100644 index 00000000000..15ae7abb539 --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/cards/ManaBarChart.java @@ -0,0 +1,151 @@ +package mage.client.cards; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Stroke; +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JComponent; + +public class ManaBarChart extends JComponent { + + HashMap pips_at_cmcs = new HashMap(); + + ManaBarChart() { + } + + ManaBarChart(HashMap pips_at_cmcs) { + this.pips_at_cmcs = pips_at_cmcs; + } + + @Override + public Dimension getPreferredSize() { + Dimension preferred = super.getPreferredSize(); + Dimension minimum = getMinimumSize(); + Dimension maximum = getMaximumSize(); + preferred.width = Math.min(Math.max(preferred.width, minimum.width), maximum.width); + preferred.height = Math.min(Math.max(preferred.height, minimum.height), maximum.height); + return preferred; + } + + public void paint(Graphics g) { + drawBar((Graphics2D) g, getBounds()); + } + + void drawBar(Graphics2D g, Rectangle area) { + Pattern regex = Pattern.compile("^([0-9]+)##(.)}"); + HashMap totals_at_cmcs = new HashMap(); + int max_num_pips = 0; + int max_cmc = 0; + + for (String key : pips_at_cmcs.keySet()) { + Matcher regexMatcher = regex.matcher(key); + int num_pips = pips_at_cmcs.get(key); + while (regexMatcher.find()) { + String cmc = regexMatcher.group(1); + int cmc_num = Integer.parseInt(cmc); + if (max_cmc < cmc_num) { + max_cmc = cmc_num; + } + + int total_at_cmc = 0; + if (totals_at_cmcs.get(cmc_num) != null) { + total_at_cmc = totals_at_cmcs.get(cmc_num); + } + totals_at_cmcs.put(cmc_num, total_at_cmc + num_pips); + if (max_num_pips < total_at_cmc + num_pips) { + max_num_pips = total_at_cmc + num_pips; + } + } + } + + if (max_num_pips <= 0) { + max_num_pips = 1; + } + int height_factor = 200 / max_num_pips; + int width_factor = 200 / (max_cmc + 2); + if (width_factor > 20) { + width_factor = 20; + } + if (width_factor < 11) { + width_factor = 11; + } + + g.setColor(new Color(130, 130, 130)); + for (int i = 0; i < max_num_pips; i++) { + if (max_num_pips > 10) { + if (i % 10 == 0) { + g.drawLine(0, 200 - 1 - i * height_factor, 400, 200 - 1 - i * height_factor); + } else if (i % 10 == 5) { + Stroke dashed = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{5}, 0); + Stroke oldstroke = g.getStroke(); + g.setStroke(dashed); + g.drawLine(0, 200 - 1 - i * height_factor, 400, 200 - 1 - i * height_factor); + g.setStroke(oldstroke); + } + } else if (i % 2 == 0) { + g.drawLine(0, 200 - 1 - i * height_factor, 400, 200 - 1 - i * height_factor); + } else if (i % 2 == 1) { + Stroke dashed = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{5}, 0); + Stroke oldstroke = g.getStroke(); + g.setStroke(dashed); + g.drawLine(0, 200 - 1 - i * height_factor, 400, 200 - 1 - i * height_factor); + g.setStroke(oldstroke); + } + } + + for (int i = 0; i < 17; i++) { + if (i % 5 == 0) { + g.drawLine(width_factor * i, 200, width_factor * i, 190); + } else { + g.drawLine(width_factor * i, 200, width_factor * i, 195); + } + + } + + HashMap running_totals_at_cmcs = new HashMap(); + for (String key : pips_at_cmcs.keySet()) { + Matcher regexMatcher = regex.matcher(key); + int num_pips = pips_at_cmcs.get(key); + while (regexMatcher.find()) { + String cmc = regexMatcher.group(1); + int cmc_num = Integer.parseInt(cmc); + String color = regexMatcher.group(2); + + int total_at_cmc = 0; + if (running_totals_at_cmcs.get(cmc_num) != null) { + total_at_cmc = running_totals_at_cmcs.get(cmc_num); + } + + if (color.equalsIgnoreCase("w")) { + g.setColor(Color.WHITE); + } + if (color.equalsIgnoreCase("u")) { + g.setColor(Color.BLUE); + } + if (color.equalsIgnoreCase("b")) { + g.setColor(Color.BLACK); + } + if (color.equalsIgnoreCase("r")) { + g.setColor(Color.RED); + } + if (color.equalsIgnoreCase("g")) { + g.setColor(Color.GREEN); + } + if (color.equalsIgnoreCase("c")) { + g.setColor(Color.DARK_GRAY); + } + g.fill(new Rectangle2D.Double(cmc_num * width_factor, 200 - 1 - total_at_cmc - num_pips * height_factor, 10, num_pips * height_factor)); + running_totals_at_cmcs.put(cmc_num, total_at_cmc + num_pips * height_factor); + } + } + + } +} diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java index f3a0d367ed2..a16607fa29c 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java @@ -325,6 +325,7 @@ public class DeckGeneratorDialog { // Generated deck has a nice unique name which corresponds to the timestamp at which it was created. String deckName = "Generated-Deck-" + dateFormat.format(new Date()); File tmp = new File(tempDir + File.separator + deckName + ".dck"); + tmp.getParentFile().mkdirs(); tmp.createNewFile(); deck.setName(deckName); Sets.saveDeck(tmp.getAbsolutePath(), deck.getDeckCardLists()); 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 fdc08874535..5b74e76cbf5 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form @@ -341,7 +341,7 @@ - + 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 a75dc8c2a84..120c35e2c03 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -1,6 +1,4 @@ - - - /* +/* * ConnectDialog.java * * Created on 20-Jan-2010, 9:37:07 PM @@ -17,7 +15,6 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.InputStreamReader; import java.io.Writer; -import java.io.Closeable; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketException; @@ -273,8 +270,8 @@ public class ConnectDialog extends MageDialog { }); btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N - btnFind3.setText("U"); - btnFind3.setToolTipText("Connect to xmage.us (USA)"); + btnFind3.setText("W"); + btnFind3.setToolTipText("Connect to vaporservermtg.com (USA)"); btnFind3.setActionCommand("connectXmageus"); btnFind3.setAlignmentY(0.0F); btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2)); @@ -646,7 +643,6 @@ public class ConnectDialog extends MageDialog { } }//GEN-LAST:event_jButton1ActionPerformed - private void jProxySettingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jProxySettingsButtonActionPerformed PreferencesDialog.main(new String[]{PreferencesDialog.OPEN_CONNECTION_TAB}); }//GEN-LAST:event_jProxySettingsButtonActionPerformed @@ -691,54 +687,54 @@ public class ConnectDialog extends MageDialog { }//GEN-LAST:event_btnFind2findPublicServerActionPerformed - private void connectXmageus(java.awt.event.ActionEvent evt) { - String serverAddress = "xmage.us"; + private void connectXmageus(java.awt.event.ActionEvent evt) { + String serverAddress = "vapormtgserver.com"; 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 doFastFlagSearch(){ + private void doFastFlagSearch() { Choice choice = new ChoiceImpl(false); // collect data from country combobox String[name][code] Map choiceItems = new LinkedHashMap<>(); - DefaultComboBoxModel flagModel = (DefaultComboBoxModel)cbFlag.getModel(); + DefaultComboBoxModel flagModel = (DefaultComboBoxModel) cbFlag.getModel(); String[] flagItem; - - for(int i = 0; i < flagModel.getSize(); i++){ - flagItem = (String[])flagModel.getElementAt(i); + + for (int i = 0; i < flagModel.getSize(); i++) { + flagItem = (String[]) flagModel.getElementAt(i); choiceItems.put(flagItem[1], flagItem[0]); } - + choice.setKeyChoices(choiceItems); choice.setMessage("Select your country"); - + // current selection value restore String needSelectValue = null; - flagItem = (String[])flagModel.getSelectedItem(); - if (flagItem != null){ - needSelectValue = flagItem[1]; + flagItem = (String[]) flagModel.getSelectedItem(); + if (flagItem != null) { + needSelectValue = flagItem[1]; } // ask for new value PickChoiceDialog dlg = new PickChoiceDialog(); dlg.setWindowSize(300, 500); dlg.showDialog(choice, needSelectValue); - if(choice.isChosen()){ + if (choice.isChosen()) { flagItem = new String[2]; flagItem[0] = choice.getChoiceValue(); - flagItem[1] = choice.getChoiceKey(); - flagModel.setSelectedItem(flagItem); + flagItem[1] = choice.getChoiceKey(); + flagModel.setSelectedItem(flagItem); } } - + public String getServer() { return this.txtServer.getText(); } 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 981d926eabe..d28badf2f79 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -9,6 +9,8 @@ package mage.client.table; import java.awt.*; import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.beans.PropertyVetoException; import java.io.File; import java.text.DateFormat; @@ -316,6 +318,20 @@ public class TablesPanel extends javax.swing.JPanel { actionButton1 = new ButtonColumn(tableTables, openTableAction, tableTables.convertColumnIndexToView(TableTableModel.ACTION_COLUMN)); actionButton2 = new ButtonColumn(tableCompleted, closedTableAction, tableCompleted.convertColumnIndexToView(MatchesTableModel.COLUMN_ACTION)); // !!!! + addTableDoubleClickListener(tableTables, openTableAction); + addTableDoubleClickListener(tableCompleted, closedTableAction); + } + + private void addTableDoubleClickListener(JTable table, Action action) { + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + int row = table.rowAtPoint(e.getPoint()); + if (e.getClickCount() == 2 && row != -1) { + action.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "" + row)); + } + } + }); } public void cleanUp() { diff --git a/Mage.Client/src/main/java/mage/client/util/CardViewEDHPowerLevelComparator.java b/Mage.Client/src/main/java/mage/client/util/CardViewEDHPowerLevelComparator.java index f8175f95180..31239d1d953 100644 --- a/Mage.Client/src/main/java/mage/client/util/CardViewEDHPowerLevelComparator.java +++ b/Mage.Client/src/main/java/mage/client/util/CardViewEDHPowerLevelComparator.java @@ -11,7 +11,7 @@ import mage.view.CardView; */ public class CardViewEDHPowerLevelComparator implements Comparator { - public int getPowerLevel(CardView card) { + private int getPowerLevel(CardView card) { int thisMaxPower = 0; @@ -306,7 +306,7 @@ public class CardViewEDHPowerLevelComparator implements Comparator { thisMaxPower = Math.max(thisMaxPower, 1); } - if (card.getCardTypes().contains("Plainswalker")) { + if (card.isPlanesWalker()) { if (card.getName().toLowerCase(Locale.ENGLISH).equals("jace, the mind sculptor")) { thisMaxPower = Math.max(thisMaxPower, 6); } @@ -509,7 +509,7 @@ public class CardViewEDHPowerLevelComparator implements Comparator { @Override public int compare(CardView o1, CardView o2) { - return Integer.valueOf(getPowerLevel(o1)).compareTo(getPowerLevel(o2)); + return Integer.compare(getPowerLevel(o1), getPowerLevel(o2)); } } diff --git a/Mage.Client/src/main/java/mage/client/util/object/SaveObjectUtil.java b/Mage.Client/src/main/java/mage/client/util/object/SaveObjectUtil.java index c319f27b5bd..b3b8673ebd8 100644 --- a/Mage.Client/src/main/java/mage/client/util/object/SaveObjectUtil.java +++ b/Mage.Client/src/main/java/mage/client/util/object/SaveObjectUtil.java @@ -57,6 +57,7 @@ public final class SaveObjectUtil { String time = now(DATE_PATTERN); File f = new File("income" + File.separator + name + '_' + time + ".save"); if (!f.exists()) { + f.getParentFile().mkdirs(); f.createNewFile(); } oos = new ObjectOutputStream(new FileOutputStream(f)); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java index 7a8695255ac..1f972175ebb 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java @@ -37,6 +37,7 @@ import java.util.regex.Pattern; import java.util.stream.IntStream; import javax.imageio.ImageIO; import javax.swing.*; + import mage.cards.repository.ExpansionRepository; import mage.client.MageFrame; import mage.client.constants.Constants; @@ -56,6 +57,8 @@ import org.apache.batik.util.SVGConstants; import org.apache.log4j.Logger; import org.mage.plugins.card.utils.CardImageUtils; +import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; + public final class ManaSymbols { private static final Logger LOGGER = Logger.getLogger(ManaSymbols.class); @@ -79,21 +82,59 @@ public final class ManaSymbols { withoutSymbols.add("MPRP"); } + private static final Map setImagesExist = new HashMap<>(); private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}"); - + private static final String[] symbols = new String[]{"0", "1", "10", "11", "12", "15", "16", "2", "3", "4", "5", "6", "7", "8", "9", - "B", "BG", "BR", "BP", "2B", - "G", "GU", "GW", "GP", "2G", - "R", "RG", "RW", "RP", "2R", - "S", "T", - "U", "UB", "UR", "UP", "2U", - "W", "WB", "WU", "WP", "2W", - "X", "C", "E"}; + "B", "BG", "BR", "BP", "2B", + "G", "GU", "GW", "GP", "2G", + "R", "RG", "RW", "RP", "2R", + "S", "T", + "U", "UB", "UR", "UP", "2U", + "W", "WB", "WU", "WP", "2W", + "X", "C", "E"}; private static final JLabel labelRender = new JLabel(); // render mana text + private static String getSvgPathToCss() { + return getImagesDir() + File.separator + "temp" + File.separator + "batic-svg-settings.css"; + } + + private static void prepareSvg(Boolean forceToCreateCss) { + File f = new File(getSvgPathToCss()); + + if (forceToCreateCss || !f.exists()) { + + // Rendering hints can't be set programatically, so + // we override defaults with a temporary stylesheet. + // These defaults emphasize quality and precision, and + // are more similar to the defaults of other SVG viewers. + // SVG documents can still override these defaults. + String css = "svg {" + + "shape-rendering: geometricPrecision;" + + "text-rendering: geometricPrecision;" + + "color-rendering: optimizeQuality;" + + "image-rendering: optimizeQuality;" + + "}"; + + FileWriter w = null; + try { + f.getParentFile().mkdirs(); + f.createNewFile(); + w = new FileWriter(f); + w.write(css); + } catch (Throwable e) { + LOGGER.error("Can't create css file for svg", e); + } finally { + StreamUtils.closeQuietly(w); + } + } + } + public static void loadImages() { + LOGGER.info("Loading symbols..."); + // TODO: delete files rename jpg->gif (it was for backward compatibility for one of the old version?) renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.SMALL)); renameSymbols(getResourceSymbolsPath(ResourceSymbolSize.MEDIUM)); @@ -101,6 +142,9 @@ public final class ManaSymbols { //renameSymbols(getSymbolsPath(ResourceSymbolSize.SVG)); // not need // TODO: remove medium sets files to "medium" folder like symbols above? + // prepare svg settings + prepareSvg(true); + // preload symbol images loadSymbolImages(15); loadSymbolImages(25); @@ -171,7 +215,7 @@ public final class ManaSymbols { } catch (Exception e) { } } - + // generate small size try { File file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM)); @@ -181,7 +225,7 @@ public final class ManaSymbols { String pathRoot = getResourceSetsPath(ResourceSetSize.SMALL) + set; for (String code : codes) { File newFile = new File(pathRoot + '-' + code + ".png"); - if(!(MageFrame.isSkipSmallSymbolGenerationForExisting() && newFile.exists())){// skip if option enabled and file already exists + if (!(MageFrame.isSkipSmallSymbolGenerationForExisting() && newFile.exists())) {// skip if option enabled and file already exists file = new File(getResourceSetsPath(ResourceSetSize.MEDIUM) + set + '-' + code + ".png"); if (file.exists()) { continue; @@ -243,26 +287,9 @@ public final class ManaSymbols { final BufferedImage[] imagePointer = new BufferedImage[1]; - // Rendering hints can't be set programatically, so - // we override defaults with a temporary stylesheet. - // These defaults emphasize quality and precision, and - // are more similar to the defaults of other SVG viewers. - // SVG documents can still override these defaults. - String css = "svg {" - + "shape-rendering: geometricPrecision;" - + "text-rendering: geometricPrecision;" - + "color-rendering: optimizeQuality;" - + "image-rendering: optimizeQuality;" - + "}"; - - File cssFile = File.createTempFile("batik-default-override-", ".css"); - FileWriter w = null; - try { - w = new FileWriter(cssFile); - w.write(css); - } finally { - StreamUtils.closeQuietly(w); - } + // css settings for svg + prepareSvg(false); + File cssFile = new File(getSvgPathToCss()); TranscodingHints transcoderHints = new TranscodingHints(); @@ -275,7 +302,7 @@ public final class ManaSymbols { shadowY = 2 * Math.round(1f / 16f * resizeToHeight); resizeToWidth = resizeToWidth - shadowX; resizeToHeight = resizeToHeight - shadowY; - }; + } if (resizeToWidth > 0) { transcoderHints.put(ImageTranscoder.KEY_WIDTH, (float) resizeToWidth); //your image width @@ -311,8 +338,6 @@ public final class ManaSymbols { t.transcode(input, null); } catch (Exception e) { throw new IOException("Couldn't convert svg file: " + svgFile + " , reason: " + e.getMessage()); - } finally { - cssFile.delete(); } BufferedImage originImage = imagePointer[0]; @@ -432,10 +457,11 @@ public final class ManaSymbols { // priority: SVG -> GIF // gif remain for backward compatibility - //boolean fileErrors = false; + int[] iconErrors = new int[2]; // 0 - svg, 1 - gif + AtomicBoolean fileErrors = new AtomicBoolean(false); Map sizedSymbols = new ConcurrentHashMap<>(); - IntStream.range(0, symbols.length).parallel().forEach(i-> { + IntStream.range(0, symbols.length).parallel().forEach(i -> { String symbol = symbols[i]; BufferedImage image = null; File file; @@ -448,7 +474,8 @@ public final class ManaSymbols { // gif if (image == null) { - //LOGGER.info("SVG symbol can't be load: " + file.getPath()); + + iconErrors[0] += 1; // svg fail file = getSymbolFileNameAsGIF(symbol, size); if (file.exists()) { @@ -460,11 +487,27 @@ public final class ManaSymbols { if (image != null) { sizedSymbols.put(symbol, image); } else { + iconErrors[1] += 1; // gif fail fileErrors.set(true); - LOGGER.warn("SVG or GIF symbol can't be load: " + symbol); } }); + // total errors + String errorInfo = ""; + if (iconErrors[0] > 0) { + errorInfo += "SVG fails - " + iconErrors[0]; + } + if (iconErrors[1] > 0) { + if (!errorInfo.isEmpty()) { + errorInfo += ", "; + } + errorInfo += "GIF fails - " + iconErrors[1]; + } + + if (!errorInfo.isEmpty()) { + LOGGER.warn("Symbols can't be load for size " + size + ": " + errorInfo); + } + manaImages.put(size, sizedSymbols); return !fileErrors.get(); } @@ -563,8 +606,8 @@ public final class ManaSymbols { public static void draw(Graphics g, String manaCost, int x, int y, int symbolWidth, Color symbolsTextColor, int symbolMarginX) { if (!manaImages.containsKey(symbolWidth)) { loadSymbolImages(symbolWidth); - } - + } + // TODO: replace with jlabel render (look at table rendere)? /* @@ -614,7 +657,7 @@ public final class ManaSymbols { return; } - manaCost = manaCost.replace("\\", ""); + manaCost = manaCost.replace("\\", ""); manaCost = UI.getDisplayManaCost(manaCost); StringTokenizer tok = new StringTokenizer(manaCost, " "); while (tok.hasMoreTokens()) { @@ -739,7 +782,7 @@ public final class ManaSymbols { replaced = REPLACE_SYMBOLS_PATTERN.matcher(replaced).replaceAll( "$1$2 message = properties.property("message"); @@ -98,6 +98,36 @@ public class DownloadJob extends AbstractLaternaBean { this.message.setValue(message); } + /** + * Inner prepare cycle from new to working + */ + public void doPrepareAndStartWork() { + if (this.state.getValue() != State.NEW) { + setError("Can't call prepare at this point."); + return; + } + + this.state.setValue(State.PREPARING); + + try { + onPreparing(); + } catch (Exception e) { + setError("Prepare error: " + e.getMessage(), e); + return; + } + + // change to working state on good prepare call + this.state.setValue(State.WORKING); + } + + + /** + * Prepare code to override in custom download tasks (it's calls before work start) + */ + public void onPreparing() throws Exception { + return; + } + /** * Sets the job's message. * @@ -131,6 +161,10 @@ public class DownloadJob extends AbstractLaternaBean { return source; } + public void setSource(Source source) { + this.source = source; + } + public Destination getDestination() { return destination; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/Downloader.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/Downloader.java index 4b71a8d16c0..497ee62d62b 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/Downloader.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/Downloader.java @@ -60,6 +60,7 @@ public class Downloader extends AbstractLaternaBean implements Disposable { for (DownloadJob j : jobs) { switch (j.getState()) { case NEW: + case PREPARING: case WORKING: j.setState(State.ABORTED); } @@ -82,8 +83,11 @@ public class Downloader extends AbstractLaternaBean implements Disposable { } public void add(DownloadJob job) { + if (job.getState() == State.PREPARING) { + throw new IllegalArgumentException("Job already preparing"); + } if (job.getState() == State.WORKING) { - throw new IllegalArgumentException("Job already running"); + throw new IllegalArgumentException("Job already working"); } if (job.getState() == State.FINISHED) { throw new IllegalArgumentException("Job already finished"); @@ -106,13 +110,22 @@ public class Downloader extends AbstractLaternaBean implements Disposable { @Override public void onMessage(DownloadJob job) { - //the job won't be processed by multiple threads + + // start to work + // the job won't be processed by multiple threads synchronized (job) { if (job.getState() != State.NEW) { return; } - job.setState(State.WORKING); + + job.doPrepareAndStartWork(); + + if (job.getState() != State.WORKING) { + return; + } } + + // download and save data try { Source src = job.getSource(); Destination dst = job.getDestination(); 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 6d695696142..df290687c19 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 @@ -8,7 +8,6 @@ import java.io.IOException; import java.util.HashMap; /** - * * @author spjspj */ public enum AltMtgOnlTokensImageSource implements CardImageSource { @@ -60,7 +59,7 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { return null; } @@ -122,7 +121,7 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { if (copyUrlToImage == null) { setupLinks(); } @@ -139,12 +138,12 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } return -1; } - + @Override public boolean isTokenSource() { return true; } - + @Override public void doPause(String httpImageUrl) { } 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 e49c334a1c2..f2d0fabf753 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 @@ -9,9 +9,9 @@ import org.mage.plugins.card.images.CardDownloadData; */ public interface CardImageSource { - String generateURL(CardDownloadData card) throws Exception; + CardImageUrls generateURL(CardDownloadData card) throws Exception; - String generateTokenUrl(CardDownloadData card) throws Exception; + CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception; String getNextHttpImageUrl(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java new file mode 100644 index 00000000000..1176ad3feda --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java @@ -0,0 +1,59 @@ +package org.mage.plugins.card.dl.sources; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author JayDi85 + */ +public class CardImageUrls { + + public String baseUrl; + public List alternativeUrls; + + public CardImageUrls() { + this.baseUrl = null; + this.alternativeUrls = new ArrayList<>(); + } + + public CardImageUrls(String baseUrl) { + this(baseUrl, null); + } + + public CardImageUrls(String baseUrl, String alternativeUrl) { + this(); + + this.baseUrl = baseUrl; + + if (alternativeUrl != null && !alternativeUrl.isEmpty()) { + this.alternativeUrls.add(alternativeUrl); + } + } + + public List getDownloadList() { + List downloadUrls = new ArrayList<>(); + + if (this.baseUrl != null && !this.baseUrl.isEmpty()) { + downloadUrls.add(this.baseUrl); + } + + // no needs in base url duplicate + if (this.alternativeUrls != null) { + for (String url : this.alternativeUrls) { + if (!url.equals(this.baseUrl)) { + downloadUrls.add(url); + } + } + } + + return downloadUrls; + } + + public void addAlternativeUrl(String url) { + if (url != null && !url.isEmpty()) { + this.alternativeUrls.add(url); + } else { + throw new IllegalArgumentException(); + } + } +} 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 new file mode 100644 index 00000000000..0fc6561b978 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java @@ -0,0 +1,255 @@ +package org.mage.plugins.card.dl.sources; + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +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 { + + instance; + + private Set supportedSets = new LinkedHashSet(); + private Set missingCards = new LinkedHashSet(); + HashMap singleLinks = null; + boolean loadedFromDialog = false; + boolean viewMissingCards = true; + HashMap singleLinksDone = null; + private static int maxTimes = 2; + + @Override + public String getSourceName() { + return ""; + } + + @Override + public float getAverageSize() { + return 260.7f; + } + + @Override + public String getNextHttpImageUrl() { + if (singleLinks == null) { + setupLinks(); + } + + for (String key : singleLinksDone.keySet()) { + if (singleLinksDone.get(key) < maxTimes) { + singleLinksDone.put(key, maxTimes); + return key; + } + } + if (maxTimes < 2) { + maxTimes++; + } + for (String key : singleLinksDone.keySet()) { + if (singleLinksDone.get(key) < maxTimes) { + singleLinksDone.put(key, maxTimes); + return key; + } + } + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + String copy = httpImageUrl; + if (copy != null) { + return singleLinks.get(copy); + } + return null; + } + + @Override + public CardImageUrls generateURL(CardDownloadData card) throws Exception { + if (singleLinks == null) { + setupLinks(); + } + String url = singleLinks.get(card.getSet() + "/" + card.getName()); + if (url != null && url.length() > 0) { + return new CardImageUrls(url); + } + url = singleLinks.get(card.getSet() + "/" + card.getName() + "." + card.getCollectorId()); + if (url != null && url.length() > 0) { + return new CardImageUrls(url); + } + return null; + } + + int ls_size_mc = 0; + int ls_size_ss = 0; + int ls_size_sl = 0; + int num_nos = 0; + + private boolean isDifferent() { + boolean isdiff = false; + if (ls_size_mc != missingCards.size()) { + ls_size_mc = missingCards.size(); + isdiff = true; + } + if (ls_size_ss != supportedSets.size()) { + ls_size_ss = supportedSets.size(); + isdiff = true; + } + if (ls_size_sl != singleLinks.size()) { + ls_size_sl = singleLinks.size(); + isdiff = true; + } + num_nos++; + if (num_nos > 2) { + num_nos = 0; + isdiff = true; + } + return isdiff; + } + + private void setupLinks() { + if (singleLinks != null && loadedFromDialog) { + if (!viewMissingCards) { + if (isDifferent() && JOptionPane.showConfirmDialog(null, + "View your missing cards and reset the list of card images to download again?", + "View missing cards (found " + missingCards.size() + ") / Reset URLs to download ", JOptionPane.YES_NO_OPTION) + == JOptionPane.YES_OPTION) { + viewMissingCards = true; + singleLinks.clear(); + loadedFromDialog = false; + supportedSets.clear(); + } else { + return; + } + } + if (!(viewMissingCards && missingCards.size() > 0)) { + return; + } + } + singleLinks = new HashMap<>(); + loadedFromDialog = false; + + final CopyPasteImageSourceDialog dialog = new CopyPasteImageSourceDialog(); + dialog.pack(); + int count = 0; + if (viewMissingCards && missingCards.size() > 0 && singleLinks.size() == 0) { + viewMissingCards = false; + String displayMissingCardsStr = "Up to the first 20 cards are:\n"; + String missingCardsStr = ""; + if (this.missingCards != null) { + for (String card : this.missingCards) { + if (count < 20) { + displayMissingCardsStr = displayMissingCardsStr + card + "\n"; + } + missingCardsStr = missingCardsStr + card + "\n"; + + count++; + } + } + StringSelection stringSelection = new StringSelection(missingCardsStr); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(stringSelection, null); + + if (isDifferent() && JOptionPane.showConfirmDialog(null, + displayMissingCardsStr + "\n\nReset the list again?\n(NB: The full list has been copied to the clipboard)", + "Your missing cards (found " + missingCards.size() + "): ", JOptionPane.YES_NO_OPTION) + == JOptionPane.YES_OPTION) { + viewMissingCards = true; + singleLinks.clear(); + loadedFromDialog = false; + supportedSets.clear(); + } else { + return; + } + } + dialog.setVisible(true); + String[] lines = dialog.getPastedData().split(System.getProperty("line.separator")); + + for (String line : lines) { + // Break into >> "\1", "\2" + Pattern regex = Pattern.compile("\\s*\"(.*?)/(.*?)\"\\s*,\\s*\"(.*?)\""); + Matcher regexMatcher = regex.matcher(line); + while (regexMatcher.find()) { + String setCode = regexMatcher.group(1); + String cardName = regexMatcher.group(2); + String imageURL = regexMatcher.group(3); + supportedSets.add(setCode); + singleLinks.put(setCode + "/" + cardName, imageURL); + isDifferent(); + } + } + + loadedFromDialog = true; + if (lines.length == 0) { + loadedFromDialog = false; + viewMissingCards = true; + } + } + + @Override + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { + try { + return generateURL(card); + } catch (Exception ex) { + } + return null; + } + + @Override + public int getTotalImages() { + if (singleLinks == null) { + setupLinks(); + } + if (singleLinks != null) { + return singleLinks.size(); + } + return -1; + } + + @Override + public boolean isTokenSource() { + return false; + } + + @Override + public ArrayList getSupportedSets() { + setupLinks(); + ArrayList supportedSetsCopy = new ArrayList<>(); + if (supportedSets.size() == 0) { + for (String setCode : Sets.getInstance().keySet()) { + supportedSets.add(setCode); + } + } + + supportedSetsCopy.addAll(supportedSets); + return supportedSetsCopy; + } + + @Override + public void doPause(String httpImageUrl) { + } + + @Override + public boolean isImageProvided(String setCode, String cardName) { + missingCards.add(setCode + "/" + cardName); + + if (singleLinks != null) { + return singleLinks.containsKey(setCode + "/" + cardName) || singleLinks.containsKey(setCode + "/" + cardName + "-a"); + } + return false; + } + + @Override + public boolean isSetSupportedComplete(String setCode) { + return false; + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form new file mode 100644 index 00000000000..fe9fa3cf9bd --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.form @@ -0,0 +1,79 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java new file mode 100644 index 00000000000..b64d7cc8105 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSourceDialog.java @@ -0,0 +1,182 @@ +package org.mage.plugins.card.dl.sources; + +import mage.util.StreamUtils; + +import java.awt.*; +import java.awt.event.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Set; +import javax.swing.*; + +public class CopyPasteImageSourceDialog extends JDialog { + + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JEditorPane txtDeckList; + + private String tmpPath; + + public CopyPasteImageSourceDialog() { + initComponents(); + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + + buttonOK.addActionListener(e -> onOK()); + buttonCancel.addActionListener(e -> onCancel()); + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + + // Close on "ESC" + contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + private void onOK() { + BufferedWriter bw = null; + try { + File temp = File.createTempFile("import_images_from_url", ".txt"); + bw = new BufferedWriter(new FileWriter(temp)); + bw.write(txtDeckList.getText()); + tmpPath = temp.getPath(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + StreamUtils.closeQuietly(bw); + } + + dispose(); + } + + private void onCancel() { + dispose(); + } + + public String getTmpPath() { + return tmpPath; + } + + private void initComponents() { + contentPane = new JPanel(); + JPanel panel1 = new JPanel(); + JPanel panel2 = new JPanel(); + buttonOK = new JButton(); + buttonCancel = new JButton(); + JPanel panel3 = new JPanel(); + txtDeckList = new JEditorPane(); + + { + contentPane.setMinimumSize(new Dimension(540, 450)); + + contentPane.setBorder(new javax.swing.border.CompoundBorder( + new javax.swing.border.TitledBorder(new javax.swing.border.EmptyBorder(0, 0, 0, 0), + "Download Images from Copy/Pasted Text", javax.swing.border.TitledBorder.CENTER, + javax.swing.border.TitledBorder.TOP, new java.awt.Font("Dialog", java.awt.Font.PLAIN, 12), + java.awt.Color.BLACK), contentPane.getBorder())); + + contentPane.addPropertyChangeListener(e -> { + if ("border".equals(e.getPropertyName())) { + throw new RuntimeException(); + } + }); + + contentPane.addPropertyChangeListener(e -> { + if ("border".equals(e.getPropertyName())) { + throw new RuntimeException(); + } + }); + + contentPane.setLayout(new GridBagLayout()); + ((GridBagLayout) contentPane.getLayout()).columnWidths = new int[]{0, 0}; + ((GridBagLayout) contentPane.getLayout()).rowHeights = new int[]{0, 0, 0}; + ((GridBagLayout) contentPane.getLayout()).columnWeights = new double[]{0.01, 1.0E-4}; + ((GridBagLayout) contentPane.getLayout()).rowWeights = new double[]{0.01, 0.0, 1.0E-4}; + + { + panel1.setLayout(new GridBagLayout()); + ((GridBagLayout) panel1.getLayout()).columnWidths = new int[]{0, 0, 0}; + ((GridBagLayout) panel1.getLayout()).rowHeights = new int[]{0, 0}; + ((GridBagLayout) panel1.getLayout()).columnWeights = new double[]{0.0, 0.01, 1.0E-4}; + ((GridBagLayout) panel1.getLayout()).rowWeights = new double[]{0.01, 1.0E-4}; + + { + panel2.setLayout(new GridBagLayout()); + ((GridBagLayout) panel2.getLayout()).columnWidths = new int[]{0, 4, 0, 0}; + ((GridBagLayout) panel2.getLayout()).rowHeights = new int[]{0, 0}; + ((GridBagLayout) panel2.getLayout()).columnWeights = new double[]{0.01, 0.0, 0.01, 1.0E-4}; + ((GridBagLayout) panel2.getLayout()).rowWeights = new double[]{0.0, 1.0E-4}; + + //---- buttonOK ---- + buttonOK.setText("Download from URLs"); + panel2.add(buttonOK, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, + new Insets(0, 0, 0, 0), 0, 0)); + + //---- buttonCancel ---- + buttonCancel.setText("Cancel"); + panel2.add(buttonCancel, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, + new Insets(0, 0, 0, 0), 0, 0)); + } + panel1.add(panel2, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + } + contentPane.add(panel1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + + { + panel3.setLayout(new GridBagLayout()); + ((GridBagLayout) panel3.getLayout()).columnWidths = new int[]{0, 0}; + ((GridBagLayout) panel3.getLayout()).rowHeights = new int[]{0, 0}; + ((GridBagLayout) panel3.getLayout()).columnWeights = new double[]{0.0, 1.0E-4}; + ((GridBagLayout) panel3.getLayout()).rowWeights = new double[]{1.0, 1.0E-4}; + + txtDeckList.setMinimumSize(new Dimension(250, 400)); + txtDeckList.setPreferredSize(new Dimension(550, 400)); + + txtDeckList.setText("// Example follows. \nNB: **DELETE ALL TEXT AND GO SELECT THIS SOURCE AGAIN TO SEE THE NAMES CARDS YOU'RE MISSING IMAGES FOR!!!***\n\"SWS/Might of the Wild\", \"http://i.imgur.com/eNXOdxp.jpg\"\n\"PTC/Wolf of Devil's Breach\", \"https://img.scryfall.com/cards/large/en/psoi/192s.jpg\"\n\nExpected columns: Name of Card (Set Trigraph\\Name), URL of image\n\n\n"); + + JScrollPane txtScrollableDeckList = new JScrollPane(txtDeckList); + panel3.add(txtScrollableDeckList, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + } + contentPane.add(panel3, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 5, 0), 0, 0)); + } + } + + Set missingCards = null; + + public void addMissingCards(Set missingCards) { + this.missingCards = missingCards; + String missingCardsStr = ""; + boolean found = false; + if (this.missingCards != null) { + for (String card : this.missingCards) { + found = true; + missingCardsStr = missingCardsStr + card + "\n"; + } + } + if (found == false) { + missingCardsStr = "\n\nNote: Leave blank to see your missing card names!\n"; + } + txtDeckList.setText(txtDeckList.getText() + "\n\nYour missing card images are:\n" + missingCardsStr); + } + + public String getPastedData() { + return txtDeckList.getText(); + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java index 385204f822c..2d7de49b9b7 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java @@ -63,16 +63,16 @@ public class GathererSets implements Iterable { "POR", "P02", "PTK", "ARC", "DD3EVG", "W16", "W17", - //"APAC" -- gatherer do not have that set, scrly have PALP + //"APAC" -- gatherer do not have that set, scryfall has PALP //"ARENA" -- is't many set with different codes, not one "CLASH", "CP", "DD3GVL", "DPA", "EURO", "FNMP", "GPX", "GRC", "GUR", "H17", "JR", "MBP", "MGDC", "MLP", "MPRP", "MPS-AKH", "PTC", "S00", "S99", "SUS", "SWS", "UGIN", "UGL", "V10", "V17", "WMCQ", // need to fix - "H09", "PD2", "PD3", "UNH", "CM1", "E02", "V11", "A25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "DDT", "8EB", "9EB", "CHR" // ok + "H09", "PD2", "PD3", "UNH", "CM1", "V11", "A25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "8EB", "9EB", "CHR" // ok // current testing }; private static final String[] symbolsBasicWithMyth = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI", "DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN", - "DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT", + "DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT", "DDU", "ALA", "CON", "ARB", "ZEN", "WWK", "ROE", "SOM", "MBS", "NPH", @@ -90,8 +90,9 @@ public class GathererSets implements Iterable { "KLD", "AER", "AKH", "HOU", "XLN", "C17", - "RIX", "DOM", "M19", // not released - "E01" + "RIX", "DOM", "M19", + "E01", "CM2", "E02", + "GS1", "BBD", "C18" }; private static final String[] symbolsOnlyMyth = { @@ -176,7 +177,7 @@ public class GathererSets implements Iterable { CheckResult res = setsToDownload.get(searchCode); if (res != null) { - logger.error(String.format("Symbols: founded duplicated code: %s", searchCode)); + logger.error(String.format("Symbols: found duplicate code: %s", searchCode)); } else { res = new CheckResult(searchCode, foundedExp, haveCommon, haveUncommon, haveRare, haveMyth); setsToDownload.put(searchCode, res); @@ -189,7 +190,7 @@ public class GathererSets implements Iterable { } // checks for founded sets only - // to early to download + // too early to download if (!canDownloadTask) { Calendar c = Calendar.getInstance(); c.setTime(foundedExp.getReleaseDate()); 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 38bb08048a6..8d3e12236c2 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 @@ -8,11 +8,11 @@ import java.util.LinkedHashSet; 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 */ public enum GrabbagImageSource implements CardImageSource { @@ -48,7 +48,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { if (singleLinks == null) { setupLinks(); } @@ -63,7 +63,7 @@ public enum GrabbagImageSource implements CardImageSource { } if (url != null) { - return getSourceName(card, url) + url; + return new CardImageUrls(getSourceName(card, url) + url); } return null; } @@ -357,10 +357,81 @@ public enum GrabbagImageSource implements CardImageSource { singleLinks.put("SWS/Yoda, Jedi Master", "6arN1Hl.png"); singleLinks.put("SWS/Y-Wing", "aQQ5zwA.jpg"); singleLinks.put("SWS/Zam Wesell", "ToG0C1r.jpg"); + singleLinks.put("SWS/Astromech Droid", "v0TpHMh.jpg"); + singleLinks.put("SWS/Buried Ruin", "QkmIWYg.png"); + singleLinks.put("SWS/Flame Trooper", "RkY7KFJ.jpg"); + singleLinks.put("SWS/Force Stasis", "FavLrcY.jpg"); + singleLinks.put("SWS/Salvage Trader", "qGwk7Bn.jpg"); + singleLinks.put("SWS/Outer Rim Gang", "kEjKQGy.png"); + singleLinks.put("SWS/Rathtar", "CYhHRqF.png"); + singleLinks.put("SWS/Riot Trooper", "PusvaQB.jpg"); + singleLinks.put("SWS/Sins of the Father", "32YHTPB.jpg"); + singleLinks.put("SWS/Upsilon-class Shuttle", "Le3F3oW.jpg"); + singleLinks.put("SWS/Finn", "TU2LI2q.jpg"); + singleLinks.put("SWS/General Hux", "UpWfcV6.png"); + singleLinks.put("SWS/Poe Dameron", "v8i21dn.png"); + singleLinks.put("SWS/Rey", "7n5ZZFA.png"); + singleLinks.put("SWS/Kylo Ren", "fFzDMTz.png"); + singleLinks.put("SWS/TIE Striker", "6b5GDUQ.jpg"); + singleLinks.put("SWS/Bludgeoning Pain", "ap5k3Wl.jpg"); + singleLinks.put("SWS/Force Protection", "GrOQLHO.jpg"); + singleLinks.put("SWS/Gerrera's Revolutionary", "FQFE1Jt.jpg"); + singleLinks.put("SWS/Thermal Detonator", "gTPLM83.jpg"); + singleLinks.put("SWS/Hammerhead Corvette", "IlhOAGv.jpg"); + singleLinks.put("SWS/U-Wing", "FmoRCmG.jpg"); + singleLinks.put("SWS/Bor Gullet", "jXafYHX.jpg"); + singleLinks.put("SWS/Imperial Hovertank", "6X1wL4d.jpg"); + singleLinks.put("SWS/Occupation", "h4mmkA5.jpg"); + singleLinks.put("SWS/Resistance", "lbNhA59.jpg"); + singleLinks.put("SWS/Jyn Erso and Cassian Andor", "o0SCGiJ.jpg"); + singleLinks.put("SWS/Chirrut Imwe", "wgtXfUF.jpg"); + singleLinks.put("SWS/Director Krennic", "52PGsH5.jpg"); + singleLinks.put("SWS/Vader's Command", "7Lql6UT.jpg"); + singleLinks.put("SWS/Delay Tactic", "ubmzD1m.jpg"); + singleLinks.put("SWS/Resistance Bomber", "Sudfkd7.jpg"); + singleLinks.put("SWS/Mouse Droid", "oO0p8QE.jpg"); + singleLinks.put("SWS/First Order Dreadnought", "80pO9Cc.jpg"); + singleLinks.put("SWS/TIE Silencer", "7yeYIjX.jpg"); + singleLinks.put("SWS/Canto Bight Enforcer", "VKPQVsn.jpg"); + singleLinks.put("SWS/Cantonica Casino", "7LiSvy6.jpg"); + singleLinks.put("SWS/Fathier", "0oKquQp.jpg"); + singleLinks.put("SWS/Code Slice", "7uNASji.jpg"); + singleLinks.put("SWS/Captain Phasma", "LWujx1B.jpg"); + singleLinks.put("SWS/Force Telepathy", "e90hswX.jpg"); + singleLinks.put("SWS/Praetorian Trooper", "pjS1wyS.jpg"); + singleLinks.put("SWS/Supreme Leader Snoke", "eewWiKE.jpg"); + singleLinks.put("SWS/Sai Tok", "FVn29tT.jpg"); + singleLinks.put("SWS/Porg Nest", "8DnNZKc.jpg"); + singleLinks.put("SWS/Inspire", "7lIXhtd.jpg"); + singleLinks.put("SWS/Force Projection", "5EfOwyn.jpg"); + singleLinks.put("SWS/Luke Skywalker, the Last Jedi", "WMmQcyD.jpg"); + singleLinks.put("SWS/Vulptex", "30WeCkw.jpg"); + singleLinks.put("SWS/Glorious Charge", "yJwvKzk.jpg"); + singleLinks.put("SWS/Plains-520b", "Fx59r9J.jpg"); + singleLinks.put("SWS/Island-520a", "jIPpWp5.jpg"); + singleLinks.put("SWS/Conscription", "An01yAe.jpg"); + singleLinks.put("SWS/Afterburn", "2ydqSvT.jpg"); + singleLinks.put("SWS/Corellian Gunship", "mZdDQWH.jpg"); + singleLinks.put("SWS/Despair", "TLTddMI.jpg"); + singleLinks.put("SWS/Dryden Vos", "6LbtUzN.jpg"); + singleLinks.put("SWS/Droid Uprising", "aWuoxho.jpg"); + singleLinks.put("SWS/Gamble", "Hwzr60O.jpg"); + singleLinks.put("SWS/Han Solo, Scrumrat", "Hqj39dG.jpg"); + singleLinks.put("SWS/Mud Trooper", "af8JaDy.jpg"); + singleLinks.put("SWS/Enfys Nest", "pstVfQg.jpg"); + singleLinks.put("SWS/Kalevan Star Yacht", "nHmSizp.jpg"); + singleLinks.put("SWS/Maelstrom Blockade", "sUYT0pc.jpg"); + singleLinks.put("SWS/Range Trooper", "kXGvTkE.jpg"); + singleLinks.put("SWS/Tobias Beckett", "hzm6ilE.jpg"); + singleLinks.put("SWS/Underground Forum", "FH2pRfU.jpg"); + singleLinks.put("SWS/Chewbacca, the Beast", "Zb5TitZ.jpg"); + // Emblems singleLinks.put("SWS/Emblem Obi-Wan Kenobi", "Qyc10aT.png"); singleLinks.put("SWS/Aurra Sing", "BLWbVJC.png"); singleLinks.put("SWS/Yoda", "zH0sYxg.png"); + singleLinks.put("SWS/Emblem Luke Skywalker", "kHELZDJ.jpg"); + // Tokens singleLinks.put("SWS/Ewok", "N2MvJyr.png"); singleLinks.put("SWS/B-Wing", "oH62AUD.png"); @@ -372,10 +443,12 @@ public enum GrabbagImageSource implements CardImageSource { singleLinks.put("SWS/Royal Guard", "9tqE8vL.png"); singleLinks.put("SWS/Tusken Raider", "gPMiSmP.png"); singleLinks.put("SWS/Droid", "4PRrWFF.png"); + singleLinks.put("SWS/Trooper 2", "tcxvGOn.jpg"); + singleLinks.put("SWS/Porg", "HBjt1A3.jpg"); } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { try { return generateURL(card); } catch (Exception ex) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java index 4099643d53d..dfee0c9a469 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java @@ -6,12 +6,12 @@ import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; + import mage.client.dialog.PreferencesDialog; import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.utils.CardImageUtils; /** - * * @author North */ public enum MagicCardsImageSource implements CardImageSource { @@ -202,13 +202,15 @@ public enum MagicCardsImageSource implements CardImageSource { add("C17"); add("XLN"); add("DDT"); + add("DDU"); add("IMA"); add("E02"); add("V17"); add("UST"); -// add("RIX"); -// add("A25"); -// add("DOM"); + add("RIX"); + add("A25"); + add("DOM"); +// add("CM2"); // add("M19"); } }; @@ -263,7 +265,8 @@ public enum MagicCardsImageSource implements CardImageSource { put("DDQ", "duel-decks-blessed-vs-cursed"); put("DDR", "duel-decks-nissa-vs-ob-nixilis"); put("DDS", "duel-decks-mind-vs-might"); - put("DDS", "duel-decks-merfolk-vs-goblin"); + put("DDT", "duel-decks-merfolk-vs-goblin"); + put("DDU", "duel-decks-elves-vs-inventors"); put("DGM", "dragons-maze"); put("DKA", "dark-ascension"); put("DRB", "from-the-vault-dragons"); @@ -339,6 +342,7 @@ public enum MagicCardsImageSource implements CardImageSource { put("WWK", "worldwake"); put("ZEN", "zendikar"); } + private static final long serialVersionUID = 1L; }; @@ -358,7 +362,7 @@ public enum MagicCardsImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -386,11 +390,11 @@ public enum MagicCardsImageSource implements CardImageSource { } url.append(".jpg"); - return url.toString(); + return new CardImageUrls(url.toString()); } @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { String name = card.getName(); // add type to name if it's not 0 if (card.getType() > 0) { @@ -403,7 +407,7 @@ public enum MagicCardsImageSource implements CardImageSource { } else { set += '-' + card.getSet(); } - return "http://magiccards.info/extras/token/" + set + '/' + name + ".jpg"; + return new CardImageUrls("http://magiccards.info/extras/token/" + set + '/' + name + ".jpg"); } @Override 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 9a754e819b3..c2ddfcc9874 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 @@ -8,10 +8,10 @@ import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; + import org.mage.plugins.card.images.CardDownloadData; /** - * * @author Pete Rossi */ public enum MagidexImageSource implements CardImageSource { @@ -189,7 +189,6 @@ public enum MagidexImageSource implements CardImageSource { supportedSets.add("CN2"); supportedSets.add("DDR"); supportedSets.add("KLD"); - supportedSets.add("MPS"); // supportedSets.add("PZ2"); // Treasure Chests supportedSets.add("C16"); supportedSets.add("PCA"); @@ -208,11 +207,15 @@ public enum MagidexImageSource implements CardImageSource { supportedSets.add("IMA"); supportedSets.add("E02"); supportedSets.add("V17"); -// supportedSets.add("UST"); -// supportedSets.add("RIX"); -// supportedSets.add("A25"); -// supportedSets.add("DOM"); -// supportedSets.add("M19"); + supportedSets.add("UST"); + supportedSets.add("DDU"); + supportedSets.add("RIX"); + supportedSets.add("A25"); + supportedSets.add("DOM"); + supportedSets.add("CM2"); + supportedSets.add("M19"); + //supportedSets.add("BBD"); + //supportedSets.add("C18"); } @Override @@ -231,7 +234,7 @@ public enum MagidexImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String cardDownloadName = card.getDownloadName().toLowerCase(Locale.ENGLISH); String cardSet = card.getSet(); @@ -245,7 +248,7 @@ public enum MagidexImageSource implements CardImageSource { // This will properly escape the url URI uri = new URI("http", "magidex.com", "/extstatic/card/" + formatSetName(cardSet) + '/' + cardDownloadName + ".jpg", null, null); - return uri.toASCIIString(); + return new CardImageUrls(uri.toASCIIString()); } private String formatSetName(String setName) { @@ -262,7 +265,7 @@ public enum MagidexImageSource implements CardImageSource { }; @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { return null; } 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 d24ba0c4994..f5104a22269 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 @@ -2,14 +2,12 @@ package org.mage.plugins.card.dl.sources; import java.util.Locale; + import org.mage.plugins.card.images.CardDownloadData; /** * Site was shutdown by wizards Feb. 2015 * - * - * - * * @author LevelX2 */ public enum MtgImageSource implements CardImageSource { @@ -32,7 +30,7 @@ public enum MtgImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -59,11 +57,11 @@ public enum MtgImageSource implements CardImageSource { } url.append(".jpg"); - return url.toString(); + return new CardImageUrls(url.toString()); } @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { return 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 4b2bf849dbf..9d82cbb425c 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 @@ -3,11 +3,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; /** - * * @author spjspj */ public enum MtgOnlTokensImageSource implements CardImageSource { @@ -59,7 +59,7 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { return null; } @@ -324,7 +324,7 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { if (copyUrlToImage == null) { setupLinks(); } 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 0b9f43a059e..fbd58ee16cd 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,4 +1,3 @@ - package org.mage.plugins.card.dl.sources; import java.io.BufferedReader; @@ -28,7 +27,6 @@ import org.jsoup.select.Elements; import org.mage.plugins.card.images.CardDownloadData; /** - * * @author LevelX2 */ public enum MythicspoilerComSource implements CardImageSource { @@ -232,6 +230,9 @@ public enum MythicspoilerComSource implements CardImageSource { supportedSets.add("RIX"); supportedSets.add("DOM"); supportedSets.add("BBD"); + supportedSets.add("M19"); +// supportedSets.add("C18"); +// supportedSets.add("CM2"); sets = new LinkedHashMap<>(); setsAliases = new HashMap<>(); @@ -390,7 +391,7 @@ public enum MythicspoilerComSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -409,11 +410,11 @@ public enum MythicspoilerComSource implements CardImageSource { .replaceAll(",", "") .replaceAll("/", ""); String link = setLinks.get(searchName); - return link; + return new CardImageUrls(link); } @Override - public String generateTokenUrl(CardDownloadData card + public CardImageUrls generateTokenUrl(CardDownloadData card ) { return 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 f38b1a80e6f..6dbc42c5c75 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 @@ -6,19 +6,33 @@ import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; +import mage.client.dialog.PreferencesDialog; import org.mage.plugins.card.images.CardDownloadData; /** * @author Quercitron, JayDi85 - * */ public enum ScryfallImageSource implements CardImageSource { instance; private final Set supportedSets; + private final Map languageAliases; ScryfallImageSource() { + // https://scryfall.com/docs/api/languages + languageAliases = new HashMap<>(); + languageAliases.put("en", "en"); + languageAliases.put("es", "es"); + languageAliases.put("jp", "ja"); + languageAliases.put("it", "it"); + languageAliases.put("fr", "fr"); + languageAliases.put("cn", "zhs"); // Simplified Chinese + languageAliases.put("de", "de"); + languageAliases.put("ko", "ko"); + languageAliases.put("pt", "pt"); + languageAliases.put("ru", "ru"); + supportedSets = new LinkedHashSet<>(); // supportedSets.add("PTC"); // supportedSets.add("LEA"); @@ -205,40 +219,62 @@ public enum ScryfallImageSource implements CardImageSource { 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("M19"); - + supportedSets.add("C18"); + supportedSets.add("CM2"); + supportedSets.add("M19"); + supportedSets.add("GS1"); } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { + + String preferredLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); + String defaultCode = "en"; + String localizedCode = languageAliases.getOrDefault(preferredLanguage, defaultCode); + // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image + + // TODO: do not use API at all? It's can help with scryfall request limits (1 request instead 2) + String baseUrl = null; + String alternativeUrl = null; // special card number like "103a" already compatible - if (card.isCollectorIdWithStr()) { - return "https://img.scryfall.com/cards/large/en/" + formatSetName(card.getSet()) + "/" + if (baseUrl == null && card.isCollectorIdWithStr()) { + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + ".jpg"; + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + card.getCollectorId() + ".jpg"; } - // double faced cards do not supporte by API (need direct link for img) + // 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 (card.isTwoFacedCard()) { - return "https://img.scryfall.com/cards/large/en/" + formatSetName(card.getSet()) + "/" + if (baseUrl == null && card.isTwoFacedCard()) { + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; } // basic cards by api call (redirect to img link) - // example: https://api.scryfall.com/cards/xln/121?format=image - return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" - + card.getCollectorId() + "?format=image"; + // example: https://api.scryfall.com/cards/xln/121/en?format=image + if (baseUrl == null) { + baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + "/" + localizedCode + "?format=image"; + alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + "/" + defaultCode + "?format=image"; + } + + return new CardImageUrls(baseUrl, alternativeUrl); } @Override - public String generateTokenUrl(CardDownloadData card) throws Exception { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception { return null; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java index e90d1cf9c5d..483bb27e866 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallSymbolsSource.java @@ -9,8 +9,13 @@ import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import mage.MageException; import mage.util.StreamUtils; +import org.jsoup.select.Elements; import org.mage.plugins.card.dl.DownloadJob; +import org.mage.plugins.card.utils.CardImageUtils; + +import javax.swing.text.Document; import static org.mage.card.arcane.ManaSymbols.getSymbolFileNameAsSVG; import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; @@ -18,14 +23,14 @@ import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; // TODO: add force to download symbols (rewrite exist files) /** - * - * @author jaydi85@gmail.com - * + * @author JayDi85 */ public class ScryfallSymbolsSource implements Iterable { - static final String SOURCE_URL = "https://assets.scryfall.com/assets/scryfall.css"; // search css-file on https://scryfall.com/docs/api/colors + //static final String SOURCE_URL = "https://assets.scryfall.com/assets/scryfall.css"; // old version with direct css-file on https://scryfall.com/docs/api/colors + static final String CSS_SOURCE_URL = "https://scryfall.com/docs/api/colors"; + static final String CSS_SOURCE_SELECTOR = "link[rel=stylesheet]"; // static final String STATE_PROP_NAME = "state"; static final String DOWNLOAD_TEMP_FILE = getImagesDir() + File.separator + "temp" + File.separator + "scryfall-symbols-source.txt"; @@ -55,21 +60,21 @@ public class ScryfallSymbolsSource implements Iterable { return jobs.iterator(); } - private void parseData(String sourcePath){ + private void parseData(String sourcePath) { String sourceData = ""; try { sourceData = new String(Files.readAllBytes(Paths.get(sourcePath))); - }catch (IOException e) { + } catch (IOException e) { LOGGER.error("Can't open file to parse data: " + sourcePath + " , reason: " + e.getMessage()); } // gen symbols list ArrayList allMageSymbols = new ArrayList<>(); - for(int i = 0; i < SYMBOLS_LIST.length; i++){ + for (int i = 0; i < SYMBOLS_LIST.length; i++) { allMageSymbols.add(SYMBOLS_LIST[i]); } - for(Integer i = SYMBOLS_NUMBER_START; i <= SYMBOLS_NUMBER_END; i++){ + for (Integer i = SYMBOLS_NUMBER_START; i <= SYMBOLS_NUMBER_END; i++) { allMageSymbols.add(String.valueOf(SYMBOLS_NUMBER_START + i)); } @@ -88,23 +93,22 @@ public class ScryfallSymbolsSource implements Iterable { // dirs maker File dir = getSymbolFileNameAsSVG("W").getParentFile(); - if(!dir.exists()){ + if (!dir.exists()) { dir.mkdirs(); } // decode and save data (only if not exist) - for(String needCode: allMageSymbols){ + for (String needCode : allMageSymbols) { String searchCode = needCode.replace("/", ""); - if(!foundedData.containsKey(searchCode)) - { + if (!foundedData.containsKey(searchCode)) { LOGGER.warn("Can't found symbol code from scryfall: " + searchCode); continue; } File destFile = getSymbolFileNameAsSVG(searchCode); - if (destFile.exists() && (destFile.length() > 0)){ + if (destFile.exists() && (destFile.length() > 0)) { continue; } FileOutputStream stream = null; @@ -118,7 +122,7 @@ public class ScryfallSymbolsSource implements Iterable { stream.write(fileData); LOGGER.info("New svg symbol downloaded: " + needCode); - } catch (Exception e) { + } catch (Exception e) { LOGGER.error("Can't decode svg icon and save to file: " + destFile.getPath() + ", reason: " + e.getMessage()); } finally { StreamUtils.closeQuietly(stream); @@ -127,23 +131,26 @@ public class ScryfallSymbolsSource implements Iterable { } - private class ScryfallSymbolsDownloadJob extends DownloadJob{ + private class ScryfallSymbolsDownloadJob extends DownloadJob { + + private String cssUrl = ""; // need to find url from colors page https://scryfall.com/docs/api/colors // listener for data parse after download complete - private class ScryDownloadOnFinishedListener implements PropertyChangeListener { + private class ScryfallDownloadOnFinishedListener implements PropertyChangeListener { private String downloadedFile; - public ScryDownloadOnFinishedListener(String ADestFile){ + public ScryfallDownloadOnFinishedListener(String ADestFile) { this.downloadedFile = ADestFile; } @Override public void propertyChange(PropertyChangeEvent evt) { - if (!evt.getPropertyName().equals(STATE_PROP_NAME)){ + + if (!evt.getPropertyName().equals(STATE_PROP_NAME)) { throw new IllegalArgumentException("Unknown download property " + evt.getPropertyName()); } - if (evt.getNewValue() != State.FINISHED){ + if (evt.getNewValue() != State.FINISHED) { return; } @@ -152,16 +159,34 @@ public class ScryfallSymbolsSource implements Iterable { } } + @Override + public void onPreparing() throws Exception { + this.cssUrl = ""; + + org.jsoup.nodes.Document doc = CardImageUtils.downloadHtmlDocument(CSS_SOURCE_URL); + org.jsoup.select.Elements cssList = doc.select(CSS_SOURCE_SELECTOR); + if (cssList.size() == 1) { + this.cssUrl = cssList.first().attr("href").toString(); + } + + if (this.cssUrl.isEmpty()) { + throw new IllegalStateException("Can't find stylesheet url from scryfall colors page."); + } else { + this.setSource(fromURL(this.cssUrl)); + } + } + private String destFile = ""; public ScryfallSymbolsDownloadJob() { - super("Scryfall symbols source", fromURL(SOURCE_URL), toFile(DOWNLOAD_TEMP_FILE)); + // download init + super("Scryfall symbols source", fromURL(""), toFile(DOWNLOAD_TEMP_FILE)); // url setup on preparing stage this.destFile = DOWNLOAD_TEMP_FILE; - this.addPropertyChangeListener(STATE_PROP_NAME, new ScryDownloadOnFinishedListener(this.destFile)); + this.addPropertyChangeListener(STATE_PROP_NAME, new ScryfallDownloadOnFinishedListener(this.destFile)); // clear dest file (always download new data) File file = new File(this.destFile); - if (file.exists()){ + if (file.exists()) { file.delete(); } } 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 589cc4640d9..da76bfc8b6f 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 @@ -16,6 +16,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.logging.Level; + import mage.constants.SubType; import org.apache.log4j.Logger; import org.mage.plugins.card.images.CardDownloadData; @@ -23,7 +24,6 @@ import org.mage.plugins.card.images.DownloadPictures; import org.mage.plugins.card.utils.CardImageUtils; /** - * * @author Quercitron */ public enum TokensMtgImageSource implements CardImageSource { @@ -58,7 +58,7 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { return null; } @@ -80,7 +80,7 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { String name = card.getName(); String set = card.getSet(); int type = card.getType(); @@ -125,7 +125,7 @@ public enum TokensMtgImageSource implements CardImageSource { String url = "http://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_' + tokenData.getNumber().trim() + '-' + tokenData.getName().trim() + ".jpg"; url = url.replace(' ', '-'); - return url; + return new CardImageUrls(url); } @Override @@ -248,7 +248,7 @@ public enum TokensMtgImageSource implements CardImageSource { List newTokensData = new ArrayList<>(); try (InputStreamReader inputReader = new InputStreamReader(inputStream, "Cp1252"); - BufferedReader reader = new BufferedReader(inputReader)) { + BufferedReader reader = new BufferedReader(inputReader)) { // we have to specify encoding to read special comma reader.readLine(); // skip header 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 593e165fff5..c482f17d4a2 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 @@ -1,13 +1,6 @@ - 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.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -19,21 +12,17 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import java.util.prefs.Preferences; import mage.cards.Sets; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; -import mage.client.MageFrame; import mage.client.dialog.PreferencesDialog; -import mage.remote.Connection; -import mage.remote.Connection.ProxyType; import org.apache.log4j.Logger; -import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.mage.plugins.card.images.CardDownloadData; +import org.mage.plugins.card.utils.CardImageUtils; /** * @author North @@ -231,13 +220,14 @@ public enum WizardCardsImageSource implements CardImageSource { supportedSets.add("DDS"); supportedSets.add("W17"); supportedSets.add("AKH"); - supportedSets.add("MPS"); supportedSets.add("CMA"); + supportedSets.add("CM2"); // Commander Anthology, Vol. II supportedSets.add("E01"); supportedSets.add("HOU"); supportedSets.add("C17"); supportedSets.add("XLN"); supportedSets.add("DDT"); // Duel Decks: Merfolk vs. Goblins + supportedSets.add("DDU"); // Duel Decks: Elves vs. Inventors supportedSets.add("IMA"); // Iconic Msters supportedSets.add("E02"); // Explorers of Ixalan supportedSets.add("V17"); // From the Vault: Transform @@ -245,7 +235,12 @@ public enum WizardCardsImageSource implements CardImageSource { supportedSets.add("RIX"); // Rivals of Ixalan supportedSets.add("A25"); // Masters 25 supportedSets.add("DOM"); // Dominaria -// supportedSets.add("M19"); // Core 2019 + supportedSets.add("BBD"); // Battlebond + supportedSets.add("GS1"); // Global Series: Jiang Yanggu and Mu Yanling + supportedSets.add("M19"); // Core 2019 + supportedSets.add("C18"); // Commander 2018 +// supportedSets.add("GRN"); // Guilds of Ravnica +// supportedSets.add("RNA"); // Ravnica Allegiance sets = new HashMap<>(); setsAliases = new HashMap<>(); @@ -282,6 +277,7 @@ public enum WizardCardsImageSource implements CardImageSource { setsAliases.put("C16", "Commander 2016"); setsAliases.put("C17", "Commander 2017"); setsAliases.put("CMA", "Commander Anthology"); + setsAliases.put("CM2", "Commander Anthology 2018"); setsAliases.put("CHK", "Champions of Kamigawa"); setsAliases.put("CHR", "Chronicles"); setsAliases.put("CMD", "Magic: The Gathering-Commander"); @@ -312,6 +308,7 @@ public enum WizardCardsImageSource implements CardImageSource { setsAliases.put("DDR", "Duel Decks: Nissa vs. Ob Nixilis"); setsAliases.put("DDS", "Duel Decks: Mind vs. Might"); setsAliases.put("DDT", "Duel Decks: Merfolk vs. Goblins"); + setsAliases.put("DDU", "Duel Decks: Elves vs. Inventors"); setsAliases.put("DGM", "Dragon's Maze"); setsAliases.put("DIS", "Dissension"); setsAliases.put("DKA", "Dark Ascension"); @@ -458,7 +455,7 @@ public enum WizardCardsImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -491,7 +488,7 @@ public enum WizardCardsImageSource implements CardImageSource { List l = new ArrayList<>(setLinks.values()); if (l.size() >= number) { link = l.get(number - 1); - } else {; + } else { link = l.get(number - 21); if (link != null) { link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a')); @@ -504,8 +501,12 @@ public enum WizardCardsImageSource implements CardImageSource { if (link != null && !link.startsWith("http://")) { link = "http://gatherer.wizards.com" + link; } - return link; + if (link != null) { + return new CardImageUrls(link); + } else { + return null; + } } private Map getSetLinks(String cardSet) { @@ -516,7 +517,7 @@ public enum WizardCardsImageSource implements CardImageSource { if (setNames == null) { setNames = Sets.getInstance().get(cardSet).getName(); } - String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); + String preferredLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); for (String setName : setNames.split("\\^")) { // String URLSetName = URLEncoder.encode(setName, "UTF-8"); String URLSetName = setName.replaceAll(" ", "%20"); @@ -526,7 +527,7 @@ public enum WizardCardsImageSource implements CardImageSource { while (page < 999) { String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?sort=cn+&page=" + page + "&action=advanced&output=spoiler&method=visual&set=+%5B%22" + URLSetName + "%22%5D"; logger.debug("URL: " + searchUrl); - Document doc = getDocument(searchUrl); + Document doc = CardImageUtils.downloadHtmlDocument(searchUrl); Elements cardsImages = doc.select("img[src^=../../Handlers/]"); if (cardsImages.isEmpty()) { break; @@ -554,8 +555,8 @@ public enum WizardCardsImageSource implements CardImageSource { cardName = cardName.substring(0, pos1); } } - Integer preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId); - setLinks.put(cardName.toLowerCase(Locale.ENGLISH) + numberChar, generateLink(preferedMultiverseId)); + Integer preferredMultiverseId = getLocalizedMultiverseId(preferredLanguage, multiverseId); + setLinks.put(cardName.toLowerCase(Locale.ENGLISH) + numberChar, generateLink(preferredMultiverseId)); } } } @@ -578,33 +579,6 @@ public enum WizardCardsImageSource implements CardImageSource { return setLinks; } - private Document getDocument(String urlString) throws NumberFormatException, IOException { - Preferences prefs = MageFrame.getPreferences(); - Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None")); - Document doc; - if (proxyType == ProxyType.NONE) { - doc = Jsoup.connect(urlString).timeout(60 * 1000).get(); - } else { - String proxyServer = prefs.get("proxyAddress", ""); - int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0")); - URL url = new URL(urlString); - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort)); - HttpURLConnection uc = (HttpURLConnection) url.openConnection(proxy); - uc.setConnectTimeout(10000); - uc.setReadTimeout(60000); - uc.connect(); - - String line; - StringBuffer tmp = new StringBuffer(); - BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream())); - while ((line = in.readLine()) != null) { - tmp.append(line); - } - doc = Jsoup.parse(String.valueOf(tmp)); - } - return doc; - } - private void getLandVariations(LinkedHashMap setLinks, String cardSet, int multiverseId, String cardName) throws IOException, NumberFormatException { CardCriteria criteria = new CardCriteria(); criteria.nameExact(cardName); @@ -612,7 +586,7 @@ public enum WizardCardsImageSource implements CardImageSource { List cards = CardRepository.instance.findCards(criteria); String urlLandDocument = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId; - Document landDoc = getDocument(urlLandDocument); + Document landDoc = CardImageUtils.downloadHtmlDocument(urlLandDocument); Elements variations = landDoc.select("a.variationlink"); if (!variations.isEmpty()) { if (variations.size() > cards.size()) { @@ -643,12 +617,12 @@ public enum WizardCardsImageSource implements CardImageSource { return "/Handlers/Image.ashx?multiverseid=" + landMultiverseId + "&type=card"; } - private int getLocalizedMultiverseId(String preferedLanguage, Integer multiverseId) throws IOException { - if (preferedLanguage.equals("en")) { + private int getLocalizedMultiverseId(String preferredLanguage, Integer multiverseId) throws IOException { + if (preferredLanguage.equals("en")) { return multiverseId; } - String languageName = languageAliases.get(preferedLanguage); + String languageName = languageAliases.get(preferredLanguage); HashMap localizedLanguageIds = getlocalizedMultiverseIds(multiverseId); if (localizedLanguageIds.containsKey(languageName)) { return localizedLanguageIds.get(languageName); @@ -659,7 +633,7 @@ public enum WizardCardsImageSource implements CardImageSource { private HashMap getlocalizedMultiverseIds(Integer englishMultiverseId) throws IOException { String cardLanguagesUrl = "http://gatherer.wizards.com/Pages/Card/Languages.aspx?multiverseid=" + englishMultiverseId; - Document cardLanguagesDoc = getDocument(cardLanguagesUrl); + Document cardLanguagesDoc = CardImageUtils.downloadHtmlDocument(cardLanguagesUrl); Elements languageTableRows = cardLanguagesDoc.select("tr.cardItem"); HashMap localizedIds = new HashMap<>(); if (!languageTableRows.isEmpty()) { @@ -699,7 +673,7 @@ public enum WizardCardsImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { return null; } @@ -708,24 +682,24 @@ public enum WizardCardsImageSource implements CardImageSource { return 60.0f; } -// private final class GetImageLinkTask implements Runnable { + // private final class GetImageLinkTask implements Runnable { // // private int multiverseId; // private String cardName; -// private String preferedLanguage; +// private String preferredLanguage; // private LinkedHashMap setLinks; // -// public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, LinkedHashMap setLinks) { +// public GetImageLinkTask(int multiverseId, String cardName, String preferredLanguage, LinkedHashMap setLinks) { // try { // this.multiverseId = multiverseId; // this.cardName = cardName; -// this.preferedLanguage = preferedLanguage; +// this.preferredLanguage = preferredLanguage; // this.setLinks = setLinks; // } catch (Exception ex) { // logger.error(ex.getMessage()); // logger.error("multiverseId: " + multiverseId); // logger.error("cardName: " + cardName); -// logger.error("preferedLanguage: " + preferedLanguage); +// logger.error("preferredLanguage: " + preferredLanguage); // logger.error("setLinks: " + setLinks.toString()); // } // } @@ -736,8 +710,8 @@ public enum WizardCardsImageSource implements CardImageSource { // if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island") || cardName.equals("Plains")) { // setLinks.putAll(getLandVariations(multiverseId, cardName)); // } else { -// Integer preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId); -// setLinks.put(cardName.toLowerCase(Locale.ENGLISH), generateLink(preferedMultiverseId)); +// Integer preferredMultiverseId = getLocalizedMultiverseId(preferredLanguage, multiverseId); +// setLinks.put(cardName.toLowerCase(Locale.ENGLISH), generateLink(preferredMultiverseId)); // } // } catch (IOException | NumberFormatException ex) { // logger.error("Exception when parsing the wizards page: " + ex.getMessage()); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 389c0be5a7d..7be47db2d1f 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -15,6 +15,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.swing.*; + import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.repository.CardCriteria; @@ -33,6 +34,7 @@ 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 static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable { @@ -42,9 +44,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private static final Logger logger = Logger.getLogger(DownloadPictures.class); - public static final String ALL_IMAGES = "- All images from that source"; - public static final String ALL_STANDARD_IMAGES = "- All images from standard from that source"; - public static final String ALL_TOKENS = "- Only all token images from that source"; + public static final String ALL_IMAGES = "- ALL images from selected source (CAN BE VERY SLOW)"; + public static final String ALL_STANDARD_IMAGES = "- Only images from STANDARD sets"; + public static final String ALL_TOKENS = "- Only token images from selected source"; private JDialog dialog; private final JProgressBar bar; @@ -76,14 +78,15 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private Proxy p = Proxy.NO_PROXY; enum DownloadSources { - WIZARDS("wizards.com", WizardCardsImageSource.instance), - MYTHICSPOILER("mythicspoiler.com", MythicspoilerComSource.instance), - TOKENS("tokens.mtg.onl", TokensMtgImageSource.instance), + WIZARDS("1. wizards.com - low quality CARDS, multi-language, can be SLOW", WizardCardsImageSource.instance), + TOKENS("2. tokens.mtg.onl - high quality TOKENS", TokensMtgImageSource.instance), + SCRYFALL("3. scryfall.com - high quality CARDS, 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), + ALTERNATIVE("7. alternative.mtg.onl", AltMtgOnlTokensImageSource.instance), + COPYPASTE("8. Copy and Paste Image URLs", CopyPasteImageSource.instance); // MTG_ONL("mtg.onl", MtgOnlTokensImageSource.instance), Not working correctly yet - ALTERNATIVE("alternative.mtg.onl", AltMtgOnlTokensImageSource.instance), - GRAB_BAG("GrabBag", GrabbagImageSource.instance), - MAGIDEX("magidex.com", MagidexImageSource.instance), - SCRYFALL("scryfall.com", ScryfallImageSource.instance); // MAGICCARDS("magiccards.info", MagicCardsImageSource.instance) private final String text; @@ -485,7 +488,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } try (InputStreamReader input = new InputStreamReader(in); - BufferedReader reader = new BufferedReader(input)) { + BufferedReader reader = new BufferedReader(input)) { String line = reader.readLine(); while (line != null) { @@ -597,25 +600,25 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')'); - String url; + CardImageUrls urls; + if (ignoreUrls.contains(card.getSet()) || card.isToken()) { if (!"0".equals(card.getCollectorId())) { continue; } - url = cardImageSource.generateTokenUrl(card); + urls = cardImageSource.generateTokenUrl(card); } else { - url = cardImageSource.generateURL(card); + urls = cardImageSource.generateURL(card); } - if (url == null) { + if (urls == null) { String imageRef = cardImageSource.getNextHttpImageUrl(); String fileName = cardImageSource.getFileForHttpImage(imageRef); if (imageRef != null && fileName != null) { imageRef = cardImageSource.getSourceName() + imageRef; try { - URL imageUrl = new URL(imageRef); card.setToken(cardImageSource.isTokenSource()); - Runnable task = new DownloadTask(card, imageUrl, fileName, cardImageSource.getTotalImages()); + Runnable task = new DownloadTask(card, imageRef, fileName, cardImageSource.getTotalImages()); executor.execute(task); } catch (Exception ex) { } @@ -626,7 +629,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } } } else { - Runnable task = new DownloadTask(card, new URL(url), cardsToDownload.size()); + Runnable task = new DownloadTask(card, urls, cardsToDownload.size()); executor.execute(task); } @@ -662,22 +665,26 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private final class DownloadTask implements Runnable { private final CardDownloadData card; - private final URL url; + private final CardImageUrls urls; private final int count; private final String actualFilename; private final boolean useSpecifiedPaths; - DownloadTask(CardDownloadData card, URL url, int count) { + DownloadTask(CardDownloadData card, String baseUrl, int count) { + this(card, new CardImageUrls(baseUrl, null), count); + } + + DownloadTask(CardDownloadData card, CardImageUrls urls, int count) { this.card = card; - this.url = url; + this.urls = urls; this.count = count; this.actualFilename = ""; useSpecifiedPaths = false; } - DownloadTask(CardDownloadData card, URL url, String actualFilename, int count) { + DownloadTask(CardDownloadData card, String baseUrl, String actualFilename, int count) { this.card = card; - this.url = url; + this.urls = new CardImageUrls(baseUrl, null); this.count = count; this.actualFilename = actualFilename; useSpecifiedPaths = true; @@ -751,14 +758,55 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } } - cardImageSource.doPause(url.getPath()); - URLConnection httpConn = url.openConnection(p); - httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); - httpConn.connect(); - int responseCode = ((HttpURLConnection) httpConn).getResponseCode(); + // can download images from many alternative urls + List downloadUrls; + if (this.urls != null) { + downloadUrls = this.urls.getDownloadList(); + } else { + downloadUrls = new ArrayList<>(); + } - if (responseCode == 200) { - // download OK + boolean isDownloadOK = false; + URLConnection httpConn = null; + List errorsList = new ArrayList<>(); + for (String currentUrl : downloadUrls) { + URL url = new URL(currentUrl); + + // on download cancel need to stop + if (cancel) { + return; + } + + // download + cardImageSource.doPause(url.getPath()); + httpConn = url.openConnection(p); + httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); + httpConn.connect(); + int responseCode = ((HttpURLConnection) httpConn).getResponseCode(); + + // check result + if (responseCode != 200) { + // show errors only on full fail (all urls were not work) + errorsList.add("Image download for " + card.getName() + + (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "") + + " (" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString()); + + if (logger.isDebugEnabled()) { + // Shows the returned html from the request to the web server + logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream())); + } + + // go to next try + continue; + } else { + // all fine + isDownloadOK = true; + break; + } + } + + // can save result + if (isDownloadOK & httpConn != null) { // save data to temp OutputStream out = null; OutputStream tfileout = null; @@ -792,8 +840,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } out.write(buf, 0, len); } - } - finally { + } finally { StreamUtils.closeQuietly(in); StreamUtils.closeQuietly(out); StreamUtils.closeQuietly(tfileout); @@ -815,15 +862,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } } else { - // download ERROR - logger.warn("Image download for " + card.getName() - + (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "") - + " (" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString() - ); - - if (logger.isDebugEnabled()) { - // Shows the returned html from the request to the web server - logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream())); + // download errors + for (String err : errorsList) { + logger.warn(err); } } 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 6b7c74587a8..fb7c42aa090 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,11 +1,17 @@ package org.mage.plugins.card.utils; +import java.io.BufferedReader; import java.io.File; +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.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; @@ -13,6 +19,8 @@ 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; @@ -22,7 +30,6 @@ public final class CardImageUtils { private static final Logger log = Logger.getLogger(CardImageUtils.class); /** - * * @param card * @return String if image exists, else null */ @@ -54,7 +61,6 @@ public final class CardImageUtils { } /** - * * @param card * @return String regardless of whether image exists */ @@ -280,4 +286,31 @@ public final class CardImageUtils { } return null; } + + public static Document downloadHtmlDocument(String urlString) throws NumberFormatException, IOException { + Preferences prefs = MageFrame.getPreferences(); + Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None")); + Document doc; + if (proxyType == ProxyType.NONE) { + doc = Jsoup.connect(urlString).timeout(60 * 1000).get(); + } else { + String proxyServer = prefs.get("proxyAddress", ""); + int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0")); + URL url = new URL(urlString); + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort)); + HttpURLConnection uc = (HttpURLConnection) url.openConnection(proxy); + uc.setConnectTimeout(10000); + uc.setReadTimeout(60000); + uc.connect(); + + String line; + StringBuffer tmp = new StringBuffer(); + BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream())); + while ((line = in.readLine()) != null) { + tmp.append(line); + } + doc = Jsoup.parse(String.valueOf(tmp)); + } + return doc; + } } diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt index 664b4d79c31..05988555120 100644 --- a/Mage.Client/src/main/resources/card-pictures-tok.txt +++ b/Mage.Client/src/main/resources/card-pictures-tok.txt @@ -357,6 +357,7 @@ |Generate|TOK:C17|Rat|||DeathtouchRatToken| |Generate|TOK:C17|Vampire|||EdgarMarkovToken| |Generate|TOK:C17|Zombie|| +|Generate|TOK:C18|Myr|||BrudicladTelchorMyrToken| |Generate|TOK:CHK|Dragon Spirit|||TatsumaDragonToken| |Generate|TOK:CHK|Elemental|||SeedGuardianToken| |Generate|TOK:CHK|Illusion|||MelokuTheCloudedMirrorToken| diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties index 3c3b31e94a7..d3ab400892f 100644 --- a/Mage.Client/src/main/resources/image.url.properties +++ b/Mage.Client/src/main/resources/image.url.properties @@ -73,6 +73,6 @@ dd3evg=ddaevg dd3gvl=ddagvl dd3jvc=ddajvc # Remove setname as soon as the images can be downloaded -ignore.urls=TOK,M19,H17 +ignore.urls=TOK,H17 # sets ordered by release time (newest goes first) -token.lookup.order=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 +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.Client/src/main/resources/mage/client/deckeditor/pennydreadful.properties b/Mage.Client/src/main/resources/mage/client/deckeditor/pennydreadful.properties index c85cbd63c55..21b36851790 100644 --- a/Mage.Client/src/main/resources/mage/client/deckeditor/pennydreadful.properties +++ b/Mage.Client/src/main/resources/mage/client/deckeditor/pennydreadful.properties @@ -1,39 +1,38 @@ -Abandon\ Hope=1 Abandon\ Reason=1 +Abandoned\ Outpost=1 +Abandoned\ Sarcophagus=1 Abattoir\ Ghoul=1 -Abbey\ Gargoyles=1 +Abduction=1 Aberrant\ Researcher=1 Abhorrent\ Overlord=1 +Abnormal\ Endurance=1 Abomination\ of\ Gudul=1 -Aboshan,\ Cephalid\ Emperor=1 +Aboshan's\ Desire=1 About\ Face=1 -Absolute\ Law=1 Absolver\ Thrull=1 Absorb\ Vis=1 Abstruse\ Interference=1 -Abuna\ Acolyte=1 +Abuna's\ Chant=1 Abundant\ Maw=1 Abyssal\ Horror=1 Abyssal\ Nocturnus=1 Abyssal\ Specter=1 -Abzan\ Advantage=1 Abzan\ Ascendancy=1 Abzan\ Banner=1 Abzan\ Battle\ Priest=1 -Abzan\ Beastmaster=1 Abzan\ Charm=1 Abzan\ Falconer=1 Abzan\ Guide=1 -Abzan\ Kin-Guard=1 Abzan\ Runemark=1 -Abzan\ Skycaptain=1 +Academy\ Drake=1 Academy\ Elite=1 +Academy\ Journeymage=1 Academy\ Raider=1 Academy\ Researchers=1 +Accelerate=1 Accomplished\ Automaton=1 Accorder's\ Shield=1 Accorder\ Paladin=1 -Accursed\ Centaur=1 Accursed\ Horde=1 Accursed\ Spirit=1 Accursed\ Witch=1 @@ -41,15 +40,18 @@ Acid-Spewer\ Dragon=1 Acid\ Web\ Spider=1 Acidic\ Sliver=1 Acolyte's\ Reward=1 +Acolyte\ of\ Xathrid=1 Acolyte\ of\ the\ Inferno=1 Acquire=1 -Acridian=1 Acrobatic\ Maneuver=1 Act\ of\ Aggression=1 Act\ of\ Heroism=1 Act\ of\ Treason=1 Act\ on\ Impulse=1 +Active\ Volcano=1 +Adamant\ Will=1 Adamaro,\ First\ to\ Desire=1 +Adanto\ Vanguard=1 Adaptive\ Snapjaw=1 Adarkar\ Sentinel=1 Adarkar\ Valkyrie=1 @@ -65,9 +67,10 @@ Advice\ from\ the\ Fae=1 Advocate\ of\ the\ Beast=1 Aegis\ Angel=1 Aegis\ Automaton=1 -Aegis\ of\ Honor=1 Aeolipile=1 Aeon\ Chronicler=1 +Aerial\ Caravan=1 +Aerial\ Engineer=1 Aerial\ Formation=1 Aerial\ Guide=1 Aerial\ Maneuver=1 @@ -83,16 +86,14 @@ Aeronaut\ Admiral=1 Aeronaut\ Tinkerer=1 Aesthir\ Glider=1 Aether\ Adept=1 -Aether\ Charge=1 Aether\ Chaser=1 Aether\ Figment=1 -Aether\ Flash=1 Aether\ Herder=1 Aether\ Inspector=1 -Aether\ Meltdown=1 Aether\ Membrane=1 Aether\ Mutation=1 Aether\ Poisoner=1 +Aether\ Shockwave=1 Aether\ Snap=1 Aether\ Spellbomb=1 Aether\ Sting=1 @@ -103,31 +104,30 @@ Aether\ Tide=1 Aether\ Tradewinds=1 Aetherborn\ Marauder=1 Aethergeode\ Miner=1 -Aetherize=1 Aetherling=1 Aethermage's\ Touch=1 Aetherplasm=1 +Aethershield\ Artificer=1 Aethersnipe=1 Aethersquall\ Ancient=1 Aetherstorm\ Roc=1 Aetherstream\ Leopard=1 +Aethertide\ Whale=1 Aethertorch\ Renegade=1 Aethertow=1 -Affa\ Guard\ Hound=1 +Aetherwind\ Basker=1 Affa\ Protector=1 Afflict=1 Afflicted\ Deserter=1 Afterlife=1 Aftershock=1 Agadeem\ Occultist=1 -Ageless\ Entity=1 -Ageless\ Sentinels=1 -Agent\ of\ Erebos=1 Agent\ of\ Horizons=1 Agent\ of\ Masks=1 Agent\ of\ the\ Fates=1 Aggressive\ Urge=1 Agility=1 +Agonizing\ Demise=1 Agonizing\ Memories=1 Agony\ Warp=1 Agoraphobia=1 @@ -137,29 +137,31 @@ Aid\ from\ the\ Cowl=1 Aim\ High=1 Ainok\ Artillerist=1 Ainok\ Bond-Kin=1 -Ainok\ Guide=1 Ainok\ Tracker=1 +Air\ Bladder=1 Air\ Elemental=1 Air\ Servant=1 Airborne\ Aid=1 Airdrop\ Aeronauts=1 -Airdrop\ Condor=1 -Ajani's\ Chosen=1 Ajani's\ Mantra=1 Ajani's\ Sunstriker=1 Akki\ Avalanchers=1 Akki\ Blizzard-Herder=1 +Akki\ Drillmaster=1 Akki\ Lavarunner=1 +Akki\ Raider=1 Akki\ Rockspeaker=1 -Akki\ Underling=1 Akki\ Underminer=1 +Akoum\ Battlesinger=1 Akoum\ Boulderfoot=1 -Akoum\ Firebird=1 Akoum\ Flameseeker=1 Akoum\ Hellkite=1 Akoum\ Stonewaker=1 +Akrasan\ Squire=1 Akroan\ Conscriptor=1 +Akroan\ Crusader=1 Akroan\ Hoplite=1 +Akroan\ Horse=1 Akroan\ Jailer=1 Akroan\ Line\ Breaker=1 Akroan\ Mastiff=1 @@ -168,10 +170,9 @@ Akroan\ Sergeant=1 Akroma's\ Blessing=1 Akroma's\ Devoted=1 Akron\ Legionnaire=1 -Akuta,\ Born\ of\ Ash=1 +Aku\ Djinn=1 Alabaster\ Kirin=1 -Alabaster\ Mage=1 -Alabaster\ Potion=1 +Alabaster\ Wall=1 Alaborn\ Musketeer=1 Alaborn\ Trooper=1 Aladdin's\ Ring=1 @@ -179,19 +180,16 @@ Alarum=1 Albino\ Troll=1 Alchemist's\ Apprentice=1 Alchemist's\ Greeting=1 -Alchemist's\ Vial=1 -Alchor's\ Tomb=1 -Alesha's\ Vanguard=1 +Aleatory=1 Algae\ Gharial=1 Alhammarret,\ High\ Arbiter=1 Aligned\ Hedron\ Network=1 Alive\ //\ Well=1 All\ Suns'\ Dawn=1 -Allay=1 Alley\ Evasion=1 Alley\ Strangler=1 Allied\ Reinforcements=1 -Allied\ Strategies=1 +Alloy\ Golem=1 Alloy\ Myr=1 Alluring\ Scent=1 Alluring\ Siren=1 @@ -201,9 +199,8 @@ Alms\ Beast=1 Alms\ of\ the\ Vein=1 Alpha\ Authority=1 Alpha\ Brawl=1 +Alpha\ Kavu=1 Alpha\ Myr=1 -Alpha\ Status=1 -Alpha\ Tyrranax=1 Alpine\ Grizzly=1 Altac\ Bloodseeker=1 Altar's\ Reap=1 @@ -212,17 +209,21 @@ Altar\ of\ Shadows=1 Altar\ of\ the\ Brood=1 Altar\ of\ the\ Lost=1 Altered\ Ego=1 +Always\ Watching=1 +Amaranthine\ Wall=1 Amass\ the\ Components=1 +Ambassador\ Laquatus=1 Ambassador\ Oak=1 Ambitious\ Aetherborn=1 Ambuscade=1 Ambuscade\ Shaman=1 -Ambush\ Commander=1 Ambush\ Krotiq=1 Ambush\ Party=1 Ambush\ Viper=1 +Amnesia=1 Amoeboid\ Changeling=1 Amok=1 +Amphibious\ Kavu=1 Amphin\ Cutthroat=1 Amphin\ Pathmage=1 Ampryn\ Tactician=1 @@ -232,49 +233,55 @@ Amrou\ Seekers=1 Amugaba=1 Amulet\ of\ Kroog=1 Ana\ Battlemage=1 +Ana\ Disciple=1 +Ana\ Sanctuary=1 +Anaba\ Ancestor=1 Anaba\ Shaman=1 Anaba\ Spirit\ Crafter=1 Anaconda=1 +Anarchist=1 Anathemancer=1 -Anavolver=1 Anax\ and\ Cymede=1 +Ancestor's\ Chosen=1 Ancestor's\ Prophet=1 Ancestral\ Memories=1 -Ancestral\ Statue=1 +Ancestral\ Tribute=1 Ancestral\ Vengeance=1 Anchor\ to\ the\ Aether=1 Ancient\ Amphitheater=1 +Ancient\ Animus=1 Ancient\ Brontodon=1 Ancient\ Carp=1 Ancient\ Crab=1 Ancient\ Hellkite=1 -Ancient\ Hydra=1 -Ancient\ Ooze=1 +Ancient\ Kavu=1 Ancient\ Runes=1 Ancient\ Silverback=1 Andradite\ Leech=1 Angel's\ Feather=1 +Angel's\ Herald=1 Angel's\ Mercy=1 Angel's\ Tomb=1 Angel's\ Trumpet=1 Angel\ of\ Condemnation=1 Angel\ of\ Deliverance=1 +Angel\ of\ Despair=1 Angel\ of\ Flight\ Alabaster=1 Angel\ of\ Fury=1 -Angel\ of\ Glory's\ Rise=1 Angel\ of\ Light=1 Angel\ of\ Mercy=1 Angel\ of\ Renewal=1 +Angel\ of\ Retribution=1 Angel\ of\ Salvation=1 +Angel\ of\ the\ Dawn=1 Angel\ of\ the\ God-Pharaoh=1 +Angelfire\ Crusader=1 Angelheart\ Vial=1 -Angelic\ Accord=1 Angelic\ Arbiter=1 Angelic\ Armaments=1 Angelic\ Benediction=1 Angelic\ Blessing=1 Angelic\ Captain=1 -Angelic\ Chorus=1 Angelic\ Curator=1 Angelic\ Edict=1 Angelic\ Favor=1 @@ -287,13 +294,14 @@ Angelic\ Shield=1 Angelic\ Skirmisher=1 Angelic\ Voices=1 Angelic\ Wall=1 +Angelsong=1 Angler\ Drake=1 Angrath's\ Marauders=1 Angry\ Mob=1 Animal\ Boneyard=1 Animal\ Magnetism=1 Animate\ Artifact=1 -Animate\ Dead=1 +Animate\ Land=1 Animate\ Wall=1 Animation\ Module=1 Animist's\ Awakening=1 @@ -308,19 +316,21 @@ Anointed\ Deacon=1 Anointer\ Priest=1 Anointer\ of\ Champions=1 Ant\ Queen=1 -Antagonism=1 -Anthousa,\ Setessan\ Hero=1 -Anthroplasm=1 +Anthem\ of\ Rakdos=1 Anticipate=1 Antler\ Skulkin=1 +Anurid\ Barkripper=1 +Anurid\ Brushhopper=1 Anurid\ Murkdiver=1 Anurid\ Scavenger=1 +Anurid\ Swarmsnapper=1 Anvilwrought\ Raptor=1 -Apathy=1 +Apes\ of\ Rath=1 Aphetto\ Dredging=1 Aphetto\ Exterminator=1 Aphetto\ Vulture=1 Aphotic\ Wisps=1 +Apocalypse\ Demon=1 Apocalypse\ Hydra=1 Apothecary\ Geist=1 Apothecary\ Initiate=1 @@ -328,21 +338,23 @@ Appeal\ //\ Authority=1 Appetite\ for\ Brains=1 Appetite\ for\ the\ Unnatural=1 Apprentice\ Wizard=1 +Approach\ of\ the\ Second\ Sun=1 Aquamoeba=1 -Aquamorph\ Entity=1 Aquastrand\ Spider=1 Aquatic\ Incursion=1 Aquitect's\ Will=1 Araba\ Mothrider=1 -Arachnoid=1 Arachnus\ Spinner=1 Arachnus\ Web=1 Aradara\ Express=1 Arashi,\ the\ Sky\ Asunder=1 +Arashin\ Cleric=1 +Arashin\ Sovereign=1 Arashin\ War\ Beast=1 Arbalest\ Elite=1 Arbiter\ of\ Knollridge=1 Arbiter\ of\ the\ Ideal=1 +Arbor\ Armament=1 Arbor\ Colossus=1 Arborback\ Stomper=1 Arc-Slogger=1 @@ -350,23 +362,25 @@ Arc\ Blade=1 Arc\ Lightning=1 Arc\ Runner=1 Arc\ Trail=1 -Arcades\ Sabboth=1 Arcane\ Adaptation=1 -Arcane\ Melee=1 +Arcane\ Flight=1 +Arcane\ Sanctum=1 Arcane\ Spyglass=1 +Arcane\ Teachings=1 +Arcanis\ the\ Omnipotent=1 Arcbound\ Bruiser=1 Arcbound\ Crusher=1 Arcbound\ Fiend=1 Arcbound\ Hybrid=1 Arcbound\ Lancer=1 Arcbound\ Overseer=1 -Arcbound\ Slith=1 +Arcbound\ Reclaimer=1 Arcbound\ Stinger=1 Arcbound\ Wanderer=1 -Arcbound\ Worker=1 -Archangel=1 +Archaeological\ Dig=1 Archdemon\ of\ Unx=1 Archers'\ Parapet=1 +Archers\ of\ Qarsi=1 Archery\ Training=1 Archetype\ of\ Aggression=1 Archetype\ of\ Courage=1 @@ -379,67 +393,75 @@ Archmage\ Ascension=1 Archon\ of\ Justice=1 Archon\ of\ Redemption=1 Archon\ of\ the\ Triumvirate=1 -Archwing\ Dragon=1 +Archweaver=1 Arctic\ Aven=1 -Arctic\ Merfolk=1 Arctic\ Nishoba=1 Arctic\ Wolves=1 Ardent\ Militia=1 Ardent\ Recruit=1 +Ardent\ Soldier=1 Arena\ Athlete=1 Argent\ Mutation=1 Argent\ Sphinx=1 +Argivian\ Blacksmith=1 +Argivian\ Restoration=1 Argothian\ Pixies=1 Argothian\ Swine=1 Argothian\ Treefolk=1 Ark\ of\ Blight=1 -Arm\ with\ Aether=1 +Armageddon\ Clock=1 Armament\ Corps=1 Armament\ Master=1 Armament\ of\ Nyx=1 Armed\ //\ Dangerous=1 Armed\ Response=1 -Armistice=1 +Armillary\ Sphere=1 Armor\ Sliver=1 Armor\ Thrull=1 +Armor\ of\ Faith=1 +Armor\ of\ Thorns=1 Armorcraft\ Judge=1 Armored\ Ascension=1 Armored\ Cancrix=1 Armored\ Griffin=1 Armored\ Pegasus=1 Armored\ Skaab=1 -Armored\ Transport=1 +Armored\ Warhorse=1 Armored\ Wolf-Rider=1 Armorer\ Guildmage=1 -Armory\ Guard=1 Armory\ of\ Iroas=1 Arms\ Dealer=1 -Army\ Ants=1 Arrest=1 Arrogant\ Bloodlord=1 -Arrogant\ Wurm=1 Arrow\ Storm=1 +Arrows\ of\ Justice=1 Arsenal\ Thresher=1 Arterial\ Flow=1 -Artful\ Maneuver=1 +Artifact\ Blast=1 +Artificer's\ Assistant=1 Artificer's\ Epiphany=1 Artificer's\ Hex=1 +Artificial\ Evolution=1 Artillerize=1 Artisan's\ Sorrow=1 Artisan\ of\ Forms=1 Artisan\ of\ Kozilek=1 +Arvad\ the\ Cursed=1 +Aryel,\ Knight\ of\ Windgrace=1 +Ascendant\ Evincar=1 Ascended\ Lawmage=1 -Ascending\ Aven=1 +Ash\ Zealot=1 Asha's\ Favor=1 -Ashcloud\ Phoenix=1 Ashcoat\ Bear=1 Ashen\ Firebeast=1 Ashen\ Ghoul=1 +Ashen\ Monstrosity=1 Ashenmoor\ Cohort=1 Ashenmoor\ Gouger=1 Ashes\ of\ the\ Fallen=1 Ashiok's\ Adept=1 Ashling's\ Prerogative=1 +Ashling,\ the\ Extinguisher=1 Ashling\ the\ Pilgrim=1 Ashnod's\ Cylix=1 Ashnod's\ Transmogrant=1 @@ -448,48 +470,48 @@ Aspect\ of\ Mongoose=1 Asphodel\ Wanderer=1 Asphyxiate=1 Aspiring\ Aeronaut=1 +Assassin's\ Strike=1 Assassinate=1 Assault\ //\ Battery=1 Assault\ Griffin=1 Assault\ Zeppelid=1 -Assemble\ the\ Legion=1 Assembled\ Alphas=1 -Assembly-Worker=1 Assert\ Authority=1 -Astral\ Cornucopia=1 Astral\ Slide=1 Astral\ Steel=1 Astrolabe=1 +Asylum\ Visitor=1 +Atarka\ Efreet=1 Atarka\ Monument=1 Atarka\ Pummeler=1 +Atogatog=1 Attended\ Knight=1 +Attune\ with\ Aether=1 Atzocan\ Archer=1 Atzocan\ Seer=1 Audacious\ Infiltrator=1 Auger\ Spree=1 Augmenting\ Automaton=1 Augur\ il-Vec=1 -Augury\ Adept=1 Augury\ Owl=1 -Auntie's\ Hovel=1 Auntie's\ Snitch=1 Aura\ Barbs=1 +Aura\ Extraction=1 Aura\ Finesse=1 -Aura\ Fracture=1 +Aura\ Graft=1 Auramancer's\ Guise=1 Auramancer=1 -Auratog=1 Auratouched\ Mage=1 -Auriok\ Bladewarden=1 Auriok\ Edgewright=1 Auriok\ Glaivemaster=1 -Auriok\ Replica=1 Auriok\ Salvagers=1 +Auriok\ Steelshaper=1 Auriok\ Sunchaser=1 Auriok\ Survivors=1 -Aurochs=1 +Auriok\ Transfixer=1 +Auriok\ Windwalker=1 Aurora\ Eidolon=1 -Aurora\ Griffin=1 +Auspicious\ Ancestor=1 Autochthon\ Wurm=1 Autumn's\ Veil=1 Autumn\ Willow=1 @@ -500,13 +522,14 @@ Avacyn's\ Pilgrim=1 Avacyn,\ Guardian\ Angel=1 Avacynian\ Missionaries=1 Avacynian\ Priest=1 -Avalanche\ Tusker=1 Avarax=1 Avarice\ Amulet=1 Avarice\ Totem=1 Avatar\ of\ Might=1 +Aven\ Archer=1 Aven\ Augur=1 Aven\ Battle\ Priest=1 +Aven\ Brigadier=1 Aven\ Cloudchaser=1 Aven\ Envoy=1 Aven\ Farseer=1 @@ -516,34 +539,41 @@ Aven\ Flock=1 Aven\ Initiate=1 Aven\ Liberator=1 Aven\ Mimeomancer=1 +Aven\ Mindcensor=1 Aven\ Redeemer=1 Aven\ Reedstalker=1 Aven\ Riftwatcher=1 +Aven\ Sentry=1 Aven\ Shrine=1 -Aven\ Skirmisher=1 Aven\ Smokeweaver=1 Aven\ Squire=1 Aven\ Sunstriker=1 Aven\ Surveyor=1 Aven\ Tactician=1 +Aven\ Trailblazer=1 +Aven\ Trooper=1 +Aven\ Warcraft=1 +Aven\ Warhawk=1 Aven\ Wind\ Guide=1 +Aven\ Wind\ Mage=1 Aven\ Windreader=1 Aven\ of\ Enduring\ Hope=1 Avenging\ Angel=1 Avenging\ Arrow=1 -Avenging\ Druid=1 Avian\ Changeling=1 Aviary\ Mechanic=1 +Aviation\ Pioneer=1 +Avizoa=1 +Avoid\ Fate=1 Awaken\ the\ Ancient=1 Awaken\ the\ Bear=1 Awakened\ Amalgam=1 Awakener\ Druid=1 Awe\ Strike=1 Awe\ for\ the\ Guilds=1 -Axebane\ Guardian=1 Axebane\ Stag=1 -Axegrinder\ Giant=1 Axelrod\ Gunnarson=1 +Ayli,\ Eternal\ Pilgrim=1 Aysen\ Bureaucrats=1 Aysen\ Crusader=1 Ayumi,\ the\ Last\ Visitor=1 @@ -559,13 +589,13 @@ Azorius\ Guildmage=1 Azorius\ Herald=1 Azorius\ Justiciar=1 Azorius\ Keyrune=1 -Azorius\ Ploy=1 +Azure\ Drake=1 Azure\ Mage=1 Back\ from\ the\ Brink=1 -Back\ to\ Nature=1 -Backlash=1 Backwoods\ Survivalists=1 Bad\ River=1 +Baffling\ End=1 +Baird,\ Steward\ of\ Argive=1 Baku\ Altar=1 Bala\ Ged\ Scorpion=1 Bala\ Ged\ Thief=1 @@ -573,8 +603,7 @@ Balance\ of\ Power=1 Balduvian\ Barbarians=1 Balduvian\ Conjurer=1 Balduvian\ Dead=1 -Balduvian\ Frostwaker=1 -Balduvian\ Horde=1 +Balduvian\ Fallen=1 Balduvian\ Rage=1 Balduvian\ Warlord=1 Baleful\ Ammit=1 @@ -582,68 +611,68 @@ Baleful\ Eidolon=1 Baleful\ Force=1 Baleful\ Stare=1 Ballista\ Charger=1 -Ballista\ Squad=1 Balloon\ Peddler=1 Ballynock\ Cohort=1 Ballynock\ Trapper=1 -Ballyrush\ Banneret=1 Baloth\ Cage\ Trap=1 +Baloth\ Gorger=1 Baloth\ Null=1 Baloth\ Pup=1 Baloth\ Woodcrasher=1 Balshan\ Beguiler=1 +Balshan\ Collaborator=1 +Balshan\ Griffin=1 Balustrade\ Spy=1 Bamboozle=1 Bandage=1 Bane\ Alley\ Broker=1 Bane\ of\ Bala\ Ged=1 Baneful\ Omen=1 -Banewasp\ Affliction=1 Banewhip\ Punisher=1 +Banisher\ Priest=1 Banishing\ Stroke=1 Banishment\ Decree=1 Banners\ Raised=1 Banshee's\ Blade=1 Banshee=1 -Banshee\ of\ the\ Dread\ Choir=1 -Bant\ Battlemage=1 Bant\ Sojourners=1 Bar\ the\ Door=1 +Barbarian\ Bully=1 +Barbarian\ Riftcutter=1 +Barbed-Back\ Wurm=1 +Barbed\ Battlegear=1 Barbed\ Lightning=1 Barbed\ Sextant=1 Barbed\ Shocker=1 Barbed\ Sliver=1 +Barbed\ Wire=1 Barishi=1 Barkhide\ Mauler=1 Barkshell\ Blessing=1 Barktooth\ Warbeard=1 Barl's\ Cage=1 -Barony\ Vampire=1 Barrage\ Ogre=1 Barrage\ Tyrant=1 Barrage\ of\ Boulders=1 -Barrage\ of\ Expendables=1 +Barrel\ Down\ Sokenzan=1 Barren\ Glory=1 Barrenton\ Cragtreads=1 +Barrenton\ Medic=1 Barricade\ Breaker=1 Barrin's\ Codex=1 -Bartel\ Runeaxe=1 -Barter\ in\ Blood=1 +Barrin's\ Unmaking=1 Basal\ Sliver=1 Basal\ Thrull=1 Basalt\ Gargoyle=1 Basandra,\ Battle\ Seraph=1 +Bash\ to\ Bits=1 Basilica\ Guards=1 Basilica\ Screecher=1 -Basking\ Rootwalla=1 Bassara\ Tower\ Archer=1 Bastion\ Enforcer=1 Bastion\ Inventor=1 Bastion\ Mastodon=1 -Bathe\ in\ Dragonfire=1 Bathe\ in\ Light=1 -Baton\ of\ Courage=1 -Battered\ Golem=1 Batterhorn=1 Battering\ Craghorn=1 Battering\ Krasis=1 @@ -651,16 +680,16 @@ Battering\ Sliver=1 Battering\ Wurm=1 Battle-Mad\ Ronin=1 Battle-Rattle\ Shaman=1 -Battle\ Brawler=1 Battle\ Hurda=1 Battle\ Mastery=1 +Battle\ Screech=1 Battle\ Sliver=1 Battle\ Squadron=1 Battle\ of\ Wits=1 Battlefield\ Medic=1 +Battlefield\ Percher=1 Battlefield\ Scavenger=1 Battlefield\ Thaumaturge=1 -Battleflight\ Eagle=1 Battlefront\ Krushok=1 Battlegate\ Mimic=1 Battlegrace\ Angel=1 @@ -671,26 +700,32 @@ Battlewand\ Oak=1 Battlewise\ Hoplite=1 Battlewise\ Valor=1 Batwing\ Brume=1 +Bay\ Falcon=1 Bayou\ Dragonfly=1 -Bazaar\ Krovod=1 -Bazaar\ Trader=1 -Beacon\ Behemoth=1 Beacon\ Hawk=1 Beacon\ of\ Destiny=1 Beacon\ of\ Destruction=1 Beacon\ of\ Immortality=1 +Beacon\ of\ Unrest=1 Bear's\ Companion=1 Bearer\ of\ Silence=1 Bearer\ of\ the\ Heavens=1 +Bearscape=1 +Beast\ Attack=1 +Beast\ Hunt=1 +Beast\ of\ Burden=1 Beastbreaker\ of\ Bala\ Ged=1 Beastcaller\ Savant=1 -Beastmaster's\ Magemark=1 +Beckon\ Apparition=1 +Bedlam=1 Bee\ Sting=1 Beetleback\ Chief=1 Beetleform\ Mage=1 -Befoul=1 +Befuddle=1 +Behemoth's\ Herald=1 Behemoth\ Sledge=1 Behind\ the\ Scenes=1 +Belbe's\ Percher=1 Belfry\ Spirit=1 Belligerent\ Brontodon=1 Belligerent\ Hatchling=1 @@ -706,36 +741,42 @@ Belltower\ Sphinx=1 Beloved\ Chaplain=1 Benalish\ Cavalry=1 Benalish\ Commander=1 +Benalish\ Emissary=1 +Benalish\ Heralds=1 Benalish\ Hero=1 +Benalish\ Honor\ Guard=1 +Benalish\ Knight=1 +Benalish\ Lancer=1 +Benalish\ Missionary=1 Benalish\ Trapper=1 Benalish\ Veteran=1 Beneath\ the\ Sands=1 Benediction\ of\ Moons=1 Benefaction\ of\ Rhonas=1 Benevolent\ Ancestor=1 +Benevolent\ Bodyguard=1 Benthic\ Behemoth=1 +Benthic\ Djinn=1 Benthic\ Explorers=1 Benthic\ Giant=1 Benthic\ Infiltrator=1 Bereavement=1 +Berserk\ Murlodont=1 +Berserkers\ of\ Blood\ Ridge=1 Bestial\ Menace=1 -Betrayal\ of\ Flesh=1 -Betrothed\ of\ Fire=1 Bewilder=1 Bident\ of\ Thassa=1 +Bile\ Blight=1 Bile\ Urchin=1 Binding\ Agony=1 -Binding\ Grasp=1 Binding\ Mummy=1 Biomantic\ Mastery=1 Biomass\ Mutation=1 Bioplasm=1 -Biorhythm=1 Bioshift=1 Biovisionary=1 Birthing\ Hulk=1 Bishop's\ Soldier=1 -Bishop\ of\ Binding=1 Bishop\ of\ Rebirth=1 Bishop\ of\ the\ Bloodstained=1 Biting\ Rain=1 @@ -745,17 +786,18 @@ Bitterblade\ Warrior=1 Bitterbow\ Sharpshooters=1 Bitterheart\ Witch=1 Bituminous\ Blast=1 -Black\ Cat=1 Black\ Knight=1 Black\ Oak\ of\ Odunos=1 Black\ Poplar\ Shaman=1 +Blackblade\ Reforged=1 Blackcleave\ Goblin=1 Blade-Tribe\ Berserkers=1 -Blade\ of\ the\ Sixth\ Pride=1 Bladed\ Bracers=1 Bladed\ Pinions=1 +Bladed\ Sentinel=1 Blades\ of\ Velis\ Vel=1 Bladetusk\ Boar=1 +Bladewing's\ Thrall=1 Blanchwood\ Armor=1 Blanchwood\ Treefolk=1 Blast\ of\ Genius=1 @@ -764,21 +806,23 @@ Blastoderm=1 Blaze=1 Blaze\ Commando=1 Blaze\ of\ Glory=1 +Blazethorn\ Scarecrow=1 Blazing\ Blade\ Askari=1 Blazing\ Hellhound=1 Blazing\ Hope=1 Blazing\ Specter=1 Blazing\ Torch=1 -Blazing\ Volley=1 Bleak\ Coven\ Vampires=1 Blessed\ Breath=1 +Blessed\ Light=1 Blessed\ Orator=1 +Blessed\ Reincarnation=1 Blessed\ Reversal=1 Blessed\ Spirits=1 Blessing=1 +Blessing\ of\ Belzenlok=1 Blessing\ of\ Leeches=1 Blessing\ of\ the\ Nephilim=1 -Blessings\ of\ Nature=1 Blight\ Herder=1 Blight\ Keeper=1 Blight\ Sickle=1 @@ -787,16 +831,17 @@ Blighted\ Bat=1 Blighted\ Cataract=1 Blighted\ Fen=1 Blighted\ Gorge=1 +Blighted\ Shaman=1 Blighted\ Steppe=1 Blighted\ Woodland=1 -Blightsoil\ Druid=1 Blightspeaker=1 Blightwidow=1 -Blind-Spot\ Giant=1 Blind\ Creeper=1 +Blind\ Fury=1 Blind\ Hunter=1 -Blind\ Phantasm=1 Blind\ Zealot=1 +Blind\ with\ Anger=1 +Blinding\ Angel=1 Blinding\ Beam=1 Blinding\ Drone=1 Blinding\ Flare=1 @@ -807,10 +852,14 @@ Blinding\ Powder=1 Blinding\ Souleater=1 Blinding\ Spray=1 Blinking\ Spirit=1 +Blinkmoth\ Infusion=1 +Blinkmoth\ Urn=1 Blinkmoth\ Well=1 +Blister\ Beetle=1 Blistercoil\ Weird=1 Blistergrub=1 Blistering\ Barrier=1 +Blistering\ Dieflyn=1 Blisterpod=1 Blitz\ Hellion=1 Blizzard\ Elemental=1 @@ -819,10 +868,11 @@ Bloated\ Toad=1 Blockade\ Runner=1 Blockbuster=1 Blood-Chin\ Fanatic=1 -Blood-Chin\ Rager=1 Blood-Cursed\ Knight=1 Blood\ Bairn=1 Blood\ Celebrant=1 +Blood\ Clock=1 +Blood\ Cultist=1 Blood\ Frenzy=1 Blood\ Funnel=1 Blood\ Host=1 @@ -836,17 +886,20 @@ Blood\ Seeker=1 Blood\ Speaker=1 Blood\ Tithe=1 Blood\ Tribute=1 -Blood\ Tyrant=1 +Blood\ Vassal=1 Bloodbond\ March=1 Bloodbond\ Vampire=1 Bloodbriar=1 +Bloodcrazed\ Goblin=1 Bloodcrazed\ Hoplite=1 Bloodcrazed\ Neonate=1 -Bloodcrazed\ Paladin=1 Bloodcurdler=1 +Bloodfire\ Colossus=1 Bloodfire\ Dwarf=1 Bloodfire\ Enforcers=1 Bloodfire\ Expert=1 +Bloodfire\ Infusion=1 +Bloodfire\ Kavu=1 Bloodfire\ Mentor=1 Bloodfray\ Giant=1 Bloodgift\ Demon=1 @@ -854,57 +907,71 @@ Bloodhall\ Ooze=1 Bloodhall\ Priest=1 Bloodhunter\ Bat=1 Bloodhusk\ Ritualist=1 +Bloodied\ Ghost=1 Bloodletter\ Quill=1 +Bloodline\ Keeper=1 Bloodline\ Shaman=1 Bloodlust\ Inciter=1 Bloodmad\ Vampire=1 Bloodmark\ Mentor=1 -Bloodpyre\ Elemental=1 Bloodrage\ Brawler=1 Bloodrage\ Vampire=1 Bloodrite\ Invoker=1 Bloodrock\ Cyclops=1 Bloodscale\ Prowler=1 Bloodscent=1 -Bloodshot\ Cyclops=1 -Bloodsoaked\ Champion=1 +Bloodshed\ Fever=1 +Bloodshot\ Trainee=1 Bloodstoke\ Howler=1 Bloodstone\ Cameo=1 +Bloodstone\ Goblin=1 +Bloodtallow\ Candle=1 Bloodthirsty\ Ogre=1 Bloodthorn\ Taunter=1 Bloodthrone\ Vampire=1 Bloodwater\ Entity=1 Blossom\ Dryad=1 +Blossoming\ Wreath=1 Blowfly\ Infestation=1 Bludgeon\ Brawl=1 Blunt\ the\ Assault=1 Blur\ of\ Blades=1 Blustersquall=1 +Boa\ Constrictor=1 Boar\ Umbra=1 +Board\ the\ Weatherlight=1 Body\ of\ Jukai=1 Bog-Strider\ Ash=1 +Bog\ Down=1 +Bog\ Elemental=1 +Bog\ Gnarr=1 Bog\ Hoodlums=1 Bog\ Imp=1 +Bog\ Initiate=1 Bog\ Raiders=1 Bog\ Serpent=1 -Bog\ Smugglers=1 Bog\ Tatters=1 Bog\ Wraith=1 +Bog\ Wreckage=1 +Bogardan\ Firefiend=1 +Bogardan\ Hellkite=1 +Bogardan\ Lancer=1 Bogardan\ Phoenix=1 Bogbrew\ Witch=1 Boggart\ Arsonists=1 Boggart\ Birth\ Rite=1 Boggart\ Brute=1 -Boggart\ Forager=1 -Boggart\ Harbinger=1 -Boggart\ Loggers=1 Boggart\ Mob=1 -Boggart\ Ram-Gang=1 Boggart\ Shenanigans=1 +Bogstomper=1 +Boiling\ Blood=1 Boiling\ Earth=1 +Boiling\ Seas=1 Bojuka\ Brigand=1 +Bola\ Warrior=1 Bold\ Defense=1 Bold\ Impaler=1 +Boldwyr\ Heavyweights=1 Boldwyr\ Intimidator=1 Bolt\ of\ Keranos=1 Boltwing\ Marauder=1 @@ -918,35 +985,35 @@ Bonded\ Fetch=1 Bonded\ Horncrest=1 Bonds\ of\ Faith=1 Bonds\ of\ Mortality=1 -Bonds\ of\ Quicksilver=1 Bone\ Flute=1 -Bone\ Harvest=1 +Bone\ Picker=1 Bone\ Saw=1 Bone\ Splinters=1 Bone\ to\ Ash=1 -Bonebreaker\ Giant=1 Bonehoard=1 Boneknitter=1 +Boneshard\ Slasher=1 Bonesplitter\ Sliver=1 Bonethorn\ Valesk=1 Boneyard\ Wurm=1 +Bontu's\ Monument=1 Booby\ Trap=1 +Book\ Burning=1 Book\ of\ Rass=1 Boon\ Satyr=1 Boon\ of\ Emrakul=1 Boon\ of\ Erebos=1 Boonweaver\ Giant=1 +Borborygmos=1 Borderland\ Behemoth=1 Borderland\ Marauder=1 Borderland\ Minotaur=1 Borderland\ Ranger=1 Boreal\ Centaur=1 Boreal\ Griffin=1 -Boris\ Devilboon=1 Boros\ Battleshaper=1 Boros\ Cluestone=1 Boros\ Elite=1 -Boros\ Fury-Shield=1 Boros\ Guildgate=1 Boros\ Guildmage=1 Boros\ Keyrune=1 @@ -957,36 +1024,31 @@ Boros\ Swiftblade=1 Borrowed\ Grace=1 Borrowed\ Hostility=1 Borrowed\ Malevolence=1 -Borrowing\ 100,000\ Arrows=1 Bosh,\ Iron\ Golem=1 +Bosk\ Banneret=1 Bottle\ Gnomes=1 Bottled\ Cloister=1 -Boulder\ Salvo=1 Boulderfall=1 -Bouncing\ Beebles=1 Bound\ //\ Determined=1 Bound\ by\ Moonsilver=1 Bound\ in\ Silence=1 Bounding\ Krasis=1 Bounteous\ Kirin=1 -Bounty\ of\ the\ Luxa=1 Bow\ of\ Nylea=1 Bower\ Passage=1 Brace\ for\ Impact=1 -Braids,\ Conjurer\ Adept=1 -Braidwood\ Sextant=1 +Braids,\ Cabal\ Minion=1 +Braidwood\ Cup=1 Brain\ Freeze=1 Brain\ Gorgers=1 -Brain\ Maggot=1 Brain\ Pry=1 Brain\ Weevil=1 Brain\ in\ a\ Jar=1 Brainbite=1 Brainspoil=1 +Bramble\ Creeper=1 Bramble\ Elemental=1 -Bramblecrush=1 Bramblesnap=1 -Bramblewood\ Paragon=1 Branching\ Bolt=1 Branded\ Brawlers=1 Brass's\ Bounty=1 @@ -994,29 +1056,31 @@ Brass-Talon\ Chimera=1 Brass\ Gnat=1 Brass\ Herald=1 Brass\ Man=1 +Brass\ Secretary=1 Brass\ Squire=1 -Brassclaw\ Orcs=1 -Bravado=1 Brave\ the\ Sands=1 +Brawl-Bash\ Ogre=1 Brawler's\ Plate=1 Brawn=1 Brazen\ Buccaneers=1 Brazen\ Freebooter=1 Brazen\ Scourge=1 Brazen\ Wolves=1 -Breach=1 +Breaching\ Hippocamp=1 Break\ Asunder=1 Break\ Open=1 Break\ of\ Day=1 Breaker\ of\ Armies=1 +Breaking\ Point=1 +Breaking\ Wave=1 Breakneck\ Rider=1 -Breath\ of\ Darigaaz=1 Breath\ of\ Fury=1 Breath\ of\ Life=1 Breath\ of\ Malfegor=1 +Breathstealer=1 Bred\ for\ the\ Hunt=1 Breeding\ Pit=1 -Breezekeeper=1 +Briar\ Patch=1 Briarberry\ Cohort=1 Briarbridge\ Patrol=1 Briarhorn=1 @@ -1029,24 +1093,23 @@ Brighthearth\ Banneret=1 Brigid,\ Hero\ of\ Kinsbaile=1 Brilliant\ Halo=1 Brilliant\ Spectrum=1 -Brilliant\ Ultimatum=1 -Brimstone\ Dragon=1 Brimstone\ Mage=1 -Brimstone\ Volley=1 Brindle\ Boar=1 Brine\ Elemental=1 Brine\ Seer=1 Brine\ Shaman=1 -Bring\ Low=1 +Bring\ to\ Light=1 +Bringer\ of\ the\ Blue\ Dawn=1 Bringer\ of\ the\ Green\ Dawn=1 Bringer\ of\ the\ Red\ Dawn=1 Brink\ of\ Disaster=1 Brink\ of\ Madness=1 Brion\ Stoutarm=1 +Bristling\ Boar=1 Brittle\ Effigy=1 Broken\ Ambitions=1 +Broken\ Bond=1 Broken\ Concentration=1 -Broken\ Fall=1 Broken\ Visage=1 Bronze\ Bombshell=1 Bronze\ Horse=1 @@ -1057,6 +1120,7 @@ Brood\ Butcher=1 Brood\ Keeper=1 Brood\ Monitor=1 Brood\ of\ Cockroaches=1 +Broodbirth\ Viper=1 Broodhatch\ Nantuko=1 Broodhunter\ Wurm=1 Broodmate\ Dragon=1 @@ -1064,32 +1128,24 @@ Broodstar=1 Broodwarden=1 Brothers\ Yamazaki=1 Brothers\ of\ Fire=1 -Browbeat=1 Brown\ Ouphe=1 Browse=1 -Bruna,\ the\ Fading\ Light=1 Brush\ with\ Death=1 -Brutal\ Deceiver=1 Brutal\ Expulsion=1 Brutalizer\ Exarch=1 Brute\ Force=1 Brute\ Strength=1 Bubbling\ Cauldron=1 Buccaneer's\ Bravado=1 -Budoka\ Gardener=1 Builder's\ Blessing=1 Built\ to\ Last=1 Built\ to\ Smash=1 Bull\ Aurochs=1 -Bull\ Cerodon=1 -Bull\ Elephant=1 Bull\ Hippo=1 Bull\ Rush=1 Bullwhip=1 -Bulwark=1 Buoyancy=1 -Burden\ of\ Guilt=1 -Buried\ Alive=1 +Burden\ of\ Greed=1 Burn\ Away=1 Burn\ from\ Within=1 Burn\ the\ Impure=1 @@ -1099,10 +1155,10 @@ Burning-Tree\ Bloodscale=1 Burning\ Anger=1 Burning\ Earth=1 Burning\ Oil=1 -Burning\ Shield\ Askari=1 +Burning\ Palm\ Efreet=1 Burning\ Sun's\ Avatar=1 Burning\ Vengeance=1 -Burnout=1 +Burning\ of\ Xinye=1 Burr\ Grafter=1 Burrenton\ Bombardier=1 Burrenton\ Shield-Bearers=1 @@ -1120,34 +1176,42 @@ Bygone\ Bishop=1 Byway\ Courier=1 Cabal\ Archon=1 Cabal\ Conditioning=1 +Cabal\ Evangel=1 Cabal\ Executioner=1 -Cabal\ Interrogator=1 +Cabal\ Inquisitor=1 +Cabal\ Paladin=1 Cabal\ Patriarch=1 -Cabal\ Ritual=1 Cabal\ Shrine=1 +Cabal\ Surgeon=1 +Cabal\ Torturer=1 Cache\ Raiders=1 -Cached\ Defenses=1 Cackling\ Counterpart=1 -Cackling\ Fiend=1 Cackling\ Flames=1 Cackling\ Imp=1 +Cackling\ Witch=1 Cacophodon=1 Cadaver\ Imp=1 +Cadaverous\ Knight=1 Cage\ of\ Hands=1 +Cagemail=1 Cairn\ Wanderer=1 Calciderm=1 Calciform\ Pools=1 Calcite\ Snapper=1 Calculated\ Dismissal=1 Caldera\ Hellion=1 +Caldera\ Kavu=1 Caldera\ Lake=1 +Caligo\ Skin-Witch=1 Call\ for\ Blood=1 Call\ for\ Unity=1 Call\ of\ the\ Conclave=1 Call\ of\ the\ Full\ Moon=1 Call\ of\ the\ Herd=1 Call\ of\ the\ Nightwing=1 +Call\ of\ the\ Wild=1 Call\ the\ Bloodline=1 +Call\ the\ Cavalry=1 Call\ the\ Gatewatch=1 Call\ the\ Scions=1 Call\ the\ Skybreaker=1 @@ -1157,50 +1221,49 @@ Call\ to\ Heel=1 Call\ to\ Mind=1 Call\ to\ Serve=1 Call\ to\ the\ Feast=1 +Call\ to\ the\ Grave=1 Call\ to\ the\ Kindred=1 +Caller\ of\ Gales=1 Caller\ of\ the\ Pack=1 -Callous\ Giant=1 +Callous\ Oppressor=1 Callow\ Jushi=1 +Caltrops=1 Campaign\ of\ Vengeance=1 Canal\ Monitor=1 Cancel=1 -Candles'\ Glow=1 Candles\ of\ Leng=1 Canker\ Abomination=1 Cankerous\ Thirst=1 Cannibalize=1 +Canopy\ Claws=1 Canopy\ Cover=1 Canopy\ Crawler=1 Canopy\ Gorger=1 Canopy\ Spider=1 -Cantivore=1 +Canyon\ Drake=1 Canyon\ Lurkers=1 Canyon\ Minotaur=1 Canyon\ Wildcat=1 Capashen\ Knight=1 -Capashen\ Standard=1 +Capashen\ Templar=1 Capashen\ Unicorn=1 Capricious\ Efreet=1 Captain's\ Call=1 Captain's\ Claws=1 Captain's\ Hook=1 +Captain's\ Maneuver=1 Captain\ of\ the\ Mists=1 Captivating\ Crew=1 -Captivating\ Glance=1 +Captive\ Flame=1 Captured\ Sunlight=1 -Captured\ by\ the\ Consulate=1 -Carapace=1 Caravan\ Escort=1 Caravan\ Hurda=1 -Caravan\ Vigil=1 Carbonize=1 Careful\ Consideration=1 Caregiver=1 Caress\ of\ Phyrexia=1 -Caribou\ Range=1 Carnage\ Altar=1 Carnage\ Gladiator=1 -Carnage\ Wurm=1 Carnassid=1 Carnifex\ Demon=1 Carnival\ Hellsteed=1 @@ -1208,37 +1271,40 @@ Carnivorous\ Moss-Beast=1 Carnivorous\ Plant=1 Carom=1 Carrier\ Thrall=1 -Carrion\ Ants=1 Carrion\ Beetles=1 Carrion\ Call=1 -Carrion\ Crow=1 Carrion\ Rats=1 Carrion\ Screecher=1 Carrion\ Thrash=1 +Carrion\ Wall=1 +Carrion\ Wurm=1 +Cartel\ Aristocrat=1 Cartographer=1 Cartouche\ of\ Ambition=1 +Cartouche\ of\ Knowledge=1 Cartouche\ of\ Strength=1 -Cartouche\ of\ Zeal=1 Carven\ Caryatid=1 Cascading\ Cataracts=1 Cast\ into\ Darkness=1 Castle=1 +Castle\ Raptors=1 Cat\ Burglar=1 Catacomb\ Sifter=1 Catacomb\ Slug=1 Catalog=1 -Catapult\ Squad=1 +Catalyst\ Elemental=1 Catch\ //\ Release=1 -Cateran\ Brute=1 -Cateran\ Persuader=1 +Cateran\ Kidnappers=1 +Cateran\ Summons=1 Caterwauling\ Boggart=1 Cathar's\ Companion=1 Cathar's\ Shield=1 Cathartic\ Adept=1 Cathedral\ Membrane=1 -Cathedral\ Sanctifier=1 +Cathedral\ of\ War=1 Cathodion=1 Caught\ in\ the\ Brights=1 +Caustic\ Caterpillar=1 Caustic\ Crawler=1 Caustic\ Hound=1 Caustic\ Rain=1 @@ -1246,58 +1312,74 @@ Caustic\ Tar=1 Cautery\ Sliver=1 Cavalry\ Master=1 Cavalry\ Pegasus=1 +Cave\ Sense=1 Cave\ Tiger=1 Cavern\ Crawler=1 Cavern\ Lampad=1 Cavern\ Thoctar=1 +Cease-Fire=1 Ceaseless\ Searblades=1 +Celestial\ Ancient=1 Celestial\ Archon=1 Celestial\ Crusader=1 Celestial\ Dawn=1 Celestial\ Flare=1 +Celestial\ Kirin=1 Celestial\ Mantle=1 Celestial\ Sword=1 Cellar\ Door=1 Cemetery\ Puca=1 -Cemetery\ Reaper=1 Cemetery\ Recruitment=1 +Cenn's\ Enlistment=1 Cenn's\ Heir=1 Cenn's\ Tactician=1 Centaur's\ Herald=1 Centaur\ Archer=1 Centaur\ Battlemaster=1 +Centaur\ Chieftain=1 Centaur\ Courser=1 Centaur\ Glade=1 Centaur\ Healer=1 Centaur\ Omenreader=1 -Centaur\ Safeguard=1 +Centaur\ Rootcaster=1 Center\ Soul=1 -Cephalid\ Constable=1 -Cephalid\ Pathmage=1 +Cephalid\ Aristocrat=1 +Cephalid\ Broker=1 +Cephalid\ Illusionist=1 +Cephalid\ Inkshrouder=1 +Cephalid\ Looter=1 Cephalid\ Retainer=1 Cephalid\ Sage=1 +Cephalid\ Scout=1 +Cephalid\ Shrine=1 Cerebral\ Eruption=1 Cerebral\ Vortex=1 +Ceremonial\ Guard=1 +Cerodon\ Yearling=1 Certain\ Death=1 Cerulean\ Sphinx=1 -Cerulean\ Wisps=1 +Cerulean\ Wyvern=1 Cessation=1 -Cetavolver=1 -Chain\ of\ Acid=1 +Ceta\ Disciple=1 +Ceta\ Sanctuary=1 Chain\ of\ Plasma=1 Chain\ of\ Silence=1 Chainbreaker=1 Chained\ Throatseeker=1 -Chalice\ of\ Life=1 +Chained\ to\ the\ Rocks=1 +Chainer's\ Torment=1 +Chainflinger=1 Chamber\ of\ Manipulation=1 +Chambered\ Nautilus=1 Chameleon\ Blur=1 Champion's\ Drake=1 Champion\ Lancer=1 Champion\ of\ Arashin=1 Champion\ of\ Dusk=1 Champion\ of\ Rhonas=1 +Champion\ of\ the\ Flame=1 Chancellor\ of\ the\ Dross=1 -Chancellor\ of\ the\ Spires=1 +Chancellor\ of\ the\ Forge=1 Chandra's\ Fury=1 Chandra's\ Ignition=1 Chandra's\ Outrage=1 @@ -1305,6 +1387,7 @@ Chandra's\ Phoenix=1 Chandra's\ Pyrohelix=1 Chandra's\ Revolution=1 Chandra's\ Spitfire=1 +Chandra\ Nalaar=1 Change\ of\ Heart=1 Changeling\ Berserker=1 Changeling\ Hero=1 @@ -1312,61 +1395,66 @@ Changeling\ Sentinel=1 Changeling\ Titan=1 Channel\ Harm=1 Channel\ the\ Suns=1 +Channeler\ Initiate=1 Chant\ of\ Vitu-Ghazi=1 Chaos\ Charm=1 Chaos\ Imps=1 Chaos\ Maw=1 Chaotic\ Backlash=1 Chaplain's\ Blessing=1 -Char-Rumbler=1 Char=1 +Charge=1 Charge\ Across\ the\ Araba=1 Charging\ Badger=1 -Charging\ Cinderhorn=1 Charging\ Griffin=1 Charging\ Monstrosaur=1 +Charging\ Paladin=1 Charging\ Rhino=1 Charging\ Slateback=1 Charging\ Tuskodon=1 -Chariot\ of\ Victory=1 -Chariot\ of\ the\ Sun=1 -Charm\ Peddler=1 Charmbreaker\ Devils=1 -Charnelhoard\ Wurm=1 +Charmed\ Griffin=1 Chartooth\ Cougar=1 Chasm\ Drake=1 Chasm\ Guide=1 +Chastise=1 Chemister's\ Trick=1 Cherished\ Hatchling=1 Chief\ of\ the\ Edge=1 Chief\ of\ the\ Foundry=1 Chief\ of\ the\ Scale=1 -Child\ of\ Gaea=1 +Chieftain\ en-Dal=1 Child\ of\ Night=1 -Child\ of\ Thorns=1 +Childhood\ Horror=1 Children\ of\ Korlis=1 +Chill\ Haunting=1 Chill\ of\ Foreboding=1 +Chill\ to\ the\ Bone=1 Chilling\ Grasp=1 Chilling\ Shade=1 +Chime\ of\ Night=1 Chimeric\ Coils=1 Chimeric\ Egg=1 Chimeric\ Idol=1 Chimeric\ Mass=1 Chimeric\ Staff=1 -Chimney\ Imp=1 Chisei,\ Heart\ of\ Oceans=1 Chitinous\ Cloak=1 Chlorophant=1 +Cho-Arrim\ Legate=1 Cho-Manno,\ Revolutionary=1 Choice\ of\ Damnations=1 Choking\ Fumes=1 Choking\ Restraints=1 +Choking\ Tethers=1 Chorus\ of\ Might=1 +Chorus\ of\ the\ Conclave=1 Chorus\ of\ the\ Tides=1 Chosen\ by\ Heliod=1 Chosen\ of\ Markov=1 +Chrome\ Steed=1 Chromescale\ Drake=1 -Chromeshell\ Crab=1 +Chromium=1 Chronatog\ Totem=1 Chronic\ Flooding=1 Chronicler\ of\ Heroes=1 @@ -1376,33 +1464,28 @@ Chronosavant=1 Chronostutter=1 Chronozoa=1 Chub\ Toad=1 +Churning\ Eddy=1 Cinder\ Barrens=1 +Cinder\ Cloud=1 Cinder\ Crawler=1 Cinder\ Elemental=1 -Cinder\ Hellion=1 -Cinder\ Marsh=1 Cinder\ Pyromancer=1 Cinder\ Seer=1 Cinder\ Shade=1 -Cinder\ Storm=1 -Cinder\ Wall=1 Cinderhaze\ Wretch=1 Circle\ of\ Affliction=1 Circle\ of\ Elders=1 Circle\ of\ Flame=1 Circle\ of\ Protection:\ Artifacts=1 -Circle\ of\ Protection:\ Black=1 Circle\ of\ Protection:\ Shadow=1 Circle\ of\ Protection:\ White=1 Circle\ of\ Solace=1 Circling\ Vultures=1 Circu,\ Dimir\ Lobotomist=1 -Circular\ Logic=1 Citadel\ Castellan=1 -Citanul\ Centaurs=1 Citanul\ Druid=1 +Citanul\ Flute=1 Citanul\ Woodreaders=1 -City\ in\ a\ Bottle=1 Civic\ Guildmage=1 Civic\ Saber=1 Civic\ Wayfinder=1 @@ -1414,15 +1497,15 @@ Clarion\ Ultimatum=1 Clash\ of\ Realities=1 Clash\ of\ Wills=1 Claustrophobia=1 -Claws\ of\ Gix=1 Claws\ of\ Valakut=1 -Claws\ of\ Wirewood=1 Clay\ Statue=1 +Cleanse=1 Cleansing\ Beam=1 +Cleansing\ Meditation=1 Cleansing\ Ray=1 +Clear=1 Clear\ Shot=1 Clear\ a\ Path=1 -Clearwater\ Goblet=1 Clergy\ en-Vec=1 Cleric\ of\ the\ Forward\ Order=1 Clickslither=1 @@ -1434,30 +1517,28 @@ Clinging\ Anemones=1 Clinging\ Mists=1 Clip\ Wings=1 Cloak\ and\ Dagger=1 -Cloak\ of\ Confusion=1 -Cloak\ of\ Invisibility=1 Cloak\ of\ Mists=1 Cloaked\ Siren=1 Clock\ of\ Omens=1 Clockspinning=1 Clockwork\ Avian=1 -Clockwork\ Beast=1 Clockwork\ Beetle=1 +Clockwork\ Condor=1 Clockwork\ Dragon=1 Clockwork\ Gnomes=1 Clockwork\ Hydra=1 -Clockwork\ Steed=1 -Clockwork\ Swarm=1 Cloistered\ Youth=1 Clone=1 Clone\ Shell=1 +Close\ Quarters=1 +Clot\ Sliver=1 Cloud\ Crusader=1 -Cloud\ Djinn=1 Cloud\ Dragon=1 Cloud\ Elemental=1 Cloud\ Manta=1 Cloud\ Spirit=1 Cloud\ Sprite=1 +Cloud\ of\ Faeries=1 Cloudblazer=1 Cloudchaser\ Kestrel=1 Cloudcrest\ Lake=1 @@ -1467,18 +1548,21 @@ Cloudheath\ Drake=1 Cloudhoof\ Kirin=1 Cloudpost=1 Cloudreach\ Cavalry=1 +Cloudreader\ Sphinx=1 Cloudseeder=1 +Cloudshift=1 Cloudskate=1 -Cloudthresher=1 Cloven\ Casting=1 Clutch\ of\ Currents=1 Clutch\ of\ Undeath=1 Clutch\ of\ the\ Undercity=1 Coal\ Golem=1 Coal\ Stoker=1 +Coalition\ Flag=1 Coalition\ Victory=1 Coast\ Watcher=1 Coastal\ Discovery=1 +Coastal\ Drake=1 Coastal\ Hornclaw=1 Coat\ with\ Venom=1 Coax\ from\ the\ Blind\ Eternities=1 @@ -1487,26 +1571,30 @@ Cobblebrute=1 Cobbled\ Wings=1 Cobra\ Trap=1 Cockatrice=1 +Codex\ Shredder=1 Coerced\ Confession=1 Coercion=1 Cognivore=1 Cogwork\ Assembler=1 Cogworker's\ Puzzleknot=1 Coiled\ Tinviper=1 -Coiling\ Oracle=1 +Coiling\ Woodworm=1 +Coils\ of\ the\ Medusa=1 +Cold-Water\ Snapper=1 Colfenor's\ Plans=1 Colfenor's\ Urn=1 Collective\ Blessing=1 +Collective\ Defiance=1 Collective\ Effort=1 Colos\ Yearling=1 Colossal\ Dreadmaw=1 Colossal\ Heroics=1 +Colossal\ Might=1 Colossal\ Whale=1 Colossapede=1 Colossus\ of\ Akros=1 Colossus\ of\ Sardia=1 Coma\ Veil=1 -Combat\ Medic=1 Combust=1 Commander's\ Authority=1 Commander\ Greven\ il-Vec=1 @@ -1519,10 +1607,10 @@ Comparative\ Analysis=1 Compelling\ Argument=1 Compelling\ Deterrence=1 Complete\ Disregard=1 +Complex\ Automaton=1 +Complicate=1 Composite\ Golem=1 -Compost=1 Compulsory\ Rest=1 -Concentrate=1 Concerted\ Effort=1 Conclave's\ Blessing=1 Conclave\ Equenaut=1 @@ -1532,21 +1620,20 @@ Concordia\ Pegasus=1 Conduit\ of\ Ruin=1 Conduit\ of\ Storms=1 Cone\ of\ Flame=1 +Confessor=1 Confirm\ Suspicions=1 Confiscate=1 +Confiscation\ Coup=1 Confront\ the\ Unknown=1 -Confusion\ in\ the\ Ranks=1 Congregate=1 Congregation\ at\ Dawn=1 -Conifer\ Strider=1 Conjured\ Currency=1 +Conjurer's\ Ban=1 Conquer=1 Conquering\ Manticore=1 -Conqueror's\ Galleon=1 Conqueror's\ Pledge=1 Consecrate\ Land=1 Consecrated\ by\ Blood=1 -Consign\ //\ Oblivion=1 Consign\ to\ Dream=1 Consign\ to\ Dust=1 Constricting\ Sliver=1 @@ -1559,14 +1646,16 @@ Consulate\ Surveillance=1 Consulate\ Turret=1 Consult\ the\ Necrosages=1 Consume\ Spirit=1 +Consume\ Strength=1 Consume\ the\ Meek=1 +Consuming\ Aberration=1 Consuming\ Bonfire=1 Consuming\ Ferocity=1 Consuming\ Fervor=1 Consuming\ Sinkhole=1 Consuming\ Vortex=1 Consumptive\ Goo=1 -Contagion\ Engine=1 +Contagion\ Clasp=1 Contagious\ Nim=1 Containment\ Membrane=1 Contaminated\ Bond=1 @@ -1577,30 +1666,26 @@ Contingency\ Plan=1 Contraband\ Kingpin=1 Contract\ Killing=1 Contradict=1 +Control\ Magic=1 Controvert=1 Conundrum\ Sphinx=1 -Convalescence=1 Convalescent\ Care=1 Conversion\ Chamber=1 Convicted\ Killer=1 Conviction=1 Convincing\ Mirage=1 Convolute=1 -Convulsing\ Licid=1 Coordinated\ Assault=1 Coordinated\ Barrage=1 Copper\ Carapace=1 Copper\ Myr=1 +Copper\ Tablet=1 Copperhoof\ Vorrac=1 Copperhorn\ Scout=1 -Coral\ Atoll=1 Coral\ Barrier=1 Coral\ Eel=1 -Coral\ Fighters=1 -Coral\ Helm=1 Coral\ Merfolk=1 Coral\ Trickster=1 -Coralhelm\ Commander=1 Coralhelm\ Guide=1 Core\ Prowler=1 Corpse\ Blockade=1 @@ -1608,14 +1693,17 @@ Corpse\ Churn=1 Corpse\ Connoisseur=1 Corpse\ Cur=1 Corpse\ Hauler=1 +Corpse\ Lunge=1 Corpse\ Traders=1 Corpsehatch=1 Corpsejack\ Menace=1 -Corpulent\ Corpse=1 +Corpseweft=1 Corrosive\ Gale=1 Corrosive\ Mentor=1 +Corrosive\ Ooze=1 Corrupt=1 Corrupt\ Eunuchs=1 +Corrupt\ Official=1 Corrupted\ Conscience=1 Corrupted\ Crossroads=1 Corrupted\ Grafstone=1 @@ -1623,26 +1711,29 @@ Corrupted\ Harvester=1 Corrupted\ Resolve=1 Corrupted\ Roots=1 Corrupted\ Zendikon=1 +Corrupting\ Licid=1 Cosi's\ Ravager=1 -Cosi's\ Trickster=1 Cosmic\ Horror=1 -Cosmic\ Larva=1 Costly\ Plunder=1 +Council\ of\ the\ Absolute=1 Counsel\ of\ the\ Soratami=1 Counterbore=1 Counterflux=1 Counterlash=1 Countermand=1 +Countervailing\ Winds=1 Countless\ Gears\ Renegade=1 +Countryside\ Crusher=1 Courageous\ Outrider=1 Courier's\ Capsule=1 Courier\ Griffin=1 -Courier\ Hawk=1 Coursers'\ Accord=1 Court\ Archers=1 Court\ Homunculus=1 Court\ Hussar=1 Court\ Street\ Denizen=1 +Courtly\ Provocateur=1 +Covenant\ of\ Blood=1 Covenant\ of\ Minds=1 Cover\ of\ Winter=1 Cowardice=1 @@ -1653,7 +1744,7 @@ Crab\ Umbra=1 Crabapple\ Cohort=1 Crackdown\ Construct=1 Crackleburr=1 -Crackling\ Doom=1 +Crackling\ Club=1 Crackling\ Perimeter=1 Crackling\ Triton=1 Cradle\ Guard=1 @@ -1665,56 +1756,62 @@ Crafty\ Pathmage=1 Crag\ Puca=1 Cragganwick\ Cremator=1 Cranial\ Archive=1 -Crash=1 +Cranial\ Extraction=1 Crash\ Landing=1 Crash\ Through=1 Crash\ of\ Rhinos=1 Crash\ the\ Ramparts=1 +Crashing\ Boars=1 +Crashing\ Centaur=1 Crashing\ Tide=1 Crater's\ Claws=1 Crater\ Elemental=1 Crater\ Hellion=1 Craterize=1 Craven\ Giant=1 -Craw\ Giant=1 Craw\ Wurm=1 Crawling\ Filth=1 Crawling\ Sensation=1 +Crazed\ Armodon=1 Crazed\ Goblin=1 +Creakwood\ Ghoul=1 Cream\ of\ the\ Crop=1 -Creeperhulk=1 Creeping\ Dread=1 Creeping\ Mold=1 Creeping\ Renaissance=1 Creepy\ Doll=1 Cremate=1 Crescendo\ of\ War=1 +Crested\ Craghorn=1 Crested\ Herdcaller=1 Crib\ Swap=1 -Crime\ //\ Punishment=1 +Crimson\ Hellkite=1 Crimson\ Mage=1 Crimson\ Manticore=1 Crimson\ Muckwader=1 Crimson\ Roc=1 +Crimson\ Wisps=1 Crippling\ Blight=1 Crippling\ Chill=1 Crocanura=1 Crocodile\ of\ the\ Crossing=1 Crookclaw\ Transmuter=1 Crop\ Sigil=1 +Crosis's\ Attendant=1 Crossbow\ Ambush=1 Crossbow\ Infantry=1 Crossroads\ Consecrator=1 +Crosstown\ Courier=1 Crossway\ Vampire=1 Crosswinds=1 Crovax,\ Ascendant\ Hero=1 +Crovax\ the\ Cursed=1 Crow\ of\ Dark\ Tidings=1 Crowd's\ Favor=1 Crowd\ of\ Cinders=1 Crown\ of\ Ascension=1 -Crown\ of\ Awe=1 -Crown\ of\ Convergence=1 Crown\ of\ Empires=1 +Crown\ of\ Flames=1 Crown\ of\ Fury=1 Crown\ of\ Suspicion=1 Crown\ of\ Vigor=1 @@ -1729,18 +1826,19 @@ Cruel\ Finality=1 Cruel\ Revival=1 Cruel\ Sadist=1 Crumble=1 -Crumbling\ Colossus=1 Crumbling\ Vestige=1 Crusader\ of\ Odric=1 +Crush=1 Crush\ Underfoot=1 Crusher\ Zendikon=1 Crushing\ Canopy=1 +Crushing\ Pain=1 Crushing\ Vines=1 Cry\ of\ Contrition=1 Cryoclasm=1 Crypsis=1 Crypt\ Champion=1 -Crypt\ Creeper=1 +Crypt\ Cobra=1 Crypt\ Ripper=1 Crypt\ of\ the\ Eternals=1 Cryptborn\ Horror=1 @@ -1748,43 +1846,43 @@ Cryptic\ Annelid=1 Cryptic\ Cruiser=1 Cryptic\ Serpent=1 Cryptolith\ Fragment=1 -Cryptoplasm=1 Cryptwailing=1 Crystal\ Ball=1 -Crystal\ Golem=1 Crystal\ Rod=1 Crystal\ Seer=1 Crystal\ Shard=1 Crystal\ Spray=1 Crystalline\ Nautilus=1 +Crystallization=1 Cudgel\ Troll=1 Culling\ Dais=1 Culling\ Drone=1 Culling\ Mark=1 +Culling\ Scales=1 Culling\ Sun=1 Cult\ of\ the\ Waxing\ Moon=1 -Cultbrand\ Cinder=1 Cultist's\ Staff=1 Cultivator's\ Caravan=1 Cultivator\ Drone=1 Cultivator\ of\ Blades=1 Cumber\ Stone=1 -Cunning=1 +Cunning\ Bandit=1 Cunning\ Breezedancer=1 Cunning\ Lethemancer=1 Cunning\ Sparkmage=1 Cunning\ Strike=1 Cunning\ Survivor=1 +Curator's\ Ward=1 +Curator\ of\ Mysteries=1 Curio\ Vendor=1 Curiosity=1 Curious\ Homunculus=1 -Curse\ of\ Bloodletting=1 -Curse\ of\ Echoes=1 -Curse\ of\ Misfortunes=1 +Curse\ of\ Death's\ Hold=1 Curse\ of\ Oblivion=1 Curse\ of\ Stalked\ Prey=1 Curse\ of\ Thirst=1 Curse\ of\ Wizardry=1 +Curse\ of\ the\ Cabal=1 Curse\ of\ the\ Nightly\ Hunt=1 Curse\ of\ the\ Swine=1 Cursebreak=1 @@ -1793,59 +1891,59 @@ Cursed\ Minotaur=1 Cursed\ Monstrosity=1 Cursed\ Rack=1 Cursed\ Scroll=1 +Curtain\ of\ Light=1 Custodi\ Soulbinders=1 Custodian\ of\ the\ Trove=1 Cut\ the\ Earthly\ Bond=1 Cut\ the\ Tethers=1 Cutthroat\ Maneuver=1 Cutthroat\ il-Dal=1 -Cyclical\ Evolution=1 +Cycle\ of\ Life=1 Cyclone\ Sire=1 Cyclopean\ Giant=1 Cyclopean\ Mummy=1 Cyclopean\ Snare=1 -Cyclopean\ Tomb=1 Cyclops\ Gladiator=1 +Cyclops\ Tyrant=1 Cyclops\ of\ Eternal\ Fury=1 Cyclops\ of\ One-Eyed\ Pass=1 -Cylian\ Elf=1 -Cylian\ Sunsinger=1 Cystbearer=1 Cytoplast\ Manipulator=1 Cytoplast\ Root-Kin=1 Cytoshape=1 Cytospawn\ Shambler=1 -D'Avenant\ Archer=1 -D'Avenant\ Healer=1 +D'Avenant\ Trapper=1 Dack's\ Duplicate=1 Dagger\ of\ the\ Worthy=1 Daggerback\ Basilisk=1 +Daggerclaw\ Imp=1 Daggerdrome\ Imp=1 Daily\ Regimen=1 Dakmor\ Lancer=1 -Dakmor\ Plague=1 Dakra\ Mystic=1 Dampen\ Thought=1 Dampening\ Pulse=1 -Damping\ Engine=1 Damping\ Matrix=1 -Dance\ of\ Many=1 Dance\ of\ Shadows=1 Dance\ of\ the\ Skywise=1 Dance\ with\ Devils=1 Dancing\ Scimitar=1 -Dandan=1 +Dandn=1 Daraja\ Griffin=1 +Darba=1 Daredevil\ Dragster=1 -Darigaaz's\ Charm=1 +Darigaaz's\ Attendant=1 +Darigaaz's\ Caldera=1 Daring\ Apprentice=1 +Daring\ Archaeologist=1 Daring\ Buccaneer=1 Daring\ Demolition=1 +Daring\ Leap=1 Daring\ Saboteur=1 Daring\ Skyjek=1 Daring\ Sleuth=1 -Daring\ Thief=1 Dark\ Banishing=1 +Dark\ Bargain=1 Dark\ Betrayal=1 Dark\ Dabbling=1 Dark\ Favor=1 @@ -1856,27 +1954,25 @@ Dark\ Intimations=1 Dark\ Nourishment=1 Dark\ Privilege=1 Dark\ Revenant=1 -Dark\ Salvation=1 +Dark\ Supplicant=1 Dark\ Temper=1 Dark\ Tutelage=1 Dark\ Withering=1 +Darkheart\ Sliver=1 Darkling\ Stalker=1 -Darklit\ Gargoyle=1 +Darkslick\ Drake=1 Darksteel\ Axe=1 Darksteel\ Brute=1 Darksteel\ Gargoyle=1 -Darksteel\ Juggernaut=1 Darksteel\ Myr=1 -Darksteel\ Relic=1 +Darksteel\ Pendant=1 Darksteel\ Sentinel=1 Darkthicket\ Wolf=1 Darkwatch\ Elves=1 -Daru\ Cavalier=1 +Darkwater\ Egg=1 Daru\ Encampment=1 -Daru\ Healer=1 Daru\ Lancer=1 -Daru\ Sanctifier=1 -Daru\ Stinger=1 +Daru\ Mender=1 Dash\ Hopes=1 Dauntless\ Aven=1 Dauntless\ Cathar=1 @@ -1884,35 +1980,38 @@ Dauntless\ Dourbark=1 Dauntless\ Onslaught=1 Dauntless\ River\ Marshal=1 Dauthi\ Cutthroat=1 -Dauthi\ Embrace=1 Dauthi\ Jackal=1 Dauthi\ Marauder=1 -Dauthi\ Mercenary=1 Dauthi\ Mindripper=1 Dauthi\ Trapper=1 Dauthi\ Warlord=1 Dawn's\ Reflection=1 +Dawn\ Elemental=1 Dawn\ Gryff=1 Dawn\ to\ Dusk=1 Dawnbringer\ Charioteers=1 Dawnfeather\ Eagle=1 +Dawnglare\ Invoker=1 Dawnglow\ Infusion=1 Dawning\ Purist=1 Dawnray\ Archer=1 Dawnstrike\ Paladin=1 Dawntreader\ Elk=1 Daxos\ of\ Meletis=1 -Day\ of\ Destiny=1 Day\ of\ the\ Dragons=1 +Daybreak\ Chaplain=1 Daybreak\ Ranger=1 Dazzling\ Beauty=1 Dazzling\ Ramparts=1 Dazzling\ Reflection=1 +Dead-Iron\ Sledge=1 Dead\ //\ Gone=1 Dead\ Drop=1 Dead\ Man's\ Chest=1 Dead\ Reveler=1 +Dead\ Ringers=1 Dead\ Weight=1 +Deadapult=1 Deadbridge\ Goliath=1 Deadbridge\ Shaman=1 Deadeye\ Brawler=1 @@ -1923,112 +2022,128 @@ Deadeye\ Rig-Hauler=1 Deadeye\ Tormentor=1 Deadlock\ Trap=1 Deadly\ Allure=1 +Deadly\ Designs=1 +Deadly\ Grub=1 Deadly\ Insect=1 Deadly\ Recluse=1 Deadly\ Wanderings=1 -Deadwood\ Treefolk=1 Dearly\ Departed=1 -Death's-Head\ Buzzard=1 Death's\ Approach=1 Death's\ Duet=1 Death's\ Presence=1 Death-Hood\ Cobra=1 Death\ Bomb=1 -Death\ Charmer=1 Death\ Cultist=1 Death\ Denied=1 Death\ Frenzy=1 Death\ Grasp=1 Death\ Match=1 -Death\ Mutation=1 +Death\ Pit\ Offering=1 Death\ Pits\ of\ Rath=1 Death\ Pulse=1 Death\ Rattle=1 Death\ Stroke=1 -Death\ Watch=1 Death\ Wind=1 Death\ by\ Dragons=1 Death\ of\ a\ Thousand\ Stings=1 Deathbellow\ Raider=1 -Deathbringer\ Regent=1 +Deathbloom\ Thallid=1 +Deathbringer\ Thoctar=1 Deathcap\ Cultivator=1 +Deathcoil\ Wurm=1 Deathcult\ Rogue=1 Deathforge\ Shaman=1 Deathgaze\ Cockatrice=1 -Deathknell\ Kami=1 +Deathgazer=1 +Deathgreeter=1 Deathless\ Ancient=1 +Deathless\ Angel=1 Deathless\ Behemoth=1 Deathmark=1 Deathmark\ Prelate=1 +Deathmask\ Nezumi=1 Deathreap\ Ritual=1 -Deathrender=1 Deathspore\ Thallid=1 Debilitating\ Injury=1 Debtor's\ Pulpit=1 +Debtors'\ Knell=1 +Decaying\ Soil=1 Deceiver\ of\ Form=1 Decimator\ Beetle=1 -Decimator\ Web=1 Decision\ Paralysis=1 -Declaration\ of\ Naught=1 +Declare\ Dominance=1 Decoction\ Module=1 Decommission=1 Decompose=1 +Decomposition=1 Deconstruct=1 Decorated\ Griffin=1 Deem\ Worthy=1 Deep-Sea\ Kraken=1 Deep-Sea\ Terror=1 Deep-Slumber\ Titan=1 -Deep\ Spawn=1 +Deep\ Freeze=1 +Deep\ Reconnaissance=1 Deepcavern\ Imp=1 Deepchannel\ Mentor=1 Deepfathom\ Skulker=1 +Deepfire\ Elemental=1 Deeproot\ Warrior=1 +Deeproot\ Waters=1 +Deeptread\ Merrow=1 Deepwater\ Hypnotist=1 +Deepwood\ Ghoul=1 +Deepwood\ Legate=1 +Deepwood\ Tantiv=1 Deepwood\ Wolverine=1 -Defang=1 Defeat=1 Defend\ the\ Hearth=1 -Defender\ of\ Chaos=1 +Defender\ en-Vec=1 Defender\ of\ Law=1 Defender\ of\ the\ Order=1 Defensive\ Formation=1 Defensive\ Maneuvers=1 -Defensive\ Stance=1 Defiant\ Bloodlord=1 Defiant\ Elf=1 Defiant\ Greatmaw=1 Defiant\ Khenra=1 Defiant\ Ogre=1 Defiant\ Salvager=1 -Defiant\ Vanguard=1 +Defiant\ Strike=1 +Defiling\ Tears=1 Deflection=1 +Deft\ Dismissal=1 Deft\ Duelist=1 Deftblade\ Elite=1 Defy\ Death=1 +Defy\ Gravity=1 Dega\ Sanctuary=1 -Degavolver=1 Deglamer=1 Dehydration=1 Deicide=1 -Delaying\ Shield=1 Delirium\ Skeins=1 -Deluge=1 -Dementia\ Bat=1 +Delusions\ of\ Mediocrity=1 +Dematerialize=1 Dementia\ Sliver=1 Demolish=1 Demolition\ Stomper=1 Demon's\ Grasp=1 +Demon's\ Herald=1 Demon's\ Horn=1 Demon's\ Jester=1 Demonfire=1 Demonic\ Appetite=1 +Demonic\ Collusion=1 +Demonic\ Consultation=1 Demonic\ Taskmaster=1 Demonic\ Torment=1 +Demonic\ Vigor=1 Demonmail\ Hauberk=1 Demonspine\ Whip=1 +Demoralize=1 Demystify=1 Denizen\ of\ the\ Deep=1 +Dense\ Canopy=1 Deny\ Existence=1 Deny\ Reality=1 Depala,\ Pilot\ Exemplar=1 @@ -2038,110 +2153,110 @@ Deranged\ Assistant=1 Deranged\ Hermit=1 Deranged\ Outcast=1 Deranged\ Whelp=1 -Descendant\ of\ Kiyomaro=1 +Dermoplasm=1 Descendant\ of\ Soramaro=1 -Desecration\ Demon=1 +Descent\ into\ Madness=1 +Desecrated\ Earth=1 Desecration\ Elemental=1 Desecration\ Plague=1 Desecrator\ Hag=1 Desert's\ Hold=1 +Desert=1 Desert\ Cerodon=1 +Desert\ Twister=1 Desert\ of\ the\ Fervent=1 Desert\ of\ the\ Glorified=1 Desert\ of\ the\ Indomitable=1 Desert\ of\ the\ Mindful=1 Desert\ of\ the\ True=1 Deserter's\ Quarters=1 -Desolation=1 Desolation\ Giant=1 Desolation\ Twin=1 Desperate\ Castaways=1 Desperate\ Charge=1 +Desperate\ Gambit=1 Desperate\ Ravings=1 Desperate\ Sentry=1 Desperate\ Stand=1 Despise=1 Despoiler\ of\ Souls=1 -Despondency=1 Destined\ //\ Lead=1 Destroy\ the\ Evidence=1 +Destructive\ Force=1 Destructive\ Tampering=1 +Destructive\ Urge=1 Detainment\ Spell=1 -Detonate=1 -Detritivore=1 -Devastating\ Summons=1 Deviant\ Glee=1 Devil's\ Play=1 Devils'\ Playground=1 Devilthorn\ Fox=1 Devoted\ Crop-Mate=1 -Devoted\ Retainer=1 Devotee\ of\ Strength=1 Devour\ in\ Flames=1 +Devour\ in\ Shadow=1 Devouring\ Greed=1 Devouring\ Light=1 Devouring\ Rage=1 +Devouring\ Strossus=1 Devouring\ Swarm=1 Devout\ Chaplain=1 +Devout\ Harpist=1 +Devout\ Lightcaster=1 Devout\ Witness=1 Dewdrop\ Spy=1 Dhund\ Operative=1 -Diabolic\ Machine=1 Diabolic\ Revelation=1 Diabolic\ Tutor=1 Diabolic\ Vision=1 -Dichotomancy=1 -Dictate\ of\ Karametra=1 -Dictate\ of\ the\ Twin\ Gods=1 +Diamond\ Faerie=1 Die\ Young=1 +Diligent\ Excavator=1 Diluvian\ Primordial=1 Dimensional\ Breach=1 Dimensional\ Infiltrator=1 Diminish=1 -Diminishing\ Returns=1 +Dimir\ Charm=1 Dimir\ Cluestone=1 Dimir\ Cutpurse=1 -Dimir\ Guildgate=1 Dimir\ Guildmage=1 Dimir\ House\ Guard=1 Dimir\ Infiltrator=1 Dimir\ Keyrune=1 Dimir\ Machinations=1 -Dimir\ Signet=1 Din\ of\ the\ Fireherd=1 Dingus\ Egg=1 -Dingus\ Staff=1 Dinosaur\ Hunter=1 Dinosaur\ Stampede=1 Dinrova\ Horror=1 Diplomacy\ of\ the\ Wastes=1 +Diplomatic\ Escort=1 Dire\ Fleet\ Captain=1 Dire\ Fleet\ Hoarder=1 Dire\ Fleet\ Interloper=1 Dire\ Fleet\ Neckbreaker=1 Dire\ Undercurrents=1 -Diregraf\ Ghoul=1 -Dirtwater\ Wraith=1 +Diregraf\ Colossus=1 +Diregraf\ Escort=1 +Dirge\ of\ Dread=1 +Dirty\ Wererat=1 Disappear=1 Disappearing\ Act=1 Disarm=1 Disaster\ Radius=1 -Disciple\ of\ Deceit=1 Disciple\ of\ Grace=1 Disciple\ of\ Griselbrand=1 -Disciple\ of\ Law=1 +Disciple\ of\ Kangee=1 Disciple\ of\ Malice=1 Disciple\ of\ Phenax=1 Disciple\ of\ Tevesh\ Szat=1 Disciple\ of\ the\ Old\ Ways=1 -Discombobulate=1 +Disciple\ of\ the\ Ring=1 Discordant\ Dirge=1 -Disdainful\ Stroke=1 +Discordant\ Spirit=1 Disease\ Carriers=1 Disembowel=1 -Disempower=1 Disentomb=1 -Disharmony=1 +Disintegrate=1 Dismal\ Failure=1 Dismantle=1 Dismiss\ into\ Dream=1 @@ -2149,17 +2264,16 @@ Disorder=1 Disowned\ Ancestor=1 Dispeller's\ Capsule=1 Dispense\ Justice=1 -Dispersal\ Shield=1 Dispersal\ Technician=1 Disperse=1 +Dispersing\ Orb=1 Displace=1 Displacement\ Wave=1 -Display\ of\ Dominance=1 Disposal\ Mummy=1 Dispossess=1 Disrupting\ Scepter=1 -Disruption\ Aura=1 Disruptive\ Pitmage=1 +Disruptive\ Student=1 Dissension\ in\ the\ Ranks=1 Dissenter's\ Deliverance=1 Dissipate=1 @@ -2168,14 +2282,14 @@ Dissolve=1 Distant\ Memories=1 Distemper\ of\ the\ Blood=1 Distended\ Mindbender=1 -Distorting\ Lens=1 -Disturbed\ Burial=1 -Dive\ Bomber=1 +Distorting\ Wake=1 +Disturbing\ Plot=1 Dive\ Down=1 Divebomber\ Griffin=1 Divergent\ Growth=1 +Diversionary\ Tactics=1 +Divest=1 Divination=1 -Divine\ Congregation=1 Divine\ Deflection=1 Divine\ Favor=1 Divine\ Offering=1 @@ -2183,7 +2297,8 @@ Divine\ Reckoning=1 Divine\ Transformation=1 Divine\ Verdict=1 Diviner's\ Wand=1 -Dizzy\ Spell=1 +Diviner\ Spirit=1 +Diving\ Griffin=1 Dizzying\ Gaze=1 Djeru's\ Renunciation=1 Djeru's\ Resolve=1 @@ -2194,36 +2309,38 @@ Docent\ of\ Perfection=1 Dodecapod=1 Dogged\ Hunter=1 Dogpile=1 +Dolmen\ Gate=1 Domesticated\ Hydra=1 Domestication=1 -Dominaria's\ Judgment=1 Dominator\ Drone=1 -Domineer=1 Dong\ Zhou,\ the\ Tyrant=1 Doom\ Cannon=1 Doomed\ Dissenter=1 +Doomed\ Necromancer=1 Doomgape=1 Doomwake\ Giant=1 Door\ to\ Nothingness=1 Doorkeeper=1 Dormant\ Gomazoa=1 Dormant\ Sliver=1 -Dormant\ Volcano=1 Dosan's\ Oldest\ Chant=1 Double\ Negative=1 -Doubling\ Chant=1 Doubtless\ One=1 Douse\ in\ Gloom=1 Down\ //\ Dirty=1 +Downdraft=1 Downpour=1 Downsize=1 +Dowsing\ Shaman=1 +Dracoplasm=1 Drag\ Down=1 Drag\ Under=1 +Dragon's\ Eye\ Savants=1 Dragon's\ Eye\ Sentry=1 +Dragon's\ Herald=1 Dragon-Scarred\ Bear=1 Dragon-Style\ Twins=1 Dragon\ Appeasement=1 -Dragon\ Arch=1 Dragon\ Bell\ Monk=1 Dragon\ Blood=1 Dragon\ Egg=1 @@ -2241,66 +2358,74 @@ Dragonlord's\ Prerogative=1 Dragonlord's\ Servant=1 Dragonrage=1 Dragonscale\ Boon=1 -Dragonscale\ General=1 Dragonshift=1 Dragonsoul\ Knight=1 -Dragonstorm=1 +Dragonstalker=1 Drain\ the\ Well=1 Draining\ Whelk=1 Drainpipe\ Vermin=1 Drake-Skull\ Cameo=1 Drake\ Familiar=1 Drake\ Hatchling=1 +Drake\ Haven=1 Drake\ Umbra=1 Drakestown\ Forgotten=1 +Drakewing\ Krasis=1 Dralnu's\ Pet=1 +Dralnu,\ Lich\ Lord=1 Dramatic\ Rescue=1 Dramatic\ Reversal=1 Drana's\ Chosen=1 Drana's\ Emissary=1 -Drana,\ Kalastria\ Bloodchief=1 Drastic\ Revelation=1 Dread=1 Dread\ Defiler=1 Dread\ Drone=1 Dread\ Reaper=1 -Dread\ Return=1 Dread\ Slag=1 -Dread\ Slaver=1 Dread\ Specter=1 +Dread\ Warlock=1 Dread\ Wight=1 Dreadbringer\ Lampads=1 -Dreadship\ Reef=1 Dreadwaters=1 Dreadwing=1 Dream's\ Grip=1 -Dream\ Cache=1 Dream\ Chisel=1 Dream\ Fighter=1 +Dream\ Leash=1 Dream\ Prowler=1 +Dream\ Salvage=1 Dream\ Thief=1 Dream\ Tides=1 Dream\ Twist=1 +Dreamborn\ Muse=1 +Dreamcaller\ Siren=1 Dreamcatcher=1 Dreampod\ Druid=1 Dreams\ of\ the\ Dead=1 Dreamscape\ Artist=1 Dreamspoiler\ Witches=1 +Dreamstealer=1 +Dreamstone\ Hedron=1 +Dreamwinder=1 Dreg\ Mangler=1 Dreg\ Reaver=1 +Dregs\ of\ Sorrow=1 Dregscape\ Zombie=1 Drekavac=1 Drelnoch=1 Drift\ of\ the\ Dead=1 +Drifter\ il-Dal=1 Drifting\ Shade=1 Drill-Skimmer=1 Drinker\ of\ Sorrow=1 +Dripping-Tongue\ Zubera=1 Dripping\ Dead=1 Driven\ //\ Despair=1 Driver\ of\ the\ Dead=1 Drogskol\ Cavalry=1 Drogskol\ Shieldmate=1 -Dromad\ Purebred=1 +Dromar's\ Attendant=1 Dromoka's\ Gift=1 Dromoka\ Captain=1 Dromoka\ Dunecaster=1 @@ -2317,6 +2442,7 @@ Dross\ Hopper=1 Dross\ Prowler=1 Dross\ Scorpion=1 Drove\ of\ Elves=1 +Drover\ of\ the\ Mighty=1 Drown\ in\ Filth=1 Drowned=1 Drowned\ Rusalka=1 @@ -2328,25 +2454,26 @@ Drownyard\ Explorers=1 Drownyard\ Temple=1 Drudge\ Beetle=1 Drudge\ Reavers=1 +Drudge\ Sentinel=1 Drudge\ Skeletons=1 +Druid's\ Call=1 Druid's\ Deliverance=1 Druid's\ Familiar=1 +Druid\ Lyrist=1 +Druid\ of\ the\ Anima=1 Druid\ of\ the\ Cowl=1 Druidic\ Satchel=1 Drumhunter=1 Drunau\ Corpse\ Trawler=1 Dry\ Spell=1 Dryad's\ Caress=1 -Dryad's\ Favor=1 Dryad\ Sophisticate=1 -Dual\ Casting=1 Dual\ Shot=1 +Dub=1 Dubious\ Challenge=1 Duct\ Crawler=1 -Due\ Respect=1 Duergar\ Assailant=1 Duergar\ Cave-Guard=1 -Duergar\ Hedge-Mage=1 Duergar\ Mine-Captain=1 Dukhara\ Peafowl=1 Dukhara\ Scavenger=1 @@ -2358,6 +2485,7 @@ Dunerider\ Outlaw=1 Dunes\ of\ the\ Dead=1 Dungeon\ Geists=1 Dungeon\ Shade=1 +Duplicity=1 Durable\ Handicraft=1 Durkwood\ Baloth=1 Durkwood\ Tracker=1 @@ -2369,25 +2497,31 @@ Duskborne\ Skymarcher=1 Duskdale\ Wurm=1 Duskhunter\ Bat=1 Duskmantle,\ House\ of\ Shadow=1 -Duskmantle\ Guildmage=1 Duskmantle\ Prowler=1 -Duskrider\ Falcon=1 +Duskrider\ Peregrine=1 +Duskwalker=1 Duskworker=1 +Dust\ Corona=1 Dust\ Elemental=1 -Dust\ Stalker=1 -Dust\ of\ Moments=1 Dutiful\ Attendant=1 Dutiful\ Return=1 Dutiful\ Servants=1 +Dutiful\ Thrull=1 Duty-Bound\ Dead=1 -Dwarven\ Bloodboiler=1 +Dwarven\ Berserker=1 +Dwarven\ Blastminer=1 Dwarven\ Demolition\ Team=1 +Dwarven\ Driller=1 +Dwarven\ Landslide=1 Dwarven\ Nomad=1 Dwarven\ Patrol=1 -Dwarven\ Ruins=1 +Dwarven\ Priest=1 +Dwarven\ Recruiter=1 Dwarven\ Shrine=1 Dwarven\ Soldier=1 +Dwarven\ Strike\ Force=1 Dwarven\ Vigilantes=1 +Dwindle=1 Dwynen,\ Gilt-Leaf\ Daen=1 Dying\ Wail=1 Dying\ Wish=1 @@ -2395,19 +2529,22 @@ Dynacharge=1 Dynavolt\ Tower=1 Eager\ Cadet=1 Eager\ Construct=1 +Eagle\ of\ the\ Watch=1 Early\ Frost=1 -Earth\ Surge=1 +Earsplitting\ Rats=1 +Earth\ Elemental=1 Earthblighter=1 Earthbrawn=1 Earthen\ Arms=1 Earthshaker=1 Eastern\ Paladin=1 Eater\ of\ Hope=1 -Ebon\ Dragon=1 -Ebon\ Stronghold=1 +Ebon\ Drake=1 +Ebonblade\ Reaper=1 Ebony\ Horse=1 Ebony\ Rhino=1 Ebony\ Treefolk=1 +Echo\ Circlet=1 Echo\ Mage=1 Echo\ Tracer=1 Echoes\ of\ the\ Kin\ Tree=1 @@ -2416,28 +2553,33 @@ Echoing\ Courage=1 Echoing\ Ruin=1 Eddytrail\ Hawk=1 Edifice\ of\ Authority=1 +Edric,\ Spymaster\ of\ Trest=1 Eel\ Umbra=1 Eerie\ Procession=1 Efficient\ Construction=1 Efreet\ Weaponmaster=1 Ego\ Erasure=1 Eidolon\ of\ Countless\ Battles=1 +Eight-and-a-Half-Tails=1 Ekundu\ Cyclops=1 Ekundu\ Griffin=1 Elaborate\ Firecannon=1 Eland\ Umbra=1 Elder\ Cathar=1 -Elder\ Druid=1 +Elder\ Deep-Fiend=1 Elder\ Land\ Wurm=1 +Elder\ Mastery=1 Elder\ Pine\ of\ Jukai=1 Elder\ of\ Laurels=1 Eldrazi\ Aggressor=1 Eldrazi\ Devastator=1 +Eldrazi\ Mimic=1 Eldrazi\ Obligator=1 Eldrazi\ Skyspawner=1 Electrify=1 Electropotence=1 Electrostatic\ Bolt=1 +Electrostatic\ Pummeler=1 Electryte=1 Elegant\ Edgecrafters=1 Elemental\ Appeal=1 @@ -2445,13 +2587,11 @@ Elemental\ Bond=1 Elemental\ Mastery=1 Elemental\ Resonance=1 Elemental\ Uprising=1 -Elephant\ Graveyard=1 +Elephant\ Ambush=1 Elephant\ Guide=1 -Elf\ Replica=1 -Elfhame\ Sanctuary=1 +Elfhame\ Druid=1 Elgaud\ Inquisitor=1 Elgaud\ Shieldmate=1 -Eliminate\ the\ Competition=1 Elite\ Arcanist=1 Elite\ Archers=1 Elite\ Cat\ Warrior=1 @@ -2460,47 +2600,49 @@ Elite\ Javelineer=1 Elite\ Skirmisher=1 Elite\ Vanguard=1 Elixir\ of\ Immortality=1 +Elixir\ of\ Vitality=1 Elkin\ Bottle=1 +Elsewhere\ Flask=1 Elusive\ Krasis=1 -Elusive\ Spellfist=1 Elusive\ Tormentor=1 -Elven\ Cache=1 Elven\ Lyre=1 +Elven\ Riders=1 Elven\ Rite=1 -Elven\ Warhounds=1 Elves\ of\ Deep\ Shadow=1 Elvish\ Aberration=1 Elvish\ Berserker=1 Elvish\ Branchbender=1 Elvish\ Eulogist=1 Elvish\ Fury=1 -Elvish\ Harbinger=1 +Elvish\ Handservant=1 Elvish\ Herder=1 Elvish\ Hexhunter=1 -Elvish\ Hunter=1 Elvish\ Lookout=1 Elvish\ Lyrist=1 Elvish\ Pathcutter=1 -Elvish\ Promenade=1 +Elvish\ Piper=1 +Elvish\ Ranger=1 Elvish\ Scrapper=1 -Elvish\ Skysweeper=1 Elvish\ Soultiller=1 Elvish\ Warrior=1 -Emancipation\ Angel=1 Embalmed\ Brawler=1 Embalmer's\ Tools=1 Ember-Eye\ Wolf=1 -Ember-Fist\ Zubera=1 +Ember\ Beast=1 Ember\ Gale=1 -Ember\ Hauler=1 +Ember\ Shot=1 Ember\ Swallower=1 Emberhorn\ Minotaur=1 Embermaw\ Hellion=1 -Embersmith=1 +Emberstrike\ Duo=1 +Emberwilde\ Augur=1 +Emberwilde\ Caliph=1 +Emblazoned\ Golem=1 Emblem\ of\ the\ Warmind=1 Embodiment\ of\ Fury=1 Embodiment\ of\ Insight=1 Embodiment\ of\ Spring=1 +Embolden=1 Embraal\ Bruiser=1 Embraal\ Gear-Smasher=1 Emergent\ Growth=1 @@ -2515,11 +2657,11 @@ Emmessi\ Tome=1 Emperor's\ Vanguard=1 Emperor\ Crocodile=1 Empty-Shrine\ Kannushi=1 -Empty\ the\ Catacombs=1 Empyreal\ Voyager=1 Empyrial\ Armor=1 Empyrial\ Plate=1 Emrakul's\ Evangel=1 +Emrakul's\ Hatcher=1 Emrakul's\ Influence=1 Enatu\ Golem=1 Encampment\ Keeper=1 @@ -2528,11 +2670,11 @@ Enchantment\ Alteration=1 Encircling\ Fissure=1 Enclave\ Cryptologist=1 Enclave\ Elite=1 -Encroach=1 Encroaching\ Wastes=1 Encrust=1 End\ Hostilities=1 Endangered\ Armodon=1 +Endbringer's\ Revel=1 Endemic\ Plague=1 Endless\ Obedience=1 Endless\ Ranks\ of\ the\ Dead=1 @@ -2540,14 +2682,15 @@ Endless\ Sands=1 Endless\ Scream=1 Endless\ Swarm=1 Endless\ Whispers=1 -Endless\ Wurm=1 Endoskeleton=1 +Endrek\ Sahr,\ Master\ Breeder=1 Endure=1 +Energizer=1 Energy\ Arc=1 Enervate=1 Enfeeblement=1 Engineered\ Might=1 -Engulf\ the\ Shore=1 +Engulfing\ Flames=1 Engulfing\ Slagwurm=1 Enhanced\ Awareness=1 Enigma\ Drake=1 @@ -2563,23 +2706,29 @@ Enraging\ Licid=1 Enshrined\ Memories=1 Enshrouding\ Mist=1 Enslave=1 +Enslaved\ Dwarf=1 Ensouled\ Scimitar=1 Entangling\ Trap=1 Entangling\ Vines=1 Enter\ the\ Unknown=1 Enthralling\ Victor=1 Entomber\ Exarch=1 +Entrails\ Feaster=1 +Entrancing\ Melody=1 Entropic\ Eidolon=1 +Envelop=1 Eon\ Hub=1 Ephara's\ Enlightenment=1 Ephara's\ Radiance=1 Ephemeral\ Shields=1 Ephemeron=1 Epic\ Proportions=1 +Epicenter=1 Epiphany\ Storm=1 Epiphany\ at\ the\ Drownyard=1 Epitaph\ Golem=1 Epochrasite=1 +Equal\ Treatment=1 Equestrian\ Skill=1 Era\ of\ Innovation=1 Eradicate=1 @@ -2588,39 +2737,42 @@ Erdwal\ Illuminator=1 Erdwal\ Ripper=1 Erebos's\ Emissary=1 Erg\ Raiders=1 -Erhnam\ Djinn=1 Eron\ the\ Relentless=1 Errand\ of\ Duty=1 +Errant\ Doomsayers=1 Errant\ Ephemeron=1 Erratic\ Mutation=1 Ersatz\ Gnomes=1 -Escape\ Routes=1 -Esper\ Battlemage=1 -Esper\ Cormorants=1 +Ertai's\ Trickery=1 +Escaped\ Null=1 +Escaped\ Shapeshifter=1 Esper\ Sojourners=1 -Esper\ Stormblade=1 Esperzoa=1 Essence\ Backlash=1 -Essence\ Bottle=1 Essence\ Depleter=1 Essence\ Drain=1 Essence\ Feed=1 +Essence\ Filter=1 Essence\ Flare=1 Essence\ Flux=1 -Etali,\ Primal\ Storm=1 +Essence\ Fracture=1 +Essence\ Leak=1 Etched\ Monstrosity=1 Etched\ Oracle=1 -Eternal\ Dragon=1 +Eternal\ Dominion=1 +Eternal\ Scourge=1 Eternal\ Thirst=1 Eternal\ of\ Harsh\ Truths=1 Eternity\ Snare=1 Ether\ Well=1 Ethercaste\ Knight=1 -Ethereal\ Ambush=1 +Ethereal\ Champion=1 Ethereal\ Guidance=1 Ethereal\ Usher=1 +Etherium\ Astrolabe=1 Ethersworn\ Shieldmage=1 Etherwrought\ Page=1 +Evacuation=1 Evanescent\ Intellect=1 Evangel\ of\ Heliod=1 Evangelize=1 @@ -2629,48 +2781,57 @@ Ever\ After=1 Everbark\ Shaman=1 Everdawn\ Champion=1 Everflame\ Eidolon=1 -Everglove\ Courier=1 +Everflowing\ Chalice=1 +Everglades=1 Evernight\ Shade=1 Evershrike=1 Evil\ Eye\ of\ Orms-by-Gore=1 Evil\ Eye\ of\ Urborg=1 Evil\ Presence=1 Evil\ Twin=1 +Eviscerate=1 Eviscerator=1 Evolution\ Charm=1 Evolution\ Vat=1 -Evolutionary\ Escalation=1 Evolving\ Wilds=1 +Evra,\ Halcyon\ Witness=1 Exalted\ Dragon=1 Exava,\ Rakdos\ Blood\ Witch=1 +Excavation\ Elephant=1 Excavator=1 -Excise=1 Exclusion\ Ritual=1 Excommunicate=1 Excoriate=1 +Excruciator=1 Execute=1 +Executioner's\ Capsule=1 Executioner's\ Hood=1 Executioner's\ Swing=1 Exemplar\ of\ Strength=1 Exert\ Influence=1 +Exhumer\ Thrull=1 Exile=1 +Exile\ into\ Darkness=1 Exiled\ Boggart=1 Exiled\ Doomsayer=1 -Exorcist=1 +Exoskeletal\ Armor=1 +Exotic\ Curse=1 Exotic\ Disease=1 Expedite=1 Expedition\ Envoy=1 Expedition\ Raptor=1 Expel\ from\ Orazca=1 Expendable\ Troops=1 +Experiment\ Kraj=1 Experimental\ Aviator=1 Exploding\ Borders=1 Explorer's\ Scope=1 Explosive\ Apparatus=1 Explosive\ Growth=1 +Explosive\ Impact=1 Explosive\ Revelation=1 -Expose\ Evil=1 Expunge=1 +Exquisite\ Archangel=1 Extinguish\ All\ Hope=1 Extract\ from\ Darkness=1 Extractor\ Demon=1 @@ -2679,6 +2840,7 @@ Extruder=1 Exultant\ Cultist=1 Exultant\ Skymarcher=1 Eye\ Gouge=1 +Eye\ for\ an\ Eye=1 Eye\ of\ the\ Storm=1 Eyeblight's\ Ending=1 Eyeblight\ Assassin=1 @@ -2688,33 +2850,32 @@ Eyes\ in\ the\ Skies=1 Eyes\ of\ the\ Watcher=1 Eyes\ of\ the\ Wisent=1 Ezuri's\ Archers=1 -Ezuri's\ Brigade=1 Fa'adiyah\ Seer=1 +Fable\ of\ Wolf\ and\ Owl=1 Fabled\ Hero=1 Fabrication\ Module=1 -Faceless\ Butcher=1 -Faceless\ Devourer=1 +Face\ of\ Fear=1 Facevaulter=1 +Fact\ or\ Fiction=1 Fade\ from\ Memory=1 Fade\ into\ Antiquity=1 Faerie\ Harbinger=1 Faerie\ Impostor=1 Faerie\ Invaders=1 Faerie\ Mechanist=1 -Faerie\ Noble=1 +Faerie\ Squadron=1 Faerie\ Swarm=1 Faerie\ Tauntings=1 Faerie\ Trickery=1 Failed\ Inspection=1 Failure\ //\ Comply=1 Fairgrounds\ Trumpeter=1 +Fairgrounds\ Warden=1 Faith's\ Fetters=1 -Faith\ Healer=1 Faith\ Unbroken=1 Faith\ of\ the\ Devoted=1 Faithbearer\ Paladin=1 Faithful\ Squire=1 -Falkenrath\ Exterminator=1 Falkenrath\ Gorger=1 Falkenrath\ Marauders=1 Falkenrath\ Noble=1 @@ -2722,38 +2883,32 @@ Falkenrath\ Reaver=1 Falkenrath\ Torturer=1 Fall\ of\ the\ Gavel=1 Fall\ of\ the\ Hammer=1 +Fall\ of\ the\ Thran=1 Fall\ of\ the\ Titans=1 Fallen\ Angel=1 Fallen\ Cleric=1 Fallen\ Ferromancer=1 Fallen\ Ideal=1 Falling\ Timber=1 -Fallow\ Earth=1 -Fallow\ Wurm=1 Fallowsage=1 -False\ Cure=1 False\ Dawn=1 -False\ Defeat=1 -Falter=1 +False\ Memories=1 Familiar's\ Ruse=1 -Familiar\ Ground=1 Famine=1 +Famished\ Ghoul=1 Famished\ Paladin=1 Fan\ Bearer=1 Fanatic\ of\ Mogis=1 Fanatic\ of\ Xenagos=1 -Fanatical\ Firebrand=1 Fang\ Skulkin=1 Fangren\ Firstborn=1 Fangren\ Hunter=1 -Fangren\ Pathcutter=1 Fanning\ the\ Flames=1 Far\ //\ Away=1 +Farbog\ Boneflinger=1 Farbog\ Revenant=1 Farm\ //\ Market=1 -Farrel's\ Mantle=1 Farrel's\ Zealot=1 -Fatal\ Attraction=1 Fatal\ Blow=1 Fatal\ Frenzy=1 Fate\ Foretold=1 @@ -2769,23 +2924,23 @@ Fateful\ Showdown=1 Fatespinner=1 Fathom\ Feeder=1 Fathom\ Fleet\ Boarder=1 +Fathom\ Fleet\ Captain=1 Fathom\ Fleet\ Cutthroat=1 Fathom\ Fleet\ Firebrand=1 Fathom\ Mage=1 Fathom\ Seer=1 +Fathom\ Trawl=1 Fatigue=1 -Faultgrinder=1 +Fault\ Riders=1 Favor\ of\ the\ Mighty=1 Favor\ of\ the\ Woods=1 -Favorable\ Destiny=1 -Favorable\ Winds=1 Favored\ Hoplite=1 Fear=1 Fearsome\ Temper=1 -Feast\ of\ Blood=1 Feast\ of\ Dreams=1 Feast\ of\ Flesh=1 Feast\ on\ the\ Fallen=1 +Feast\ or\ Famine=1 Feat\ of\ Resistance=1 Feebleness=1 Feed\ the\ Pack=1 @@ -2794,90 +2949,88 @@ Feeling\ of\ Dread=1 Felhide\ Brawler=1 Felhide\ Minotaur=1 Felhide\ Petrifier=1 -Felhide\ Spiritbinder=1 Felidar\ Cub=1 Felidar\ Sovereign=1 Fell\ Flagship=1 -Femeref\ Archers=1 Femeref\ Healer=1 Femeref\ Knight=1 Femeref\ Scouts=1 Fen\ Hauler=1 -Fen\ Stalker=1 Fencer's\ Magemark=1 Fencing\ Ace=1 -Fend\ Off=1 Fendeep\ Summoner=1 +Feral\ Abomination=1 Feral\ Animist=1 Feral\ Contest=1 +Feral\ Hydra=1 Feral\ Incarnation=1 +Feral\ Instinct=1 Feral\ Invocation=1 Feral\ Krushok=1 Feral\ Lightning=1 Feral\ Prowler=1 Feral\ Shadow=1 Feral\ Thallid=1 -Feral\ Throwback=1 -Ferocious\ Charge=1 Ferocity=1 -Feroz's\ Ban=1 Ferropede=1 Ferrovore=1 Fertile\ Imagination=1 Fertile\ Thicket=1 -Fertilid=1 Fervent\ Cathar=1 Fervent\ Charge=1 Fervent\ Denial=1 Fervent\ Paincaster=1 +Fervent\ Strike=1 Fervor=1 Festercreep=1 Festergloom=1 Festerhide\ Boar=1 Festering\ Evil=1 Festering\ Goblin=1 -Festering\ March=1 Festering\ Mummy=1 Festering\ Newt=1 Festering\ Wound=1 +Festival\ of\ the\ Guildpact=1 Fetid\ Horror=1 Fetid\ Imp=1 Fettergeist=1 Feudkiller's\ Verdict=1 Fevered\ Strength=1 -Fiddlehead\ Kami=1 +Fevered\ Visions=1 Field\ Creeper=1 +Field\ Surgeon=1 Field\ of\ Souls=1 Fiend\ Binder=1 -Fiend\ of\ the\ Shadows=1 Fierce\ Invocation=1 -Fiery\ Bombardment=1 Fiery\ Cannonade=1 Fiery\ Conclusion=1 Fiery\ Fall=1 +Fiery\ Finish=1 Fiery\ Hellhound=1 Fiery\ Impulse=1 -Fiery\ Justice=1 -Fiery\ Mantle=1 +Fiery\ Intervention=1 Fiery\ Temper=1 +Fight\ or\ Flight=1 Fight\ to\ the\ Death=1 Fighting\ Chance=1 Fighting\ Drake=1 Filigree\ Angel=1 Filigree\ Crawler=1 Filigree\ Familiar=1 -Filigree\ Fracture=1 Filigree\ Sages=1 Fill\ with\ Fright=1 +Filth=1 +Filthy\ Cur=1 Final-Sting\ Faerie=1 -Final\ Judgment=1 +Final\ Parting=1 Final\ Punishment=1 Final\ Revels=1 Final\ Reward=1 Finest\ Hour=1 Fire-Belly\ Changeling=1 +Fire-Field\ Ogre=1 +Fire\ Ambush=1 Fire\ Ants=1 -Fire\ Dragon=1 Fire\ Drake=1 Fire\ Elemental=1 Fire\ Imp=1 @@ -2889,28 +3042,26 @@ Fire\ Tempest=1 Fire\ Whip=1 Fire\ at\ Will=1 Fireball=1 +Firebrand\ Archer=1 Firebreathing=1 Firecannon\ Blast=1 -Firecat\ Blitz=1 -Firedrinker\ Satyr=1 Firefiend\ Elemental=1 +Firefist\ Adept=1 Firefist\ Striker=1 Firefly=1 Fireforger's\ Puzzleknot=1 Firefright\ Mage=1 -Firehoof\ Cavalry=1 Firemane\ Angel=1 Firemane\ Avenger=1 Firemantle\ Mage=1 -Firemaw\ Kavu=1 Firemind's\ Foresight=1 Fires\ of\ Undeath=1 Fires\ of\ Yavimaya=1 +Firescreamer=1 Fireshrieker=1 -Fireslinger=1 +Firestorm\ Hellkite=1 Firestorm\ Phoenix=1 Firewake\ Sliver=1 -Firewing\ Phoenix=1 First\ Response=1 First\ Volley=1 Fishliver\ Oil=1 @@ -2919,50 +3070,54 @@ Fissure\ Vent=1 Fists\ of\ Ironwood=1 Fists\ of\ the\ Anvil=1 Fists\ of\ the\ Demigod=1 -Fit\ of\ Rage=1 Five-Alarm\ Fire=1 Flailing\ Drake=1 Flailing\ Manticore=1 Flame-Kin\ War\ Scout=1 Flame-Kin\ Zealot=1 +Flame-Wreathed\ Phoenix=1 +Flame\ Burst=1 +Flame\ Elemental=1 Flame\ Fusillade=1 -Flame\ Jab=1 Flame\ Javelin=1 +Flame\ Spirit=1 Flame\ Wave=1 -Flameblade\ Adept=1 Flameblade\ Angel=1 Flameblast\ Dragon=1 Flameborn\ Hellion=1 -Flameborn\ Viron=1 Flamebreak=1 Flamecast\ Wheel=1 Flamecore\ Elemental=1 Flamekin\ Bladewhirl=1 Flamekin\ Brawler=1 -Flamekin\ Spitfire=1 +Flames\ of\ the\ Blood\ Hand=1 Flames\ of\ the\ Firebrand=1 Flameshadow\ Conjuring=1 -Flamespeaker's\ Will=1 Flamespeaker\ Adept=1 Flametongue\ Kavu=1 Flamewave\ Invoker=1 +Flaming\ Sword=1 +Flare=1 Flaring\ Flame-Kin=1 Flash\ Conscription=1 -Flash\ Flood=1 +Flash\ Foliage=1 +Flash\ of\ Defiance=1 Flashfreeze=1 Flatten=1 +Flay=1 Flayed\ Nim=1 Flayer\ Drone=1 -Flayer\ of\ the\ Hatebound=1 Flaying\ Tendrils=1 -Fledgling\ Djinn=1 Fledgling\ Dragon=1 -Fledgling\ Griffin=1 +Fledgling\ Imp=1 +Fledgling\ Mawcor=1 +Fledgling\ Osprey=1 +Fleecemane\ Lion=1 Fleet\ Swallower=1 Fleetfeather\ Cockatrice=1 Fleetfeather\ Sandals=1 +Fleetfoot\ Panther=1 Fleeting\ Aven=1 -Fleeting\ Distraction=1 Fleeting\ Image=1 Fleeting\ Memories=1 Fleetwheel\ Cruiser=1 @@ -2973,41 +3128,43 @@ Flesh\ Allergy=1 Flesh\ Reaver=1 Flesh\ to\ Dust=1 Fleshbag\ Marauder=1 -Fleshformer=1 -Fleshgrafter=1 -Fleshpulper\ Giant=1 Fleshwrither=1 Flickerform=1 Flickering\ Spirit=1 Flight=1 Flight\ Spellbomb=1 +Flight\ of\ Fancy=1 Fling=1 +Flint\ Golem=1 Flinthoof\ Boar=1 Flitterstep\ Eidolon=1 Flood\ Plain=1 Flood\ of\ Recollection=1 Floodbringer=1 Floodchaser=1 +Floodgate=1 Floodtide\ Serpent=1 Floodwater\ Dam=1 Floodwaters=1 Flourishing\ Defenses=1 Flow\ of\ Ideas=1 +Flowstone\ Armor=1 Flowstone\ Blade=1 Flowstone\ Channeler=1 Flowstone\ Charger=1 Flowstone\ Crusher=1 +Flowstone\ Embrace=1 Flowstone\ Flood=1 -Flowstone\ Giant=1 -Flowstone\ Hellion=1 Flowstone\ Mauler=1 Flowstone\ Overseer=1 Flowstone\ Salamander=1 Flowstone\ Sculpture=1 Flowstone\ Shambler=1 Flowstone\ Slide=1 +Flowstone\ Strike=1 +Flowstone\ Surge=1 +Flowstone\ Thopter=1 Flowstone\ Wyvern=1 -Flurry\ of\ Horns=1 Flurry\ of\ Wings=1 Fluxcharger=1 Flying\ Carpet=1 @@ -3015,35 +3172,30 @@ Flying\ Crane\ Technique=1 Flying\ Men=1 Fodder\ Cannon=1 Fodder\ Launch=1 -Foe-Razer\ Regent=1 Fog=1 -Fog\ Bank=1 Fog\ Elemental=1 Fog\ Patch=1 Fog\ of\ Gnats=1 Fogwalker=1 Fold\ into\ Aether=1 Folk\ of\ the\ Pines=1 -Fomori\ Nomad=1 -Font\ of\ Fertility=1 +Followed\ Footsteps=1 Font\ of\ Fortunes=1 -Font\ of\ Ire=1 Font\ of\ Return=1 Font\ of\ Vigor=1 Fool's\ Demise=1 +Fool's\ Tome=1 Foot\ Soldiers=1 +Footbottom\ Feast=1 Foratog=1 Forbidden\ Lore=1 -Forbidding\ Watchtower=1 Force\ Away=1 -Force\ Bubble=1 Force\ of\ Nature=1 Force\ of\ Savagery=1 Forced\ Adaptation=1 -Forced\ Fruition=1 -Forced\ Retreat=1 Forced\ Worship=1 Forcemage\ Advocate=1 +Forebear's\ Blade=1 Forerunner\ of\ Slaughter=1 Forerunner\ of\ the\ Coalition=1 Forerunner\ of\ the\ Empire=1 @@ -3052,21 +3204,20 @@ Forerunner\ of\ the\ Legion=1 Foresee=1 Foreshadow=1 Forest=1 +Forfend=1 Forge\ Armor=1 Forge\ Devil=1 Forgeborn\ Oreads=1 -Forgestoker\ Dragon=1 Forgotten\ Creation=1 Forgotten\ Lore=1 Foriysian\ Interceptor=1 Foriysian\ Totem=1 Fork\ in\ the\ Road=1 Forked-Branch\ Garami=1 +Forked\ Lightning=1 Forlorn\ Pseudamma=1 Form\ of\ the\ Dinosaur=1 -Form\ of\ the\ Dragon=1 Formless\ Nurturing=1 -Forsake\ the\ Worldly=1 Forsaken\ Drifters=1 Forsaken\ Sanctuary=1 Fortified\ Rampart=1 @@ -3077,108 +3228,114 @@ Fortuitous\ Find=1 Fortune's\ Favor=1 Fortune\ Thief=1 Fossil\ Find=1 +Foul\ Emissary=1 +Foul\ Familiar=1 Foul\ Imp=1 Foul\ Orchard=1 +Foul\ Presence=1 Foul\ Renewal=1 -Foul\ Spirit=1 Foundry\ Assembler=1 Foundry\ Champion=1 Foundry\ Hornet=1 -Foundry\ Inspector=1 Foundry\ Screecher=1 Foundry\ of\ the\ Consuls=1 Fountain\ of\ Youth=1 Fourth\ Bridge\ Prowler=1 -Foxfire\ Oak=1 Fractured\ Loyalty=1 +Fragmentize=1 +Frantic\ Purification=1 Frantic\ Salvage=1 -Frazzle=1 Freejam\ Regent=1 +Freewind\ Equenaut=1 +Freewind\ Falcon=1 +Frenetic\ Ogre=1 Frenetic\ Raptor=1 Frenetic\ Sliver=1 -Frenzied\ Fugue=1 Frenzied\ Goblin=1 +Frenzied\ Rage=1 Frenzied\ Raptor=1 Frenzied\ Tilling=1 +Frenzy\ Sliver=1 Fresh\ Meat=1 Fresh\ Volunteers=1 Fretwork\ Colony=1 -Freyalise's\ Radiance=1 +Freyalise's\ Winds=1 +Frightcrawler=1 Frightful\ Delusion=1 +Frightshroud\ Courier=1 Frilled\ Deathspitter=1 Frilled\ Sandwalla=1 -Frogtosser\ Banneret=1 +Frilled\ Sea\ Serpent=1 From\ Beyond=1 From\ Under\ the\ Floorboards=1 Frontier\ Bivouac=1 Frontier\ Guide=1 -Frontier\ Mastodon=1 Frontline\ Devastator=1 Frontline\ Medic=1 Frontline\ Rebel=1 Frontline\ Sage=1 Frontline\ Strategist=1 Frost\ Lynx=1 -Frost\ Ogre=1 -Frost\ Walker=1 +Frost\ Marsh=1 +Frost\ Raptor=1 Frostburn\ Weird=1 Frostweb\ Spider=1 -Frostwielder=1 -Frostwind\ Invoker=1 Frozen\ Aether=1 Frozen\ Solid=1 Fuel\ for\ the\ Cause=1 -Fugitive\ Druid=1 Fugitive\ Wizard=1 Fugue=1 +Fulgent\ Distraction=1 Full\ Moon's\ Rise=1 Fumarole=1 -Funeral\ March=1 +Fumiko\ the\ Lowblood=1 +Funeral\ Pyre=1 Fungal\ Behemoth=1 +Fungal\ Infection=1 +Fungal\ Plots=1 Fungal\ Reaches=1 Fungal\ Shambler=1 -Fungal\ Sprouting=1 Fungus\ Sliver=1 +Furious\ Assault=1 Furious\ Reprisal=1 +Furious\ Resistance=1 Furnace\ Brood=1 Furnace\ Celebration=1 Furnace\ Dragon=1 Furnace\ Scamp=1 Furnace\ Spirit=1 Furnace\ Whelp=1 -Furnace\ of\ Rath=1 Furor\ of\ the\ Bitten=1 Furtive\ Homunculus=1 Fury\ Charm=1 -Fury\ Sliver=1 Furyblade\ Vampire=1 Furystoke\ Giant=1 Fusion\ Elemental=1 Future\ Sight=1 Fylamarid=1 -Fyndhorn\ Elder=1 -Fyndhorn\ Elves=1 Fyndhorn\ Pollen=1 -Gabriel\ Angelfire=1 Gaea's\ Anthem=1 -Gaea's\ Avenger=1 Gaea's\ Blessing=1 Gaea's\ Bounty=1 Gaea's\ Embrace=1 +Gaea's\ Herald=1 Gaea's\ Liege=1 +Gaea's\ Protector=1 Gaea's\ Revenge=1 Gainsay=1 Gale\ Force=1 Galepowder\ Mage=1 Galestrike=1 +Gallant\ Cavalry=1 +Gallantry=1 Gallows\ Warden=1 Gallows\ at\ Willow\ Hill=1 -Galvanic\ Alchemist=1 -Galvanic\ Arc=1 Galvanic\ Bombardment=1 Galvanic\ Juggernaut=1 +Galvanic\ Key=1 Galvanoth=1 Game-Trail\ Changeling=1 +Game\ Trail=1 Gamekeeper=1 Gang\ of\ Devils=1 Gang\ of\ Elk=1 @@ -3187,16 +3344,17 @@ Gangrenous\ Zombies=1 Gargantuan\ Gorilla=1 Gargoyle\ Castle=1 Gargoyle\ Sentinel=1 +Garna,\ the\ Bloodflame=1 Garruk's\ Companion=1 Garruk's\ Horde=1 Garruk's\ Packleader=1 Garrulous\ Sycophant=1 +Garza\ Zol,\ Plague\ Queen=1 Gaseous\ Form=1 Gate\ Hound=1 Gate\ Smasher=1 -Gate\ to\ the\ Aether=1 -Gate\ to\ the\ Afterlife=1 Gatecreeper\ Vine=1 +Gatekeeper\ of\ Malakir=1 Gateway\ Shade=1 Gathan\ Raiders=1 Gather\ Courage=1 @@ -3206,52 +3364,56 @@ Gatherer\ of\ Graces=1 Gatstaf\ Arsonists=1 Gatstaf\ Shepherd=1 Gauntlets\ of\ Chaos=1 +Gavony\ Ironwright=1 Gavony\ Unhallowed=1 Gaze\ of\ Adamaro=1 Gaze\ of\ Justice=1 Gearseeker\ Serpent=1 Gearshift\ Ace=1 +Gearsmith\ Guardian=1 +Gearsmith\ Prodigy=1 Geier\ Reach\ Bandit=1 Geist-Fueled\ Scarecrow=1 Geist-Honored\ Monk=1 Geist\ of\ the\ Archives=1 Geist\ of\ the\ Lonely\ Vigil=1 -Geist\ of\ the\ Moors=1 Geistblast=1 Geistflame=1 Gelatinous\ Genesis=1 Gelectrode=1 Gelid\ Shackles=1 -Gemhide\ Sliver=1 +Gem\ of\ Becoming=1 Gemini\ Engine=1 -Gempalm\ Strider=1 +Gempalm\ Avenger=1 Gemstone\ Array=1 General's\ Kabuto=1 +General\ Tazri=1 Genesis=1 -Genesis\ Hydra=1 Genju\ of\ the\ Cedars=1 Genju\ of\ the\ Falls=1 Genju\ of\ the\ Fens=1 +Genju\ of\ the\ Fields=1 Genju\ of\ the\ Realm=1 Genju\ of\ the\ Spires=1 Geosurge=1 Geralf's\ Mindcrusher=1 Gerrard's\ Battle\ Cry=1 +Gerrard's\ Command=1 Gerrard's\ Irregulars=1 -Geyser\ Glider=1 +Geth's\ Grimoire=1 Geyserfield\ Stalker=1 -Ghastly\ Discovery=1 +Ghastbark\ Twins=1 Ghastly\ Remains=1 -Ghazban\ Ogre=1 -Ghirapur\ Aether\ Grid=1 +Ghazbn\ Ogre=1 Ghirapur\ Gearcrafter=1 Ghirapur\ Guide=1 Ghirapur\ Orrery=1 Ghirapur\ Osprey=1 -Ghitu\ Encampment=1 +Ghitu\ Chronicler=1 Ghitu\ Fire-Eater=1 Ghitu\ Fire=1 Ghitu\ Firebreathing=1 +Ghitu\ Journeymage=1 Ghitu\ Slinger=1 Ghitu\ War\ Cry=1 Ghor-Clan\ Bloodscale=1 @@ -3269,7 +3431,6 @@ Ghostfire=1 Ghostfire\ Blade=1 Ghostflame\ Sliver=1 Ghostform=1 -Ghosthelm\ Courier=1 Ghostly\ Changeling=1 Ghostly\ Possession=1 Ghostly\ Sentinel=1 @@ -3278,19 +3439,16 @@ Ghostly\ Visit=1 Ghostly\ Wings=1 Ghosts\ of\ the\ Damned=1 Ghosts\ of\ the\ Innocent=1 +Ghoul's\ Feast=1 Ghoulcaller's\ Accomplice=1 Ghoulcaller's\ Bell=1 -Ghoulcaller's\ Chant=1 Ghoulflesh=1 -Ghoulraiser=1 Ghoulsteed=1 -Ghoultree=1 -Giant\ Ambush\ Beetle=1 +Giant's\ Ire=1 Giant\ Badger=1 Giant\ Caterpillar=1 Giant\ Cockroach=1 Giant\ Crab=1 -Giant\ Dustwasp=1 Giant\ Growth=1 Giant\ Harbinger=1 Giant\ Mantis=1 @@ -3302,28 +3460,30 @@ Giant\ Spectacle=1 Giant\ Spider=1 Giant\ Strength=1 Giant\ Tortoise=1 +Giant\ Trap\ Door\ Spider=1 Giantbaiting=1 Gibbering\ Descent=1 Gibbering\ Fiend=1 -Gibbering\ Kami=1 +Gibbering\ Hyenas=1 Gideon's\ Avenger=1 Gideon's\ Defeat=1 +Gideon's\ Intervention=1 Gideon's\ Lawkeeper=1 Gideon's\ Phalanx=1 Gideon's\ Reproach=1 +Gift\ of\ Granite=1 +Gift\ of\ Growth=1 Gift\ of\ Immortality=1 Gift\ of\ Orzhova=1 -Gift\ of\ Paradise=1 Gift\ of\ Strength=1 Gift\ of\ Tusks=1 Gift\ of\ the\ Deity=1 Gift\ of\ the\ Gargantuan=1 -Gigantiform=1 -Gigantomancer=1 Gigapede=1 Gild=1 Gilded\ Cerodon=1 Gilded\ Light=1 +Gilded\ Lotus=1 Gilded\ Sentinel=1 Gilt-Leaf\ Ambush=1 Gilt-Leaf\ Seer=1 @@ -3333,30 +3493,35 @@ Giltspire\ Avenger=1 Gisa's\ Bidding=1 Give\ //\ Take=1 Give\ No\ Ground=1 -Glacial\ Crasher=1 Glacial\ Crevasses=1 Glacial\ Plating=1 Glacial\ Ray=1 Glacial\ Stalker=1 Glacial\ Wall=1 +Glade\ Gnarr=1 Glade\ Watcher=1 Gladehart\ Cavalry=1 +Glamer\ Spinners=1 Glamerdye=1 Glare\ of\ Heresy=1 Glare\ of\ Subdual=1 Glarecaster=1 +Glaring\ Aegis=1 Glaring\ Spotlight=1 +Glass\ Asp=1 Glass\ Golem=1 Glassblower's\ Puzzleknot=1 Glassdust\ Hulk=1 -Glasses\ of\ Urza=1 +Glaze\ Fiend=1 +Gleam\ of\ Authority=1 Gleam\ of\ Battle=1 Gleam\ of\ Resistance=1 Gleaming\ Barrier=1 -Glen\ Elendra\ Pranksters=1 -Gliding\ Licid=1 +Gleancrawler=1 +Glen\ Elendra\ Liege=1 Glimmerdust\ Nap=1 Glimmerpoint\ Stag=1 +Glimmerpost=1 Glimpse\ the\ Future=1 Glimpse\ the\ Sun\ God=1 Glint-Eye\ Nephilim=1 @@ -3364,20 +3529,23 @@ Glint-Sleeve\ Artisan=1 Glint=1 Glint\ Hawk\ Idol=1 Glintwing\ Invoker=1 -Glissa's\ Courier=1 +Glissa's\ Scorn=1 Glissa\ Sunseeker=1 Glistening\ Oil=1 Glitterfang=1 +Glittering\ Lion=1 Gloom\ Surgeon=1 Gloomhunter=1 -Gloomlance=1 +Gloomwidow's\ Feast=1 Gloomwidow=1 Glorifier\ of\ Dusk=1 Glorious\ Anthem=1 +Glorious\ Charge=1 +Glory-Bound\ Initiate=1 Glory\ Seeker=1 Glory\ of\ Warfare=1 -Gloryscale\ Viashino=1 Glowering\ Rogon=1 +Glowing\ Anemone=1 Gluttonous\ Slime=1 Gluttonous\ Zombie=1 Glyph\ Keeper=1 @@ -3389,6 +3557,7 @@ Gnarlroot\ Trapper=1 Gnarlwood\ Dryad=1 Gnathosaur=1 Gnawing\ Zombie=1 +Goatnapper=1 Gobbling\ Ooze=1 Gobhobbler\ Rats=1 Goblin\ Archaeologist=1 @@ -3396,27 +3565,24 @@ Goblin\ Arsonist=1 Goblin\ Artillery=1 Goblin\ Assault=1 Goblin\ Bangchuckers=1 +Goblin\ Barrage=1 Goblin\ Battle\ Jester=1 -Goblin\ Berserker=1 Goblin\ Boom\ Keg=1 -Goblin\ Brawler=1 Goblin\ Brigand=1 Goblin\ Bully=1 Goblin\ Burrows=1 Goblin\ Cadets=1 Goblin\ Cannon=1 -Goblin\ Cavaliers=1 Goblin\ Chariot=1 -Goblin\ Clearcutter=1 Goblin\ Commando=1 Goblin\ Deathraiders=1 Goblin\ Digging\ Team=1 -Goblin\ Dirigible=1 -Goblin\ Dynamo=1 +Goblin\ Diplomats=1 Goblin\ Elite\ Infantry=1 -Goblin\ Festival=1 +Goblin\ Fire\ Fiend=1 Goblin\ Firebug=1 Goblin\ Fireslinger=1 +Goblin\ Firestarter=1 Goblin\ Flectomancer=1 Goblin\ Freerunner=1 Goblin\ Furrier=1 @@ -3428,20 +3594,19 @@ Goblin\ Glory\ Chaser=1 Goblin\ Goon=1 Goblin\ Grappler=1 Goblin\ Grenadiers=1 -Goblin\ Lackey=1 +Goblin\ Kaboomist=1 Goblin\ Legionnaire=1 Goblin\ Machinist=1 Goblin\ Medics=1 Goblin\ Mountaineer=1 -Goblin\ Mutant=1 Goblin\ Outlander=1 +Goblin\ Patrol=1 Goblin\ Piker=1 -Goblin\ Psychopath=1 Goblin\ Pyromancer=1 Goblin\ Raider=1 Goblin\ Rally=1 Goblin\ Razerunners=1 -Goblin\ Ringleader=1 +Goblin\ Rimerunner=1 Goblin\ Roughrider=1 Goblin\ Settler=1 Goblin\ Shortcutter=1 @@ -3451,32 +3616,36 @@ Goblin\ Sky\ Raider=1 Goblin\ Snowman=1 Goblin\ Spelunkers=1 Goblin\ Striker=1 +Goblin\ Swine-Rider=1 Goblin\ Taskmaster=1 Goblin\ Test\ Pilot=1 Goblin\ Trailblazer=1 Goblin\ Trenches=1 -Goblin\ Tunneler=1 Goblin\ Turncoat=1 +Goblin\ War\ Buggy=1 Goblin\ War\ Paint=1 Goblin\ War\ Wagon=1 Goblin\ Warchief=1 +Goblins\ of\ the\ Flarg=1 Goblinslide=1 God-Favored\ General=1 God-Pharaoh's\ Faithful=1 +Godhead\ of\ Awe=1 Godo's\ Irregulars=1 Gods'\ Eye,\ Gate\ to\ the\ Reikai=1 +Gods\ Willing=1 Godtoucher=1 -Godtracker\ of\ Jund=1 +Goham\ Djinn=1 Gold-Forged\ Sentinel=1 Gold\ Myr=1 -Golden\ Guardian=1 +Golden\ Demise=1 Golden\ Hind=1 Golden\ Urn=1 +Golden\ Wish=1 Goldenglow\ Moth=1 Goldenhide\ Ox=1 Goldmeadow\ Dodger=1 Goldmeadow\ Harrier=1 -Goldmeadow\ Lookout=1 Goldmeadow\ Stalwart=1 Goldnight\ Commander=1 Goldnight\ Redeemer=1 @@ -3484,34 +3653,33 @@ Golem's\ Heart=1 Golem-Skin\ Gauntlets=1 Golem\ Foundry=1 Golgari\ Cluestone=1 -Golgari\ Decoy=1 Golgari\ Germination=1 Golgari\ Guildgate=1 Golgari\ Guildmage=1 Golgari\ Keyrune=1 -Golgari\ Longlegs=1 Golgari\ Rotwurm=1 Golgari\ Signet=1 Goliath\ Beetle=1 Goliath\ Sphinx=1 -Goliath\ Spider=1 Gomazoa=1 Gone\ Missing=1 +Gonti's\ Aether\ Heart=1 Gonti's\ Machinations=1 Gore-House\ Chainwalker=1 +Gore\ Swine=1 Gorehorn\ Minotaurs=1 -Gorger\ Wurm=1 +Goretusk\ Firebeast=1 Gorgon's\ Head=1 Gorgon\ Flail=1 Gorgon\ Recluse=1 -Gorilla\ Chieftain=1 +Gorilla\ Titan=1 +Gorilla\ War\ Cry=1 Gorilla\ Warrior=1 Goring\ Ceratops=1 Gossamer\ Chains=1 Gossamer\ Phantasm=1 Govern\ the\ Guildless=1 Grab\ the\ Reins=1 -Graceblade\ Artisan=1 Graceful\ Adept=1 Graceful\ Antelope=1 Graceful\ Reprieve=1 @@ -3520,11 +3688,12 @@ Graf\ Mole=1 Graf\ Rats=1 Grafted\ Exoskeleton=1 Grand\ Melee=1 +Grand\ Warlord\ Radha=1 Grandmother\ Sengir=1 +Granite\ Gargoyle=1 Granite\ Grip=1 Granite\ Shard=1 Granitic\ Titan=1 -Granulate=1 Grapeshot\ Catapult=1 Grapple\ with\ the\ Past=1 Grappling\ Hook=1 @@ -3533,73 +3702,72 @@ Grasp\ of\ Phantoms=1 Grasp\ of\ the\ Hieromancer=1 Grasping\ Dunes=1 Grasping\ Scoundrel=1 -Grassland\ Crusader=1 Grasslands=1 Grave-Shell\ Scarab=1 Grave\ Betrayal=1 Grave\ Birthing=1 -Grave\ Bramble=1 -Grave\ Defiler=1 Grave\ Peril=1 -Grave\ Strength=1 +Grave\ Servitude=1 Gravebane\ Zombie=1 Gravebind=1 Graveblade\ Marauder=1 Gravedigger=1 Gravel\ Slinger=1 +Gravelgill\ Axeshark=1 Gravelgill\ Duo=1 Graven\ Abomination=1 Graven\ Dominator=1 Gravepurge=1 Graverobber\ Spider=1 -Gravespawn\ Sovereign=1 -Gravetiller\ Wurm=1 Gravity\ Negator=1 Gravity\ Well=1 +Graxiplon=1 Graypelt\ Hunter=1 Grazing\ Gladehart=1 Grazing\ Kelpie=1 Grazing\ Whiptail=1 +Great-Horn\ Krushok=1 +Great\ Hart=1 Great\ Teacher's\ Decree=1 Greatbow\ Doyen=1 +Greater\ Basilisk=1 Greater\ Forgeling=1 Greater\ Harvester=1 Greater\ Mossdog=1 Greater\ Sandwurm=1 -Greater\ Stone\ Spirit=1 Greatsword=1 +Greel's\ Caress=1 Greenhilt\ Trainee=1 Greenseeker=1 Greenside\ Watcher=1 Greenweaver\ Druid=1 +Greenwheel\ Liberator=1 Gremlin\ Infestation=1 -Gremlin\ Mine=1 Grenzo,\ Dungeon\ Warden=1 Grid\ Monitor=1 Gridlock=1 -Grief\ Tyrant=1 Griffin\ Dreamfinder=1 Griffin\ Guide=1 -Griffin\ Protector=1 Griffin\ Sentinel=1 +Grifter's\ Blade=1 Grim\ Affliction=1 -Grim\ Backwoods=1 Grim\ Captain's\ Call=1 Grim\ Contest=1 Grim\ Discovery=1 Grim\ Flowering=1 -Grim\ Guardian=1 Grim\ Haruspex=1 +Grim\ Poppet=1 Grim\ Reminder=1 Grim\ Return=1 Grim\ Roustabout=1 Grim\ Strider=1 -Grimclaw\ Bats=1 -Grimoire\ of\ the\ Dead=1 +Grimoire\ Thief=1 Grind\ //\ Dust=1 Grindclock=1 Grinning\ Demon=1 Grinning\ Ignus=1 +Grinning\ Totem=1 +Grip\ of\ Amnesia=1 Grip\ of\ Desolation=1 Grip\ of\ the\ Roil=1 Griptide=1 @@ -3626,17 +3794,18 @@ Grotesque\ Mutation=1 Ground\ Assault=1 Ground\ Rift=1 Groundling\ Pouncer=1 -Groundshaker\ Sliver=1 Groundskeeper=1 Grove\ Rumbler=1 Grove\ of\ the\ Guardian=1 Grovetender\ Druids=1 +Grow\ from\ the\ Ashes=1 Growing\ Ranks=1 Grozoth=1 Gruesome\ Deformity=1 Gruesome\ Encore=1 Gruesome\ Fate=1 Gruesome\ Slaughter=1 +Grunn,\ the\ Lonely\ King=1 Gruul\ Charm=1 Gruul\ Cluestone=1 Gruul\ Guildgate=1 @@ -3645,72 +3814,70 @@ Gruul\ Keyrune=1 Gruul\ Nodorog=1 Gruul\ Ragebeast=1 Gruul\ Scrapper=1 -Gruul\ Signet=1 -Gruul\ Turf=1 Gruul\ War\ Chant=1 Gruul\ War\ Plow=1 Gryff's\ Boon=1 Guan\ Yu's\ 1,000-Li\ March=1 Guan\ Yu,\ Sainted\ Warrior=1 +Guard\ Dogs=1 Guard\ Duty=1 Guard\ Gomazoa=1 Guardian\ Automaton=1 Guardian\ Seraph=1 Guardian\ Shield-Bearer=1 +Guardian\ Zendikon=1 Guardian\ of\ Pilgrims=1 Guardian\ of\ Solitude=1 Guardian\ of\ Tazeem=1 -Guardian\ of\ Vitu-Ghazi=1 Guardian\ of\ the\ Ages=1 Guardian\ of\ the\ Gateless=1 Guardians\ of\ Akrasa=1 +Guardians\ of\ Koilos=1 Guardians\ of\ Meletis=1 Guerrilla\ Tactics=1 Guild\ Feud=1 Guildscorn\ Ward=1 Guile=1 -Guise\ of\ Fire=1 +Guilty\ Conscience=1 Guma=1 Gurmag\ Drowner=1 Gurmag\ Swiftwing=1 -Gurzigost=1 Gust-Skimmer=1 Gust\ Walker=1 Gustcloak\ Cavalier=1 -Gustcloak\ Harrier=1 +Gustcloak\ Runner=1 +Gustcloak\ Savior=1 Gustcloak\ Sentinel=1 +Gustha's\ Scepter=1 Gustrider\ Exuberant=1 -Gutless\ Ghoul=1 Gutter\ Grime=1 Gutter\ Skulk=1 -Guttersnipe=1 +Gutwrencher\ Oni=1 +Guul\ Draz\ Assassin=1 Guul\ Draz\ Overseer=1 Guul\ Draz\ Specter=1 Gwafa\ Hazid,\ Profiteer=1 Gwyllion\ Hedge-Mage=1 -Gyre\ Sage=1 -Haazda\ Exonerator=1 Haazda\ Shield\ Mate=1 -Haazda\ Snare\ Squad=1 +Hada\ Spy\ Patrol=1 Hag\ Hedge-Mage=1 +Hagra\ Crocodile=1 Hagra\ Diabolist=1 Hagra\ Sharpshooter=1 -Hail\ Storm=1 Hail\ of\ Arrows=1 Hair-Strung\ Koto=1 +Halam\ Djinn=1 Halcyon\ Glaze=1 -Halfdane=1 Halimar\ Excavator=1 Halimar\ Tidecaller=1 Halimar\ Wavewatch=1 -Hall\ of\ Triumph=1 -Hallowed\ Ground=1 +Hallar,\ the\ Firefletcher=1 +Hallowed\ Moonlight=1 Halo\ Hunter=1 -Halt\ Order=1 Hamlet\ Captain=1 Hamletback\ Goliath=1 +Hammer\ of\ Bogardan=1 Hammer\ of\ Purphoros=1 -Hammer\ of\ Ruin=1 Hammerfist\ Giant=1 Hammerhand=1 Hammerhead\ Shark=1 @@ -3719,41 +3886,48 @@ Hammerheim\ Deadeye=1 Hana\ Kami=1 Hanabi\ Blast=1 Hand\ of\ Cruelty=1 -Hand\ of\ Honor=1 +Hand\ of\ Emrakul=1 Hand\ of\ Justice=1 Hand\ of\ Silumgar=1 Hand\ of\ the\ Praetors=1 +Hand\ to\ Hand=1 Hands\ of\ Binding=1 +Hanweir\ Battlements=1 Hanweir\ Lancer=1 +Hanweir\ Militia\ Captain=1 Hanweir\ Watchkeep=1 Hapatra's\ Mark=1 Hapatra,\ Vizier\ of\ Poisons=1 -Harbinger\ of\ Spring=1 +Haphazard\ Bombardment=1 Harbinger\ of\ the\ Hunt=1 +Harbor\ Bandit=1 +Harbor\ Guardian=1 Harbor\ Serpent=1 Hardened\ Berserker=1 Hardy\ Veteran=1 Harm's\ Way=1 -Harmless\ Assault=1 +Harmattan\ Efreet=1 Harmless\ Offering=1 Harmonic\ Convergence=1 -Harness\ by\ Force=1 Harness\ the\ Storm=1 Harpoon\ Sniper=1 Harrier\ Griffin=1 Harrier\ Naga=1 +Harrow=1 Harrowing\ Journey=1 -Harsh\ Justice=1 +Harsh\ Deceiver=1 +Harsh\ Scrutiny=1 Haru-Onna=1 Harvest\ Gwyllion=1 Harvest\ Hand=1 Harvest\ Mage=1 -Harvest\ Pyre=1 Harvest\ Season=1 Harvester\ Troll=1 Harvestguard\ Alseids=1 Hasran\ Ogress=1 +Hatchet\ Bully=1 Hate\ Weaver=1 +Hateflayer=1 Haunted\ Angel=1 Haunted\ Cadaver=1 Haunted\ Cloak=1 @@ -3765,27 +3939,33 @@ Haunting\ Apparition=1 Haunting\ Echoes=1 Haunting\ Hymn=1 Havengul\ Runebinder=1 +Havengul\ Skaab=1 Havengul\ Vampire=1 +Havenwood\ Battleground=1 Havenwood\ Wurm=1 Havoc\ Demon=1 +Havoc\ Devils=1 Havoc\ Festival=1 Havoc\ Sower=1 Hawkeater\ Moth=1 Hazardous\ Conditions=1 Haze\ Frog=1 Haze\ of\ Pollen=1 +Hazerider\ Drake=1 +Hazezon\ Tamar=1 Hazoret's\ Favor=1 Hazoret's\ Monument=1 Hazoret's\ Undying\ Fury=1 Hazy\ Homunculus=1 +He\ Who\ Hungers=1 Head\ Games=1 -Headhunter=1 Headless\ Skaab=1 Headstrong\ Brute=1 Headwater\ Sentries=1 -Heal\ the\ Scars=1 +Heal=1 Healer's\ Headdress=1 Healer\ of\ the\ Pride=1 +Healing\ Grace=1 Healing\ Hands=1 Healing\ Leaves=1 Healing\ Salve=1 @@ -3793,9 +3973,7 @@ Heap\ Doll=1 Heart-Piercer\ Bow=1 Heart-Piercer\ Manticore=1 Heart\ Warden=1 -Heart\ of\ Bogardan=1 Hearth\ Kami=1 -Hearthcage\ Giant=1 Hearthfire\ Hobgoblin=1 Heartlash\ Cinder=1 Heartless\ Pillage=1 @@ -3816,24 +3994,25 @@ Heavy\ Ballista=1 Heavy\ Fog=1 Heavy\ Infantry=1 Heavy\ Mattock=1 +Hecatomb=1 +Heckling\ Fiends=1 Hedonist's\ Trove=1 Hedron-Field\ Purists=1 Hedron\ Alignment=1 +Hedron\ Archive=1 Hedron\ Blade=1 Hedron\ Crawler=1 Hedron\ Matrix=1 +Hedron\ Rover=1 Hedron\ Scrabbler=1 Heed\ the\ Mists=1 -Heedless\ One=1 +Heidar,\ Rimewind\ Master=1 Heir\ of\ Falkenrath=1 Heir\ of\ the\ Wilds=1 Heirs\ of\ Stromkirk=1 Hekma\ Sentinels=1 Heliod's\ Emissary=1 -Heliophial=1 Helium\ Squirter=1 -Hell's\ Thunder=1 -Hell-Bent\ Raider=1 Hellcarver\ Demon=1 Helldozer=1 Hellhole\ Flailer=1 @@ -3843,51 +4022,56 @@ Hellion\ Eruption=1 Hellkite\ Charger=1 Hellkite\ Hatchling=1 Hellraiser\ Goblin=1 -Hellspark\ Elemental=1 Helm\ of\ the\ Ghastlord=1 Helm\ of\ the\ Gods=1 +Helm\ of\ the\ Host=1 Hematite\ Golem=1 Henchfiend\ of\ Ukor=1 Henge\ Guardian=1 Herald\ of\ Anafenza=1 -Herald\ of\ Dromoka=1 +Herald\ of\ Faith=1 Herald\ of\ Kozilek=1 -Herald\ of\ Serra=1 +Herald\ of\ Secret\ Streams=1 Herald\ of\ Torment=1 -Herald\ of\ War=1 Herald\ of\ the\ Fair=1 Herald\ of\ the\ Host=1 +Herald\ of\ the\ Pantheon=1 Herbal\ Poultice=1 Herdchaser\ Dragon=1 +Heretic's\ Punishment=1 Hermetic\ Study=1 Hermit\ Druid=1 Hermit\ of\ the\ Natterknolls=1 Hero's\ Demise=1 +Hero's\ Resolve=1 Hero\ of\ Goma\ Fada=1 Hero\ of\ Iroas=1 Hero\ of\ Leina\ Tower=1 +Heroes'\ Bane=1 Heroes'\ Podium=1 Heroes'\ Reunion=1 Heroes\ Remembered=1 Heroic\ Defiance=1 +Heroic\ Reinforcements=1 Heron's\ Grace\ Champion=1 Hesitation=1 Hewed\ Stone\ Retainers=1 Hex=1 -Hexplate\ Golem=1 Hibernation's\ End=1 -Hibernation=1 Hidden\ Ancients=1 -Hidden\ Dragonslayer=1 +Hidden\ Gibbons=1 +Hidden\ Guerrillas=1 Hidden\ Herbalists=1 Hidden\ Horror=1 -Hidden\ Retreat=1 -Hidden\ Stag=1 +Hidden\ Stockpile=1 Hideous\ End=1 Hideous\ Laughter=1 +Hideous\ Visage=1 Hidetsugu's\ Second\ Rite=1 Hieroglyphic\ Illumination=1 +Hieromancer's\ Cage=1 Hierophant's\ Chalice=1 +High\ Ground=1 High\ Priest\ of\ Penance=1 High\ Sentinels\ of\ Arashin=1 Highborn\ Ghoul=1 @@ -3904,15 +4088,17 @@ Higure,\ the\ Still\ Wind=1 Hijack=1 Hikari,\ Twilight\ Guardian=1 Hill\ Giant=1 -Hillcomber\ Giant=1 Hinder=1 +Hindering\ Light=1 Hindering\ Touch=1 Hindervines=1 Hint\ of\ Insanity=1 Hinterland\ Drake=1 Hinterland\ Hermit=1 Hinterland\ Logger=1 +Hired\ Blade=1 Hired\ Giant=1 +Hired\ Muscle=1 Hired\ Torturer=1 Hisoka's\ Guard=1 Hisoka,\ Minamo\ Sensei=1 @@ -3921,6 +4107,7 @@ Hissing\ Miasma=1 Hit\ //\ Run=1 Hitchclaw\ Recluse=1 Hivestone=1 +Hivis\ of\ the\ Scale=1 Hixus,\ Prison\ Warden=1 Hoard-Smelter\ Dragon=1 Hoarder's\ Greed=1 @@ -3930,38 +4117,38 @@ Hold\ at\ Bay=1 Hold\ the\ Gates=1 Hold\ the\ Line=1 Holdout\ Settlement=1 +Holistic\ Wisdom=1 Hollow\ Dogs=1 +Hollow\ Specter=1 Hollowborn\ Barghest=1 -Hollowhenge\ Scavenger=1 Hollowhenge\ Spirit=1 Hollowsage=1 -Holy\ Justiciar=1 Holy\ Mantle=1 Holy\ Strength=1 +Homarid\ Explorer=1 Homarid\ Spawning\ Bed=1 -Homicidal\ Seclusion=1 Homing\ Lightning=1 -Homing\ Sliver=1 -Homura,\ Human\ Ascendant=1 Honden\ of\ Cleansing\ Fire=1 Honden\ of\ Infinite\ Rage=1 Honden\ of\ Life's\ Web=1 Honden\ of\ Night's\ Reach=1 Honden\ of\ Seeing\ Winds=1 Honed\ Khopesh=1 -Honor's\ Reward=1 +Honor-Worn\ Shaku=1 Honor\ Guard=1 Honorable\ Passage=1 Honored\ Crop-Captain=1 Honored\ Hierarch=1 Honored\ Hydra=1 -Hooded\ Assassin=1 Hooded\ Brawler=1 Hooded\ Horror=1 +Hooded\ Kavu=1 +Hoof\ Skulkin=1 Hoofprints\ of\ the\ Stag=1 Hope\ Against\ Hope=1 Hope\ Charm=1 Hope\ Tender=1 +Hope\ and\ Glory=1 Hopeful\ Eidolon=1 Hopping\ Automaton=1 Horde\ of\ Boggarts=1 @@ -3972,55 +4159,51 @@ Horizon\ Drake=1 Horizon\ Scholar=1 Horizon\ Seed=1 Horizon\ Spellbomb=1 -Horn\ of\ Deafening=1 Horncaller's\ Chant=1 Horned\ Cheetah=1 Horned\ Helm=1 -Horned\ Troll=1 Horned\ Turtle=1 +Hornet\ Cannon=1 Hornet\ Harasser=1 Hornet\ Sting=1 Hornswoggle=1 Horobi's\ Whisper=1 +Horrible\ Hordes=1 Horribly\ Awry=1 Horrifying\ Revelation=1 Horror\ of\ Horrors=1 Horror\ of\ the\ Broken\ Lands=1 -Horror\ of\ the\ Dim=1 Horseshoe\ Crab=1 +Hostile\ Minotaur=1 Hostile\ Realm=1 Hostility=1 Hot\ Soup=1 -Hotheaded\ Giant=1 -Hound\ of\ Griselbrand=1 Hound\ of\ the\ Farbogs=1 Hour\ of\ Eternity=1 Hour\ of\ Need=1 +Hour\ of\ Revelation=1 Hover\ Barrier=1 +Hoverguard\ Observer=1 Hoverguard\ Sweepers=1 Hovermyr=1 Howl\ from\ Beyond=1 -Howl\ of\ the\ Horde=1 Howl\ of\ the\ Night\ Pack=1 Howlgeist=1 -Howling\ Banshee=1 -Howling\ Wolf=1 +Howling\ Gale=1 +Howling\ Golem=1 Howlpack\ Resurgence=1 Howlpack\ Wolf=1 Howltooth\ Hollow=1 Hubris=1 +Hulking\ Cyclops=1 Hulking\ Devil=1 -Hulking\ Goblin=1 -Hulking\ Ogre=1 Hum\ of\ the\ Radix=1 Human\ Frailty=1 Humble=1 Humble\ Budoka=1 Humble\ the\ Brute=1 Humbler\ of\ Mortals=1 -Hunding\ Gjornersen=1 Hundred-Handed\ One=1 -Hundred-Talon\ Kami=1 Hundred-Talon\ Strike=1 Hundroog=1 Hunger\ of\ the\ Nim=1 @@ -4028,7 +4211,6 @@ Hungering\ Yeti=1 Hungry\ Flames=1 Hungry\ Mist=1 Hungry\ Spriggan=1 -Hunt\ Down=1 Hunt\ the\ Hunter=1 Hunt\ the\ Weak=1 Hunted\ Dragon=1 @@ -4041,40 +4223,44 @@ Hunter's\ Ambush=1 Hunter's\ Insight=1 Hunter's\ Prowess=1 Hunter\ of\ Eyeblights=1 +Hunters'\ Feast=1 Hunting\ Cheetah=1 Hunting\ Drake=1 -Hunting\ Kavu=1 Hunting\ Moa=1 Hunting\ Pack=1 Hunting\ Triad=1 Hunting\ Wilds=1 Hurloon\ Minotaur=1 Hurloon\ Shaman=1 +Hurly-Burly=1 Hurricane=1 +Hush=1 Hussar\ Patrol=1 -Hyalopterous\ Lemure=1 Hydra\ Broodmaster=1 Hydroform=1 Hydrolash=1 +Hydromorph\ Guardian=1 +Hydromorph\ Gull=1 Hydrosurge=1 Hyena\ Pack=1 Hymn\ of\ Rebirth=1 Hypersonic\ Dragon=1 Hypervolt\ Grasp=1 +Hypnotic\ Cloud=1 Hypnotic\ Siren=1 Hypnotic\ Specter=1 +Hypochondria=1 +Hysterical\ Blindness=1 Hythonia\ the\ Cruel=1 Ib\ Halfheart,\ Goblin\ Tactician=1 Icatian\ Crier=1 Icatian\ Lieutenant=1 -Icatian\ Phalanx=1 Icatian\ Priest=1 -Icatian\ Scout=1 Icatian\ Town=1 Ice\ Cage=1 +Ice\ Cauldron=1 Ice\ Floe=1 Ice\ Over=1 -Ice\ Storm=1 Iceberg=1 Icefall=1 Icefeather\ Aven=1 @@ -4083,15 +4269,18 @@ Ichor\ Rats=1 Ichor\ Slick=1 Icy\ Blast=1 Icy\ Manipulator=1 +Icy\ Prison=1 Identity\ Crisis=1 Identity\ Thief=1 Idle\ Thoughts=1 +Ifh-Bff\ Efreet=1 Igneous\ Golem=1 Igneous\ Pouncer=1 Ignite\ Disorder=1 Ignite\ Memories=1 +Ignoble\ Soldier=1 Ignorant\ Bliss=1 -Ihsan's\ Shade=1 +Iizuka\ the\ Ruthless=1 Ikiral\ Outrider=1 Illness\ in\ the\ Ranks=1 Illuminate=1 @@ -4100,22 +4289,25 @@ Illuminated\ Wings=1 Illusion\ //\ Reality=1 Illusionary\ Forces=1 Illusionary\ Servant=1 -Illusionary\ Wall=1 -Illusionist's\ Stratagem=1 +Illusionist's\ Bracers=1 +Illusory\ Ambusher=1 Illusory\ Angel=1 Illusory\ Demon=1 Illusory\ Gains=1 Illusory\ Wrappings=1 Imagecrafter=1 +Imaginary\ Pet=1 Imaginary\ Threats=1 Imi\ Statue=1 -Immerwolf=1 +Immaculate\ Magistrate=1 Imminent\ Doom=1 Immobilizer\ Eldrazi=1 +Immobilizing\ Ink=1 Immolating\ Glare=1 -Immolating\ Souleater=1 Immolation=1 Immortal\ Coil=1 +Immortal\ Servitude=1 +Imp's\ Mischief=1 Impale=1 Impatience=1 Impeccable\ Timing=1 @@ -4125,84 +4317,80 @@ Imperial\ Ceratops=1 Imperial\ Hellkite=1 Imperial\ Lancer=1 Imperiosaur=1 -Imperious\ Perfect=1 +Impetuous\ Devils=1 Impetuous\ Sunchaser=1 Implement\ of\ Combustion=1 Implement\ of\ Examination=1 Implement\ of\ Ferocity=1 Implement\ of\ Improvement=1 Implement\ of\ Malice=1 -Implode=1 Imprisoned\ in\ the\ Moon=1 Impromptu\ Raid=1 Improvised\ Armor=1 -Imps'\ Taunt=1 -Impulsive\ Maneuvers=1 -In\ Garruk's\ Wake=1 +In\ Bolas's\ Clutches=1 In\ Oketra's\ Name=1 In\ the\ Web\ of\ War=1 Inaction\ Injunction=1 Iname,\ Death\ Aspect=1 Iname,\ Life\ Aspect=1 -Iname\ as\ One=1 Incandescent\ Soulstoke=1 -Incendiary=1 Incendiary\ Command=1 -Incendiary\ Flow=1 Incendiary\ Sabotage=1 Incite=1 Incite\ Hysteria=1 Incite\ War=1 Incorrigible\ Youths=1 -Increasing\ Savagery=1 Incremental\ Blight=1 Incremental\ Growth=1 Incubator\ Drone=1 Incurable\ Ogre=1 Incursion\ Specialist=1 Indebted\ Samurai=1 +Indentured\ Oaf=1 Indestructibility=1 Index=1 Indigo\ Faerie=1 Indomitable\ Ancients=1 Indomitable\ Archangel=1 Indrik\ Stomphowler=1 +Induce\ Despair=1 Induce\ Paranoia=1 Induced\ Amnesia=1 Indulgent\ Aristocrat=1 Indulgent\ Tormentor=1 Inertia\ Bubble=1 -Inescapable\ Brute=1 Inexorable\ Blob=1 Inexorable\ Tide=1 Infantry\ Veteran=1 Infected\ Vermin=1 -Infectious\ Bloodlust=1 Infectious\ Horror=1 Infectious\ Host=1 -Infernal\ Caretaker=1 +Infectious\ Rage=1 +Infernal\ Harvest=1 Infernal\ Kirin=1 Infernal\ Scarring=1 Inferno=1 +Inferno\ Elemental=1 Inferno\ Fist=1 Inferno\ Jet=1 Inferno\ Trap=1 Infest=1 +Infested\ Roothold=1 Infiltration\ Lens=1 Infiltrator's\ Magemark=1 Infiltrator\ il-Kor=1 Infinite\ Obliteration=1 Infinite\ Reflection=1 -Inflame=1 Infuse=1 Infuse\ with\ the\ Elements=1 Infused\ Arrows=1 Ingenious\ Skaab=1 Inheritance=1 Initiate's\ Companion=1 +Initiate\ of\ Blood=1 Ink-Treader\ Nephilim=1 Ink\ Dissolver=1 -Inkfathom\ Infiltrator=1 +Inkfathom\ Divers=1 Inkfathom\ Witch=1 Inner-Chamber\ Guard=1 Inner-Flame\ Acolyte=1 @@ -4211,12 +4399,11 @@ Inner\ Struggle=1 Innocence\ Kami=1 Inquisitor's\ Flail=1 Inquisitor's\ Ox=1 -Inquisitor\ Exarch=1 Insatiable\ Gorgers=1 Insatiable\ Harpy=1 -Insatiable\ Souleater=1 Insidious\ Will=1 Insight=1 +Insolence=1 Inspiration=1 Inspired\ Charge=1 Inspired\ Sprite=1 @@ -4226,48 +4413,54 @@ Inspirit=1 Instigator\ Gang=1 Instill\ Furor=1 Instill\ Infection=1 -Insubordination=1 Insult\ //\ Injury=1 -Intangible\ Virtue=1 -Interdict=1 -Interpret\ the\ Signs=1 Intervene=1 +Intet,\ the\ Dreamer=1 +Intimidation=1 Intimidation\ Bolt=1 Intimidator\ Initiate=1 +Into\ Thin\ Air=1 Into\ the\ Core=1 Into\ the\ Fray=1 Into\ the\ Maw\ of\ Hell=1 Into\ the\ Void=1 -Into\ the\ Wilds=1 Intrepid\ Hero=1 Intrepid\ Provisioner=1 +Inundate=1 Invader\ Parasite=1 -Invasion\ Plans=1 Invasive\ Species=1 Invasive\ Surgery=1 Inventor's\ Apprentice=1 Inventor's\ Goggles=1 Invert\ the\ Skies=1 +Inverter\ of\ Truth=1 +Invigorate=1 +Invigorated\ Rampage=1 +Invigorating\ Boon=1 +Invigorating\ Falls=1 Invincible\ Hymn=1 Invisibility=1 -Invocation\ of\ Saint\ Traft=1 +Invoke\ the\ Divine=1 +Invoke\ the\ Firemind=1 Invulnerability=1 Ion\ Storm=1 Iona's\ Blessing=1 -Iona's\ Judgment=1 Ior\ Ruin\ Expedition=1 Ire\ Shaman=1 Ire\ of\ Kaminari=1 Iridescent\ Drake=1 Iroas's\ Champion=1 +Iron-Barb\ Hellion=1 Iron-Heart\ Chimera=1 +Iron\ Lance=1 Iron\ League\ Steed=1 Iron\ Myr=1 +Iron\ Star=1 +Iron\ Tusk\ Elephant=1 Iron\ Will=1 Ironclad\ Revolutionary=1 Ironclad\ Slayer=1 Ironclaw\ Buzzardiers=1 -Ironclaw\ Orcs=1 Ironfist\ Crusher=1 Ironhoof\ Ox=1 Irontread\ Crusher=1 @@ -4275,6 +4468,7 @@ Ironwright's\ Cleansing=1 Irradiate=1 Irresistible\ Prey=1 Isao,\ Enlightened\ Bushi=1 +Ishi-Ishi,\ Akki\ Crackshot=1 Island=1 Isleback\ Spawn=1 Isolation\ Cell=1 @@ -4283,36 +4477,40 @@ Isperia's\ Skywatch=1 Isperia\ the\ Inscrutable=1 It\ of\ the\ Horrid\ Swarm=1 Ith,\ High\ Arcanist=1 -Ivory\ Charm=1 Ivory\ Crane\ Netsuke=1 Ivory\ Cup=1 Ivory\ Gargoyle=1 +Ivory\ Giant=1 Ivory\ Guardians=1 Ivory\ Tower=1 Ivorytusk\ Fortress=1 Ivy\ Dancer=1 +Ivy\ Elemental=1 Ivy\ Lane\ Denizen=1 +Ivy\ Seer=1 Iwamori\ of\ the\ Open\ Fist=1 Ixalli's\ Diviner=1 Ixalli's\ Keeper=1 +Ixidor's\ Will=1 Ixidron=1 +Izzet\ Chemister=1 Izzet\ Chronarch=1 Izzet\ Cluestone=1 Izzet\ Guildgate=1 Izzet\ Guildmage=1 Izzet\ Keyrune=1 +Jabari's\ Banner=1 Jace's\ Ingenuity=1 Jace's\ Mindseeker=1 Jace's\ Sanctum=1 Jace's\ Scrutiny=1 -Jackal\ Familiar=1 Jackal\ Pup=1 Jackalope\ Herd=1 -Jacques\ le\ Vert=1 +Jaddi\ Lifestrider=1 Jaddi\ Offshoot=1 Jade\ Bearer=1 Jade\ Guardian=1 -Jade\ Leech=1 +Jade\ Idol=1 Jade\ Mage=1 Jade\ Monolith=1 Jade\ Statue=1 @@ -4324,67 +4522,70 @@ Jagwasp\ Swarm=1 Jalira,\ Master\ Polymorphist=1 Jalum\ Tome=1 Jamuraan\ Lion=1 -Jangling\ Automaton=1 Janjeet\ Sentry=1 Jar\ of\ Eyeballs=1 Jarad's\ Orders=1 Jareth,\ Leonine\ Titan=1 -Jasmine\ Boreal=1 Jasmine\ Seer=1 Jawbone\ Skulkin=1 -Jaws\ of\ Stone=1 +Jaya's\ Immolating\ Inferno=1 Jaya\ Ballard,\ Task\ Mage=1 Jayemdae\ Tome=1 -Jedit's\ Dragoons=1 Jedit\ Ojanen=1 Jedit\ Ojanen\ of\ Efrava=1 Jeering\ Instigator=1 Jelenn\ Sphinx=1 Jerrard\ of\ the\ Closed\ Fist=1 +Jeskai\ Ascendancy=1 Jeskai\ Banner=1 Jeskai\ Charm=1 Jeskai\ Elder=1 Jeskai\ Infiltrator=1 -Jeskai\ Runemark=1 Jeskai\ Student=1 Jeskai\ Windscout=1 -Jetting\ Glasskite=1 +Jester's\ Scepter=1 +Jeweled\ Torque=1 +Jhessian\ Balmgiver=1 Jhessian\ Infiltrator=1 Jhessian\ Lookout=1 Jhessian\ Thief=1 Jhessian\ Zombies=1 +Jhoira's\ Familiar=1 Jhoira's\ Timebug=1 Jhoira's\ Toolbox=1 +Jilt=1 Jinxed\ Choker=1 Jinxed\ Idol=1 +Jinxed\ Ring=1 +Jiwari,\ the\ Earth\ Aflame=1 +Jodah's\ Avenger=1 +Jodah,\ Archmage\ Eternal=1 Johtull\ Wurm=1 Join\ the\ Ranks=1 Joiner\ Adept=1 Jokulmorder=1 -Jolrael's\ Centaur=1 Jolrael,\ Empress\ of\ Beasts=1 Jolt=1 -Jor\ Kadeen,\ the\ Prevailer=1 +Jolting\ Merfolk=1 Joraga\ Auxiliary=1 Joraga\ Bard=1 Joraga\ Invocation=1 Jori\ En,\ Ruin\ Diver=1 Jorubai\ Murk\ Lurker=1 -Jotun\ Grunt=1 -Jotun\ Owl\ Keeper=1 Journey\ of\ Discovery=1 +Jousting\ Lance=1 Joven's\ Ferrets=1 Joyous\ Respite=1 Judge\ Unworthy=1 Judge\ of\ Currents=1 +Jugan,\ the\ Rising\ Star=1 Juggernaut=1 Juju\ Bubble=1 -Jump=1 -Jund\ Hackblade=1 -Jund\ Panorama=1 +Jukai\ Messenger=1 +Jund\ Battlemage=1 +Jund\ Charm=1 Jund\ Sojourners=1 Jungle\ Barrier=1 -Jungle\ Basin=1 Jungle\ Creeper=1 Jungle\ Delver=1 Jungle\ Shrine=1 @@ -4395,20 +4596,24 @@ Juniper\ Order\ Advocate=1 Junk\ Golem=1 Junktroller=1 Junkyo\ Bell=1 -Junun\ Efreet=1 Jushi\ Apprentice=1 Just\ Fate=1 Just\ the\ Wind=1 Juvenile\ Gloomwidow=1 Juxtapose=1 Jwar\ Isle\ Avenger=1 +Jwari\ Scuttler=1 Jwari\ Shapeshifter=1 +Jtun\ Grunt=1 +Jtun\ Owl\ Keeper=1 Kabira\ Vindicator=1 +Kaboom!=1 Kabuto\ Moth=1 Kaervek's\ Hex=1 Kaervek's\ Torch=1 Kaervek\ the\ Merciless=1 Kagemaro's\ Clutch=1 +Kagemaro,\ First\ to\ Suffer=1 Kaho,\ Minamo\ Historian=1 Kaijin\ of\ the\ Vanishing\ Touch=1 Kalastria\ Healer=1 @@ -4416,51 +4621,55 @@ Kalastria\ Nightwatch=1 Kaleidostone=1 Kalonian\ Behemoth=1 Kalonian\ Twingrove=1 +Kamahl's\ Desire=1 +Kamahl's\ Druidic\ Vow=1 +Kamahl's\ Sledge=1 Kamahl,\ Pit\ Fighter=1 Kami\ of\ Ancient\ Law=1 -Kami\ of\ Empty\ Graves=1 Kami\ of\ Fire's\ Roar=1 Kami\ of\ Lunacy=1 -Kami\ of\ Tattered\ Shoji=1 +Kami\ of\ Twisted\ Reflection=1 Kami\ of\ the\ Honored\ Dead=1 -Kami\ of\ the\ Hunt=1 Kami\ of\ the\ Painted\ Road=1 -Kami\ of\ the\ Palace\ Fields=1 Kami\ of\ the\ Tended\ Garden=1 -Kami\ of\ the\ Waning\ Moon=1 -Kapsho\ Kitefins=1 Karametra's\ Acolyte=1 Karametra's\ Favor=1 -Karma=1 -Karn,\ Silver\ Golem=1 -Karoo=1 -Karoo\ Meerkat=1 +Karn's\ Temporal\ Sundering=1 Karplusan\ Giant=1 Karplusan\ Strider=1 +Karplusan\ Wolverine=1 +Karplusan\ Yeti=1 +Karstoderm=1 Kashi-Tribe\ Elite=1 Kashi-Tribe\ Reaver=1 Kashi-Tribe\ Warriors=1 +Katabatic\ Winds=1 Kathari\ Bomber=1 Kathari\ Remnant=1 +Kathari\ Screecher=1 Kavu\ Aggressor=1 +Kavu\ Chameleon=1 Kavu\ Climber=1 +Kavu\ Glider=1 +Kavu\ Howler=1 Kavu\ Mauler=1 Kavu\ Predator=1 Kavu\ Primarch=1 Kavu\ Recluse=1 -Kavu\ Scout=1 -Kavu\ Titan=1 +Kavu\ Runner=1 +Kazandu\ Refuge=1 Kazandu\ Tuskcaller=1 +Kazarov,\ Sengir\ Pureblood=1 Kazuul's\ Toll\ Collector=1 Kazuul,\ Tyrant\ of\ the\ Cliffs=1 Kazuul\ Warlord=1 Kederekt\ Creeper=1 Kederekt\ Leviathan=1 -Kederekt\ Parasite=1 Keeneye\ Aven=1 Keening\ Apparition=1 Keening\ Banshee=1 Keening\ Stone=1 +Keeper\ of\ Kookus=1 Keeper\ of\ Progenitus=1 Keeper\ of\ the\ Beasts=1 Keeper\ of\ the\ Dead=1 @@ -4468,34 +4677,33 @@ Keeper\ of\ the\ Flame=1 Keeper\ of\ the\ Lens=1 Keeper\ of\ the\ Light=1 Keeper\ of\ the\ Mind=1 -Keeper\ of\ the\ Nine\ Gales=1 Keepsake\ Gorgon=1 -Kefnet's\ Last\ Word=1 Kefnet's\ Monument=1 -Kei\ Takahashi=1 Keiga,\ the\ Tide\ Star=1 -Keldon\ Arsonist=1 Keldon\ Berserker=1 Keldon\ Champion=1 Keldon\ Halberdier=1 Keldon\ Mantle=1 -Keldon\ Marauders=1 Keldon\ Megaliths=1 Keldon\ Necropolis=1 -Keldon\ Vandals=1 +Keldon\ Overseer=1 +Keldon\ Raider=1 +Keldon\ Twilight=1 +Keldon\ Warcaller=1 Keldon\ Warlord=1 +Kelinore\ Bat=1 +Kemba's\ Legion=1 Kemba's\ Skyguard=1 -Kemba,\ Kha\ Regent=1 +Kemuri-Onna=1 +Kentaro,\ the\ Smiling\ Cat=1 Kessig\ Cagebreakers=1 Kessig\ Dire\ Swine=1 Kessig\ Forgemaster=1 Kessig\ Prowler=1 Kessig\ Recluse=1 -Kessig\ Wolf=1 Key\ to\ the\ City=1 Keymaster\ Rogue=1 Kezzerdrix=1 -Khabal\ Ghoul=1 Khalni\ Gem=1 Khenra\ Charioteer=1 Khenra\ Eternal=1 @@ -4504,6 +4712,7 @@ Kheru\ Bloodsucker=1 Kheru\ Dreadmaw=1 Kheru\ Lich\ Lord=1 Kheru\ Spellsnatcher=1 +Kiku's\ Shadow=1 Kiku,\ Night's\ Flower=1 Kill-Suit\ Cultist=1 Kill\ Shot=1 @@ -4522,87 +4731,95 @@ King\ Cheetah=1 King\ Crab=1 King\ Macar,\ the\ Gold-Cursed=1 Kingfisher=1 +Kingpin's\ Pet=1 Kinjalli's\ Caller=1 Kinsbaile\ Balloonist=1 -Kinsbaile\ Borderguard=1 Kinsbaile\ Skirmisher=1 +Kinscaer\ Harpoonist=1 Kiora's\ Dismissal=1 Kiora's\ Follower=1 Kird\ Chieftain=1 Kiri-Onna=1 +Kiss\ of\ the\ Amesha=1 Kite\ Shield=1 Kitesail=1 Kitesail\ Apprentice=1 Kitesail\ Corsair=1 Kitesail\ Scout=1 +Kithkin\ Armor=1 Kithkin\ Daggerdare=1 +Kithkin\ Greatheart=1 Kithkin\ Harbinger=1 Kithkin\ Healer=1 Kithkin\ Mourncaller=1 -Kithkin\ Rabble=1 Kithkin\ Spellduster=1 +Kithkin\ Zealot=1 Kithkin\ Zephyrnaut=1 -Kitsune\ Blademaster=1 Kitsune\ Bonesetter=1 Kitsune\ Dawnblade=1 Kitsune\ Diviner=1 -Kitsune\ Loreweaver=1 -Kitsune\ Mystic=1 +Kitsune\ Healer=1 Kitsune\ Palliator=1 Kitsune\ Riftwalker=1 Kiyomaro,\ First\ to\ Stand=1 -Kjeldoran\ Dead=1 Kjeldoran\ Elite\ Guard=1 Kjeldoran\ Frostbeast=1 Kjeldoran\ Gargoyle=1 +Kjeldoran\ Home\ Guard=1 Kjeldoran\ Javelineer=1 Kjeldoran\ Outpost=1 Kjeldoran\ Outrider=1 Kjeldoran\ Royal\ Guard=1 Kjeldoran\ Skycaptain=1 Kjeldoran\ War\ Cry=1 +Knacksaw\ Clique=1 +Knight's\ Pledge=1 Knight-Captain\ of\ Eos=1 Knight\ Errant=1 Knight\ Watch=1 Knight\ of\ Cliffhaven=1 -Knight\ of\ Dawn=1 Knight\ of\ Dusk=1 +Knight\ of\ Glory=1 Knight\ of\ Infamy=1 +Knight\ of\ New\ Benalia=1 Knight\ of\ Obligation=1 Knight\ of\ Stromgald=1 Knight\ of\ Sursi=1 +Knight\ of\ Valor=1 Knight\ of\ the\ Holy\ Nimbus=1 Knight\ of\ the\ Mists=1 Knight\ of\ the\ Pilgrim's\ Road=1 Knight\ of\ the\ Skyward\ Eye=1 Knight\ of\ the\ Stampede=1 +Knight\ of\ the\ Tusk=1 Knighthood=1 Knightly\ Valor=1 -Knights\ of\ Thorn=1 Knollspine\ Dragon=1 -Knollspine\ Invocation=1 Knotvine\ Mystic=1 Knotvine\ Paladin=1 +Knowledge\ Exploitation=1 Knowledge\ Pool=1 -Knowledge\ Vault=1 Knowledge\ and\ Power=1 Knucklebone\ Witch=1 Kobold\ Drill\ Sergeant=1 -Kobold\ Overlord=1 Kobold\ Taskmaster=1 Kodama's\ Might=1 Kodama\ of\ the\ Center\ Tree=1 Kodama\ of\ the\ North\ Tree=1 +Kodama\ of\ the\ South\ Tree=1 Kolaghan\ Aspirant=1 Kolaghan\ Forerunners=1 Kolaghan\ Monument=1 Kolaghan\ Stormsinger=1 +Konda's\ Banner=1 Konda's\ Hatamoto=1 +Konda,\ Lord\ of\ Eiganjo=1 Kongming,\ "Sleeping\ Dragon"=1 Kookus=1 Kor\ Bladewhirl=1 Kor\ Cartographer=1 Kor\ Castigator=1 +Kor\ Chant=1 Kor\ Duelist=1 Kor\ Entanglers=1 Kor\ Hookmaster=1 @@ -4612,7 +4829,6 @@ Kor\ Sky\ Climber=1 Korozda\ Gorgon=1 Korozda\ Guildmage=1 Korozda\ Monitor=1 -Koth's\ Courier=1 Kothophed,\ Soul\ Hoarder=1 Kozilek's\ Channeler=1 Kozilek's\ Pathfinder=1 @@ -4627,58 +4843,61 @@ Kraken\ Hatchling=1 Kraken\ of\ the\ Straits=1 Krakilin=1 Kranioceros=1 -Krark's\ Thumb=1 -Krark-Clan\ Engineers=1 -Krark-Clan\ Grunt=1 -Krark-Clan\ Ogre=1 Krasis\ Incubation=1 Kraul\ Warrior=1 Krenko's\ Enforcer=1 -Kris\ Mage=1 -Krosan\ Beast=1 +Krosan\ Avenger=1 Krosan\ Cloudscraper=1 +Krosan\ Colossus=1 Krosan\ Drover=1 +Krosan\ Druid=1 Krosan\ Groundshaker=1 +Krosan\ Reclamation=1 Krosan\ Tusker=1 Krosan\ Vorine=1 Krosan\ Warchief=1 +Krosan\ Wayfarer=1 Krovikan\ Fetish=1 +Krovikan\ Horror=1 Krovikan\ Rot=1 Krovikan\ Scoundrel=1 -Krovikan\ Sorcerer=1 Krovikan\ Vampire=1 -Krovikan\ Whispers=1 Kruin\ Outlaw=1 Kruin\ Striker=1 -Krumar\ Bond-Kin=1 Kudzu=1 Kujar\ Seedsculptor=1 Kukemssa\ Serpent=1 Kuldotha\ Flamefiend=1 Kuldotha\ Phoenix=1 -Kuldotha\ Ringleader=1 Kulrath\ Knight=1 +Kumano's\ Blessing=1 +Kumano's\ Pupils=1 Kumano,\ Master\ Yamabushi=1 Kumena's\ Awakening=1 +Kumena's\ Speaker=1 +Kuon,\ Ogre\ Ascendant=1 Kurgadon=1 Kurkesh,\ Onakke\ Ancient=1 Kuro's\ Taken=1 Kuro,\ Pitlord=1 -Kyren\ Glider=1 +Kusari-Gama=1 +Kwende,\ Pride\ of\ Femeref=1 +Kyoki,\ Sanity's\ Eclipse=1 +Kyren\ Legate=1 Kyren\ Sniper=1 Kytheon's\ Irregulars=1 Kytheon's\ Tactics=1 Lab\ Rats=1 Laboratory\ Brute=1 +Labyrinth\ Champion=1 Labyrinth\ Guardian=1 Labyrinth\ Minotaur=1 +Laccolith\ Grunt=1 Laccolith\ Rig=1 -Lady\ Caleria=1 -Lady\ Evangela=1 +Laccolith\ Warrior=1 Lady\ Orca=1 Lagac\ Lizard=1 Lagonna-Band\ Elder=1 -Lake\ of\ the\ Dead=1 Lambholt\ Elder=1 Lambholt\ Pacifist=1 Lammastide\ Weave=1 @@ -4688,16 +4907,22 @@ Landslide=1 Lantern-Lit\ Graveyard=1 Lantern\ Kami=1 Lantern\ Scout=1 +Lantern\ Spirit=1 Lapse\ of\ Certainty=1 Laquatus's\ Champion=1 +Laquatus's\ Disdain=1 +Larceny=1 +Larger\ Than\ Life=1 Lash\ Out=1 Lashknife=1 Lashknife\ Barrier=1 Lashweed\ Lurker=1 Last-Ditch\ Effort=1 Last\ Breath=1 +Last\ Caress=1 Last\ Gasp=1 Last\ Kiss=1 +Last\ Laugh=1 Last\ Stand=1 Last\ Thoughts=1 Last\ Word=1 @@ -4706,49 +4931,45 @@ Latch\ Seeker=1 Latchkey\ Faerie=1 Lathnu\ Hellion=1 Lathnu\ Sailback=1 -Latulla's\ Orders=1 Launch=1 -Launch\ Party=1 Lava\ Axe=1 Lava\ Burst=1 +Lava\ Dart=1 Lava\ Flow=1 Lava\ Hounds=1 -Lava\ Zombie=1 +Lava\ Runner=1 Lavaball\ Trap=1 Lavaborn\ Muse=1 -Lavacore\ Elemental=1 Lavafume\ Invoker=1 -Lavamancer's\ Skill=1 +Lavalanche=1 Lavastep\ Raider=1 Lavinia\ of\ the\ Tenth=1 -Lawbringer=1 Lawless\ Broker=1 Lay\ Bare\ the\ Heart=1 Lay\ Claim=1 Lay\ Waste=1 Lay\ of\ the\ Land=1 Lead-Belly\ Chimera=1 +Lead\ Astray=1 Lead\ Golem=1 Lead\ by\ Example=1 Leaden\ Fists=1 Leaden\ Myr=1 -Leaf\ Arrow=1 +Leaf\ Dancer=1 Leaf\ Gilder=1 Leafcrown\ Dryad=1 Leafdrake\ Roost=1 -Leap\ of\ Flame=1 Leaping\ Lizard=1 Leaping\ Master=1 Learn\ from\ the\ Past=1 Leashling=1 -Leatherback\ Baloth=1 Leave\ //\ Chance=1 -Leave\ No\ Trace=1 Leave\ in\ the\ Dust=1 Leech\ Bonder=1 +Leeches=1 Leeching\ Licid=1 -Leechridden\ Swamp=1 Leering\ Emblem=1 +Leering\ Gargoyle=1 Leery\ Fogbeast=1 Legacy's\ Allure=1 Legacy\ Weapon=1 @@ -4757,6 +4978,7 @@ Legion's\ Judgment=1 Legion\ Conquistador=1 Legion\ Lieutenant=1 Lens\ of\ Clarity=1 +Leonin\ Abunas=1 Leonin\ Armorguard=1 Leonin\ Battlemage=1 Leonin\ Bola=1 @@ -4769,146 +4991,162 @@ Leonin\ Snarecaster=1 Leonin\ Squire=1 Leonin\ Sun\ Standard=1 Leshrac's\ Rite=1 +Lesser\ Gargadon=1 Lesser\ Werewolf=1 Lethal\ Sting=1 +Lethargy\ Trap=1 Leveler=1 +Leviathan=1 Levitation=1 Ley\ Druid=1 +Ley\ Line=1 Leyline\ Phantom=1 Leyline\ of\ Lightning=1 Leyline\ of\ Vitality=1 +Lhurgoyf=1 Liar's\ Pendulum=1 +Liberate=1 +Liberated\ Dwarf=1 +Lich's\ Caress=1 +Lich's\ Mastery=1 Lich's\ Tomb=1 Liege\ of\ the\ Pit=1 -Life's\ Legacy=1 -Life\ //\ Death=1 -Life\ Chisel=1 +Life's\ Finale=1 +Life\ Goes\ On=1 Life\ and\ Limb=1 Lifecraft\ Awakening=1 Lifecraft\ Cavalry=1 Lifecrafter's\ Gift=1 -Lifesmith=1 +Lifegift=1 Lifespark\ Spellbomb=1 Lifespinner=1 Lifespring\ Druid=1 -Light\ of\ Day=1 Light\ of\ Sanction=1 Lightbringer=1 Lightkeeper\ of\ Emeria=1 -Lightmine\ Field=1 Lightning-Rig\ Crew=1 Lightning\ Blast=1 Lightning\ Blow=1 Lightning\ Cloud=1 -Lightning\ Coils=1 -Lightning\ Crafter=1 -Lightning\ Dragon=1 Lightning\ Elemental=1 Lightning\ Hounds=1 Lightning\ Javelin=1 -Lightning\ Prowess=1 Lightning\ Reaver=1 Lightning\ Reflexes=1 Lightning\ Rift=1 Lightning\ Runner=1 -Lightning\ Surge=1 Lightning\ Talons=1 Lightning\ Volley=1 Lightwielder\ Paladin=1 Liliana's\ Defeat=1 Liliana's\ Elite=1 Liliana's\ Indignation=1 -Liliana's\ Mastery=1 -Liliana's\ Reaver=1 Liliana's\ Shade=1 -Lim-Dul's\ Cohort=1 -Lim-Dul's\ High\ Guard=1 -Lim-Dul\ the\ Necromancer=1 +Liliana's\ Specter=1 +Lilting\ Refrain=1 +Lim-Dl's\ Cohort=1 +Lim-Dl's\ High\ Guard=1 +Lim-Dl\ the\ Necromancer=1 +Limestone\ Golem=1 Limits\ of\ Solidarity=1 Linessa,\ Zephyr\ Mage=1 -Lingering\ Death=1 +Lingering\ Mirage=1 +Lingering\ Phantom=1 Lingering\ Tormentor=1 +Linvala,\ the\ Preserver=1 +Lionheart\ Maverick=1 +Liquid\ Fire=1 Liquimetal\ Coating=1 +Lithatog=1 +Lithomancer's\ Focus=1 +Lithophage=1 Liturgy\ of\ Blood=1 Liu\ Bei,\ Lord\ of\ Shu=1 Live\ Fast=1 Livewire\ Lash=1 +Living\ Airship=1 +Living\ Death=1 Living\ Destiny=1 Living\ Hive=1 Living\ Inferno=1 -Living\ Lore=1 +Living\ Lands=1 +Living\ Terrain=1 Living\ Totem=1 Living\ Tsunami=1 -Living\ Wall=1 -Livonya\ Silone=1 +Llanowar\ Behemoth=1 +Llanowar\ Cavalry=1 +Llanowar\ Dead=1 Llanowar\ Empath=1 +Llanowar\ Envoy=1 Llanowar\ Mentor=1 +Llanowar\ Scout=1 Llanowar\ Sentinel=1 +Llanowar\ Vanguard=1 Loafing\ Giant=1 Loam\ Dryad=1 Loam\ Dweller=1 -Loam\ Larva=1 Loam\ Lion=1 Loamdragger\ Giant=1 +Loathsome\ Catoblepas=1 Lobber\ Crew=1 -Lobotomy=1 Locket\ of\ Yesterdays=1 Lockjaw\ Snapper=1 -Locust\ Miser=1 +Locust\ Swarm=1 Lodestone\ Myr=1 +Lone\ Missionary=1 Lone\ Revenant=1 Lone\ Rider=1 Lone\ Wolf=1 -Lonely\ Sandbar=1 Long-Finned\ Skywhale=1 Long-Forgotten\ Gohei=1 Long\ Road\ Home=1 Longbow\ Archer=1 Longshot\ Squad=1 +Longtusk\ Cub=1 +Lookout's\ Dispersal=1 Looming\ Altisaur=1 Looming\ Hoverguard=1 Looming\ Shade=1 Looming\ Spires=1 -Looter\ il-Kor=1 -Lord\ of\ the\ Accursed=1 +Lord\ of\ Shatterskull\ Pass=1 Lord\ of\ the\ Pit=1 Lore\ Broker=1 Lorescale\ Coatl=1 +Lorthos,\ the\ Tidemaker=1 Lose\ Calm=1 Lose\ Hope=1 Lost\ Auramancers=1 -Lost\ Hours=1 Lost\ Leonin=1 Lost\ Order\ of\ Jarkeld=1 +Lost\ in\ Thought=1 Lost\ in\ a\ Labyrinth=1 Lost\ in\ the\ Mist=1 -Lotleth\ Troll=1 -Lotus-Eye\ Mystics=1 +Lost\ in\ the\ Woods=1 Lotus\ Path\ Djinn=1 Lowland\ Basilisk=1 Lowland\ Giant=1 -Lowland\ Tracker=1 -Loxodon\ Convert=1 Loxodon\ Gatekeeper=1 Loxodon\ Hierarch=1 -Loxodon\ Mender=1 +Loxodon\ Line\ Breaker=1 Loxodon\ Mystic=1 +Loxodon\ Partisan=1 Loxodon\ Peacekeeper=1 Loxodon\ Punisher=1 Loyal\ Cathar=1 +Loyal\ Gyrfalcon=1 Loyal\ Pegasus=1 Lu\ Bu,\ Master-at-Arms=1 Lu\ Meng,\ Wu\ General=1 Lucent\ Liminid=1 Ludevic's\ Test\ Subject=1 -Lull=1 Lullmage\ Mentor=1 +Lumbering\ Satyr=1 Lumberknot=1 -Lumengrid\ Drake=1 +Lumengrid\ Augur=1 Lumengrid\ Gargoyle=1 +Lumengrid\ Sentinel=1 Lumengrid\ Warden=1 Luminate\ Primordial=1 -Luminesce=1 Luminous\ Angel=1 Luminous\ Bonds=1 Luminous\ Wake=1 @@ -4919,47 +5157,47 @@ Lunarch\ Mantle=1 Lunk\ Errant=1 Lupine\ Prototype=1 Lurching\ Rotbeast=1 +Lure=1 Lurebound\ Scarecrow=1 Lurking\ Arynx=1 Lurking\ Chupacabra=1 -Lurking\ Crocodile=1 -Lurking\ Evil=1 Lurking\ Informant=1 -Lurking\ Jackals=1 Lurking\ Skirge=1 Lush\ Growth=1 +Lust\ for\ War=1 Luxa\ River\ Shrine=1 Lyev\ Decree=1 Lyev\ Skyknight=1 Lymph\ Sliver=1 Lys\ Alana\ Bowmaster=1 Lys\ Alana\ Scarblade=1 -Lyzolda,\ the\ Blood\ Witch=1 Macabre\ Waltz=1 Macetail\ Hystrodon=1 +Machinate=1 Mad\ Auntie=1 Mad\ Prophet=1 Madblind\ Mountain=1 Madcap\ Skills=1 Madrush\ Cyclops=1 Maelstrom\ Djinn=1 +Maga,\ Traitor\ to\ Mortals=1 Mage-Ring\ Bully=1 Mage-Ring\ Network=1 Mage-Ring\ Responder=1 Mage\ Slayer=1 -Mage\ il-Vec=1 Magebane\ Armor=1 Magefire\ Wings=1 -Mageta's\ Boon=1 Magewright's\ Stone=1 Maggot\ Carrier=1 Maggot\ Therapy=1 +Magister\ Sphinx=1 Magister\ of\ Worth=1 +Magistrate's\ Veto=1 +Magma\ Burst=1 Magma\ Giant=1 Magma\ Mine=1 Magma\ Phoenix=1 -Magma\ Spray=1 -Magma\ Vein=1 +Magma\ Rift=1 Magmaquake=1 Magmaroth=1 Magmasaur=1 @@ -4967,58 +5205,64 @@ Magmatic\ Chasm=1 Magmatic\ Core=1 Magmatic\ Insight=1 Magmaw=1 -Magnetic\ Flux=1 -Magnetic\ Mine=1 Magnetic\ Theft=1 Magnifying\ Glass=1 Magnivore=1 Magosi,\ the\ Waterveil=1 Magus\ of\ the\ Abyss=1 -Magus\ of\ the\ Arena=1 Magus\ of\ the\ Candelabra=1 +Magus\ of\ the\ Coffers=1 Magus\ of\ the\ Disk=1 Magus\ of\ the\ Future=1 Magus\ of\ the\ Jar=1 Magus\ of\ the\ Library=1 Magus\ of\ the\ Mirror=1 Magus\ of\ the\ Scroll=1 +Magus\ of\ the\ Tabernacle=1 +Magus\ of\ the\ Vineyard=1 Mahamoti\ Djinn=1 Majestic\ Heliopterus=1 +Major\ Teroh=1 Make\ Mischief=1 Make\ Obsolete=1 Make\ a\ Stand=1 +Make\ a\ Wish=1 Makeshift\ Mannequin=1 Makeshift\ Mauler=1 Makeshift\ Munitions=1 Makindi\ Aeronaut=1 +Makindi\ Griffin=1 Makindi\ Patrol=1 Makindi\ Shieldmate=1 Makindi\ Sliderunner=1 +Malach\ of\ the\ Dawn=1 Malachite\ Golem=1 Malakir\ Bloodwitch=1 Malakir\ Cullblade=1 Malakir\ Familiar=1 Malakir\ Soothsayer=1 +Malevolent\ Awakening=1 Malevolent\ Whispers=1 Malfunction=1 +Malicious\ Advice=1 +Mammoth\ Spider=1 Mammoth\ Umbra=1 Man-o'-War=1 Mana\ Bloom=1 -Mana\ Breach=1 Mana\ Clash=1 Mana\ Cylix=1 -Mana\ Geyser=1 Mana\ Leech=1 -Mana\ Prism=1 Mana\ Seism=1 Mana\ Skimmer=1 Manabarbs=1 Manacles\ of\ Decay=1 Manaforce\ Mace=1 Manaforge\ Cinder=1 +Managorger\ Hydra=1 Manakin=1 Manalith=1 Manaplasm=1 +Mangara's\ Blessing=1 Mangara\ of\ Corondor=1 Manglehorn=1 Maniacal\ Rage=1 @@ -5027,19 +5271,21 @@ Manic\ Vandal=1 Mannichi,\ the\ Fevered\ Dream=1 Manor\ Gargoyle=1 Manor\ Skeleton=1 -Manriki-Gusari=1 Manta\ Ray=1 Manta\ Riders=1 Manticore\ Eternal=1 Manticore\ of\ the\ Gauntlet=1 +Mantis\ Engine=1 Mantle\ of\ Leadership=1 Mantle\ of\ Webs=1 Map\ the\ Wastes=1 Marang\ River\ Skeleton=1 +Marauder's\ Axe=1 Marauding\ Boneslasher=1 Marauding\ Looter=1 +Marauding\ Maulhorn=1 Marble\ Chalice=1 -March\ from\ the\ Tomb=1 +Marble\ Titan=1 March\ of\ the\ Drowned=1 March\ of\ the\ Machines=1 March\ of\ the\ Returned=1 @@ -5054,20 +5300,16 @@ Mardu\ Roughrider=1 Mardu\ Runemark=1 Mardu\ Skullhunter=1 Mardu\ Warshrieker=1 -Marhault\ Elsdragon=1 +Marionette\ Master=1 Marisi's\ Twinclaws=1 Maritime\ Guard=1 -Marjhan=1 Mark\ for\ Death=1 Mark\ of\ Eviction=1 -Mark\ of\ Fury=1 -Mark\ of\ Mutiny=1 Mark\ of\ Sakiko=1 Mark\ of\ the\ Oni=1 Mark\ of\ the\ Vampire=1 Marked\ by\ Honor=1 Marker\ Beetles=1 -Market\ Festival=1 Markov\ Blademaster=1 Markov\ Crusader=1 Markov\ Dreadknight=1 @@ -5075,11 +5317,12 @@ Markov\ Patrician=1 Markov\ Warlord=1 Maro=1 Marrow\ Bats=1 +Marrow\ Chomper=1 +Marrow\ Shards=1 Marsh\ Casualties=1 Marsh\ Flitter=1 Marsh\ Hulk=1 Marsh\ Lurker=1 -Marsh\ Threader=1 Marshal's\ Anthem=1 Marshaling\ Cry=1 Marshdrinker\ Giant=1 @@ -5088,38 +5331,37 @@ Martial\ Glory=1 Martial\ Law=1 Martyr's\ Cause=1 Martyr's\ Cry=1 +Martyr\ of\ Bones=1 Martyr\ of\ Dusk=1 Martyr\ of\ Frost=1 Martyred\ Rusalka=1 +Martyrs'\ Tomb=1 Martyrs\ of\ Korlis=1 +Marwyn,\ the\ Nurturer=1 Masako\ the\ Humorless=1 Mask\ of\ Avacyn=1 -Mask\ of\ Memory=1 +Mask\ of\ Intolerance=1 Mask\ of\ Riddles=1 Mask\ of\ the\ Mimic=1 Masked\ Admirers=1 -Masked\ Gorgon=1 Mass\ Appeal=1 Mass\ Calcify=1 Mass\ Polymorph=1 Mass\ of\ Ghouls=1 -Massive\ Raid=1 Master's\ Call=1 Master\ Decoy=1 -Master\ Healer=1 Master\ Splicer=1 Master\ Thief=1 Master\ Trinketeer=1 Master\ Warcraft=1 +Master\ of\ Arms=1 Master\ of\ Diversion=1 Master\ of\ Pearls=1 Master\ of\ Predicaments=1 Master\ the\ Way=1 -Mastery\ of\ the\ Unseen=1 Masticore=1 Masumaro,\ First\ to\ Live=1 Matca\ Rioters=1 -Matopi\ Golem=1 Matsu-Tribe\ Birdstalker=1 Matsu-Tribe\ Decoy=1 Matsu-Tribe\ Sniper=1 @@ -5131,54 +5373,64 @@ Mausoleum\ Guard=1 Mausoleum\ Harpy=1 Mausoleum\ Turnkey=1 Maverick\ Thopterist=1 +Mavren\ Fein,\ Dusk\ Apostle=1 Maw\ of\ Kozilek=1 Maw\ of\ the\ Mire=1 Maw\ of\ the\ Obzedat=1 Mawcor=1 +Mayor\ of\ Avabruck=1 Maze\ Abomination=1 Maze\ Behemoth=1 Maze\ Glider=1 Maze\ Rusher=1 +Maze\ Sentinel=1 Maze\ of\ Shadows=1 Meadowboon=1 Meandering\ River=1 Meandering\ Towershell=1 Measure\ of\ Wickedness=1 +Meddle=1 Medicine\ Runner=1 Meditation\ Puzzle=1 -Megantic\ Sliver=1 +Megatherium=1 +Megatog=1 Meglonoth=1 Megrim=1 Melancholy=1 +Melek,\ Izzet\ Paragon=1 +Melesse\ Spirit=1 Meletis\ Astronomer=1 Meletis\ Charlatan=1 Melira's\ Keepers=1 Meloku\ the\ Clouded\ Mirror=1 Melt\ Terrain=1 -Meltdown=1 +Memorial\ to\ Folly=1 +Memorial\ to\ Glory=1 +Memorial\ to\ Unity=1 Memory's\ Journey=1 Memory\ Erosion=1 Menacing\ Ogre=1 Mending\ Hands=1 Mending\ Touch=1 Meng\ Huo's\ Horde=1 +Mental\ Discipline=1 Mental\ Vapors=1 +Mephidross\ Vampire=1 Mephitic\ Ooze=1 Mer-Ek\ Nightblade=1 +Mercadian\ Bazaar=1 Merchant's\ Dockhand=1 Merciless\ Eternal=1 Merciless\ Javelineer=1 Merciless\ Resolve=1 Mercurial\ Chemister=1 -Mercurial\ Geists=1 Mercurial\ Kite=1 Mercurial\ Pretender=1 -Mercy\ Killing=1 Merfolk\ Assassin=1 Merfolk\ Looter=1 Merfolk\ Mesmerist=1 +Merfolk\ Mistbinder=1 Merfolk\ Observer=1 -Merfolk\ Raiders=1 Merfolk\ Seastalkers=1 Merfolk\ Seer=1 Merfolk\ Skyscout=1 @@ -5194,10 +5446,10 @@ Merrow\ Bonegnawer=1 Merrow\ Commerce=1 Merrow\ Grimeblotter=1 Merrow\ Harbinger=1 +Merrow\ Levitator=1 Merrow\ Witsniper=1 Mesa\ Enchantress=1 -Mesa\ Pegasus=1 -Mesmeric\ Fiend=1 +Mesa\ Unicorn=1 Mesmeric\ Sliver=1 Mesmeric\ Trance=1 Messenger's\ Speed=1 @@ -5207,23 +5459,25 @@ Metal\ Fatigue=1 Metallic\ Mastery=1 Metallurgeon=1 Metalspinner's\ Puzzleknot=1 -Metamorphose=1 +Metamorphic\ Wurm=1 Metathran\ Aerostat=1 -Metathran\ Elite=1 Metathran\ Soldier=1 +Metathran\ Transport=1 +Metathran\ Zombie=1 +Meteor\ Shower=1 Meteorite=1 +Metrognome=1 Metropolis\ Sprite=1 Miasmic\ Mummy=1 Midnight\ Banshee=1 Midnight\ Charm=1 -Midnight\ Duelist=1 +Midnight\ Covenant=1 Midnight\ Entourage=1 Midnight\ Guard=1 Midnight\ Haunting=1 Midnight\ Oil=1 -Midnight\ Recovery=1 +Midnight\ Ritual=1 Midnight\ Scavengers=1 -Midsummer\ Revel=1 Might\ Beyond\ Reason=1 Might\ Makes\ Right=1 Might\ Sliver=1 @@ -5236,21 +5490,22 @@ Mightstone=1 Mighty\ Emergence=1 Mighty\ Leap=1 Militant\ Inquisitor=1 -Military\ Intelligence=1 +Militant\ Monk=1 Militia's\ Pride=1 Millennial\ Gargoyle=1 Millikin=1 Millstone=1 Mimeofacture=1 +Mimic\ Vat=1 Miming\ Slime=1 Mina\ and\ Denn,\ Wildborn=1 Minamo\ Scrollkeeper=1 Minamo\ Sightbender=1 Mind\ Bend=1 +Mind\ Burst=1 Mind\ Control=1 Mind\ Extraction=1 Mind\ Grind=1 -Mind\ Maggots=1 Mind\ Peel=1 Mind\ Raker=1 Mind\ Rot=1 @@ -5258,79 +5513,79 @@ Mind\ Shatter=1 Mind\ Sludge=1 Mind\ Spring=1 Mindclaw\ Shaman=1 -Mindcrank=1 -Mindculling=1 Mindlash\ Sliver=1 Mindleech\ Mass=1 Mindless\ Automaton=1 Mindless\ Null=1 Mindlock\ Orb=1 Mindmelter=1 -Mindmoil=1 Mindreaver=1 -Mindscour\ Dragon=1 Mindshrieker=1 -Mindsparker=1 Mindstab=1 Mindstab\ Thrull=1 Mindstatic=1 Mindswipe=1 Mindwarper=1 +Mindwrack\ Liege=1 +Mine\ Bearer=1 Mine\ Excavation=1 -Miner's\ Bane=1 Minion\ Reflector=1 -Minion\ of\ Leshrac=1 -Minion\ of\ Tevesh\ Szat=1 Minion\ of\ the\ Wastes=1 Minions'\ Murmurs=1 Minister\ of\ Impediments=1 Minotaur\ Abomination=1 Minotaur\ Aggressor=1 +Minotaur\ Explorer=1 +Minotaur\ Illusionist=1 Minotaur\ Skullcleaver=1 Minotaur\ Sureshot=1 +Minotaur\ Tactician=1 Miraculous\ Recovery=1 +Mirage\ Mirror=1 Mirari=1 Mire's\ Malice=1 Mire's\ Toll=1 Mire\ Boa=1 -Mirko\ Vosk,\ Mind\ Drinker=1 +Mire\ Kavu=1 +Mire\ Shade=1 Mirozel=1 Mirran\ Mettle=1 Mirran\ Spy=1 Mirri,\ Cat\ Warrior=1 Mirri\ the\ Cursed=1 Mirror-Mad\ Phantasm=1 -Mirror\ Golem=1 -Mirror\ Mockery=1 Mirror\ Sheen=1 +Mirror\ Strike=1 +Mirror\ Wall=1 Mirror\ of\ Fate=1 Mirrorweave=1 +Mirrorwood\ Treefolk=1 Mirrorworks=1 Mischievous\ Poltergeist=1 Misery\ Charm=1 Misfortune's\ Gain=1 Misguided\ Rage=1 Mishra's\ Groundbreaker=1 +Mishra's\ Self-Replicator=1 Mishra,\ Artificer\ Prodigy=1 Misinformation=1 +Misstep=1 Mist-Cloaked\ Herald=1 Mist\ Intruder=1 Mist\ Leopard=1 Mist\ Raven=1 -Mistblade\ Shinobi=1 Mistcutter\ Hydra=1 -Mistfire\ Adept=1 Mistfire\ Weaver=1 Mistform\ Dreamer=1 Mistform\ Mask=1 Mistform\ Mutant=1 -Mistform\ Seaswift=1 Mistform\ Shrieker=1 Mistform\ Skyreaver=1 Mistform\ Sliver=1 Mistform\ Stalker=1 Mistform\ Ultimus=1 Mistform\ Wakecaster=1 +Mistform\ Wall=1 Mistform\ Warchief=1 Misthoof\ Kirin=1 Mistmeadow\ Skulk=1 @@ -5344,16 +5599,15 @@ Mizzium\ Mortars=1 Mizzium\ Skin=1 Mizzium\ Transreliquat=1 Mnemonic\ Nexus=1 -Mnemonic\ Wall=1 Moan\ of\ the\ Unhallowed=1 Moaning\ Wall=1 -Mob\ Mentality=1 Mobile\ Fort=1 Mobile\ Garrison=1 -Mobilization=1 +Mockery\ of\ Nature=1 Mogg\ Bombers=1 Mogg\ Flunkies=1 Mogg\ Hollows=1 +Mogg\ Salvage=1 Mogg\ Sentry=1 Mogg\ Squad=1 Mogis's\ Marauder=1 @@ -5366,52 +5620,60 @@ Moldervine\ Cloak=1 Moldgraf\ Monstrosity=1 Moldgraf\ Scavenger=1 Molimo,\ Maro-Sorcerer=1 -Molten\ Birth=1 Molten\ Disaster=1 Molten\ Firebird=1 -Molten\ Frame=1 +Molten\ Hydra=1 +Molten\ Influence=1 Molten\ Nursery=1 Molten\ Primordial=1 Molten\ Psyche=1 Molten\ Ravager=1 Molten\ Sentry=1 Molten\ Slagheap=1 +Molten\ Vortex=1 Moltensteel\ Dragon=1 +Molting\ Harpy=1 Molting\ Skin=1 Molting\ Snakeskin=1 +Moment\ of\ Craving=1 Moment\ of\ Heroism=1 Moment\ of\ Triumph=1 Momentary\ Blink=1 Momentous\ Fall=1 -Momentum=1 +Momir\ Vig,\ Simic\ Visionary=1 Monastery\ Flock=1 Monastery\ Loremaster=1 Mondronen\ Shaman=1 Monk\ Idealist=1 Monk\ Realist=1 Monomania=1 +Monstrify=1 +Monstrous\ Growth=1 +Monstrous\ Hound=1 Monstrous\ Onslaught=1 -Moon\ Heron=1 Moonbow\ Illusionist=1 Moonglove\ Changeling=1 -Moonglove\ Extract=1 Moonglove\ Winnower=1 Moonhold=1 Moonlace=1 -Moonlight\ Geist=1 +Moonlight\ Bargain=1 Moonlight\ Hunt=1 Moonlit\ Strider=1 Moonmist=1 Moonring\ Island=1 Moonring\ Mirror=1 Moonsilver\ Spear=1 +Moonwing\ Moth=1 Moorish\ Cavalry=1 Moorland\ Drifter=1 -Moorland\ Haunt=1 +Morality\ Shift=1 +Moratorium\ Stone=1 Morbid\ Bloom=1 Morbid\ Curiosity=1 Mordant\ Dragon=1 Morgue\ Burst=1 +Morgue\ Thrull=1 +Morgue\ Toad=1 Morinfen=1 Moriok\ Reaver=1 Moriok\ Replica=1 @@ -5419,53 +5681,60 @@ Moriok\ Rigger=1 Moriok\ Scavenger=1 Morkrut\ Banshee=1 Morkrut\ Necropod=1 +Morningtide=1 Moroii=1 +Morphling=1 Morsel\ Theft=1 Morselhoarder=1 Mortal's\ Ardor=1 Mortal's\ Resolve=1 Mortal\ Combat=1 Mortal\ Obstinacy=1 +Mortal\ Wound=1 Mortarpod=1 Mortician\ Beetle=1 Mortipede=1 -Mortis\ Dogs=1 +Mortiphobia=1 +Mortivore=1 Mortuary=1 Mortuary\ Mire=1 Mortus\ Strider=1 Mosquito\ Guard=1 +Moss\ Diamond=1 +Moss\ Kami=1 Moss\ Monster=1 Mossbridge\ Troll=1 -Mossdog=1 Mossfire\ Egg=1 Mothdust\ Changeling=1 +Mothrider\ Samurai=1 Mountain=1 Mountain\ Valley=1 Mountain\ Yeti=1 -Mounted\ Archers=1 -Mourning\ Thrull=1 +Mourner's\ Shield=1 +Mournful\ Zombie=1 +Mourning=1 Mournwhelk=1 Mournwillow=1 Mouth\ //\ Feed=1 -Mtenda\ Herder=1 +Mtenda\ Griffin=1 Muck\ Drubb=1 -Mudbrawler\ Raiders=1 Mudbutton\ Clanger=1 Mudbutton\ Torchrunner=1 -Mudhole=1 Mugging=1 Mul\ Daya\ Channelers=1 Mulch=1 Multani's\ Acolyte=1 +Multani's\ Harmony=1 Multani's\ Presence=1 -Multiform\ Wonder=1 Mummy\ Paramount=1 +Munda's\ Vanguard=1 Munda,\ Ambush\ Leader=1 Mundungu=1 Murasa\ Pyromancer=1 Murasa\ Ranger=1 Murder=1 Murder\ Investigation=1 +Murder\ of\ Crows=1 Murderer's\ Axe=1 Murderous\ Betrayal=1 Murderous\ Compulsion=1 @@ -5475,42 +5744,48 @@ Murderous\ Spoils=1 Murk\ Strider=1 Murmuring\ Phantasm=1 Murmurs\ from\ Beyond=1 +Muscle\ Burst=1 Muse\ Vessel=1 +Musician=1 Mutant's\ Prey=1 Mutiny=1 Muzzle=1 Mwonvuli\ Beast\ Tracker=1 +Mwonvuli\ Ooze=1 Mycoid\ Shepherd=1 Mycologist=1 Mycosynth\ Fiend=1 Mycosynth\ Wellspring=1 -Myojin\ of\ Cleansing\ Fire=1 +Myojin\ of\ Infinite\ Rage=1 Myr\ Adapter=1 Myr\ Galvanizer=1 Myr\ Incubator=1 -Myr\ Landshaper=1 -Myr\ Mindservant=1 Myr\ Moonvessel=1 Myr\ Propagator=1 Myr\ Prototype=1 +Myr\ Reservoir=1 Myr\ Sire=1 Myr\ Turbine=1 +Myr\ Welder=1 Myrsmith=1 -Mystic\ Crusader=1 +Mysteries\ of\ the\ Deep=1 Mystic\ Decree=1 -Mystic\ Enforcer=1 Mystic\ Genesis=1 Mystic\ Meditation=1 Mystic\ Melting=1 Mystic\ Monastery=1 Mystic\ Penitent=1 +Mystic\ Restraints=1 +Mystic\ Snake=1 Mystic\ Speculation=1 +Mystic\ Veil=1 Mystic\ Zealot=1 Mystic\ of\ the\ Hidden\ Way=1 Mystifying\ Maze=1 Mythic\ Proportions=1 Nacatl\ Hunt-Pride=1 Nacatl\ Outlander=1 +Nacatl\ Savage=1 Nacatl\ War-Pride=1 Naga\ Oracle=1 Naga\ Vitalist=1 @@ -5519,66 +5794,68 @@ Nagging\ Thoughts=1 Nahiri's\ Machinations=1 Nakaya\ Shade=1 Naked\ Singularity=1 -Nameless\ Inversion=1 +Nalathni\ Dragon=1 Nameless\ One=1 Nantuko\ Blightcutter=1 -Nantuko\ Cultivator=1 Nantuko\ Disciple=1 +Nantuko\ Elder=1 Nantuko\ Husk=1 +Nantuko\ Mentor=1 Nantuko\ Monastery=1 Nantuko\ Shade=1 Nantuko\ Shaman=1 +Nantuko\ Tracer=1 Nantuko\ Vigilante=1 +Narcissism=1 Narcolepsy=1 Narnam\ Cobra=1 +Narnam\ Renegade=1 +Narrow\ Escape=1 Narwhal=1 -Nath\ of\ the\ Gilt-Leaf=1 +Nath's\ Buffoon=1 +Nath's\ Elite=1 Natural\ Affinity=1 Natural\ Connection=1 -Natural\ End=1 +Natural\ Emergence=1 Natural\ Obsolescence=1 Natural\ Spring=1 Naturalize=1 Nature's\ Blessing=1 Nature's\ Kiss=1 -Nature's\ Lore=1 Nature's\ Panoply=1 -Nature's\ Ruin=1 +Nature's\ Resurgence=1 Nature's\ Spiral=1 Nature's\ Way=1 -Nature's\ Wrath=1 -Nav\ Squad\ Commandos=1 +Nature's\ Will=1 +Navigator's\ Compass=1 Navigator's\ Ruin=1 Naya\ Battlemage=1 -Naya\ Hushblade=1 -Naya\ Sojourners=1 +Naya\ Panorama=1 Near-Death\ Experience=1 Nearheath\ Chaplain=1 -Nearheath\ Pilgrim=1 Nearheath\ Stalker=1 Nebelgast\ Herald=1 Nebuchadnezzar=1 -Necratog=1 +Neck\ Snap=1 +Necra\ Disciple=1 +Necra\ Sanctuary=1 Necravolver=1 -Necrite=1 Necrobite=1 -Necrogen\ Mists=1 Necrogen\ Scudder=1 Necrogen\ Spellbomb=1 Necrogenesis=1 Necrologia=1 Necromancer's\ Assistant=1 Necromancer's\ Covenant=1 -Necromancer's\ Stockpile=1 Necromantic\ Summons=1 Necromantic\ Thirst=1 Necromaster\ Dragon=1 +Necroplasm=1 Necropolis\ Fiend=1 Necropouncer=1 -Necroskitter=1 -Necrotic\ Sliver=1 +Necrosavant=1 +Necrotic\ Plague=1 Nectar\ Faerie=1 -Needle\ Specter=1 Needle\ Storm=1 Needlebite\ Trap=1 Needlebug=1 @@ -5586,8 +5863,7 @@ Needlepeak\ Spider=1 Needleshot\ Gourna=1 Needletooth\ Raptor=1 Nef-Crop\ Entangler=1 -Nefarious\ Lich=1 -Nefashu=1 +Nefarox,\ Overlord\ of\ Grixis=1 Neglected\ Heirloom=1 Neheb,\ the\ Worthy=1 Neko-Te=1 @@ -5597,20 +5873,24 @@ Nemesis\ Mask=1 Nemesis\ Trap=1 Nemesis\ of\ Mortals=1 Nephalia\ Academy=1 -Nephalia\ Drownyard=1 Nephalia\ Moondrakes=1 +Nephalia\ Seakite=1 Nephalia\ Smuggler=1 Nessian\ Asp=1 Nessian\ Courser=1 Nessian\ Demolok=1 Nessian\ Game\ Warden=1 Nessian\ Wilds\ Ravager=1 +Nest\ Invader=1 Nest\ Robber=1 Nest\ of\ Scarabs=1 +Nested\ Ghoul=1 +Nesting\ Wurm=1 Netcaster\ Spider=1 +Nether\ Horror=1 Netherborn\ Phalanx=1 +Netter\ en-Dal=1 Nettle\ Drone=1 -Nettletooth\ Djinn=1 Nettlevine\ Blight=1 Nettling\ Curse=1 Neurok\ Commando=1 @@ -5618,11 +5898,9 @@ Neurok\ Familiar=1 Neurok\ Hoversail=1 Neurok\ Invisimancer=1 Neurok\ Prodigy=1 -Neurok\ Replica=1 Neurok\ Stealthsuit=1 Neurok\ Transmuter=1 Neutralizing\ Blast=1 -Neverending\ Torment=1 Nevermaker=1 New\ Benalia=1 New\ Horizons=1 @@ -5632,14 +5910,16 @@ Nezumi\ Bone-Reader=1 Nezumi\ Cutthroat=1 Nezumi\ Graverobber=1 Nezumi\ Ronin=1 +Nezumi\ Shadow-Watcher=1 Niblis\ of\ Dusk=1 Niblis\ of\ Frost=1 -Niblis\ of\ the\ Breath=1 Niblis\ of\ the\ Urn=1 -Night\ //\ Day=1 +Nicol\ Bolas=1 Night\ Dealings=1 Night\ Market\ Aeronaut=1 Night\ Market\ Guard=1 +Night\ Market\ Lookout=1 +Night\ Terrors=1 Nightbird's\ Clutches=1 Nightcreep=1 Nightfire\ Giant=1 @@ -5648,20 +5928,23 @@ Nighthaze=1 Nighthowler=1 Nightmare=1 Nightmare\ Incursion=1 +Nightmare\ Lash=1 Nightmare\ Void=1 Nightmarish\ End=1 +Nightscape\ Apprentice=1 Nightscape\ Battlemage=1 Nightscape\ Familiar=1 Nightshade\ Assassin=1 Nightshade\ Peddler=1 Nightshade\ Schemers=1 +Nightshade\ Seer=1 Nightshade\ Stinger=1 Nightsnare=1 -Nightsoil\ Kami=1 -Nightveil\ Specter=1 Nightwing\ Shade=1 Nihilistic\ Glee=1 +Nihilith=1 Nikko-Onna=1 +Nim\ Abomination=1 Nim\ Devourer=1 Nim\ Grotesque=1 Nim\ Lasher=1 @@ -5674,7 +5957,6 @@ Nimble\ Innovator=1 Nimbus\ Naiad=1 Nimbus\ Swimmer=1 Nimbus\ Wings=1 -Nimbus\ of\ the\ Isles=1 Ninth\ Bridge\ Patrol=1 Nirkana\ Assassin=1 Nirkana\ Cutthroat=1 @@ -5685,6 +5967,8 @@ Nissa's\ Judgment=1 Nissa's\ Pilgrimage=1 Nissa's\ Renewal=1 Nissa's\ Revelation=1 +Niv-Mizzet,\ Dracogenius=1 +Niv-Mizzet,\ the\ Firemind=1 Niveous\ Wisps=1 Nivix,\ Aerie\ of\ the\ Firemind=1 Nivix\ Barrier=1 @@ -5694,7 +5978,6 @@ No-Dachi=1 No\ Rest\ for\ the\ Wicked=1 Nobilis\ of\ War=1 Noble\ Elephant=1 -Noble\ Purpose=1 Noble\ Quarry=1 Noble\ Stand=1 Noble\ Templar=1 @@ -5703,36 +5986,37 @@ Nocturnal\ Raid=1 Noggin\ Whack=1 Noggle\ Bandit=1 Noggle\ Hedge-Mage=1 -Noggle\ Ransacker=1 +Nomad\ Decoy=1 Nomad\ Mythmaker=1 Nomad\ Outpost=1 +Nomad\ Stadium=1 Nomads'\ Assembly=1 -Nomads\ en-Kor=1 Noose\ Constrictor=1 Noosegraf\ Mob=1 +Norwood\ Priestess=1 Norwood\ Ranger=1 Nostalgic\ Dreams=1 -Nosy\ Goblin=1 Not\ Forgotten=1 -Nova\ Chaser=1 +Not\ of\ This\ World=1 +Nourish=1 Nova\ Pentacle=1 Novijen,\ Heart\ of\ Progress=1 Novijen\ Sages=1 -Noxious\ Dragon=1 +Noxious\ Hatchling=1 Noxious\ Vapors=1 -Noyan\ Dar,\ Roil\ Shaper=1 Nucklavee=1 Nuisance\ Engine=1 Null\ Caller=1 Null\ Champion=1 Null\ Profusion=1 Nullify=1 +Nullmage\ Advocate=1 Nullmage\ Shepherd=1 Nullstone\ Gargoyle=1 Nulltread\ Gargantuan=1 Numbing\ Dose=1 Numot,\ the\ Devastator=1 -Nurturer\ Initiate=1 +Nurturing\ Licid=1 Nylea's\ Disciple=1 Nylea's\ Emissary=1 Nylea's\ Presence=1 @@ -5748,13 +6032,14 @@ Oakenform=1 Oakgnarl\ Warrior=1 Oakheart\ Dryads=1 Oashra\ Cultivator=1 +Oasis=1 Oasis\ Ritualist=1 Oath\ of\ Ajani=1 Oath\ of\ Chandra=1 Oath\ of\ Gideon=1 Oath\ of\ Jace=1 Oath\ of\ Liliana=1 -Oath\ of\ Scholars=1 +Oath\ of\ Teferi=1 Oath\ of\ the\ Ancient\ Wood=1 Oathkeeper,\ Takeno's\ Daisho=1 Oathsworn\ Giant=1 @@ -5768,7 +6053,6 @@ Obelisk\ of\ Jund=1 Obelisk\ of\ Naya=1 Oblivion\ Crown=1 Oblivion\ Strike=1 -Oboro\ Breezecaller=1 Oboro\ Envoy=1 Obscuring\ Aether=1 Observant\ Alseid=1 @@ -5776,12 +6060,17 @@ Obsessive\ Search=1 Obsessive\ Skinner=1 Obsianus\ Golem=1 Obsidian\ Battle-Axe=1 +Obsidian\ Fireheart=1 +Obstinate\ Familiar=1 +Obzedat's\ Aid=1 +Ocular\ Halo=1 +Oculus=1 Odds\ //\ Ends=1 Odious\ Trow=1 Odric,\ Lunarch\ Marshal=1 Odric,\ Master\ Tactician=1 Odunos\ River\ Trawler=1 -Odylic\ Wraith=1 +Off\ Balance=1 Offalsnout=1 Offering\ to\ Asha=1 Ogre's\ Cleaver=1 @@ -5793,26 +6082,34 @@ Ogre\ Leadfoot=1 Ogre\ Marauder=1 Ogre\ Menial=1 Ogre\ Recluse=1 +Ogre\ Resister=1 Ogre\ Savant=1 +Ogre\ Sentry=1 Ogre\ Shaman=1 Ogre\ Slumlord=1 +Ogre\ Taskmaster=1 Ohran\ Yeti=1 Ojutai's\ Breath=1 Ojutai's\ Summons=1 Ojutai\ Interceptor=1 +Ojutai\ Monument=1 Oketra's\ Attendant=1 Oketra's\ Avenger=1 Oketra's\ Last\ Mercy=1 -Okina\ Nightwatch=1 +Okina,\ Temple\ to\ the\ Grandfathers=1 Okk=1 Old-Growth\ Dryads=1 +Old\ Ghastbark=1 Olivia's\ Bloodsworn=1 Olivia's\ Dragoon=1 Omen\ Machine=1 Omenspeaker=1 Ominous\ Sphinx=1 Omnibian=1 +On\ Serra's\ Wings=1 +Onakke\ Ogre=1 Ondu\ Champion=1 +Ondu\ Cleric=1 Ondu\ Giant=1 Ondu\ Greathorn=1 Ondu\ Rising=1 @@ -5821,19 +6118,26 @@ One-Eyed\ Scarecrow=1 One\ Dozen\ Eyes=1 One\ Thousand\ Lashes=1 One\ With\ the\ Wind=1 -One\ with\ Nature=1 One\ with\ Nothing=1 Ongoing\ Investigation=1 +Oni\ Possession=1 Oni\ of\ Wild\ Places=1 Onulet=1 Onward\ //\ Victory=1 +Onyx\ Goblet=1 +Oona's\ Blackguard=1 Oona's\ Gatewarden=1 Oona's\ Grace=1 +Oona's\ Prowler=1 +Oona,\ Queen\ of\ the\ Fae=1 Ooze\ Flux=1 Ooze\ Garden=1 -Opal-Eye,\ Konda's\ Yojimbo=1 +Opal\ Acrolith=1 +Opal\ Archangel=1 Opal\ Avenger=1 +Opal\ Caryatid=1 Opal\ Champion=1 +Opal\ Gargoyle=1 Opal\ Guardian=1 Opal\ Lake\ Gatekeepers=1 Opaline\ Sliver=1 @@ -5842,38 +6146,41 @@ Open\ Fire=1 Open\ into\ Wonder=1 Open\ the\ Armory=1 Ophidian=1 -Ophidian\ Eye=1 Opportunist=1 Opportunity=1 Oppressive\ Rays=1 Oppressive\ Will=1 -Opulent\ Palace=1 +Oracle's\ Attendants=1 Oracle's\ Insight=1 Oracle's\ Vault=1 +Oracle\ en-Vec=1 Oracle\ of\ Bones=1 Oracle\ of\ Dust=1 -Oracle\ of\ Nectars=1 Oran-Rief\ Hydra=1 Oran-Rief\ Invoker=1 +Oran-Rief\ Recluse=1 Orator\ of\ Ojutai=1 Oraxid=1 Orazca\ Frillback=1 Orazca\ Raptor=1 Orazca\ Relic=1 Orb\ of\ Dreams=1 +Orbs\ of\ Warding=1 Orbweaver\ Kumo=1 -Orc\ Sureshot=1 Orchard\ Spirit=1 Orchard\ Warden=1 Orcish\ Artillery=1 Orcish\ Bloodpainter=1 +Orcish\ Cannonade=1 Orcish\ Cannoneers=1 -Orcish\ Farmer=1 +Orcish\ Captain=1 Orcish\ Librarian=1 Orcish\ Lumberjack=1 Orcish\ Mechanics=1 Orcish\ Oriflamme=1 +Orcish\ Spy=1 Orcish\ Squatters=1 +Orcish\ Vandal=1 Orcish\ Veteran=1 Ordeal\ of\ Erebos=1 Ordeal\ of\ Heliod=1 @@ -5881,7 +6188,6 @@ Ordeal\ of\ Nylea=1 Ordeal\ of\ Purphoros=1 Ordeal\ of\ Thassa=1 Order\ //\ Chaos=1 -Order\ of\ Whiteclay=1 Order\ of\ Yawgmoth=1 Order\ of\ the\ Golden\ Cricket=1 Order\ of\ the\ Sacred\ Bell=1 @@ -5890,34 +6196,38 @@ Order\ of\ the\ White\ Shield=1 Ordered\ Migration=1 Ordruun\ Commando=1 Ordruun\ Veteran=1 +Ore\ Gorger=1 Oreskos\ Sun\ Guide=1 Oreskos\ Swiftclaw=1 +Organ\ Grinder=1 Orgg=1 Origin\ Spellbomb=1 -Orim's\ Prayer=1 Orim,\ Samite\ Healer=1 Ornamental\ Courage=1 -Ornate\ Kanzashi=1 Ornery\ Kudu=1 Ornitharch=1 Orochi\ Eggwatcher=1 +Orochi\ Hatchery=1 Orochi\ Leafcaller=1 Orochi\ Ranger=1 Orochi\ Sustainer=1 Oros,\ the\ Avenger=1 +Orzhov\ Charm=1 Orzhov\ Cluestone=1 Orzhov\ Euthanist=1 Orzhov\ Guildgate=1 Orzhov\ Guildmage=1 Orzhov\ Keyrune=1 -Orzhov\ Signet=1 Orzhova,\ the\ Church\ of\ Deals=1 Osai\ Vultures=1 +Ostiary\ Thrull=1 Ostracize=1 Otarian\ Juggernaut=1 +Otepec\ Huntmaster=1 Otherworldly\ Journey=1 Otherworldly\ Outburst=1 Ouphe\ Vandals=1 +Outbreak=1 Outland\ Boar=1 Outland\ Colossus=1 Outmaneuver=1 @@ -5925,43 +6235,43 @@ Outnumber=1 Outrage\ Shaman=1 Outrider\ en-Kor=1 Outrider\ of\ Jhess=1 -Outwit=1 Ovalchase\ Daredevil=1 Ovalchase\ Dragster=1 Overblaze=1 Overcome=1 -Overeager\ Apprentice=1 Overgrown\ Armasaur=1 -Overgrown\ Estate=1 Override=1 Overrule=1 Overrun=1 Overwhelm=1 Overwhelming\ Denial=1 -Overwhelming\ Intellect=1 Overwhelming\ Stampede=1 Ovinize=1 Ovinomancer=1 Oviya\ Pashiri,\ Sage\ Lifecrafter=1 Owl\ Familiar=1 +Oxidda\ Daredevil=1 Oxidda\ Golem=1 -Oxidize=1 +Oxidda\ Scrapmelter=1 +Oyobi,\ Who\ Split\ the\ Heavens=1 Pacification\ Array=1 Pacifism=1 Pack's\ Disdain=1 Pack\ Guardian=1 -Padeem,\ Consul\ of\ Innovation=1 Pain\ //\ Suffering=1 Pain\ Kami=1 Pain\ Magnification=1 Pain\ Seer=1 +Painbringer=1 Painful\ Lesson=1 +Painful\ Memories=1 Painful\ Quandary=1 +Painful\ Truths=1 Painsmith=1 Painted\ Bluffs=1 +Painwracker\ Oni=1 Palace\ Familiar=1 Palace\ Guard=1 -Paladin\ en-Vec=1 Paladin\ of\ Prahv=1 Paladin\ of\ the\ Bloodstained=1 Pale\ Recluse=1 @@ -5971,51 +6281,57 @@ Paleoloth=1 Palinchron=1 Palisade\ Giant=1 Palladia-Mors=1 -Palladium\ Myr=1 -Palliation\ Accord=1 Pallid\ Mycoderm=1 Pallimud=1 -Pandemonium=1 +Panacea=1 Panic=1 Panic\ Attack=1 Panic\ Spellbomb=1 +Panoptic\ Mirror=1 Panther\ Warriors=1 Paperfin\ Rascal=1 -Paradox\ Haze=1 Paragon\ of\ Eternal\ Wilds=1 Paragon\ of\ Fierce\ Defiance=1 Paragon\ of\ Gathering\ Mists=1 Paragon\ of\ New\ Dawns=1 Paragon\ of\ Open\ Graves=1 Paragon\ of\ the\ Amesha=1 +Parallax\ Wave=1 Parallectric\ Feedback=1 Paralyze=1 Paralyzing\ Grasp=1 Paranoid\ Delusions=1 Paranoid\ Parish-Blade=1 -Parapet=1 +Parapet\ Watchers=1 Paraselene=1 +Parasitic\ Bond=1 +Parasitic\ Implant=1 Parasitic\ Strix=1 +Parch=1 +Pardic\ Collaborator=1 Pardic\ Dragon=1 Pardic\ Firecat=1 +Pardic\ Lancer=1 Pardic\ Miner=1 +Pardic\ Wanderer=1 Pariah's\ Shield=1 Part\ the\ Veil=1 +Patagia\ Golem=1 Patagia\ Viper=1 Patchwork\ Gnomes=1 Path\ of\ Anger's\ Flame=1 Path\ of\ Bravery=1 -Path\ of\ Peace=1 Pathmaker\ Initiate=1 +Pathrazer\ of\ Ulamog=1 Pathway\ Arrows=1 -Patrol\ Signaler=1 +Patriarch's\ Desire=1 +Patron\ of\ the\ Akki=1 Patron\ of\ the\ Kitsune=1 Patron\ of\ the\ Moon=1 Patron\ of\ the\ Nezumi=1 -Patron\ of\ the\ Orochi=1 Patron\ of\ the\ Valiant=1 Patron\ of\ the\ Wild=1 -Pavel\ Maliki=1 +Pawn\ of\ Ulamog=1 Pay\ No\ Heed=1 Peace\ Strider=1 Peace\ and\ Quiet=1 @@ -6024,41 +6340,46 @@ Peacewalker\ Colossus=1 Peach\ Garden\ Oath=1 Peak\ Eruption=1 Pearl\ Shard=1 -Pedantic\ Learning=1 +Pearlspear\ Courier=1 Peel\ from\ Reality=1 Peema\ Aether-Seer=1 Peema\ Outrider=1 +Peer\ Pressure=1 Peer\ Through\ Depths=1 +Pegasus\ Charger=1 +Pegasus\ Courser=1 +Pegasus\ Refuge=1 Pegasus\ Stampede=1 Pelakka\ Wurm=1 Penance=1 Pendelhaven\ Elder=1 -Pendrell\ Flux=1 +Pendrell\ Drake=1 Pennon\ Blade=1 Pensive\ Minotaur=1 Pentagram\ of\ the\ Ages=1 Pentarch\ Paladin=1 Pentarch\ Ward=1 Pentavus=1 +Penumbra\ Bobcat=1 Penumbra\ Kavu=1 Penumbra\ Spider=1 Penumbra\ Wurm=1 Peppersmoke=1 Peregrination=1 -Peregrine\ Drake=1 Peregrine\ Griffin=1 Peregrine\ Mask=1 Perilous\ Forays=1 +Perilous\ Myr=1 Perilous\ Predicament=1 -Perilous\ Research=1 Perilous\ Shadow=1 Perilous\ Voyage=1 -Perimeter\ Captain=1 +Perish\ the\ Thought=1 Permafrost\ Trap=1 Permeating\ Mass=1 Perpetual\ Timepiece=1 Perplex=1 Perplexing\ Chimera=1 +Persecute=1 Personal\ Incarnation=1 Personal\ Sanctuary=1 Persuasion=1 @@ -6066,30 +6387,31 @@ Pestilence\ Demon=1 Pestilent\ Souleater=1 Petalmane\ Baku=1 Petals\ of\ Insight=1 -Petra\ Sphinx=1 Petradon=1 Petrahydrox=1 -Petrified\ Plating=1 +Petravark=1 Petrified\ Wood-Kin=1 Pewter\ Golem=1 -Phage\ the\ Untouchable=1 Phalanx\ Formation=1 Phalanx\ Leader=1 Phantasmagorian=1 +Phantasmal\ Abomination=1 Phantasmal\ Bear=1 Phantasmal\ Dragon=1 Phantasmal\ Fiend=1 -Phantasmal\ Forces=1 +Phantasmal\ Mount=1 Phantasmal\ Terrain=1 +Phantatog=1 +Phantom\ Beast=1 +Phantom\ Centaur=1 +Phantom\ Flock=1 Phantom\ General=1 Phantom\ Monster=1 -Phantom\ Nantuko=1 Phantom\ Nomad=1 +Phantom\ Tiger=1 Phantom\ Warrior=1 -Phantom\ Wings=1 Phantom\ Wurm=1 Pharagax\ Giant=1 -Pharika's\ Chosen=1 Pharika's\ Cure=1 Pharika's\ Disciple=1 Pharika's\ Mender=1 @@ -6104,66 +6426,72 @@ Phthisis=1 Phylactery\ Lich=1 Phyresis=1 Phyrexia's\ Core=1 +Phyrexian\ Battleflies=1 +Phyrexian\ Bloodstock=1 Phyrexian\ Colossus=1 Phyrexian\ Defiler=1 Phyrexian\ Denouncer=1 +Phyrexian\ Devourer=1 Phyrexian\ Digester=1 -Phyrexian\ Driver=1 -Phyrexian\ Furnace=1 +Phyrexian\ Etchings=1 Phyrexian\ Gargantua=1 -Phyrexian\ Ghoul=1 Phyrexian\ Grimoire=1 Phyrexian\ Hulk=1 Phyrexian\ Hydra=1 +Phyrexian\ Infiltrator=1 Phyrexian\ Ingester=1 +Phyrexian\ Ironfoot=1 Phyrexian\ Juggernaut=1 Phyrexian\ Monitor=1 -Phyrexian\ Plaguelord=1 -Phyrexian\ Portal=1 Phyrexian\ Prowler=1 +Phyrexian\ Reaper=1 Phyrexian\ Rebirth=1 -Phyrexian\ Snowcrusher=1 +Phyrexian\ Slayer=1 Phyrexian\ Splicer=1 -Phyrexian\ Swarmlord=1 Phyrexian\ Totem=1 Phyrexian\ Vatmother=1 -Phyrexian\ War\ Beast=1 +Phyrexian\ Vault=1 +Phytoburst=1 Phytohydra=1 Phytotitan=1 Pia's\ Revolution=1 Pianna,\ Nomad\ Captain=1 Pick\ the\ Brain=1 Pierce\ Strider=1 +Pierce\ the\ Sky=1 Piety\ Charm=1 Pilfered\ Plans=1 Pilgrim's\ Eye=1 +Pilgrim\ of\ Justice=1 +Pilgrim\ of\ Virtue=1 Pilgrim\ of\ the\ Fires=1 -Pillaging\ Horde=1 -Pillar\ of\ Light=1 +Pillage=1 +Pillar\ Tombs\ of\ Aku=1 Pillar\ of\ Origins=1 Pillar\ of\ War=1 +Pillar\ of\ the\ Paruns=1 +Pillarfield\ Ox=1 Pillory\ of\ the\ Sleepless=1 Pin\ to\ the\ Earth=1 +Pincer\ Spider=1 Pincher\ Beetles=1 +Pine\ Barrens=1 Pine\ Walker=1 Pinecrest\ Ridge=1 Pinion\ Feast=1 -Pinpoint\ Avalanche=1 Pious\ Evangel=1 Pious\ Interdiction=1 Pious\ Kitsune=1 -Pious\ Warrior=1 +Piper's\ Melody=1 Piranha\ Marsh=1 Pirate's\ Cutlass=1 Pirate's\ Pillage=1 Pirate's\ Prize=1 Pirate\ Ship=1 -Piston\ Sledge=1 Pit\ Fight=1 Pit\ Keeper=1 -Pit\ Spawn=1 +Pit\ Raptor=1 Pit\ Trap=1 -Pitchburn\ Devils=1 Pitfall\ Trap=1 Pith\ Driller=1 Pitiless\ Horde=1 @@ -6173,37 +6501,30 @@ Plagiarize=1 Plague\ Beetle=1 Plague\ Belcher=1 Plague\ Boiler=1 -Plague\ Dogs=1 -Plague\ Fiend=1 Plague\ Sliver=1 +Plague\ Spores=1 Plague\ Wind=1 -Plague\ Witch=1 Plague\ of\ Vermin=1 -Plagued\ Rusalka=1 Plaguemaw\ Beast=1 Plains=1 Planar\ Cleansing=1 -Planar\ Despair=1 -Planar\ Gate=1 Planar\ Guide=1 Planar\ Outburst=1 Planar\ Overlay=1 +Planar\ Void=1 Planeswalker's\ Fury=1 Planeswalker's\ Mirth=1 Planeswalker's\ Scorn=1 -Plasm\ Capture=1 +Plasma\ Elemental=1 Plated\ Crusher=1 Plated\ Geopede=1 Plated\ Pegasus=1 Plated\ Seastrider=1 -Plated\ Slagwurm=1 Plated\ Spider=1 Plaxcaster\ Frogling=1 Plaxmanta=1 Plea\ for\ Guidance=1 -Plea\ for\ Power=1 Pledge\ of\ Loyalty=1 -Plover\ Knights=1 Plow\ Through\ Reito=1 Plumes\ of\ Peace=1 Plumeveil=1 @@ -6211,57 +6532,52 @@ Plummet=1 Plunder=1 Poison\ the\ Well=1 Poisonbelly\ Ogre=1 -Polar\ Kraken=1 Polis\ Crusher=1 Pollen\ Lullaby=1 +Pollen\ Remedy=1 Pollenbright\ Wings=1 Polluted\ Bonds=1 Polluted\ Dead=1 +Polymorphist's\ Jest=1 Polymorphous\ Rush=1 Pontiff\ of\ Blight=1 Ponyback\ Brigade=1 Pooling\ Venom=1 -Porcelain\ Legionnaire=1 Pore\ Over\ the\ Pages=1 -Port\ Inspector=1 Portent\ of\ Betrayal=1 Possessed\ Aven=1 Possessed\ Barbarian=1 +Possessed\ Centaur=1 Possessed\ Nomad=1 Possessed\ Skaab=1 -Postmortem\ Lunge=1 Poultice\ Sliver=1 Pounce=1 Pouncing\ Cheetah=1 -Pouncing\ Wurm=1 -Power\ Conduit=1 -Power\ Sink=1 +Pouncing\ Kavu=1 +Power\ Armor=1 +Power\ Taint=1 Power\ of\ Fire=1 Powerstone\ Minefield=1 -Praetor's\ Grasp=1 +Powerstone\ Shard=1 Prahv,\ Spires\ of\ Order=1 Prakhata\ Club\ Security=1 Prakhata\ Pillar-Bug=1 Precinct\ Captain=1 Precise\ Strike=1 Precognition=1 +Precognition\ Field=1 Precursor\ Golem=1 -Predator's\ Gambit=1 Predator's\ Rapport=1 Predator,\ Flagship=1 Predator\ Dragon=1 Predatory\ Advantage=1 -Predatory\ Focus=1 -Predatory\ Hunger=1 Predatory\ Nightstalker=1 -Predatory\ Rampage=1 Predatory\ Urge=1 -Preeminent\ Captain=1 Premature\ Burial=1 Prepare\ //\ Fight=1 Prescient\ Chimera=1 +Presence\ of\ the\ Master=1 Presence\ of\ the\ Wise=1 -Press\ for\ Answers=1 Press\ into\ Service=1 Press\ the\ Advantage=1 Pressure\ Point=1 @@ -6271,15 +6587,14 @@ Prickleboar=1 Prickly\ Boggart=1 Pride\ Guardian=1 Pride\ of\ Conquerors=1 +Priest\ of\ Gix=1 Priest\ of\ Iroas=1 Priest\ of\ Urabrask=1 Priest\ of\ the\ Blood\ Rite=1 -Priest\ of\ the\ Wakening\ Sun=1 Priests\ of\ Norn=1 Primal\ Bellow=1 -Primal\ Boost=1 +Primal\ Beyond=1 Primal\ Clay=1 -Primal\ Cocoon=1 Primal\ Druid=1 Primal\ Forcemage=1 Primal\ Huntbeast=1 @@ -6289,23 +6604,29 @@ Primal\ Visitation=1 Primal\ Whisperer=1 Primeval\ Force=1 Primeval\ Light=1 +Primeval\ Shambler=1 +Primevals'\ Glorious\ Rebirth=1 Primitive\ Etchings=1 Primitive\ Justice=1 -Princess\ Lucrezia=1 +Primordial\ Sage=1 +Primordial\ Wurm=1 Prism\ Array=1 Prism\ Ring=1 +Prismatic\ Boon=1 +Prismatic\ Lens=1 Prismwake\ Merrow=1 Prison\ Barricade=1 Prison\ Term=1 Pristine\ Angel=1 Pristine\ Skywise=1 -Pristine\ Talisman=1 Private\ Research=1 +Prized\ Elephant=1 Prized\ Unicorn=1 Prizefighter\ Construct=1 Processor\ Assault=1 Prodigal\ Pyromancer=1 Prodigal\ Sorcerer=1 +Profane\ Command=1 Profane\ Prayers=1 Profaner\ of\ the\ Dead=1 Profit\ //\ Loss=1 @@ -6314,25 +6635,28 @@ Prognostic\ Sphinx=1 Promise\ of\ Power=1 Promised\ Kannushi=1 Propeller\ Pioneer=1 +Proper\ Burial=1 Prophet\ of\ Distortion=1 Prophet\ of\ Kruphix=1 Prophetic\ Bolt=1 Prophetic\ Ravings=1 Prosperous\ Pirates=1 +Protean\ Hydra=1 Protean\ Raider=1 -Protect\ //\ Serve=1 Protection\ of\ the\ Hekma=1 Protective\ Bubble=1 Proteus\ Machine=1 +Protomatter\ Powder=1 +Prototype\ Portal=1 Proven\ Combatant=1 Providence=1 -Provoke=1 Prowess\ of\ the\ Fair=1 Prowler's\ Helm=1 Prowling\ Nightstalker=1 Prowling\ Pangolin=1 Prying\ Blade=1 Prying\ Questions=1 +Psionic\ Gift=1 Psionic\ Sliver=1 Psychatog=1 Psychic\ Barrier=1 @@ -6340,83 +6664,91 @@ Psychic\ Drain=1 Psychic\ Intrusion=1 Psychic\ Membrane=1 Psychic\ Miasma=1 +Psychic\ Overload=1 Psychic\ Possession=1 Psychic\ Puppetry=1 Psychic\ Purge=1 Psychic\ Rebuttal=1 +Psychic\ Spear=1 Psychic\ Spiral=1 Psychic\ Surgery=1 +Psychic\ Symbiont=1 Psychic\ Trance=1 +Psychic\ Transfer=1 Psychogenic\ Probe=1 Psychotic\ Episode=1 Psychotic\ Fury=1 Psychotrope\ Thallid=1 Pterodon\ Knight=1 Pteron\ Ghost=1 +Public\ Execution=1 Puca's\ Mischief=1 +Puffer\ Extract=1 Pull\ Under=1 Pull\ from\ Eternity=1 Pull\ from\ the\ Deep=1 Pulling\ Teeth=1 -Pulmonic\ Sliver=1 Pulsating\ Illusion=1 Pulse\ of\ Llanowar=1 Pulse\ of\ the\ Dross=1 Pulse\ of\ the\ Fields=1 Pulse\ of\ the\ Forge=1 -Pulsemage\ Advocate=1 +Pulse\ of\ the\ Grid=1 +Pulse\ of\ the\ Tangle=1 Puncture\ Blast=1 +Puncture\ Bolt=1 Puncturing\ Blow=1 Puncturing\ Light=1 Punish\ Ignorance=1 -Punish\ the\ Enemy=1 Puppet\ Conjurer=1 +Puppet\ Strings=1 Puppeteer=1 Puppeteer\ Clique=1 Pure\ //\ Simple=1 +Pure\ Reflection=1 Puresight\ Merrow=1 Purge\ the\ Profane=1 Purging\ Scythe=1 -Purify=1 -Purify\ the\ Grave=1 Purity=1 Purphoros's\ Emissary=1 Pursue\ Glory=1 Pursuit\ of\ Flight=1 +Pus\ Kami=1 Put\ Away=1 +Putrefaction=1 Putrefax=1 Putrefy=1 Putrid\ Cyclops=1 -Putrid\ Imp=1 -Putrid\ Leech=1 Putrid\ Raptor=1 Putrid\ Warrior=1 +Pygmy\ Kavu=1 Pygmy\ Pyrosaur=1 +Pygmy\ Razorback=1 Pygmy\ Troll=1 Pyramid\ of\ the\ Pantheon=1 Pyre\ Charger=1 Pyre\ Hound=1 -Pyreheart\ Wolf=1 Pyrewild\ Shaman=1 Pyric\ Salamander=1 +Pyrite\ Spellbomb=1 +Pyroclasm=1 Pyroclast\ Consul=1 -Pyroconvergence=1 Pyrohemia=1 Pyromancer's\ Assault=1 Pyromancer's\ Gauntlet=1 Pyromancer's\ Swath=1 -Pyromatics=1 +Pyromancy=1 +Pyromania=1 Pyrotechnics=1 Pyrrhic\ Revival=1 Python=1 Pyxis\ of\ Pandemonium=1 Qal\ Sisma\ Behemoth=1 Qarsi\ Deceiver=1 -Qarsi\ High\ Priest=1 -Qarsi\ Sadist=1 Qasali\ Ambusher=1 +Quag\ Sickness=1 Quag\ Vampires=1 -Quagnoth=1 +Quagmire\ Druid=1 Quarry\ Beetle=1 Quarry\ Colossus=1 Quarry\ Hauler=1 @@ -6424,78 +6756,81 @@ Quash=1 Queen's\ Agent=1 Queen's\ Bay\ Soldier=1 Queen's\ Commission=1 +Quenchable\ Fire=1 Quest\ for\ Ancient\ Secrets=1 -Quest\ for\ Pure\ Flame=1 Quest\ for\ Renewal=1 Quest\ for\ Ula's\ Temple=1 Quest\ for\ the\ Gemblades=1 -Quest\ for\ the\ Goblin\ Lord=1 Quest\ for\ the\ Gravelord=1 -Quest\ for\ the\ Nihil\ Stone=1 -Quickchange=1 +Quicken=1 Quicksand=1 Quicksilver\ Behemoth=1 Quicksilver\ Dagger=1 Quicksilver\ Dragon=1 -Quicksilver\ Elemental=1 +Quicksilver\ Fountain=1 Quicksilver\ Geyser=1 +Quicksilver\ Wall=1 Quicksmith\ Genius=1 Quicksmith\ Rebel=1 Quicksmith\ Spy=1 Quiet\ Contemplation=1 Quiet\ Purity=1 Quiet\ Speculation=1 +Quietus\ Spike=1 Quill-Slinger\ Boggart=1 Quilled\ Slagwurm=1 Quilled\ Sliver=1 Quilled\ Wolf=1 Quillmane\ Baku=1 Quirion\ Dryad=1 -Quirion\ Trailblazer=1 +Quirion\ Explorer=1 +Quirion\ Sentinel=1 Qumulox=1 Rabble-Rouser=1 Rabid\ Bite=1 Rabid\ Bloodsucker=1 +Rabid\ Rats=1 Rabid\ Wolverines=1 Rabid\ Wombat=1 Rack\ and\ Ruin=1 -Radha,\ Heir\ to\ Keld=1 Radiant's\ Dragoons=1 Radiant's\ Judgment=1 Radiant,\ Archangel=1 -Radiant\ Essence=1 Radiant\ Flames=1 -Radiant\ Kavu=1 Radiant\ Purge=1 +Radiating\ Lightning=1 Radjan\ Spirit=1 -Rag\ Man=1 +Raff\ Capashen,\ Ship's\ Mage=1 Ragamuffyn=1 -Rage\ Extractor=1 Rage\ Forger=1 -Rage\ Nimbus=1 Rage\ Reflection=1 +Rage\ Thrower=1 Rage\ Weaver=1 Rage\ of\ Purphoros=1 -Rageform=1 +Rageblood\ Shaman=1 Ragemonger=1 Ragged\ Veins=1 Raging\ Goblin=1 +Raging\ Gorilla=1 +Raging\ Kavu=1 Raging\ Minotaur=1 Raging\ Regisaur=1 Raging\ Swordtooth=1 -Ragnar=1 Rags\ //\ Riches=1 Raid\ Bombardment=1 Raiders'\ Spoils=1 Raiders'\ Wake=1 -Rain\ of\ Blades=1 Rain\ of\ Daggers=1 Rain\ of\ Embers=1 Rain\ of\ Rust=1 Rain\ of\ Salt=1 Rain\ of\ Thorns=1 +Rainbow\ Crow=1 +Rainbow\ Efreet=1 Raise\ Dead=1 Raised\ by\ Wolves=1 +Raka\ Disciple=1 +Raka\ Sanctuary=1 Rakalite=1 Rakavolver=1 Rakdos\ Augermage=1 @@ -6511,29 +6846,32 @@ Rakdos\ Ragemutt=1 Rakdos\ Ringleader=1 Rakdos\ Riteknife=1 Rakdos\ Shred-Freak=1 +Rakdos\ Signet=1 +Rakeclaw\ Gargantuan=1 Raking\ Canopy=1 Rakish\ Heir=1 Rakka\ Mar=1 Raksha\ Golden\ Cub=1 -Rakshasa's\ Disdain=1 Rakshasa's\ Secret=1 Rakshasa\ Deathdealer=1 Rakshasa\ Gravecaller=1 Rakshasa\ Vizier=1 Rally\ the\ Forces=1 Rally\ the\ Horde=1 +Rally\ the\ Peasants=1 Rally\ the\ Righteous=1 Rallying\ Roar=1 Ramirez\ DePietro=1 +Ramosian\ Commander=1 Ramosian\ Revivalist=1 +Rampaging\ Cyclops=1 Rampaging\ Hippo=1 Rampant\ Growth=1 Ramroller=1 -Ramses\ Overdark=1 Ramunap\ Hydra=1 +Ramunap\ Ruins=1 Rancid\ Rats=1 Ranger's\ Guile=1 -Ranger's\ Path=1 Ranger\ en-Vec=1 Ranging\ Raptors=1 Rapacious\ One=1 @@ -6541,47 +6879,51 @@ Raptor\ Companion=1 Raptor\ Hatchling=1 Ratcatcher=1 Rathi\ Dragon=1 -Rathi\ Intimidator=1 +Rathi\ Fiend=1 Rathi\ Trapper=1 +Rats'\ Feast=1 Rats\ of\ Rath=1 Rattleblaze\ Scarecrow=1 Rattleclaw\ Mystic=1 +Ravaged\ Highlands=1 Ravaging\ Blaze=1 Ravaging\ Riftwurm=1 -Raven's\ Run\ Dragoon=1 Raven\ Familiar=1 Raven\ Guild\ Initiate=1 Ravenous\ Baloth=1 Ravenous\ Bloodseeker=1 Ravenous\ Daggertooth=1 Ravenous\ Demon=1 +Ravenous\ Harpy=1 Ravenous\ Intruder=1 -Ravenous\ Skirge=1 Raving\ Oni-Slave=1 Ray\ of\ Command=1 +Ray\ of\ Dissolution=1 +Ray\ of\ Distortion=1 Razaketh's\ Rite=1 Razia's\ Purification=1 Razia,\ Boros\ Archangel=1 Razing\ Snidd=1 Razor\ Barrier=1 +Razor\ Boomerang=1 Razor\ Golem=1 Razor\ Hippogriff=1 +Razor\ Pendulum=1 Razor\ Swine=1 -Razorfield\ Rhino=1 -Razorfield\ Thresher=1 Razorfin\ Abolisher=1 Razorfoot\ Griffin=1 -Razorjaw\ Oni=1 +Razorgrass\ Screen=1 Razormane\ Masticore=1 Razortip\ Whip=1 Razortooth\ Rats=1 Reach\ Through\ Mists=1 Reach\ of\ Branches=1 Reach\ of\ Shadows=1 -Read\ the\ Bones=1 -Ready\ //\ Willing=1 +Read\ the\ Runes=1 +Reality\ Acid=1 Reality\ Anchor=1 Reality\ Hemorrhage=1 +Reality\ Ripple=1 Reality\ Spasm=1 Reality\ Strobe=1 Realm\ Razer=1 @@ -6589,6 +6931,7 @@ Realm\ Seekers=1 Realms\ Uncharted=1 Realmwright=1 Reap=1 +Reap\ Intellect=1 Reap\ What\ Is\ Sown=1 Reap\ the\ Seagraf=1 Reaper\ of\ Flight\ Moonsilver=1 @@ -6611,8 +6954,10 @@ Recantation=1 Reciprocate=1 Reckless\ Charge=1 Reckless\ Cohort=1 +Reckless\ Embermage=1 Reckless\ Fireweaver=1 Reckless\ Imp=1 +Reckless\ Ogre=1 Reckless\ One=1 Reckless\ Racer=1 Reckless\ Rage=1 @@ -6620,15 +6965,17 @@ Reckless\ Reveler=1 Reckless\ Scholar=1 Reckless\ Spite=1 Reckless\ Waif=1 +Reckless\ Wurm=1 Reclaim=1 -Reclaiming\ Vines=1 Reclusive\ Artificer=1 Reclusive\ Wight=1 Recollect=1 +Reconstruction=1 +Recoup=1 Recover=1 Recumbent\ Bliss=1 Recuperate=1 -Recurring\ Insight=1 +Recurring\ Nightmare=1 Red\ Cliffs\ Armada=1 Red\ Sun's\ Zenith=1 Redeem=1 @@ -6639,33 +6986,40 @@ Reduce\ in\ Stature=1 Reduce\ to\ Ashes=1 Reduce\ to\ Dreams=1 Redwood\ Treefolk=1 -Reef\ Shaman=1 Reflex\ Sliver=1 Reflexes=1 Refraction\ Trap=1 +Refresh=1 +Refreshing\ Rain=1 Refuse\ //\ Cooperate=1 -Regathan\ Firecat=1 Regenerate=1 Regeneration=1 Regress=1 -Reincarnation=1 +Reign\ of\ the\ Pit=1 Reinforced\ Bulwark=1 Reinforcements=1 Reins\ of\ the\ Vinesteed=1 +Reiterate=1 Reito\ Lantern=1 Reiver\ Demon=1 Rejuvenate=1 +Rejuvenation\ Chamber=1 Rekindled\ Flame=1 Reknit=1 +Relearn=1 Release\ the\ Ants=1 Release\ the\ Gremlins=1 Release\ to\ the\ Wind=1 +Relentless\ Assault=1 Relentless\ Hunter=1 Relentless\ Raptor=1 +Relentless\ Rats=1 Relentless\ Skaabs=1 +Relic\ Bane=1 Relic\ Barrier=1 Relic\ Crush=1 Relic\ Putrescence=1 +Relic\ Runner=1 Relic\ Seeker=1 Relic\ Ward=1 Relief\ Captain=1 @@ -6673,26 +7027,24 @@ Reliquary\ Monk=1 Remember\ the\ Fallen=1 Reminisce=1 Remorseless\ Punishment=1 -Remove\ Soul=1 Rend\ Flesh=1 -Rend\ Spirit=1 +Render\ Silent=1 Rending\ Vines=1 Renegade's\ Getaway=1 -Renegade\ Demon=1 Renegade\ Doppelganger=1 Renegade\ Freighter=1 Renegade\ Krasis=1 -Renegade\ Map=1 +Renegade\ Rallier=1 Renegade\ Tactics=1 Renegade\ Warlord=1 Renegade\ Wheelsmith=1 Renewed\ Faith=1 +Renounce=1 Renounce\ the\ Guilds=1 Renowned\ Weaver=1 Repay\ in\ Kind=1 Repeal=1 Repeating\ Barrage=1 -Repel=1 Repel\ Intruders=1 Repel\ the\ Abominable=1 Repentance=1 @@ -6700,7 +7052,6 @@ Repentant\ Vampire=1 Repopulate=1 Reprisal=1 Reprocess=1 -Repulse=1 Requiem\ Angel=1 Reroute=1 Rescind=1 @@ -6710,29 +7061,35 @@ Research\ //\ Development=1 Research\ Assistant=1 Research\ the\ Deep=1 Reservoir\ Walker=1 +Resilient\ Wanderer=1 Resistance\ Fighter=1 Resize=1 Resolute\ Archangel=1 Resolute\ Blademaster=1 Resolute\ Survivors=1 -Resounding\ Roar=1 Resounding\ Scream=1 Resounding\ Silence=1 +Resounding\ Thunder=1 +Resounding\ Wave=1 Resourceful\ Return=1 Resplendent\ Griffin=1 +Resplendent\ Mentor=1 Rest\ for\ the\ Weary=1 Restless\ Apparition=1 Restless\ Bones=1 -Restless\ Dead=1 +Restless\ Dreams=1 Restock=1 Restoration\ Gearsmith=1 Restoration\ Specialist=1 Restore\ the\ Peace=1 +Restrain=1 Resupply=1 Resurrection=1 -Resuscitate=1 +Retaliate=1 Retaliation=1 Retaliator\ Griffin=1 +Retether=1 +Rethink=1 Retraction\ Helix=1 Retreat\ to\ Coralhelm=1 Retreat\ to\ Emeria=1 @@ -6747,34 +7104,34 @@ Returned\ Centaur=1 Returned\ Phalanx=1 Returned\ Reveler=1 Revealing\ Wind=1 -Reveka,\ Wizard\ Savant=1 +Reveille\ Squad=1 Revel\ in\ Riches=1 Revel\ of\ the\ Fallen\ God=1 Revelsong\ Horn=1 Revenant=1 Revenant\ Patriarch=1 -Revenge\ of\ the\ Hunted=1 Reverberate=1 Revered\ Dead=1 Revered\ Elder=1 +Revered\ Unicorn=1 Reverence=1 Reverent\ Hunter=1 Reversal\ of\ Fortune=1 -Reverse\ Damage=1 Reverse\ Engineer=1 Reverse\ the\ Sands=1 Revive=1 -Revive\ the\ Fallen=1 Reviving\ Dose=1 Reviving\ Melody=1 Reviving\ Vapors=1 Revoke\ Existence=1 Revoke\ Privileges=1 Revolutionary\ Rebuff=1 +Reward\ the\ Faithful=1 Rewards\ of\ Diversity=1 Reweave=1 Rewind=1 Rhet-Crop\ Spearmaster=1 +Rhonas's\ Last\ Stand=1 Rhonas's\ Monument=1 Rhonas's\ Stalwart=1 Rhox=1 @@ -6783,17 +7140,20 @@ Rhox\ Brute=1 Rhox\ Charger=1 Rhox\ Maulers=1 Rhox\ Meditant=1 +Rhox\ Oracle=1 Rhox\ Pikemaster=1 Rhox\ War\ Monk=1 -Rhys\ the\ Exiled=1 -Rhystic\ Deluge=1 -Ribbons\ of\ Night=1 +Rhystic\ Shield=1 +Rib\ Cage\ Spider=1 +Ribbon\ Snake=1 Ribbons\ of\ the\ Reikai=1 Riddle\ of\ Lightning=1 Riddleform=1 Riddlesmith=1 Ride\ Down=1 Ridge\ Rannet=1 +Ridged\ Kusite=1 +Ridgeline\ Rager=1 Ridgescale\ Tusker=1 Ridgetop\ Raptor=1 Riding\ the\ Dilu\ Horse=1 @@ -6801,24 +7161,22 @@ Rift\ Elemental=1 Riftmarked\ Knight=1 Riftsweeper=1 Riftwing\ Cloudskate=1 -Rigging\ Runner=1 -Righteous\ Aura=1 Righteous\ Authority=1 Righteous\ Avengers=1 Righteous\ Blow=1 Righteous\ Charge=1 +Righteous\ Fury=1 Righteousness=1 Rile=1 Rime\ Transfusion=1 Rimebound\ Dead=1 Rimefeather\ Owl=1 -Rimehorn\ Aurochs=1 +Rimescale\ Dragon=1 Rimewind\ Cryomancer=1 +Rimewind\ Taskmage=1 Ring\ of\ Evos\ Isle=1 Ring\ of\ Gix=1 Ring\ of\ Kalonia=1 -Ring\ of\ Ma'ruf=1 -Ring\ of\ Renewal=1 Ring\ of\ Thune=1 Ring\ of\ Valkas=1 Ring\ of\ Xathrid=1 @@ -6827,47 +7185,51 @@ Ringwarden\ Owl=1 Riot\ Control=1 Riot\ Gear=1 Riot\ Piker=1 -Riot\ Ringleader=1 -Rip-Clan\ Crasher=1 +Riot\ Spikes=1 Riparian\ Tiger=1 Ripscale\ Predator=1 Riptide\ Biologist=1 Riptide\ Chimera=1 Riptide\ Chronologist=1 -Riptide\ Crab=1 +Riptide\ Entrancer=1 Riptide\ Mangler=1 Riptide\ Pilferer=1 -Riptide\ Shapeshifter=1 +Riptide\ Replicator=1 Rise\ from\ the\ Grave=1 Rise\ from\ the\ Tides=1 Rise\ of\ Eagles=1 Rise\ to\ the\ Challenge=1 Risen\ Sanctuary=1 +Rishadan\ Airship=1 +Rishkar's\ Expertise=1 Rising\ Miasma=1 +Rite\ of\ Belzenlok=1 Rite\ of\ Ruin=1 Rite\ of\ Undoing=1 -Rite\ of\ the\ Serpent=1 Rites\ of\ Initiation=1 Rites\ of\ Reaping=1 Rites\ of\ Refusal=1 -Rith's\ Grove=1 +Rith's\ Attendant=1 Ritual\ of\ Rejuvenation=1 Ritual\ of\ Restoration=1 -Ritual\ of\ Steel=1 +Ritual\ of\ Subdual=1 Ritual\ of\ the\ Returned=1 Rivalry=1 -Riven\ Turnbull=1 +Rivals'\ Duel=1 River's\ Grasp=1 River\ Bear=1 River\ Darter=1 River\ Heralds'\ Boon=1 River\ Hoopoe=1 +River\ Kaijin=1 River\ Merfolk=1 River\ Serpent=1 +River\ Sneak=1 Riverfall\ Mimic=1 Riverwheel\ Aerialists=1 Riverwise\ Augur=1 Rix\ Maadi,\ Dungeon\ Palace=1 +Rix\ Maadi\ Guildmage=1 Roar\ of\ Challenge=1 Roar\ of\ Jukai=1 Roar\ of\ Reclamation=1 @@ -6875,13 +7237,15 @@ Roar\ of\ the\ Crowd=1 Roar\ of\ the\ Wurm=1 Roaring\ Primadox=1 Roaring\ Slagwurm=1 +Robber\ Fly=1 Robe\ of\ Mirrors=1 Roc\ Egg=1 +Roc\ Hatchling=1 Rock\ Badger=1 +Rock\ Basilisk=1 Rock\ Hydra=1 Rock\ Jockey=1 Rock\ Slide=1 -Rockcaster\ Platoon=1 Rockshard\ Elemental=1 Rockslide\ Ambush=1 Rockslide\ Elemental=1 @@ -6891,9 +7255,9 @@ Rofellos,\ Llanowar\ Emissary=1 Rogue's\ Gloves=1 Rogue's\ Passage=1 Rogue\ Kavu=1 +Rogue\ Refiner=1 Rogue\ Skycaptain=1 Roil's\ Retribution=1 -Roil\ Elemental=1 Roil\ Spout=1 Roiling\ Horror=1 Roiling\ Terrain=1 @@ -6901,9 +7265,9 @@ Roiling\ Waters=1 Roilmage's\ Trick=1 Rollick\ of\ Abandon=1 Rolling\ Spoil=1 -Rolling\ Stones=1 Rolling\ Temblor=1 Rolling\ Thunder=1 +Rona,\ Disciple\ of\ Gix=1 Ronin\ Cavekeeper=1 Ronin\ Cliffrider=1 Ronin\ Houndmaster=1 @@ -6914,17 +7278,16 @@ Ronom\ Unicorn=1 Roofstalker\ Wight=1 Rooftop\ Storm=1 Root-Kin\ Ally=1 -Root\ Elemental=1 -Root\ Greevil=1 Root\ Out=1 +Root\ Snare=1 Rootborn\ Defenses=1 Rootbreaker\ Wurm=1 Rootgrapple=1 +Rooting\ Kavu=1 Rootrunner=1 Roots=1 Rootwalla=1 Rootwater\ Alligator=1 -Rootwater\ Depths=1 Rootwater\ Diver=1 Rootwater\ Hunter=1 Rootwater\ Matriarch=1 @@ -6933,17 +7296,19 @@ Rorix\ Bladewing=1 Rosheen\ Meanderer=1 Rot\ Farm\ Skeleton=1 Rot\ Shambler=1 +Rot\ Wolf=1 Rotcrown\ Ghoul=1 Roterothopter=1 Rotfeaster\ Maggot=1 Rotted\ Hulk=1 -Rotted\ Hystrix=1 Rottenheart\ Ghoul=1 +Rotting\ Giant=1 Rotting\ Legion=1 Rotting\ Mastodon=1 -Rough\ //\ Tumble=1 +Roughshod\ Mentor=1 Rouse\ the\ Mob=1 Royal\ Assassin=1 +Royal\ Decree=1 Royal\ Trooper=1 Rubbleback\ Rhino=1 Rubblebelt\ Maaka=1 @@ -6951,7 +7316,7 @@ Rubblebelt\ Raiders=1 Rubblehulk=1 Rude\ Awakening=1 Rugged\ Highlands=1 -Ruin\ Ghost=1 +Ruham\ Djinn=1 Ruin\ Processor=1 Ruin\ Rat=1 Ruin\ in\ Their\ Wake=1 @@ -6961,17 +7326,18 @@ Ruinous\ Gremlin=1 Ruinous\ Minotaur=1 Ruinous\ Path=1 Ruins\ of\ Oran-Rief=1 +Ruins\ of\ Trokair=1 Rukh\ Egg=1 Rumbling\ Aftershocks=1 Rumbling\ Baloth=1 -Rumbling\ Crescendo=1 +Rumbling\ Slum=1 Rummaging\ Goblin=1 Rummaging\ Wizard=1 Run\ Aground=1 +Run\ Amok=1 Run\ Wild=1 -Runaway\ Carriage=1 -Rune-Cervin\ Rider=1 Rune\ of\ Protection:\ Artifacts=1 +Rune\ of\ Protection:\ Lands=1 Runeboggle=1 Runechanter's\ Pike=1 Runeclaw\ Bear=1 @@ -6979,25 +7345,26 @@ Runed\ Servitor=1 Runed\ Stalactite=1 Runeflare\ Trap=1 Runes\ of\ the\ Deus=1 -Runewing=1 Runic\ Repetition=1 Runner's\ Bane=1 Rush\ of\ Adrenaline=1 Rush\ of\ Battle=1 Rush\ of\ Blood=1 Rush\ of\ Ice=1 -Rush\ of\ Knowledge=1 Rush\ of\ Vitality=1 Rushing-Tide\ Zubera=1 -Rushing\ River=1 +Rushwood\ Dryad=1 Rushwood\ Herbalist=1 Rust\ Scarab=1 -Rust\ Tick=1 Rusted\ Relic=1 Rusted\ Sentinel=1 +Rusted\ Slasher=1 +Rustic\ Clachan=1 +Rusting\ Golem=1 Rustmouth\ Ogre=1 Rustrazor\ Butcher=1 Rustspore\ Ram=1 +Rustwing\ Falcon=1 Ruthless\ Cullblade=1 Ruthless\ Deathfang=1 Ruthless\ Disposal=1 @@ -7005,31 +7372,28 @@ Ruthless\ Instincts=1 Ruthless\ Knave=1 Ruthless\ Ripper=1 Ruthless\ Sniper=1 +Ryusei,\ the\ Falling\ Star=1 Saberclaw\ Golem=1 -Sabertooth\ Alley\ Cat=1 Sabertooth\ Outrider=1 Sabertooth\ Wyvern=1 Sabretooth\ Tiger=1 -Sacellum\ Archers=1 Sacellum\ Godspeaker=1 -Sachi,\ Daughter\ of\ Seshiro=1 Sacred\ Armory=1 -Sacred\ Boon=1 Sacred\ Excavation=1 +Sacred\ Ground=1 Sacred\ Mesa=1 Sacred\ Nectar=1 Sacred\ Prey=1 +Sacred\ Rites=1 Sacred\ Wolf=1 Saddleback\ Lagac=1 Sadistic\ Augermage=1 -Sadistic\ Glee=1 -Sadistic\ Sacrament=1 Sadistic\ Skymarcher=1 Safe\ Passage=1 Safeguard=1 -Safehold\ Duo=1 Safehold\ Sentry=1 Safewright\ Quest=1 +Saffi\ Eriksdotter=1 Sage's\ Dousing=1 Sage's\ Row\ Denizen=1 Sage-Eye\ Avengers=1 @@ -7037,19 +7401,20 @@ Sage-Eye\ Harrier=1 Sage\ Aven=1 Sage\ Owl=1 Sage\ of\ Ancient\ Lore=1 -Sage\ of\ Epityr=1 -Sage\ of\ Fables=1 +Sage\ of\ Lat-Nam=1 Sage\ of\ Shaila's\ Claim=1 Sage\ of\ the\ Inward\ Eye=1 Sages\ of\ the\ Anima=1 Sagu\ Archer=1 Sagu\ Mauler=1 Saheeli's\ Artistry=1 +Sailmonger=1 Sailor\ of\ Means=1 Sakiko,\ Mother\ of\ Summer=1 Sakura-Tribe\ Springcaller=1 Salivating\ Gremlins=1 Salt\ Flats=1 +Salt\ Marsh=1 Salt\ Road\ Ambushers=1 Salt\ Road\ Patrol=1 Salt\ Road\ Quartermasters=1 @@ -7058,25 +7423,29 @@ Saltcrusted\ Steppe=1 Saltfield\ Recluse=1 Saltskitter=1 Salvage\ Drone=1 +Salvage\ Scout=1 Salvage\ Scuttler=1 Salvage\ Slasher=1 Salvage\ Titan=1 +Salvager\ of\ Secrets=1 +Salvaging\ Station=1 Samite\ Archer=1 Samite\ Blessing=1 Samite\ Censer-Bearer=1 Samite\ Healer=1 +Samite\ Ministration=1 Samite\ Pilgrim=1 +Samite\ Sanctuary=1 Samurai\ of\ the\ Pale\ Curtain=1 Sanctified\ Charge=1 Sanctifier\ of\ Souls=1 -Sanctimony=1 Sanctuary\ Cat=1 Sanctum\ Gargoyle=1 Sanctum\ Guardian=1 Sanctum\ Plowbeast=1 +Sanctum\ Spirit=1 Sand\ Golem=1 Sand\ Strangler=1 -Sandbar\ Crocodile=1 Sandbar\ Merfolk=1 Sandbar\ Serpent=1 Sandblast=1 @@ -7085,16 +7454,16 @@ Sands\ of\ Delirium=1 Sandskin=1 Sandsower=1 Sandsteppe\ Citadel=1 -Sandsteppe\ Mastodon=1 +Sandsteppe\ Outcast=1 Sandsteppe\ Scavenger=1 Sandstone\ Bridge=1 +Sandstone\ Deadfall=1 Sandstone\ Warrior=1 +Sandstorm\ Eidolon=1 Sandwurm\ Convergence=1 -Sangrite\ Surge=1 -Sangrophage=1 +Sangromancer=1 Sanguimancy=1 Sanguinary\ Mage=1 -Sanguine\ Bond=1 Sanguine\ Glorifier=1 Sanguine\ Guard=1 Sanguine\ Praetor=1 @@ -7103,37 +7472,44 @@ Sanitarium\ Skeleton=1 Sanity\ Gnawers=1 Sanity\ Grinding=1 Sapphire\ Drake=1 +Sapphire\ Leech=1 +Saprazzan\ Legate=1 +Saprazzan\ Raider=1 Saproling\ Burst=1 +Saproling\ Migration=1 Sapseep\ Forest=1 +Sarcatog=1 Sarcomancy=1 Sarcomite\ Myr=1 Sarkhan's\ Rage=1 Sarpadian\ Empires,\ Vol.\ VII=1 Saruli\ Gatekeepers=1 +Sasaya,\ Orochi\ Ascendant=1 Satyr\ Firedancer=1 Satyr\ Grovedancer=1 Satyr\ Hedonist=1 Satyr\ Nyx-Smith=1 Satyr\ Piper=1 +Satyr\ Rambler=1 Savage\ Alliance=1 +Savage\ Beating=1 Savage\ Conception=1 -Savage\ Firecat=1 Savage\ Gorilla=1 -Savage\ Hunger=1 Savage\ Knuckleblade=1 -Savage\ Lands=1 Savage\ Punch=1 +Savage\ Silhouette=1 Savage\ Stomp=1 -Savage\ Summoning=1 Savage\ Surge=1 Savage\ Thallid=1 Savage\ Twister=1 -Savannah\ Lions=1 Saving\ Grace=1 Saving\ Grasp=1 Savra,\ Queen\ of\ the\ Golgari=1 +Sawback\ Manticore=1 +Sawtooth\ Loon=1 +Sawtooth\ Ogre=1 Sawtooth\ Thresher=1 -Scab-Clan\ Giant=1 +Scab-Clan\ Berserker=1 Scab-Clan\ Mauler=1 Scabland=1 Scald=1 @@ -7143,42 +7519,48 @@ Scale\ Blessing=1 Scale\ of\ Chiss-Goria=1 Scalebane's\ Elite=1 Scaled\ Behemoth=1 +Scaled\ Hulk=1 Scaleguard\ Sentinels=1 Scalpelexis=1 +Scandalmonger=1 Scapegoat=1 +Scar=1 Scarab\ Feast=1 Scarblade\ Elite=1 -Scare\ Tactics=1 Scarecrow=1 Scarred\ Puma=1 +Scarred\ Vinebreeder=1 Scars\ of\ the\ Veteran=1 +Scarscale\ Ritual=1 +Scarwood\ Bandits=1 +Scarwood\ Treefolk=1 Scathe\ Zombies=1 Scatter\ Arc=1 Scatter\ the\ Seeds=1 Scatter\ to\ the\ Winds=1 +Scattering\ Stroke=1 Scattershot=1 +Scavenged\ Weaponry=1 Scavenger\ Drake=1 Scavenger\ Folk=1 -Scavenging\ Ghoul=1 Scavenging\ Scarab=1 Scent\ of\ Brine=1 -Scent\ of\ Ivy=1 Scent\ of\ Jasmine=1 Scent\ of\ Nightshade=1 -Scepter\ of\ Dominance=1 Scepter\ of\ Empires=1 -Scepter\ of\ Fugue=1 Scepter\ of\ Insight=1 Schismotivate=1 Scholar\ of\ Athreos=1 +Scholar\ of\ Stars=1 +School\ of\ Piranha=1 Scion\ Summoner=1 Scion\ of\ Glaciers=1 Scion\ of\ Ugin=1 Scion\ of\ Vitu-Ghazi=1 -Scion\ of\ the\ Ur-Dragon=1 Scion\ of\ the\ Wild=1 Scorch\ the\ Fields=1 Scorched\ Rusalka=1 +Scorching\ Lava=1 Scorchwalker=1 Scoria\ Elemental=1 Scoria\ Wurm=1 @@ -7187,9 +7569,12 @@ Scornful\ Aether-Lich=1 Scornful\ Egotist=1 Scour=1 Scour\ from\ Existence=1 +Scour\ the\ Laboratory=1 +Scoured\ Barrens=1 Scourge\ Devil=1 +Scourge\ Servant=1 Scourge\ Wolf=1 -Scourge\ of\ Fleets=1 +Scourge\ of\ Geier\ Reach=1 Scourge\ of\ Kher\ Ridges=1 Scourge\ of\ Numai=1 Scourge\ of\ Skola\ Vale=1 @@ -7197,11 +7582,12 @@ Scourge\ of\ the\ Nobilis=1 Scourgemark=1 Scourglass=1 Scouring\ Sands=1 +Scout's\ Warning=1 Scout\ the\ Borders=1 Scragnoth=1 Scrambleverse=1 Scrapbasket=1 -Scrapdiver\ Serpent=1 +Scrapheap=1 Scrapper\ Champion=1 Scrapskin\ Drake=1 Scrapyard\ Mongrel=1 @@ -7209,6 +7595,8 @@ Scrapyard\ Salvo=1 Screaming\ Fury=1 Screaming\ Seahawk=1 Screamreach\ Brawler=1 +Screams\ from\ Within=1 +Screams\ of\ the\ Damned=1 Screeching\ Bat=1 Screeching\ Drake=1 Screeching\ Griffin=1 @@ -7219,7 +7607,6 @@ Screeching\ Sliver=1 Scrib\ Nibblers=1 Scribe\ of\ the\ Mindful=1 Scrivener=1 -Scroll\ Thief=1 Scroll\ of\ Avacyn=1 Scroll\ of\ Griselbrand=1 Scroll\ of\ Origins=1 @@ -7239,29 +7626,32 @@ Scythe\ Leopard=1 Scythe\ Tiger=1 Scythe\ of\ the\ Wretched=1 Sea\ Drake=1 -Sea\ Eagle=1 Sea\ Gate\ Loremaster=1 +Sea\ Gate\ Wreckage=1 Sea\ God's\ Revenge=1 Sea\ Legs=1 Sea\ Monster=1 +Sea\ Scryer=1 Sea\ Serpent=1 -Sea\ Spirit=1 +Sea\ Snidd=1 Sea\ Sprite=1 Seacoast\ Drake=1 -Seafloor\ Debris=1 Seagraf\ Skaab=1 Seal\ of\ Cleansing=1 Seal\ of\ Doom=1 -Seal\ of\ Fire=1 Seal\ of\ Primordium=1 +Seal\ of\ Strength=1 +Sealed\ Fate=1 Sealock\ Monster=1 -Seance=1 Search\ Warrant=1 Search\ the\ City=1 Searing\ Flesh=1 Searing\ Light=1 Searing\ Meditation=1 +Searing\ Rays=1 +Searing\ Spear=1 Searing\ Touch=1 +Searing\ Wind=1 Seascape\ Aerialist=1 Seashell\ Cameo=1 Seaside\ Citadel=1 @@ -7270,18 +7660,18 @@ Seasinger=1 Seasoned\ Marshal=1 Second\ Guess=1 Second\ Harvest=1 -Second\ Sight=1 -Second\ Thoughts=1 +Second\ Sunrise=1 +Second\ Wind=1 Secret\ Plans=1 Secret\ Salvage=1 Secretkeeper=1 -Secrets\ of\ the\ Dead=1 Secrets\ of\ the\ Golden\ City=1 -Security\ Blockade=1 +Security\ Detail=1 Sedge\ Scorpion=1 Sedge\ Troll=1 Sedraxis\ Alchemist=1 Sedraxis\ Specter=1 +See\ Beyond=1 See\ Red=1 Seed\ Guardian=1 Seed\ Spark=1 @@ -7292,23 +7682,22 @@ Seeds\ of\ Strength=1 Seek\ the\ Horizon=1 Seek\ the\ Wilds=1 Seeker\ of\ Insight=1 -Seeker\ of\ the\ Way=1 Seekers'\ Squire=1 Seer's\ Lantern=1 Seer's\ Sundial=1 Seer\ of\ the\ Last\ Tomorrow=1 -Seething\ Anger=1 Seething\ Pathblazer=1 Segmented\ Krotiq=1 Seismic\ Elemental=1 Seismic\ Rupture=1 +Seismic\ Shift=1 Seismic\ Spike=1 Seismic\ Stomp=1 Seismic\ Strike=1 Seizan,\ Perverter\ of\ Truth=1 Seize\ the\ Soul=1 Sejiri\ Merfolk=1 -Sekki,\ Seasons'\ Guide=1 +Sek'Kuar,\ Deathkeeper=1 Select\ for\ Inspection=1 Selective\ Memory=1 Selesnya\ Charm=1 @@ -7323,6 +7712,7 @@ Selesnya\ Signet=1 Self-Assembler=1 Self-Inflicted\ Wound=1 Selfless\ Cathar=1 +Selfless\ Exorcist=1 Selhoff\ Occultist=1 Selkie\ Hedge-Mage=1 Sell-Sword\ Brute=1 @@ -7332,32 +7722,30 @@ Send\ to\ Sleep=1 Sengir\ Autocrat=1 Sengir\ Nosferatu=1 Sengir\ Vampire=1 +Sensation\ Gorger=1 +Sensei\ Golden-Tail=1 Senseless\ Rage=1 Sensor\ Splicer=1 Sentinel\ Spider=1 -Sentinel\ Totem=1 Sentinel\ of\ the\ Eternal\ Watch=1 +Sentinel\ of\ the\ Pearl\ Trident=1 Sentinels\ of\ Glen\ Elendra=1 -Sentry\ Oak=1 Sentry\ of\ the\ Underworld=1 Separatist\ Voidmage=1 Septic\ Rats=1 Sepulchral\ Primordial=1 Sequestered\ Stash=1 -Seraph=1 -Seraph\ of\ Dawn=1 Seraph\ of\ the\ Masses=1 Seraph\ of\ the\ Suns=1 -Seraph\ of\ the\ Sword=1 Serendib\ Efreet=1 Serendib\ Sorcerer=1 Serene\ Offering=1 Serene\ Remembrance=1 Serene\ Steward=1 -Serpent\ Generator=1 +Serene\ Sunset=1 +Sergeant-at-Arms=1 Serpent\ Skin=1 Serpent\ Warrior=1 -Serpentine\ Basilisk=1 Serpentine\ Kavu=1 Serpentine\ Spike=1 Serra's\ Blessing=1 @@ -7369,6 +7757,10 @@ Serra\ Angel=1 Serra\ Avenger=1 Serra\ Aviary=1 Serra\ Bestiary=1 +Serra\ Disciple=1 +Serra\ Sphinx=1 +Serra\ Zealot=1 +Serrated\ Biskelion=1 Serum\ Raker=1 Serum\ Tank=1 Servant\ of\ Nefarox=1 @@ -7376,11 +7768,16 @@ Servant\ of\ Tymaret=1 Servant\ of\ Volrath=1 Servo\ Exhibition=1 Servo\ Schematic=1 +Seshiro\ the\ Anointed=1 Set\ Adrift=1 Setessan\ Battle\ Priest=1 +Setessan\ Griffin=1 Setessan\ Oathsworn=1 Setessan\ Starbreaker=1 Setessan\ Tactics=1 +Seton's\ Desire=1 +Seton's\ Scout=1 +Settle\ the\ Score=1 Sever\ Soul=1 Sever\ the\ Bloodline=1 Severed\ Legion=1 @@ -7390,11 +7787,11 @@ Sewerdreg=1 Sewn-Eye\ Drake=1 Shackles=1 Shade's\ Breath=1 +Shade's\ Form=1 Shade\ of\ Trokair=1 Shadow\ Alley\ Denizen=1 Shadow\ Glider=1 Shadow\ Guildmage=1 -Shadow\ Lance=1 Shadow\ Rider=1 Shadow\ Slice=1 Shadow\ Sliver=1 @@ -7403,44 +7800,48 @@ Shadowblood\ Egg=1 Shadowcloak\ Vampire=1 Shadowed\ Caravel=1 Shadowfeed=1 +Shadowmage\ Infiltrator=1 Shadows\ of\ the\ Past=1 +Shadowstorm=1 Shadowstorm\ Vizier=1 -Shah\ of\ Naar\ Isle=1 Shake\ the\ Foundations=1 +Shaleskin\ Bruiser=1 +Shaleskin\ Plower=1 Shaman's\ Trance=1 Shaman\ of\ Spring=1 -Shaman\ of\ the\ Pack=1 Shamble\ Back=1 Shambleshark=1 Shambling\ Attendants=1 Shambling\ Ghoul=1 -Shambling\ Goblin=1 Shambling\ Remains=1 Shambling\ Shell=1 Shambling\ Strider=1 +Shambling\ Swarm=1 +Shanna,\ Sisay's\ Legacy=1 Shanodin\ Dryads=1 Shape\ Anew=1 Shape\ Stealer=1 -Shape\ of\ the\ Wiitigo=1 Shape\ the\ Sands=1 Shaper\ Apprentice=1 Shaper\ Guildmage=1 -Shaper\ Parasite=1 Shapers\ of\ Nature=1 -Shapeshifter=1 +Shapeshifter's\ Marrow=1 Shard\ Convergence=1 Shard\ Phoenix=1 Shard\ of\ Broken\ Glass=1 Sharding\ Sphinx=1 +Shared\ Discovery=1 Shared\ Fate=1 Sharpened\ Pitchfork=1 Shatter=1 Shattered\ Angel=1 +Shattered\ Crypt=1 Shattered\ Dreams=1 Shattered\ Perception=1 Shattering\ Blow=1 Shatterskull\ Giant=1 Shatterskull\ Recruit=1 +Shauku's\ Minion=1 Shed\ Weakness=1 Sheer\ Drop=1 Shefet\ Monitor=1 @@ -7450,10 +7851,12 @@ Shelter=1 Sheltered\ Aerie=1 Sheltering\ Light=1 Shield\ Bearer=1 -Shield\ Mate=1 +Shield\ Dancer=1 Shield\ Wall=1 Shield\ of\ the\ Ages=1 +Shield\ of\ the\ Avatar=1 Shield\ of\ the\ Oversoul=1 +Shield\ of\ the\ Realm=1 Shield\ of\ the\ Righteous=1 Shielded\ Aether\ Thief=1 Shielded\ Passage=1 @@ -7462,26 +7865,26 @@ Shielding\ Plax=1 Shieldmage\ Elder=1 Shields\ of\ Velis\ Vel=1 Shifting\ Borders=1 -Shifting\ Loyalties=1 -Shifty\ Doppelganger=1 +Shifting\ Sky=1 Shimatsu\ the\ Bloodcloaked=1 Shimian\ Specter=1 -Shimmer\ Myr=1 Shimmering\ Barrier=1 +Shimmering\ Efreet=1 +Shimmering\ Glasskite=1 Shimmering\ Grotto=1 +Shimmering\ Mirage=1 Shimmering\ Wings=1 Shimmerscale\ Drake=1 -Shinen\ of\ Fear's\ Chill=1 -Shinen\ of\ Flight's\ Wings=1 -Shinen\ of\ Fury's\ Fire=1 Shinen\ of\ Life's\ Roar=1 Shinewend=1 Shining\ Aerosaur=1 +Shinka\ Gatekeeper=1 Shipbreaker\ Kraken=1 Shipwreck\ Looter=1 Shipwreck\ Moray=1 Shipwreck\ Singer=1 Shirei,\ Shizo's\ Caretaker=1 +Shisato,\ Whispering\ Hunter=1 Shiv's\ Embrace=1 Shivan\ Dragon=1 Shivan\ Emissary=1 @@ -7491,16 +7894,21 @@ Shivan\ Oasis=1 Shivan\ Phoenix=1 Shivan\ Raptor=1 Shivan\ Sand-Mage=1 +Shivan\ Wumpus=1 Shivan\ Wurm=1 Shizuko,\ Caller\ of\ Autumn=1 +Shoal\ Serpent=1 Shock=1 -Shock\ Troops=1 Shockmaw\ Dragon=1 Shore\ Keeper=1 Shore\ Snapper=1 Shorecrasher\ Mimic=1 +Shoreline\ Raider=1 Shoreline\ Ranger=1 +Short\ Sword=1 Shoulder\ to\ Shoulder=1 +Shoving\ Match=1 +Shower\ of\ Coals=1 Shower\ of\ Sparks=1 Showstopper=1 Shrapnel\ Blast=1 @@ -7509,34 +7917,30 @@ Shreds\ of\ Sanity=1 Shrewd\ Hatchling=1 Shrewd\ Negotiation=1 Shriek\ Raptor=1 +Shriek\ of\ Dread=1 Shriekgeist=1 Shriekhorn=1 Shrike\ Harpy=1 Shrill\ Howler=1 Shrine\ of\ Boundless\ Growth=1 +Shrine\ of\ Limitless\ Power=1 Shrine\ of\ Loyal\ Legions=1 Shrine\ of\ Piercing\ Vision=1 Shrine\ of\ the\ Forsaken\ Gods=1 Shrink=1 Shriveling\ Rot=1 Shrouded\ Lore=1 -Shrouded\ Serpent=1 +Shu\ Cavalry=1 Shu\ Elite\ Companions=1 -Shu\ General=1 Shu\ Soldier-Farmers=1 -Shuko=1 -Shunt=1 Shuriken=1 Shyft=1 Sibilant\ Spirit=1 -Sibsig\ Host=1 Sibsig\ Icebreakers=1 -Sibsig\ Muckdraggers=1 Sicken=1 Sickening\ Dreams=1 Sickle\ Ripper=1 Sickleslicer=1 -Sidar\ Jabari=1 Sideswipe=1 Sidewinder\ Naga=1 Sidisi's\ Pet=1 @@ -7545,31 +7949,32 @@ Siege\ Mastodon=1 Siege\ Modification=1 Siege\ Wurm=1 Siege\ of\ Towers=1 -Siegecraft=1 +Siegebreaker\ Giant=1 Sift=1 Sift\ Through\ Sands=1 -Sifter\ Wurm=1 Sifter\ of\ Skulls=1 +Sigarda's\ Aid=1 Sigardian\ Priest=1 Sight\ Beyond\ Sight=1 Sight\ of\ the\ Scalelords=1 Sighted-Caste\ Sorcerer=1 Sightless\ Brawler=1 +Sightless\ Ghoul=1 Sigil\ Blessing=1 Sigil\ Captain=1 +Sigil\ Tracer=1 Sigil\ of\ Distinction=1 Sigil\ of\ Valor=1 +Sigil\ of\ the\ Empty\ Throne=1 Sigil\ of\ the\ Nayan\ Gods=1 -Sigil\ of\ the\ New\ Dawn=1 Sigiled\ Behemoth=1 -Sigiled\ Paladin=1 Sigiled\ Skink=1 Sigiled\ Starfish=1 Signal\ the\ Clans=1 Silburlind\ Snapper=1 Silence\ the\ Believers=1 +Silent-Chant\ Zubera=1 Silent\ Artisan=1 -Silent\ Attendant=1 Silent\ Departure=1 Silent\ Observer=1 Silent\ Sentinel=1 @@ -7578,27 +7983,26 @@ Silhana\ Starfletcher=1 Silk\ Net=1 Silkbind\ Faerie=1 Silkenfist\ Fighter=1 +Silkenfist\ Order=1 Silklash\ Spider=1 Silkweaver\ Elite=1 -Silkwing\ Scout=1 +Silt\ Crawler=1 Silumgar\ Assassin=1 Silumgar\ Butcher=1 Silumgar\ Monument=1 Silumgar\ Sorcerer=1 Silumgar\ Spell-Eater=1 Silver-Inlaid\ Dagger=1 -Silver\ Drake=1 -Silver\ Knight=1 Silver\ Myr=1 Silver\ Seraph=1 Silver\ Wyvern=1 Silverback\ Ape=1 -Silverblade\ Paladin=1 Silverchase\ Fox=1 Silverclad\ Ferocidons=1 Silvercoat\ Lion=1 Silverfur\ Partisan=1 Silvergill\ Douser=1 +Silverskin\ Armor=1 Silverstorm\ Samurai=1 Silverstrike=1 Silvos,\ Rogue\ Elemental=1 @@ -7615,30 +8019,32 @@ Simic\ Manipulator=1 Simic\ Ragworm=1 Simic\ Sky\ Swallower=1 Simoon=1 -Sin\ Collector=1 +Sin\ Prodder=1 Sindbad=1 +Singe-Mind\ Ogre=1 +Singe=1 Singing\ Bell\ Strike=1 Singing\ Tree=1 Sinister\ Concoction=1 Sinister\ Possession=1 Sinister\ Strength=1 Sink\ into\ Takenuma=1 +Sinking\ Feeling=1 Sins\ of\ the\ Past=1 Sinuous\ Striker=1 Sir\ Shandlar\ of\ Eberyn=1 -Sire\ of\ the\ Storm=1 +Sire\ of\ Insanity=1 Siren's\ Ruse=1 Siren\ Lookout=1 Siren\ Reaver=1 Siren\ Song\ Lyre=1 Siren\ of\ the\ Fanged\ Coast=1 Siren\ of\ the\ Silent\ Song=1 -Sirocco=1 +Sisay's\ Ingenuity=1 Sisay's\ Ring=1 Sisters\ of\ Stone\ Death=1 Sivitri\ Scarzam=1 Sixth\ Sense=1 -Sizzle=1 Skaab\ Goliath=1 Skarrg,\ the\ Rage\ Pits=1 Skarrg\ Goliath=1 @@ -7650,6 +8056,7 @@ Skeletal\ Grimace=1 Skeletal\ Kathari=1 Skeletal\ Vampire=1 Skeletal\ Wurm=1 +Skeleton\ Archer=1 Skeleton\ Key=1 Skeleton\ Scavengers=1 Skeleton\ Shard=1 @@ -7661,34 +8068,36 @@ Skinbrand\ Goblin=1 Skinrender=1 Skinshifter=1 Skinthinner=1 +Skinwing=1 Skirge\ Familiar=1 Skirk\ Alarmist=1 Skirk\ Drill\ Sergeant=1 -Skirk\ Marauder=1 Skirk\ Outrider=1 Skirk\ Prospector=1 Skirk\ Ridge\ Exhumer=1 Skirk\ Shaman=1 Skirk\ Volcanist=1 -Skirsdag\ Cultist=1 Skirsdag\ Flayer=1 Skirsdag\ High\ Priest=1 Skirsdag\ Supplicant=1 Skitter\ of\ Lizards=1 Skittering\ Heartstopper=1 +Skittering\ Horror=1 Skittering\ Invasion=1 +Skittering\ Monstrosity=1 Skittering\ Skirge=1 +Skittering\ Surveyor=1 Skitterskin=1 +Skittish\ Kavu=1 Skittish\ Valesk=1 +Skizzik=1 Skulduggery=1 -Skulking\ Fugitive=1 Skulking\ Ghost=1 Skulking\ Knight=1 -Skull\ Catapult=1 -Skull\ Fracture=1 +Skull\ Collector=1 Skull\ Rend=1 +Skull\ of\ Orm=1 Skullcage=1 -Skullmane\ Baku=1 Skullmead\ Cauldron=1 Skullmulcher=1 Skullsnatcher=1 @@ -7696,12 +8105,13 @@ Skulltap=1 Sky\ Ruin\ Drake=1 Sky\ Scourer=1 Sky\ Skiff=1 +Sky\ Spirit=1 +Sky\ Swallower=1 Sky\ Terror=1 Skybind=1 Skyblade\ of\ the\ Legion=1 Skyblinder\ Staff=1 -Skyclaw\ Thrash=1 -Skyfire\ Kirin=1 +Skycloud\ Egg=1 Skygames=1 Skyhunter\ Cub=1 Skyhunter\ Prowler=1 @@ -7711,6 +8121,7 @@ Skylasher=1 Skyline\ Cascade=1 Skyline\ Predator=1 Skymarch\ Bloodletter=1 +Skymarcher\ Aspirant=1 Skymark\ Roc=1 Skyraker\ Giant=1 Skyreach\ Manta=1 @@ -7730,12 +8141,12 @@ Skyshroud\ Elite=1 Skyshroud\ Forest=1 Skyshroud\ Ranger=1 Skyshroud\ Sentinel=1 -Skyshroud\ Troll=1 -Skyshroud\ Troopers=1 +Skyshroud\ Vampire=1 Skyshroud\ War\ Beast=1 Skysnare\ Spider=1 Skyspear\ Cavalry=1 Skyswirl\ Harrier=1 +Skyward\ Eye\ Prophets=1 Skywatcher\ Adept=1 Skywhaler's\ Shot=1 Skywinder\ Drake=1 @@ -7748,8 +8159,8 @@ Slash\ Panther=1 Slash\ of\ Talons=1 Slashing\ Tiger=1 Slate\ Street\ Ruffian=1 -Slate\ of\ Ancestry=1 Slaughter=1 +Slaughter\ Cry=1 Slaughter\ Drone=1 Slaughterhorn=1 Slaughterhouse\ Bouncer=1 @@ -7764,41 +8175,55 @@ Sleep=1 Sleep\ Paralysis=1 Sleeper's\ Robe=1 Sleeper\ Agent=1 +Sleeping\ Potion=1 +Slice\ and\ Dice=1 Slice\ in\ Twain=1 Slime\ Molding=1 +Slimefoot,\ the\ Stowaway=1 +Slimy\ Kavu=1 Slingbow\ Trap=1 -Slinking\ Giant=1 +Slingshot\ Goblin=1 +Slinking\ Serpent=1 +Slinking\ Skirge=1 +Slinn\ Voda,\ the\ Rising\ Deep=1 Slip\ Through\ Space=1 Slippery\ Scoundrel=1 Slipstream\ Eel=1 Slipstream\ Serpent=1 +Sliptide\ Serpent=1 Slith\ Ascendant=1 +Slith\ Bloodletter=1 Slith\ Firewalker=1 Slith\ Predator=1 Slith\ Strider=1 Slither\ Blade=1 Slitherhead=1 +Slithering\ Shade=1 +Slithermuse=1 +Slithery\ Stalker=1 Sliver\ Construct=1 Sliversmith=1 Slobad,\ Goblin\ Tinkerer=1 +Slow\ Motion=1 Sludge\ Crawler=1 Sludge\ Strider=1 Sluggishness=1 Sluiceway\ Scorpion=1 Slum\ Reaper=1 +Slumbering\ Dragon=1 Slumbering\ Tora=1 Sly\ Requisitioner=1 Smash=1 +Smash\ to\ Smithereens=1 Smelt-Ward\ Gatekeepers=1 Smelt=1 Smite=1 Smite\ the\ Monstrous=1 +Smogsteed\ Rider=1 Smoke\ Teller=1 Smokebraider=1 Smokespew\ Invoker=1 -Smokestack=1 Smolder\ Initiate=1 -Smoldering\ Butcher=1 Smoldering\ Efreet=1 Smoldering\ Spires=1 Smoldering\ Tar=1 @@ -7806,35 +8231,31 @@ Smoldering\ Werewolf=1 Smother=1 Smothering\ Abomination=1 Snake\ Cult\ Initiation=1 +Snake\ Umbra=1 Snake\ of\ the\ Golden\ Grove=1 -Snakeform=1 Snapback=1 -Snapping\ Creeper=1 Snapping\ Drake=1 Snapping\ Gnarlid=1 Snapping\ Sailback=1 Snapping\ Thragg=1 -Snapsail\ Glider=1 Snare\ Thopter=1 -Snarling\ Undorak=1 Sneaky\ Homunculus=1 -Snow\ Fortress=1 +Snorting\ Gahr=1 Snowhorn\ Rider=1 Snubhorn\ Sentry=1 Soar=1 +Soaring\ Hope=1 Soaring\ Seacliff=1 +Soilshaper=1 Sokenzan\ Renegade=1 Sokenzan\ Spellblade=1 Sol'kanar\ the\ Swamp\ King=1 -Sol\ Grail=1 -Solar\ Blast=1 Solar\ Tide=1 Solarion=1 Soldevi\ Digger=1 Soldevi\ Golem=1 Soldevi\ Machinist=1 Soldevi\ Simulacrum=1 -Soldier\ Replica=1 Soldier\ of\ the\ Pantheon=1 Solemn\ Offering=1 Solemn\ Recruit=1 @@ -7845,7 +8266,6 @@ Solitary\ Hunter=1 Soliton=1 Soltari\ Champion=1 Soltari\ Crusader=1 -Soltari\ Emissary=1 Soltari\ Lancer=1 Soltari\ Monk=1 Soltari\ Priest=1 @@ -7854,97 +8274,106 @@ Somber\ Hoverguard=1 Somberwald\ Alpha=1 Somberwald\ Spider=1 Somberwald\ Stag=1 -Song\ of\ Blood=1 +Somnomancer=1 +Somnophore=1 +Song\ of\ Serenity=1 Songstitcher=1 +Sonic\ Seizure=1 Soot\ Imp=1 Sootfeather\ Flock=1 -Soothing\ Balm=1 Sootstoke\ Kindler=1 -Sootwalkers=1 Sophic\ Centaur=1 +Soramaro,\ First\ to\ Dream=1 +Soratami\ Cloud\ Chariot=1 Soratami\ Cloudskater=1 +Soratami\ Mindsweeper=1 Soratami\ Mirror-Guard=1 Soratami\ Mirror-Mage=1 +Soratami\ Rainshaper=1 Soratami\ Savant=1 Soratami\ Seer=1 Sorcerer's\ Strongbox=1 +Sorcerer's\ Wand=1 Sorin's\ Thirst=1 Sorin's\ Vengeance=1 Sorrow's\ Path=1 Sosuke's\ Summons=1 Sosuke,\ Son\ of\ Seshiro=1 -Soul's\ Majesty=1 +Soul's\ Fire=1 +Soul's\ Grace=1 +Soul's\ Might=1 +Soul\ Channeling=1 Soul\ Collector=1 Soul\ Conduit=1 Soul\ Exchange=1 Soul\ Feast=1 Soul\ Foundry=1 +Soul\ Kiss=1 Soul\ Link=1 Soul\ Manipulation=1 Soul\ Net=1 Soul\ Nova=1 Soul\ Ransom=1 -Soul\ Reap=1 +Soul\ Rend=1 +Soul\ Salvage=1 Soul\ Seizer=1 +Soul\ Separator=1 Soul\ Shepherd=1 Soul\ Shred=1 -Soul\ Snuffers=1 Soul\ Stair\ Expedition=1 -Soul\ Strings=1 -Soul\ Summons=1 Soul\ Swallower=1 Soul\ Tithe=1 Soul\ of\ Magma=1 Soul\ of\ the\ Rapids=1 Soulblade\ Djinn=1 Soulblast=1 -Soulbound\ Guardians=1 Soulbright\ Flamekin=1 Soulcage\ Fiend=1 Soulcatcher=1 Soulcatchers'\ Aerie=1 Souldrinker=1 +Soulgorger\ Orgg=1 Soulless\ Revival=1 Soulmender=1 Soulquake=1 Souls\ of\ the\ Faultless=1 -Soulscour=1 Soulstinger=1 Soulsworn\ Jury=1 Soulsworn\ Spirit=1 Soultether\ Golem=1 -Southern\ Elephant=1 Southern\ Paladin=1 Sowing\ Salt=1 Spare\ from\ Evil=1 Spark\ Jolt=1 +Spark\ Mage=1 Spark\ Spray=1 Spark\ Trooper=1 Spark\ of\ Creativity=1 Sparkmage's\ Gambit=1 -Sparkmage\ Apprentice=1 Sparkspitter=1 +Sparktongue\ Dragon=1 +Sparring\ Construct=1 +Sparring\ Golem=1 Sparring\ Mummy=1 -Spatial\ Contortion=1 +Spatial\ Binding=1 +Spawn\ of\ Thraxes=1 Spawnbinder\ Mage=1 Spawnbroker=1 Spawning\ Bed=1 Spawning\ Breath=1 Spawnsire\ of\ Ulamog=1 -Spawnwrithe=1 Spear\ of\ Heliod=1 Spearbreaker\ Behemoth=1 Spearpoint\ Oread=1 Species\ Gorger=1 Specter's\ Shroud=1 -Specter's\ Wail=1 Spectra\ Ward=1 Spectral\ Bears=1 Spectral\ Flight=1 -Spectral\ Gateguards=1 -Spectral\ Lynx=1 +Spectral\ Force=1 +Spectral\ Guardian=1 +Spectral\ Prison=1 Spectral\ Reserves=1 -Spectral\ Rider=1 Spectral\ Searchlight=1 Spectral\ Shepherd=1 Spectral\ Shield=1 @@ -7956,24 +8385,26 @@ Spell\ Burst=1 Spell\ Contortion=1 Spell\ Rupture=1 Spell\ Shrivel=1 -Spell\ Snip=1 +Spell\ Swindle=1 Spell\ Syphon=1 +Spellbane\ Centaur=1 +Spellbinder=1 Spellbook=1 Spellbound\ Dragon=1 Spellheart\ Chimera=1 Spellshift=1 -Spellshock=1 +Spelltithe\ Enforcer=1 Spelltwine=1 Spellweaver\ Eternal=1 -Spellwild\ Ouphe=1 -Sphere\ of\ Law=1 +Spellweaver\ Helix=1 +Sphere\ of\ Duty=1 +Sphere\ of\ Grace=1 Sphere\ of\ Purity=1 +Sphere\ of\ Reason=1 Sphere\ of\ Truth=1 Sphere\ of\ the\ Suns=1 -Sphinx's\ Decree=1 Sphinx's\ Disciple=1 Sphinx's\ Herald=1 -Sphinx's\ Tutelage=1 Sphinx-Bone\ Wand=1 Sphinx\ Summoner=1 Sphinx\ of\ Jwar\ Isle=1 @@ -7981,31 +8412,31 @@ Sphinx\ of\ Lost\ Truths=1 Sphinx\ of\ Magosi=1 Sphinx\ of\ Uthuun=1 Sphinx\ of\ the\ Chimes=1 +Spider\ Climb=1 Spider\ Spawning=1 -Spidersilk\ Net=1 -Spiderwig\ Boggart=1 Spidery\ Grasp=1 Spike-Tailed\ Ceratops=1 Spike\ Breeder=1 Spike\ Cannibal=1 Spike\ Colony=1 -Spike\ Feeder=1 +Spike\ Drone=1 Spike\ Hatcher=1 Spike\ Jester=1 Spike\ Rogue=1 Spike\ Soldier=1 Spike\ Tiller=1 +Spike\ Worker=1 Spikeshot\ Elder=1 Spikeshot\ Goblin=1 Spiketail\ Drakeling=1 Spiketail\ Hatchling=1 +Spin\ Engine=1 Spin\ into\ Myth=1 Spinal\ Graft=1 -Spinal\ Parasite=1 -Spinal\ Villain=1 Spincrusher=1 Spinebiter=1 Spined\ Basher=1 +Spined\ Fluke=1 Spined\ Sliver=1 Spined\ Thopter=1 Spined\ Wurm=1 @@ -8013,27 +8444,28 @@ Spineless\ Thug=1 Spiny\ Starfish=1 Spiraling\ Duelist=1 Spiraling\ Embers=1 -Spire\ Barrage=1 Spire\ Monitor=1 Spire\ Owl=1 Spire\ Patrol=1 -Spire\ Serpent=1 Spire\ Tracer=1 Spire\ Winder=1 Spireside\ Infiltrator=1 Spirespine=1 Spirit\ Away=1 +Spirit\ Bonds=1 Spirit\ Cairn=1 +Spirit\ Flare=1 Spirit\ Loop=1 Spirit\ Mirror=1 Spirit\ Shackle=1 Spirit\ Weaver=1 Spirit\ en-Dal=1 Spirit\ en-Kor=1 +Spirit\ of\ the\ Hearth=1 Spirit\ of\ the\ Hunt=1 Spiritmonger=1 Spiritual\ Visit=1 -Spite\ //\ Malice=1 +Spiritualize=1 Spite\ of\ Mogis=1 Spitebellows=1 Spiteflame\ Witch=1 @@ -8042,15 +8474,16 @@ Spiteful\ Bully=1 Spiteful\ Motives=1 Spiteful\ Returned=1 Spiteful\ Shadows=1 -Spitfire\ Handler=1 Spitting\ Drake=1 Spitting\ Earth=1 Spitting\ Gourna=1 Spitting\ Hydra=1 Spitting\ Sliver=1 +Spitting\ Slug=1 +Spitting\ Spider=1 Splatter\ Thug=1 Splendid\ Agony=1 -Splinter=1 +Splendid\ Reclamation=1 Splinterfright=1 Split-Tail\ Miko=1 Splitting\ Headache=1 @@ -8061,9 +8494,10 @@ Spontaneous\ Combustion=1 Spontaneous\ Mutation=1 Spore\ Burst=1 Spore\ Cloud=1 -Spore\ Flower=1 +Spore\ Swarm=1 Sporeback\ Troll=1 -Sporemound=1 +Sporecap\ Spider=1 +Sporecrown\ Thallid=1 Sporesower\ Thallid=1 Sporoloth\ Ancient=1 Spotted\ Griffin=1 @@ -8071,7 +8505,6 @@ Spread\ the\ Sickness=1 Spreading\ Algae=1 Spreading\ Flames=1 Spreading\ Rot=1 -Spring\ //\ Mind=1 Spring\ Cleaning=1 Springing\ Tiger=1 Springsage\ Ritual=1 @@ -8079,33 +8512,31 @@ Sprinting\ Warbrute=1 Sprite\ Noble=1 Sprout=1 Sprouting\ Thrinax=1 -Spur\ Grappler=1 Spurnmage\ Advocate=1 Spurred\ Wolverine=1 +Spy\ Network=1 +Squadron\ Hawk=1 Squall=1 Squall\ Drifter=1 Squall\ Line=1 -Squallmonger=1 Squeaking\ Pie\ Grubfellows=1 Squeaking\ Pie\ Sneak=1 Squealing\ Devil=1 -Squee's\ Embrace=1 +Squee's\ Toy=1 +Squee,\ the\ Immortal=1 Squelch=1 Squelching\ Leeches=1 Squire's\ Devotion=1 Squire=1 Squirming\ Mass=1 Stab\ Wound=1 -Stabbing\ Pain=1 Stabilizer=1 -Staff\ of\ Zegon=1 Staff\ of\ the\ Death\ Magus=1 Staff\ of\ the\ Flame\ Magus=1 Staff\ of\ the\ Mind\ Magus=1 Staff\ of\ the\ Sun\ Magus=1 Staff\ of\ the\ Wild\ Magus=1 Stag\ Beetle=1 -Staggershock=1 Stalker\ Hag=1 Stalking\ Assassin=1 Stalking\ Bloodsucker=1 @@ -8113,22 +8544,25 @@ Stalking\ Drone=1 Stalking\ Stones=1 Stalking\ Tiger=1 Stalking\ Yeti=1 -Stallion\ of\ Ashmouth=1 Stalwart\ Aven=1 Stalwart\ Shield-Bearers=1 +Stamina=1 +Stampede=1 Stampeding\ Elk\ Herd=1 Stampeding\ Horncrest=1 Stampeding\ Rhino=1 -Stampeding\ Serow=1 Stampeding\ Wildebeests=1 Stand\ //\ Deliver=1 +Stand\ Firm=1 Stand\ Together=1 +Standardize=1 Standing\ Troops=1 Stangg=1 +Star-Crowned\ Stag=1 +Star\ Compass=1 Starlight=1 Starlight\ Invoker=1 Starlit\ Sanctum=1 -Starstorm=1 Start\ //\ Finish=1 Start\ Your\ Engines=1 Starved\ Rusalka=1 @@ -8145,16 +8579,21 @@ Steadfast\ Guard=1 Steadfast\ Sentinel=1 Steady\ Progress=1 Steal\ Artifact=1 -Steal\ Enchantment=1 +Steal\ Strength=1 Stealer\ of\ Secrets=1 Steam\ Augury=1 Steam\ Blast=1 Steam\ Catapult=1 Steam\ Spitter=1 +Steam\ Vines=1 +Steamclaw=1 +Steamcore\ Weird=1 +Steamflogger\ Boss=1 Steel\ Golem=1 -Steel\ Wall=1 +Steel\ Leaf\ Paladin=1 +Steel\ Sabotage=1 Steelclad\ Serpent=1 -Steelform\ Sliver=1 +Steeling\ Stance=1 Steelshaper\ Apprentice=1 Steeple\ Roc=1 Stenchskipper=1 @@ -8163,12 +8602,13 @@ Stensia\ Bloodhall=1 Stensia\ Innkeeper=1 Stensia\ Masquerade=1 Steppe\ Glider=1 -Steppe\ Lynx=1 Stern\ Constable=1 +Stern\ Judge=1 Stern\ Mentor=1 Stern\ Proctor=1 Steward\ of\ Solidarity=1 Steward\ of\ Valeron=1 +Still\ Life=1 Stingerfling\ Spider=1 Stinging\ Licid=1 Stinging\ Shot=1 @@ -8182,7 +8622,6 @@ Stitch\ in\ Time=1 Stitched\ Drake=1 Stitched\ Mangler=1 Stitcher's\ Apprentice=1 -Stitcher's\ Graft=1 Stitchwing\ Skaab=1 Stoic\ Angel=1 Stoic\ Builder=1 @@ -8192,33 +8631,31 @@ Stoke\ the\ Flames=1 Stolen\ Goods=1 Stolen\ Grain=1 Stolen\ Identity=1 -Stomp\ and\ Howl=1 Stomper\ Cub=1 Stomping\ Slabs=1 +Stone-Seeder\ Hierophant=1 Stone-Tongue\ Basilisk=1 Stone\ Calendar=1 Stone\ Giant=1 -Stone\ Golem=1 Stone\ Haven\ Medic=1 Stone\ Haven\ Outfitter=1 Stone\ Idol\ Trap=1 Stone\ Quarry=1 +Stone\ Spirit=1 Stonebrow,\ Krosan\ Hero=1 Stonecloaker=1 Stoneforge\ Acolyte=1 -Stoneforge\ Masterwork=1 Stonefury=1 Stonehands=1 Stonehewer\ Giant=1 Stoneshaker\ Shaman=1 +Stoneshock\ Giant=1 Stonewise\ Fortifier=1 Stonewood\ Invocation=1 -Stonewood\ Invoker=1 Stonework\ Puma=1 Stonewright=1 Stonybrook\ Angler=1 Stonybrook\ Schoolmaster=1 -Storage\ Matrix=1 Storm\ Crow=1 Storm\ Elemental=1 Storm\ Entity=1 @@ -8234,25 +8671,28 @@ Storm\ Sculptor=1 Storm\ Seeker=1 Storm\ Shaman=1 Storm\ Spirit=1 +Storm\ the\ Vault=1 Stormblood\ Berserker=1 Stormchaser\ Chimera=1 -Stormcloud\ Djinn=1 -Stormcrag\ Elemental=1 Stormfront\ Pegasus=1 Stormfront\ Riders=1 Stormrider\ Rig=1 Stormrider\ Spirit=1 Stormscale\ Anarch=1 +Stormscape\ Apprentice=1 Stormscape\ Battlemage=1 Stormscape\ Familiar=1 Stormtide\ Leviathan=1 Stormwatch\ Eagle=1 Stormwing\ Dragon=1 -Strafe=1 +Strands\ of\ Night=1 Strandwalker=1 Strange\ Augmentation=1 Strangling\ Soot=1 +Strangling\ Spores=1 Strata\ Scythe=1 +Stratadon=1 +Stratozeppelid=1 Stratus\ Walk=1 Straw\ Golem=1 Stream\ Hopper=1 @@ -8262,50 +8702,62 @@ Stream\ of\ Unconsciousness=1 Streambed\ Aquitects=1 Street\ Savvy=1 Street\ Spasm=1 +Street\ Sweeper=1 Streetbreaker\ Wurm=1 Strength\ from\ the\ Fallen=1 Strength\ in\ Numbers=1 Strength\ of\ Arms=1 +Strength\ of\ Isolation=1 +Strength\ of\ Lunacy=1 Strength\ of\ Night=1 +Strength\ of\ Unity=1 Strength\ of\ the\ Pack=1 Strength\ of\ the\ Tajuru=1 Strider\ Harness=1 -Stroke\ of\ Genius=1 -Stromgald\ Cabal=1 -Stromkirk\ Condemned=1 +Strip\ Bare=1 +Striped\ Riverwinder=1 Stromkirk\ Mentor=1 +Stromkirk\ Noble=1 Stromkirk\ Occultist=1 -Stromkirk\ Patrol=1 Strongarm\ Monk=1 Strongarm\ Tactics=1 +Strongarm\ Thug=1 +Stronghold\ Assassin=1 +Stronghold\ Biologist=1 +Stronghold\ Confessor=1 Stronghold\ Discipline=1 +Stronghold\ Machinist=1 Stronghold\ Overseer=1 Stronghold\ Rats=1 +Stronghold\ Taskmaster=1 +Stronghold\ Zeppelin=1 Structural\ Collapse=1 Structural\ Distortion=1 -Struggle\ //\ Survive=1 Struggle\ for\ Sanity=1 +Student\ of\ Elements=1 Student\ of\ Ojutai=1 Stuffy\ Doll=1 Stun=1 Stun\ Sniper=1 +Stunted\ Growth=1 Stupefying\ Touch=1 Sturdy\ Hatchling=1 Sturmgeist=1 Stymied\ Hopes=1 -Su-Chi=1 -Subterranean\ Shambler=1 +Subjugator\ Angel=1 +Submerged\ Boneyard=1 +Subterranean\ Scout=1 Subtle\ Strike=1 Succumb\ to\ Temptation=1 Sudden\ Death=1 Sudden\ Disappearance=1 Sudden\ Impact=1 -Sudden\ Reclamation=1 Sudden\ Spoiling=1 Sudden\ Storm=1 Sudden\ Strength=1 Suffer\ the\ Past=1 Suicidal\ Charge=1 +Sulam\ Djinn=1 Sulfur\ Elemental=1 Sulfuric\ Vapors=1 Sulfurous\ Blast=1 @@ -8313,42 +8765,44 @@ Sultai\ Ascendancy=1 Sultai\ Banner=1 Sultai\ Charm=1 Sultai\ Flayer=1 -Sultai\ Runemark=1 -Sultai\ Skullkeeper=1 +Sultai\ Scavenger=1 Sultai\ Soothsayer=1 Summary\ Dismissal=1 Summit\ Apes=1 Summit\ Prowler=1 Summon\ the\ School=1 Summoner's\ Bane=1 +Summoner's\ Egg=1 Summoning\ Station=1 -Summoning\ Trap=1 Sun's\ Bounty=1 Sun-Collared\ Raptor=1 Sun-Crested\ Pterodon=1 Sun-Crowned\ Hunters=1 -Sun\ Clasp=1 Sun\ Sentinel=1 Sunastian\ Falconer=1 Sunbeam\ Spellbomb=1 +Sunbird's\ Invocation=1 Sunblade\ Elf=1 +Sunblast\ Angel=1 Sunbond=1 Sunbringer's\ Touch=1 Suncrusher=1 Sunder\ from\ Within=1 Sundering\ Growth=1 Sundering\ Vitae=1 +Sunfire\ Balm=1 Sunflare\ Shaman=1 Sunforger=1 Sungrace\ Pegasus=1 -Sunhome,\ Fortress\ of\ the\ Legion=1 +Sungrass\ Egg=1 Sunhome\ Enforcer=1 Sunhome\ Guildmage=1 Sunken\ City=1 Sunken\ Hope=1 +Sunlance=1 Sunrise\ Seeker=1 Sunrise\ Sovereign=1 -Sunscape\ Battlemage=1 +Sunscape\ Apprentice=1 Sunscorched\ Desert=1 Sunseed\ Nurturer=1 Sunset\ Pyramid=1 @@ -8360,11 +8814,14 @@ Sunstrike\ Legionnaire=1 Suntail\ Hawk=1 Suntouched\ Myr=1 Sunweb=1 +Superior\ Numbers=1 Supernatural\ Stamina=1 Supply\ //\ Demand=1 Supply\ Caravan=1 +Suppress=1 Suppression\ Bonds=1 Supreme\ Exemplar=1 +Supreme\ Inquisitor=1 Suq'Ata\ Assassin=1 Suq'Ata\ Lancer=1 Sure\ Strike=1 @@ -8373,13 +8830,14 @@ Surge\ Node=1 Surge\ of\ Righteousness=1 Surge\ of\ Thoughtweft=1 Surge\ of\ Zeal=1 -Surging\ Dementia=1 +Surgespanner=1 Surging\ Flame=1 Surging\ Might=1 Surging\ Sentinels=1 Surprise\ Deployment=1 -Surrakar\ Marauder=1 +Surrakar\ Banisher=1 Surrakar\ Spellblade=1 +Surreal\ Memoir=1 Surveilling\ Sprite=1 Survey\ the\ Wreckage=1 Survival\ Cache=1 @@ -8390,14 +8848,14 @@ Suspension\ Field=1 Suture\ Spirit=1 Sutured\ Ghoul=1 Svogthos,\ the\ Restless\ Tomb=1 -Swab\ Goblin=1 +Svyelunite\ Temple=1 Swaggering\ Corsair=1 +Swallowing\ Plague=1 Swamp=1 Swamp\ Mosquito=1 Swarm\ Intelligence=1 Swarm\ Surge=1 Swarm\ of\ Bloodflies=1 -Swarm\ of\ Rats=1 Swarmborn\ Giant=1 Swashbuckling=1 Swat=1 @@ -8407,6 +8865,7 @@ Sweatworks\ Brawler=1 Sweep\ Away=1 Swell\ of\ Courage=1 Swell\ of\ Growth=1 +Swelter=1 Swerve=1 Swift\ Justice=1 Swift\ Kick=1 @@ -8418,45 +8877,47 @@ Swift\ Warkite=1 Swirl\ the\ Mists=1 Swirling\ Spriggan=1 Switcheroo=1 -Swooping\ Talon=1 Sword-Point\ Diplomacy=1 Sword\ Dancer=1 -Sword\ of\ Kaldra=1 -Sword\ of\ the\ Ages=1 Swordwise\ Centaur=1 Sworn\ Guardian=1 Sygg,\ River\ Guide=1 +Sylvan\ Awakening=1 Sylvan\ Basilisk=1 Sylvan\ Bounty=1 Sylvan\ Echoes=1 -Sylvan\ Hierophant=1 Sylvan\ Messenger=1 Sylvan\ Might=1 Sylvan\ Primordial=1 Sylvan\ Ranger=1 +Sylvok\ Explorer=1 Sylvok\ Replica=1 Symbiosis=1 +Symbiotic\ Deployment=1 Symbiotic\ Wurm=1 -Symbol\ of\ Unsummoning=1 Synchronized\ Strike=1 Synchronous\ Sliver=1 Syncopate=1 Syndic\ of\ Tithes=1 Syndicate\ Enforcer=1 +Syndicate\ Trafficker=1 +Synod\ Artificer=1 Synod\ Centurion=1 Synod\ Sanctum=1 +Syphon\ Soul=1 Szadek,\ Lord\ of\ Secrets=1 +Sance=1 Tablet\ of\ Epityr=1 Tablet\ of\ the\ Guilds=1 Tah-Crop\ Elite=1 Tah-Crop\ Skirmisher=1 +Tahngarth's\ Glare=1 Tahngarth's\ Rage=1 Taigam's\ Scheming=1 Taigam's\ Strike=1 Tail\ Slash=1 Tainted\ Remedy=1 -Tainted\ Specter=1 -Tainted\ Strike=1 +Tainted\ Sigil=1 Taj-Nar\ Swordsmith=1 Tajic,\ Blade\ of\ the\ Legion=1 Tajuru\ Archer=1 @@ -8468,9 +8929,8 @@ Tajuru\ Warcaller=1 Take\ Down=1 Take\ Inventory=1 Take\ Possession=1 -Take\ Up\ Arms=1 +Take\ Vengeance=1 Take\ into\ Custody=1 -Takeno's\ Cavalry=1 Takeno,\ Samurai\ General=1 Takenuma\ Bleeder=1 Takklemaggot=1 @@ -8478,12 +8938,12 @@ Talas\ Researcher=1 Talent\ of\ the\ Telepath=1 Talisman\ of\ Impulse=1 Talisman\ of\ Unity=1 -Tallowisp=1 Talon\ Trooper=1 Talon\ of\ Pain=1 Talonrend=1 Talrand's\ Invocation=1 Talruum\ Champion=1 +Talruum\ Minotaur=1 Talruum\ Piper=1 Talus\ Paladin=1 Tamiyo's\ Journal=1 @@ -8493,138 +8953,130 @@ Tangle=1 Tangle\ Angler=1 Tangle\ Asp=1 Tangle\ Golem=1 -Tangle\ Hulk=1 Tangle\ Mantis=1 Tangle\ Spider=1 Tanglebloom=1 Tangleclaw\ Werewolf=1 Tangleroot=1 +Tanglesap=1 Tanglewalker=1 Tapestry\ of\ the\ Ages=1 Tar\ Fiend=1 Tar\ Pit\ Warrior=1 -Tar\ Pitcher=1 -Tar\ Snare=1 -Tarox\ Bladewing=1 -Tasigur's\ Cruelty=1 Tasseled\ Dromedary=1 Taste\ for\ Mayhem=1 -Taste\ of\ Blood=1 Tatsumasa,\ the\ Dragon's\ Fang=1 +Tattered\ Drake=1 Tattered\ Haunter=1 Tatterkite=1 Tattermunge\ Duo=1 Tattermunge\ Maniac=1 Tattermunge\ Witch=1 -Taunting\ Elf=1 -Tavern\ Swindler=1 +Tatyova,\ Benthic\ Druid=1 Tawnos's\ Coffin=1 Tawnos's\ Wand=1 Teardrop\ Kami=1 -Tears\ of\ Rage=1 Tears\ of\ Valakut=1 Tectonic\ Rift=1 -Teetering\ Peaks=1 -Teferi's\ Drake=1 +Teferi's\ Care=1 Teferi's\ Honor\ Guard=1 -Teferi's\ Moat=1 Tel-Jilad\ Archers=1 Tel-Jilad\ Chosen=1 Tel-Jilad\ Defiance=1 Tel-Jilad\ Fallen=1 -Tel-Jilad\ Justice=1 +Tel-Jilad\ Lifebreather=1 Tel-Jilad\ Outrider=1 +Tel-Jilad\ Stylus=1 +Tel-Jilad\ Wolf=1 +Telekinetic\ Bonds=1 Telekinetic\ Sliver=1 Telemin\ Performance=1 Telepathic\ Spies=1 Telepathy=1 Teleportal=1 -Telethopter=1 Telim'Tor's\ Darts=1 +Telim'Tor=1 Teller\ of\ Tales=1 Telling\ Time=1 Temmet,\ Vizier\ of\ Naktamun=1 +Temper=1 Tempest\ Caller=1 Tempest\ Drake=1 Tempest\ of\ Light=1 Temple\ Acolyte=1 Temple\ Altisaur=1 -Temple\ of\ Mystery=1 Temporal\ Adept=1 Temporal\ Cascade=1 Temporal\ Distortion=1 -Temporal\ Eddy=1 Temporal\ Fissure=1 Temporal\ Isolation=1 Tempting\ Licid=1 +Tempting\ Wurm=1 Temur\ Ascendancy=1 Temur\ Banner=1 Temur\ Charger=1 Temur\ Charm=1 -Temur\ Runemark=1 -Temur\ War\ Shaman=1 Tenacious\ Dead=1 Tenacious\ Hunter=1 Tenacity=1 -Tendrils\ of\ Agony=1 Teneb,\ the\ Harvester=1 +Tenement\ Crasher=1 Tenza,\ Godo's\ Maul=1 Tephraderm=1 Terashi's\ Cry=1 Terashi's\ Grasp=1 Terashi's\ Verdict=1 Teremko\ Griffin=1 -Terminal\ Moraine=1 -Teroh's\ Faithful=1 +Teroh's\ Vanguard=1 Terra\ Eternal=1 Terra\ Stomper=1 Terraformer=1 Terrarion=1 -Terrifying\ Presence=1 Territorial\ Baloth=1 +Territorial\ Gorger=1 Territorial\ Hammerskull=1 Terror=1 Terror\ of\ the\ Fairgrounds=1 Terrus\ Wurm=1 +Teshar,\ Ancestor's\ Apostle=1 Test\ of\ Faith=1 +Testament\ of\ Faith=1 Tethered\ Skirge=1 Tethmos\ High\ Priest=1 +Tetsuko\ Umezawa,\ Fugitive=1 +Teysa,\ Envoy\ of\ Ghosts=1 Tezzeret's\ Ambition=1 Tezzeret's\ Gambit=1 Tezzeret's\ Touch=1 -Thalakos\ Dreamsower=1 +Thada\ Adel,\ Acquisitor=1 Thalakos\ Drifters=1 +Thalakos\ Lowlands=1 Thalakos\ Mistfolk=1 -Thalakos\ Scout=1 Thalakos\ Seer=1 Thalia's\ Lancers=1 Thallid=1 -Thallid\ Devourer=1 Thallid\ Germinator=1 +Thallid\ Omnivore=1 Thallid\ Shell-Dweller=1 +Thallid\ Soothsayer=1 Thassa's\ Bounty=1 Thassa's\ Devourer=1 Thassa's\ Emissary=1 Thassa's\ Ire=1 Thassa's\ Rebuff=1 -That\ Which\ Was\ Taken=1 -Thaumatic\ Compass=1 -Thawing\ Glaciers=1 -The\ Fallen=1 +The\ First\ Eruption=1 The\ Hive=1 The\ Lady\ of\ the\ Mountain=1 +The\ Mending\ of\ Dominaria=1 The\ Unspeakable=1 The\ Wretched=1 Theft\ of\ Dreams=1 -Thelon\ of\ Havenwood=1 Thelonite\ Druid=1 -Thelonite\ Hermit=1 -Thermal\ Navigator=1 +Thermal\ Flux=1 Thermopod=1 Thick-Skinned\ Goblin=1 -Thicket\ Basilisk=1 Thief\ of\ Hope=1 -Thieves'\ Auction=1 +Thieves'\ Fortune=1 Thieving\ Magpie=1 Thieving\ Sprite=1 Thing\ from\ the\ Deep=1 @@ -8632,54 +9084,55 @@ Think\ Tank=1 Thirst=1 Thirsting\ Axe=1 Thistledown\ Duo=1 -Thopter\ Assembly=1 +Thopter\ Arrest=1 Thopter\ Engineer=1 Thopter\ Spy\ Network=1 Thopter\ Squadron=1 Thorn-Thrash\ Viashino=1 Thorn\ Elemental=1 -Thorn\ Thallid=1 Thornbite\ Staff=1 Thornbow\ Archer=1 -Thorncaster\ Sliver=1 Thorned\ Moloch=1 Thornhide\ Wolves=1 +Thornscape\ Apprentice=1 Thornscape\ Battlemage=1 Thornscape\ Master=1 Thorntooth\ Witch=1 Thornweald\ Archer=1 +Thornwind\ Faeries=1 +Thornwood\ Falls=1 Those\ Who\ Serve=1 Thought\ Courier=1 Thought\ Devourer=1 Thought\ Dissector=1 Thought\ Eater=1 +Thought\ Gorger=1 Thought\ Harvester=1 Thought\ Hemorrhage=1 Thought\ Prison=1 -Thoughtcutter\ Agent=1 +Thought\ Reflection=1 +Thoughtbind=1 +Thoughtbound\ Primoc=1 Thoughtflare=1 +Thoughtleech=1 Thoughtpicker\ Witch=1 Thoughtrender\ Lamia=1 Thoughts\ of\ Ruin=1 -Thoughtweft\ Gambit=1 -Thoughtweft\ Trio=1 Thousand-legged\ Kami=1 Thousand\ Winds=1 Thraben\ Foulbloods=1 Thraben\ Gargoyle=1 -Thraben\ Purebloods=1 Thraben\ Sentry=1 Thraben\ Standard\ Bearer=1 Thran\ Forge=1 +Thran\ Foundry=1 Thran\ Golem=1 -Thran\ Lens=1 -Thran\ Turbine=1 +Thran\ Temporal\ Gateway=1 Thran\ Weaponry=1 Thrash\ of\ Raptors=1 Thrashing\ Mossdog=1 Threaten=1 Three\ Dreams=1 -Three\ Tragedies=1 Thresher\ Lizard=1 Thrill-Kill\ Assassin=1 Thrill\ of\ the\ Hunt=1 @@ -8691,14 +9144,11 @@ Thriving\ Rats=1 Thriving\ Rhino=1 Thriving\ Turtle=1 Throat\ Slitter=1 -Throne\ Warden=1 Throne\ of\ Bone=1 Throne\ of\ Empires=1 -Throne\ of\ Geth=1 Throne\ of\ the\ God-Pharaoh=1 Throttle=1 Throwing\ Knife=1 -Thrull\ Champion=1 Thrull\ Parasite=1 Thrull\ Retainer=1 Thrull\ Surgeon=1 @@ -8707,64 +9157,61 @@ Thumbscrews=1 Thunder-Thrash\ Elder=1 Thunder\ Brute=1 Thunder\ Spirit=1 -Thunder\ Strike=1 Thunder\ Totem=1 -Thunder\ Wall=1 Thunder\ of\ Hooves=1 Thunderblade\ Charge=1 Thunderblust=1 Thunderbolt=1 -Thunderclap=1 Thunderclap\ Wyvern=1 +Thundercloud\ Elemental=1 Thundercloud\ Shaman=1 Thunderheads=1 +Thunderherd\ Migration=1 Thundering\ Giant=1 Thundering\ Spineback=1 Thundering\ Tanadon=1 Thundermare=1 Thunderous\ Might=1 -Thunderous\ Wrath=1 +Thunderscape\ Battlemage=1 Thundersong\ Trumpeter=1 Thunderstaff=1 +Tiana,\ Ship's\ Caretaker=1 Tibor\ and\ Lumia=1 -Ticking\ Gnomes=1 -Tidal\ Bore=1 -Tidal\ Courier=1 -Tidal\ Kraken=1 -Tidal\ Surge=1 +Tidal\ Visionary=1 Tidal\ Wave=1 Tide\ Drifter=1 Tide\ of\ War=1 Tideforce\ Elemental=1 +Tidehollow\ Strix=1 Tideshaper\ Mystic=1 Tidewalker=1 Tidewater\ Minion=1 Tidings=1 Tidy\ Conclusion=1 Tiger\ Claws=1 +Tigereye\ Cameo=1 Tightening\ Coils=1 Tilonalli's\ Crown=1 Tilonalli's\ Knight=1 Tilonalli's\ Skinshifter=1 Timber\ Gorge=1 +Timberland\ Ruins=1 Timbermare=1 +Timbermaw\ Larva=1 Timberpack\ Wolf=1 Time\ Bomb=1 Time\ Ebb=1 Time\ Stop=1 Time\ and\ Tide=1 Time\ of\ Heroes=1 -Time\ of\ Need=1 +Time\ of\ Ice=1 Time\ to\ Feed=1 Time\ to\ Reflect=1 Timebender=1 Timecrafting=1 Timely\ Hordemate=1 -Timesifter=1 Timid\ Drake=1 Tin-Wing\ Chimera=1 -Tin\ Street\ Hooligan=1 -Tin\ Street\ Market=1 Tine\ Shrike=1 Tireless\ Missionaries=1 Tishana's\ Wayfinder=1 @@ -8777,6 +9224,7 @@ Titania's\ Boon=1 Titania's\ Chosen=1 Titanic\ Bulvox=1 Titanic\ Growth=1 +Titanic\ Ultimatum=1 Titanium\ Golem=1 Tivadar's\ Crusade=1 Tivadar\ of\ Thorn=1 @@ -8787,28 +9235,29 @@ Toil\ //\ Trouble=1 Toil\ to\ Renown=1 Toils\ of\ Night\ and\ Day=1 Tolarian\ Drake=1 +Tolarian\ Emissary=1 +Tolarian\ Scholar=1 Tolarian\ Sentinel=1 Tolarian\ Serpent=1 Tolsimir\ Wolfblood=1 Tomb\ Robber=1 +Tomb\ of\ Urami=1 Tomb\ of\ the\ Spirit\ Dragon=1 -Tombfire=1 +Tome\ Scour=1 Tomorrow,\ Azami's\ Familiar=1 +Toolcraft\ Exemplar=1 Tooth\ Collector=1 Tooth\ and\ Claw=1 Tooth\ of\ Chiss-Goria=1 Topan\ Ascetic=1 Topan\ Freeblade=1 -Topple=1 Topplegeist=1 Tor\ Wauki=1 Torch\ Fiend=1 Torch\ Gauntlet=1 -Torch\ Slinger=1 Torch\ Song=1 Torchling=1 -Torii\ Watchward=1 -Torment=1 +Torgaar,\ Famine\ Incarnate=1 Torment\ of\ Scarabs=1 Torment\ of\ Venom=1 Tormented\ Angel=1 @@ -8818,18 +9267,25 @@ Tormented\ Soul=1 Tormented\ Thoughts=1 Tormenting\ Voice=1 Tormentor\ Exarch=1 +Tornado=1 Tornado\ Elemental=1 +Torpid\ Moloch=1 Torpor\ Dust=1 Torrent\ of\ Fire=1 Torrent\ of\ Souls=1 Torrent\ of\ Stone=1 Torsten\ Von\ Ursus=1 Tortoise\ Formation=1 -Torture\ Chamber=1 +Torture=1 +Toshiro\ Umezawa=1 +Totally\ Lost=1 Totem-Guide\ Hartebeest=1 +Totem\ Speaker=1 +Touch\ of\ Invisibility=1 Touch\ of\ Moonglove=1 Touch\ of\ the\ Eternal=1 Touch\ of\ the\ Void=1 +Touchstone=1 Tower\ Above=1 Tower\ Defense=1 Tower\ Drake=1 @@ -8843,11 +9299,7 @@ Tower\ of\ Murmurs=1 Towering\ Baloth=1 Towering\ Indrik=1 Town\ Gossipmonger=1 -Toxic\ Iguanar=1 Toxic\ Nim=1 -Trace\ of\ Abundance=1 -Tracker's\ Instincts=1 -Tracker=1 Trade\ Routes=1 Trade\ Secrets=1 Tradewind\ Rider=1 @@ -8857,20 +9309,18 @@ Tragic\ Poet=1 Trail\ of\ Evidence=1 Trail\ of\ Mystery=1 Trailblazer's\ Boots=1 -Train\ of\ Thought=1 Trained\ Armodon=1 Trained\ Caracal=1 Trained\ Orgg=1 -Training\ Drone=1 +Trained\ Pronghorn=1 Trait\ Doctoring=1 Traitor's\ Clutch=1 -Traitor's\ Roar=1 Traitorous\ Blood=1 Traitorous\ Instinct=1 Tranquil\ Cove=1 Tranquil\ Expanse=1 Tranquil\ Garden=1 -Tranquil\ Path=1 +Transcendence=1 Transgress\ the\ Mind=1 Transguild\ Courier=1 Transguild\ Promenade=1 @@ -8879,36 +9329,36 @@ Transmogrifying\ Licid=1 Trap\ Digger=1 Trap\ Essence=1 Trapjaw\ Kelpie=1 -Traproot\ Kami=1 +Trapmaker's\ Snare=1 Traumatize=1 Travel\ Preparations=1 Traveler's\ Amulet=1 Traveling\ Plague=1 -Treacherous\ Link=1 Treacherous\ Urge=1 +Treacherous\ Werewolf=1 Tread\ Upon=1 Treasure\ Cruise=1 +Treasure\ Hunter=1 Treasure\ Keeper=1 Treasure\ Trove=1 Treasured\ Find=1 Treasury\ Thrull=1 Tree\ Monkey=1 -Treefolk\ Harbinger=1 +Treefolk\ Healer=1 Treefolk\ Mystic=1 Treefolk\ Seedlings=1 Treespring\ Lorian=1 -Treetop\ Bracers=1 +Treetop\ Rangers=1 Treetop\ Sentinel=1 Tremor=1 Trench\ Wurm=1 +Trenching\ Steed=1 Trepanation\ Blade=1 Trespasser's\ Curse=1 Trespasser\ il-Vec=1 -Trespassing\ Souleater=1 -Tresserhorn\ Sinks=1 Tresserhorn\ Skyknight=1 Trestle\ Troll=1 -Treva's\ Ruins=1 +Treva's\ Attendant=1 Triad\ of\ Fates=1 Trial\ //\ Error=1 Trial\ of\ Ambition=1 @@ -8917,18 +9367,19 @@ Trial\ of\ Solidarity=1 Trial\ of\ Strength=1 Trial\ of\ Zeal=1 Triangle\ of\ War=1 +Triassic\ Egg=1 Tribal\ Flames=1 -Tribal\ Forcemage=1 +Tribal\ Golem=1 Tribal\ Unity=1 Tribute\ to\ Hunger=1 Tribute\ to\ the\ Wild=1 +Trickbind=1 Trickery\ Charm=1 Tricks\ of\ the\ Trade=1 +Trickster\ Mage=1 Triclopean\ Sight=1 +Trigon\ of\ Corruption=1 Trigon\ of\ Infestation=1 -Trigon\ of\ Mending=1 -Trigon\ of\ Rage=1 -Trigon\ of\ Thought=1 Trip\ Noose=1 Trip\ Wire=1 Triskaidekaphobia=1 @@ -8939,18 +9390,20 @@ Triton\ Fortune\ Hunter=1 Triton\ Shorethief=1 Triton\ Tactics=1 Triumph\ of\ Ferocity=1 +Triumph\ of\ Gerrard=1 Troll-Horn\ Cameo=1 -Troll\ Ascetic=1 -Trolls\ of\ Tel-Jilad=1 Tromokratis=1 Tromp\ the\ Domains=1 Trophy\ Hunter=1 Trophy\ Mage=1 +Tropical\ Storm=1 Trostani's\ Judgment=1 Trostani's\ Summoner=1 Troubled\ Healer=1 +Troublesome\ Spirit=1 Trove\ of\ Temptation=1 True-Faith\ Censer=1 +True\ Believer=1 True\ Conviction=1 Truefire\ Paladin=1 Trueheart\ Duelist=1 @@ -8961,14 +9414,15 @@ Trusted\ Advisor=1 Trusted\ Forcemage=1 Trusty\ Companion=1 Trusty\ Machete=1 +Trusty\ Packbeast=1 Truth\ or\ Tale=1 Trygon\ Predator=1 Tukatongue\ Thallid=1 -Tuknir\ Deathlock=1 Tuktuk\ Grunts=1 Tuktuk\ Scrapper=1 Tuktuk\ the\ Explorer=1 Tumble\ Magnet=1 +Tundra\ Kavu=1 Tunnel\ Vision=1 Tunneling\ Geopede=1 Turbulent\ Dreams=1 @@ -8977,9 +9431,10 @@ Turn\ Against=1 Turn\ Aside=1 Turn\ the\ Tables=1 Turn\ the\ Tide=1 +Turn\ to\ Dust=1 Turn\ to\ Frog=1 Turn\ to\ Mist=1 -Turnabout=1 +Turn\ to\ Slag=1 Turntimber\ Basilisk=1 Turntimber\ Grove=1 Turntimber\ Ranger=1 @@ -8987,11 +9442,11 @@ Turtleshell\ Changeling=1 Tusked\ Colossodon=1 Tuskguard\ Captain=1 Twiddle=1 +Twigwalker=1 +Twilight\ Drover=1 Twilight\ Shepherd=1 -Twin\ Bolt=1 Twinblade\ Slasher=1 Twincast=1 -Twinflame=1 Twinning\ Glass=1 Twins\ of\ Maurer\ Estate=1 Twinstrike=1 @@ -9000,13 +9455,15 @@ Twisted\ Abomination=1 Twisted\ Image=1 Twitch=1 Two-Headed\ Cerberus=1 +Two-Headed\ Dragon=1 +Two-Headed\ Giant=1 Two-Headed\ Giant\ of\ Foriys=1 Two-Headed\ Sliver=1 +Two-Headed\ Zombie=1 Tymaret,\ the\ Murder\ King=1 Typhoid\ Rats=1 Tyrannize=1 Tyrant's\ Choice=1 -Tyrant's\ Machine=1 Tyrant\ of\ Valakut=1 Tyrranax=1 Uba\ Mask=1 @@ -9017,11 +9474,11 @@ Uktabi\ Drake=1 Uktabi\ Efreet=1 Uktabi\ Faerie=1 Uktabi\ Orangutan=1 +Uktabi\ Wildcats=1 Ukud\ Cobra=1 Ulamog's\ Despoiler=1 Ulamog's\ Nullifier=1 Ulamog's\ Reclaimer=1 -Ulasht,\ the\ Hate\ Seed=1 Ulcerate=1 Ulrich's\ Kindred=1 Ultimate\ Price=1 @@ -9042,11 +9499,12 @@ Unbridled\ Growth=1 Unburden=1 Uncaged\ Fury=1 Unchecked\ Growth=1 -Uncle\ Istvan=1 +Uncomfortable\ Chill=1 Uncontrollable\ Anger=1 Unconventional\ Tactics=1 Uncovered\ Clues=1 Undead\ Alchemist=1 +Undead\ Gladiator=1 Undead\ Leotau=1 Undead\ Minotaur=1 Undead\ Servant=1 @@ -9057,11 +9515,13 @@ Undercity\ Shade=1 Undercity\ Troll=1 Undergrowth\ Scavenger=1 Underhanded\ Designs=1 +Undertaker=1 Underworld\ Coinsmith=1 -Underworld\ Dreams=1 Undo=1 -Undying\ Flames=1 Undying\ Rage=1 +Unerring\ Sling=1 +Unesh,\ Criosphinx\ Sovereign=1 +Unexpected\ Results=1 Unflinching\ Courage=1 Unforge=1 Unfriendly\ Fire=1 @@ -9074,62 +9534,68 @@ Uninvited\ Geist=1 Unity\ of\ Purpose=1 Universal\ Solvent=1 Unknown\ Shores=1 -Unlicensed\ Disintegration=1 Unliving\ Psychopath=1 Unmake\ the\ Graves=1 Unnatural\ Aggression=1 Unnatural\ Endurance=1 Unnatural\ Predation=1 -Unnatural\ Speed=1 -Unnerve=1 Unnerving\ Assault=1 Unquenchable\ Thirst=1 Unravel\ the\ Aether=1 Unraveling\ Mummy=1 Unruly\ Mob=1 -Unscythe,\ Killer\ of\ Kings=1 Unstable\ Footing=1 Unstable\ Frontier=1 Unstable\ Hulk=1 Unstoppable\ Ash=1 -Unsubstantiate=1 Unsummon=1 Untamed\ Hunger=1 +Untamed\ Kavu=1 Untamed\ Might=1 Untamed\ Wilds=1 Untethered\ Express=1 Unwavering\ Initiate=1 Unwilling\ Recruit=1 -Unworthy\ Dead=1 +Unwind=1 +Unyaro\ Bee\ Sting=1 Unyaro\ Bees=1 Unyielding\ Krumar=1 -Updraft\ Elemental=1 +Uphill\ Battle=1 Uproot=1 -Upwelling=1 Ur-Golem's\ Eye=1 Urban\ Burgeoning=1 Urban\ Evolution=1 Urbis\ Protector=1 +Urborg\ Elf=1 +Urborg\ Emissary=1 Urborg\ Mindsucker=1 +Urborg\ Phantom=1 +Urborg\ Shambler=1 +Urborg\ Skeleton=1 Urborg\ Stalker=1 +Urborg\ Syphon-Mage=1 Urborg\ Uprising=1 +Urborg\ Volcano=1 Urge\ to\ Feed=1 +Urgoros,\ the\ Empty\ One=1 Ursapine=1 -Ursine\ Fylgja=1 Urza's\ Armor=1 +Urza's\ Blueprints=1 Urza's\ Chalice=1 -Urza's\ Factory=1 Urza's\ Guilt=1 -Urza's\ Miter=1 -Utopia\ Mycon=1 +Urza's\ Tome=1 +Uthden\ Troll=1 Utopia\ Vow=1 +Utter\ End=1 Utvara\ Scalper=1 Uyo,\ Silent\ Prophet=1 +Vacuumelt=1 Vaevictis\ Asmadi=1 Vagrant\ Plowbeasts=1 Valakut\ Fireboar=1 Valakut\ Invoker=1 Valakut\ Predator=1 +Valduk,\ Keeper\ of\ the\ Flame=1 Valeron\ Outlander=1 Valeron\ Wardens=1 Valiant\ Guard=1 @@ -9142,12 +9608,9 @@ Valor\ in\ Akros=1 Vampire's\ Bite=1 Vampire's\ Zeal=1 Vampire\ Aristocrat=1 -Vampire\ Bats=1 -Vampire\ Champion=1 Vampire\ Cutthroat=1 Vampire\ Envoy=1 Vampire\ Interloper=1 -Vampire\ Lacerator=1 Vampire\ Nighthawk=1 Vampire\ Noble=1 Vampire\ Outcasts=1 @@ -9164,25 +9627,26 @@ Vandalize=1 Vanguard's\ Shield=1 Vanguard\ of\ Brimaz=1 Vanish\ into\ Memory=1 -Vanishing=1 Vanishment=1 Vanquish=1 -Vanquish\ the\ Foul=1 Vanquish\ the\ Weak=1 +Vaporkin=1 +Vaporous\ Djinn=1 Varchild's\ Crusader=1 +Varolz,\ the\ Scar-Striped=1 Vassal's\ Duty=1 +Vassal\ Soul=1 Vastwood\ Animist=1 Vastwood\ Gorger=1 -Vastwood\ Hydra=1 Vastwood\ Zendikon=1 Vault\ Skyward=1 Vaultbreaker=1 Vebulid=1 +Vec\ Townships=1 +Vectis\ Agents=1 Vectis\ Silencers=1 Vector\ Asp=1 -Vedalken\ Aethermage=1 Vedalken\ Anatomist=1 -Vedalken\ Archmage=1 Vedalken\ Blademaster=1 Vedalken\ Certarch=1 Vedalken\ Dismisser=1 @@ -9196,34 +9660,39 @@ Vedalken\ Outlander=1 Vedalken\ Plotter=1 Veil\ of\ Secrecy=1 Veilborn\ Ghoul=1 +Veiled\ Apparition=1 Veiled\ Crocodile=1 +Veiled\ Sentry=1 +Veiled\ Serpent=1 Veilstone\ Amulet=1 Vein\ Drinker=1 Venarian\ Glimmer=1 Vendetta=1 +Venerable\ Kumo=1 Venerable\ Lammasu=1 Venerable\ Monk=1 Venerated\ Teacher=1 Vengeance=1 -Vengeful\ Archon=1 Vengeful\ Firebrand=1 Vengeful\ Rebel=1 Vengeful\ Rebirth=1 Vengeful\ Vampire=1 Venomous\ Dragonfly=1 -Venomous\ Fangs=1 Venomspout\ Brackus=1 Venser's\ Diffusion=1 +Venser's\ Journal=1 Vent\ Sentinel=1 +Ventifact\ Bottle=1 Verdant\ Automaton=1 Verdant\ Eidolon=1 Verdant\ Embrace=1 +Verdant\ Field=1 Verdant\ Force=1 Verdant\ Haven=1 Verdant\ Rebirth=1 Verdant\ Sun's\ Avatar=1 Verdant\ Touch=1 -Verdeloth\ the\ Ancient=1 +Verdigris=1 Vermiculos=1 Vertigo\ Spawn=1 Vesper\ Ghoul=1 @@ -9234,39 +9703,37 @@ Vessel\ of\ Nascency=1 Vessel\ of\ Paramnesia=1 Vessel\ of\ Volatility=1 Vestige\ of\ Emrakul=1 +Vesuvan\ Shapeshifter=1 +Veteran's\ Armaments=1 Veteran's\ Reflexes=1 Veteran's\ Sidearm=1 Veteran\ Armorer=1 -Veteran\ Bodyguard=1 +Veteran\ Armorsmith=1 Veteran\ Cathar=1 -Veteran\ Cavalier=1 Veteran\ Motorist=1 Veteran\ Warleader=1 Veteran\ of\ the\ Depths=1 Vex=1 -Vexing\ Arcanix=1 -Vexing\ Beetle=1 Vexing\ Scuttler=1 -Vhati\ il-Dal=1 Vial\ of\ Dragonfire=1 +Vial\ of\ Poison=1 Viashino\ Bladescout=1 Viashino\ Cutthroat=1 -Viashino\ Fangtail=1 Viashino\ Firstblade=1 +Viashino\ Grappler=1 Viashino\ Outrider=1 Viashino\ Racketeer=1 Viashino\ Runner=1 Viashino\ Sandscout=1 Viashino\ Sandstalker=1 -Viashino\ Sandswimmer=1 +Viashino\ Skeleton=1 Viashino\ Slasher=1 Viashino\ Slaughtermaster=1 -Viashino\ Spearhunter=1 -Viashino\ Warrior=1 -Viashino\ Weaponsmith=1 -Viashivan\ Dragon=1 Vibrating\ Sphere=1 -Vicious\ Betrayal=1 +Vicious\ Conquistador=1 +Vicious\ Hunger=1 +Vicious\ Kavu=1 +Vicious\ Offering=1 Vicious\ Shadows=1 Victorious\ Destruction=1 Victory's\ Herald=1 @@ -9274,10 +9741,15 @@ Victual\ Sliver=1 View\ from\ Above=1 Vigean\ Graftmage=1 Vigean\ Hydropon=1 +Vigean\ Intuition=1 +Vigil\ for\ the\ Lost=1 +Vigilance=1 +Vigilant\ Baloth=1 Vigilant\ Drake=1 -Vigilant\ Martyr=1 +Vigilant\ Sentry=1 Vigilante\ Justice=1 Vigor\ Mortis=1 +Vigorous\ Charge=1 Vildin-Pack\ Outcast=1 Vile\ Aggregate=1 Vile\ Deacon=1 @@ -9302,7 +9774,7 @@ Vineshaper\ Mystic=1 Vineweft=1 Vintara\ Snapper=1 Violent\ Impact=1 -Violent\ Ultimatum=1 +Violet\ Pall=1 Viper's\ Kiss=1 Viral\ Drake=1 Viridescent\ Wisps=1 @@ -9310,52 +9782,54 @@ Viridian\ Acolyte=1 Viridian\ Betrayers=1 Viridian\ Claw=1 Viridian\ Emissary=1 -Viridian\ Harvest=1 Viridian\ Joiner=1 Viridian\ Lorebearers=1 Viridian\ Revel=1 Viridian\ Shaman=1 +Viridian\ Zealot=1 Virulent\ Swipe=1 Virulent\ Wound=1 Visara\ the\ Dreadful=1 Viscerid\ Armor=1 -Viscerid\ Deepwalker=1 +Viscerid\ Drone=1 Viscid\ Lemures=1 Vision\ Skeins=1 Visionary\ Augmenter=1 Visions\ of\ Brutality=1 Vital\ Splicer=1 Vital\ Surge=1 +Vitality\ Charm=1 +Vitalizing\ Cascade=1 Vitaspore\ Thallid=1 +Vithian\ Renegades=1 Vithian\ Stinger=1 Vitu-Ghazi,\ the\ City-Tree=1 Vitu-Ghazi\ Guildmage=1 -Vivid\ Marsh=1 +Vivify=1 Vivisection=1 Vizier\ of\ Deferment=1 +Vizier\ of\ Many\ Faces=1 Vizier\ of\ Remedies=1 Vizier\ of\ Tumbling\ Sands=1 Vizier\ of\ the\ Anointed=1 Vizier\ of\ the\ True=1 Vizkopa\ Confessor=1 Vizkopa\ Guildmage=1 +Vizzerdrix=1 +Vodalian\ Arcanist=1 +Vodalian\ Hypnotist=1 Vodalian\ Knights=1 +Vodalian\ Merchant=1 +Vodalian\ Serpent=1 Voice\ of\ All=1 Voice\ of\ Duty=1 Voice\ of\ Grace=1 Voice\ of\ Law=1 Voice\ of\ Reason=1 -Voice\ of\ Truth=1 -Voice\ of\ the\ Provinces=1 -Voice\ of\ the\ Woods=1 -Voiceless\ Spirit=1 -Voices\ from\ the\ Void=1 -Void=1 Void\ Attendant=1 Void\ Grafter=1 Void\ Maw=1 Void\ Shatter=1 -Void\ Snare=1 Void\ Squall=1 Void\ Stalker=1 Voidmage\ Apprentice=1 @@ -9367,34 +9841,38 @@ Volatile\ Rig=1 Volcanic\ Awakening=1 Volcanic\ Dragon=1 Volcanic\ Geyser=1 -Volcanic\ Hammer=1 Volcanic\ Rambler=1 Volcanic\ Rush=1 Volcanic\ Spray=1 Volcanic\ Strength=1 Volcanic\ Upheaval=1 +Volcanic\ Wind=1 Volcano\ Hellion=1 Volcano\ Imp=1 Voldaren\ Duelist=1 Voldaren\ Pariah=1 Volition\ Reins=1 -Volley\ of\ Boulders=1 +Volrath's\ Curse=1 Volrath's\ Dungeon=1 +Volrath's\ Gardens=1 Volrath's\ Laboratory=1 Volrath's\ Shapeshifter=1 Volt\ Charge=1 +Voltaic\ Brawler=1 Voltaic\ Construct=1 +Voltaic\ Servant=1 Volunteer\ Reserves=1 +Vona's\ Hunger=1 Voodoo\ Doll=1 Voracious\ Cobra=1 Voracious\ Dragon=1 Voracious\ Null=1 Voracious\ Vampire=1 Voracious\ Wurm=1 -Vorosh,\ the\ Hunter=1 Vorrac\ Battlehorns=1 -Vorstclaw=1 Vortex\ Elemental=1 +Votary\ of\ the\ Conclave=1 +Vow\ of\ Duty=1 Vow\ of\ Flight=1 Vow\ of\ Lightning=1 Vow\ of\ Malice=1 @@ -9403,10 +9881,14 @@ Voyage's\ End=1 Voyager\ Drake=1 Voyager\ Staff=1 Voyaging\ Satyr=1 +Vug\ Lizard=1 +Vulpine\ Goliath=1 Vulshok\ Battlemaster=1 +Vulshok\ Berserker=1 Vulshok\ Gauntlets=1 +Vulshok\ Heartstoker=1 Vulshok\ Morningstar=1 -Vulshok\ Refugee=1 +Vulshok\ Replica=1 Vulshok\ Sorcerer=1 Vulshok\ War\ Boar=1 Vulturous\ Zombie=1 @@ -9416,8 +9898,8 @@ Wake\ of\ Vultures=1 Wake\ the\ Reflections=1 Wakedancer=1 Waker\ of\ the\ Wilds=1 -Wakestone\ Gargoyle=1 Waking\ Nightmare=1 +Walk\ the\ Plank=1 Walker\ of\ Secret\ Ways=1 Walker\ of\ the\ Grove=1 Walker\ of\ the\ Wastes=1 @@ -9426,6 +9908,7 @@ Walking\ Atlas=1 Walking\ Corpse=1 Walking\ Desecration=1 Walking\ Dream=1 +Walking\ Sponge=1 Walking\ Wall=1 Wall\ of\ Air=1 Wall\ of\ Blood=1 @@ -9435,24 +9918,25 @@ Wall\ of\ Denial=1 Wall\ of\ Diffusion=1 Wall\ of\ Distortion=1 Wall\ of\ Essence=1 +Wall\ of\ Faith=1 Wall\ of\ Fire=1 Wall\ of\ Forgotten\ Pharaohs=1 Wall\ of\ Frost=1 -Wall\ of\ Junk=1 -Wall\ of\ Kelp=1 Wall\ of\ Light=1 Wall\ of\ Limbs=1 +Wall\ of\ Mist=1 Wall\ of\ Mulch=1 -Wall\ of\ Razors=1 Wall\ of\ Resurgence=1 Wall\ of\ Souls=1 Wall\ of\ Spears=1 Wall\ of\ Stone=1 Wall\ of\ Swords=1 Wall\ of\ Tanglecord=1 -Wall\ of\ Torches=1 Wall\ of\ Vines=1 -Wall\ of\ Wood=1 +Wall\ of\ Vipers=1 +Wall\ of\ Wonder=1 +Wallop=1 +Wand\ of\ Denial=1 Wand\ of\ the\ Elements=1 Wander\ in\ Death=1 Wanderbrine\ Rootcutters=1 @@ -9472,11 +9956,11 @@ Waning\ Wurm=1 Wanted\ Scoundrels=1 War-Name\ Aspirant=1 War-Spike\ Changeling=1 -War-Torch\ Goblin=1 War-Wing\ Siren=1 War\ Barge=1 War\ Behemoth=1 War\ Dance=1 +War\ Elemental=1 War\ Falcon=1 War\ Flare=1 War\ Horn=1 @@ -9487,27 +9971,24 @@ Warbreak\ Trumpeter=1 Warbringer=1 Warchanter\ of\ Mogis=1 Warchief\ Giant=1 -Warclamp\ Mastiff=1 +Warcry\ Phoenix=1 Ward\ of\ Piety=1 Warden\ of\ Evos\ Isle=1 Warden\ of\ Geometries=1 -Warden\ of\ the\ Beyond=1 Warden\ of\ the\ Eye=1 Wardscale\ Dragon=1 Warfire\ Javelineer=1 Warleader's\ Helix=1 -Warlord's\ Axe=1 +Warlord's\ Fury=1 Warmind\ Infantry=1 Warmonger's\ Chariot=1 Warmonger=1 -Warmth=1 Warning=1 Warp\ Artifact=1 Warp\ World=1 Warpath\ Ghoul=1 Warped\ Devotion=1 Warped\ Landscape=1 -Warped\ Physique=1 Warped\ Researcher=1 Warren-Scourge\ Elf=1 Warren\ Pilferers=1 @@ -9518,9 +9999,10 @@ Warrior\ en-Kor=1 Warriors'\ Lesson=1 Warthog=1 Wasp\ Lancer=1 +Waste\ Away=1 Wasteland\ Scorpion=1 +Wasteland\ Strangler=1 Wasteland\ Viper=1 -Wastes=1 Watchdog=1 Watcher\ Sliver=1 Watcher\ in\ the\ Web=1 @@ -9540,31 +10022,30 @@ Waterspout\ Elemental=1 Waterspout\ Weavers=1 Watertrap\ Weaver=1 Waterveil\ Cavern=1 -Waterwhirl=1 Wave-Wing\ Elemental=1 Wave\ of\ Indifference=1 Wavecrash\ Triton=1 -Waves\ of\ Aggression=1 +Waveskimmer\ Aven=1 +Wax\ //\ Wane=1 Waxing\ Moon=1 Waxmane\ Baku=1 Way\ of\ the\ Thief=1 -Wayfarer's\ Bauble=1 +Wayfaring\ Giant=1 Wayfaring\ Temple=1 Waylay=1 -Wayward\ Angel=1 Wayward\ Giant=1 Wayward\ Servant=1 Wayward\ Soul=1 Weakness=1 Weakstone=1 Weapon\ Surge=1 +Weaponcraft\ Enthusiast=1 Weapons\ Trainer=1 Wear\ Away=1 Weathered\ Bodyguards=1 Weatherseed\ Elf=1 Weatherseed\ Faeries=1 Weatherseed\ Totem=1 -Weatherseed\ Treefolk=1 Weave\ Fate=1 Weaver\ of\ Currents=1 Weaver\ of\ Lies=1 @@ -9576,12 +10057,12 @@ Weed\ Strangle=1 Wei\ Elite\ Companions=1 Wei\ Infantry=1 Wei\ Night\ Raiders=1 -Wei\ Strike\ Force=1 Weight\ of\ Conscience=1 +Weight\ of\ Memory=1 Weight\ of\ Spires=1 Weight\ of\ the\ Underworld=1 +Weird\ Harvest=1 Weirded\ Vampire=1 -Weirding\ Shaman=1 Weirding\ Wood=1 Welcome\ to\ the\ Fold=1 Welder\ Automaton=1 @@ -9591,7 +10072,7 @@ Weldfast\ Wingsmith=1 Welding\ Sparks=1 Welkin\ Guide=1 Welkin\ Tern=1 -Wellgabber\ Apothecary=1 +Well\ of\ Life=1 Western\ Paladin=1 Wetland\ Sambar=1 Wharf\ Infiltrator=1 @@ -9600,21 +10081,24 @@ Where\ Ancients\ Tread=1 Whetwheel=1 Whims\ of\ the\ Fates=1 Whimwader=1 -Whip-Spine\ Drake=1 Whip\ Sergeant=1 +Whip\ Silk=1 +Whip\ of\ Erebos=1 Whipcorder=1 -Whipgrass\ Entangler=1 +Whipkeeper=1 Whiplash\ Trap=1 -Whipstitched\ Zombie=1 Whiptail\ Moloch=1 Whiptail\ Wurm=1 +Whiptongue\ Frog=1 Whirler\ Rogue=1 Whirlermaker=1 Whirling\ Catapult=1 Whirling\ Dervish=1 -Whirlpool\ Whelm=1 +Whirlpool\ Drake=1 Whirlwind\ Adept=1 +Whisper,\ Blood\ Liturgist=1 Whispering\ Madness=1 +Whispering\ Shade=1 Whispering\ Specter=1 Whispers\ of\ Emrakul=1 Whispersilk\ Cloak=1 @@ -9622,16 +10106,16 @@ White\ Knight=1 White\ Shield\ Crusader=1 Whitemane\ Lion=1 Whiteout=1 -Whitewater\ Naiads=1 +Whitesun's\ Passage=1 Wicked\ Akuba=1 -Wicked\ Pact=1 +Wicked\ Reward=1 Wicker\ Warcrawler=1 Wicker\ Witch=1 -Wight\ of\ Precinct\ Six=1 Wiitigo=1 Wild-Field\ Scarecrow=1 Wild\ Aesthir=1 Wild\ Beastmaster=1 +Wild\ Colos=1 Wild\ Dogs=1 Wild\ Evocation=1 Wild\ Griffin=1 @@ -9639,8 +10123,9 @@ Wild\ Guess=1 Wild\ Hunger=1 Wild\ Instincts=1 Wild\ Leotau=1 -Wild\ Mongrel=1 -Wild\ Nacatl=1 +Wild\ Mammoth=1 +Wild\ Might=1 +Wild\ Onslaught=1 Wild\ Ox=1 Wild\ Pair=1 Wild\ Ricochet=1 @@ -9657,28 +10142,26 @@ Wildfire\ Eternal=1 Wildgrowth\ Walker=1 Wildheart\ Invoker=1 Wildsize=1 -Wildslayer\ Elves=1 -Wildwood\ Geist=1 Wildwood\ Rebirth=1 Will-Forged\ Golem=1 -Will\ of\ the\ Naga=1 Willbender=1 +Willbreaker=1 Willow\ Priestess=1 -Wilt-Leaf\ Cavaliers=1 Wily\ Bandar=1 Wily\ Goblin=1 Wind-Kin\ Raiders=1 +Wind-Scarred\ Crag=1 Wind\ Dancer=1 Wind\ Drake=1 Wind\ Shear=1 -Wind\ Spirit=1 Wind\ Strider=1 Windborne\ Charge=1 Windbrisk\ Raptor=1 +Windgrace\ Acolyte=1 Winding\ Wurm=1 +Windreaper\ Falcon=1 Windreaver=1 Windrider\ Patrol=1 -Winds\ of\ Qal\ Sisma=1 Winds\ of\ Rath=1 Winds\ of\ Rebuke=1 Windseeker\ Centaur=1 @@ -9686,17 +10169,19 @@ Windstorm=1 Windwright\ Mage=1 Wine\ of\ Blood\ and\ Iron=1 Wing\ Puncture=1 +Wing\ Shards=1 Wing\ Snare=1 Wing\ Splicer=1 -Wingbeat\ Warrior=1 +Wing\ Storm=1 Wingcrafter=1 Winged\ Coatl=1 Winged\ Shepherd=1 -Winged\ Sliver=1 +Wingmate\ Roc=1 Wingrattle\ Scarecrow=1 Wings\ of\ Aesthir=1 Wings\ of\ Velis\ Vel=1 Wingsteed\ Rider=1 +Winnow=1 Winnower\ Patrol=1 Winter\ Blast=1 Winterflame=1 @@ -9705,14 +10190,15 @@ Wirecat=1 Wirefly\ Hive=1 Wirewood\ Elf=1 Wirewood\ Guardian=1 -Wishmonger=1 +Wirewood\ Savage=1 Wispweaver\ Angel=1 Wistful\ Thinking=1 Wit's\ End=1 Witch's\ Familiar=1 +Witch's\ Mist=1 Witch-Maw\ Nephilim=1 -Witch\ Hunter=1 Witches'\ Eye=1 +Withered\ Wretch=1 Withering\ Gaze=1 Withering\ Hex=1 Withering\ Wisps=1 @@ -9729,28 +10215,27 @@ Woebearer=1 Woebringer\ Demon=1 Woeleecher=1 Wojek\ Apothecary=1 -Wojek\ Embermage=1 -Wojek\ Halberdiers=1 Wojek\ Siren=1 Wolf-Skull\ Shaman=1 Wolfbriar\ Elemental=1 +Wolfhunter's\ Quiver=1 Wolfir\ Avenger=1 -Wolfir\ Silverheart=1 Wolfkin\ Bond=1 Wonder=1 Wood\ Elemental=1 -Wood\ Sage=1 Woodborn\ Behemoth=1 Woodcloaker=1 Woodcutter's\ Grit=1 Wooden\ Sphere=1 Wooden\ Stake=1 Woodland\ Changeling=1 +Woodland\ Druid=1 Woodland\ Guidance=1 Woodland\ Patrol=1 Woodland\ Sleuth=1 Woodland\ Stream=1 Woodland\ Wanderer=1 +Woodlot\ Crawler=1 Woodlurker\ Mimic=1 Woodripper=1 Woodweaver's\ Puzzleknot=1 @@ -9758,28 +10243,34 @@ Woodwraith\ Corrupter=1 Woodwraith\ Strangler=1 Woolly\ Loxodon=1 Woolly\ Mammoths=1 -Woolly\ Razorback=1 Woolly\ Spider=1 Woolly\ Thoctar=1 Word\ of\ Seizing=1 Word\ of\ Undoing=1 Words\ of\ War=1 +Words\ of\ Waste=1 Words\ of\ Wilding=1 -Words\ of\ Wind=1 Workshop\ Assistant=1 World\ Queller=1 World\ Shaper=1 World\ at\ War=1 Worldgorger\ Dragon=1 +Worldheart\ Phoenix=1 +Worldly\ Counsel=1 Worldpurge=1 Worldslayer=1 Worm\ Harvest=1 +Wormfang\ Drake=1 Wormfang\ Manta=1 Wormwood\ Dryad=1 Wormwood\ Treefolk=1 Wort,\ Boggart\ Auntie=1 Wort,\ the\ Raidmother=1 +Worthy\ Cause=1 +Wound\ Reflection=1 Wrangle=1 +Wrap\ in\ Flames=1 +Wrath\ of\ Marit\ Lage=1 Wreak\ Havoc=1 Wreath\ of\ Geists=1 Wrecking\ Ball=1 @@ -9787,9 +10278,8 @@ Wrecking\ Ogre=1 Wren's\ Run\ Packmaster=1 Wren's\ Run\ Vanquisher=1 Wretched\ Camel=1 -Wring\ Flesh=1 +Wretched\ Gryff=1 Writ\ of\ Passage=1 -Write\ into\ Being=1 Wu\ Elite\ Cavalry=1 Wu\ Longbowman=1 Wu\ Warship=1 @@ -9802,24 +10292,26 @@ Wyluli\ Wolf=1 Xathrid\ Gorgon=1 Xathrid\ Slyblade=1 Xenic\ Poltergeist=1 -Xenograft=1 +Yamabushi's\ Flame=1 Yamabushi's\ Storm=1 -Yavimaya's\ Embrace=1 +Yare=1 +Yargle,\ Glutton\ of\ Urborg=1 Yavimaya\ Ancients=1 Yavimaya\ Ants=1 Yavimaya\ Dryad=1 Yavimaya\ Enchantress=1 -Yavimaya\ Granger=1 Yavimaya\ Kavu=1 +Yavimaya\ Sapherd=1 Yavimaya\ Scion=1 Yavimaya\ Wurm=1 Yawgmoth's\ Edict=1 Yawgmoth\ Demon=1 Yawning\ Fissure=1 -Ydwen\ Efreet=1 Yeva's\ Forcemage=1 +Yeva,\ Nature's\ Herald=1 Yew\ Spirit=1 Yixlid\ Jailer=1 +Yoke\ of\ the\ Damned=1 Yoked\ Ox=1 Yoked\ Plowbeast=1 Yomiji,\ Who\ Bars\ the\ Way=1 @@ -9831,26 +10323,29 @@ Youthful\ Knight=1 Youthful\ Scholar=1 Yuki-Onna=1 Yukora,\ the\ Prisoner=1 +Zada's\ Commando=1 Zada,\ Hedron\ Grinder=1 Zameck\ Guildmage=1 +Zanikev\ Locust=1 +Zap=1 Zarichi\ Tiger=1 Zealot\ il-Vec=1 -Zealots\ en-Dal=1 Zealous\ Guardian=1 Zealous\ Inquisitor=1 -Zealous\ Strike=1 +Zebra\ Unicorn=1 Zektar\ Shrine\ Expedition=1 Zendikar's\ Roil=1 +Zendikar\ Farguide=1 Zendikar\ Incarnate=1 Zendikar\ Resurgent=1 Zenith\ Seeker=1 Zephid's\ Embrace=1 Zephid=1 +Zephyr\ Charge=1 Zephyr\ Net=1 -Zephyr\ Scribe=1 Zephyr\ Spirit=1 +Zephyr\ Sprite=1 Zerapa\ Minotaur=1 -Zetalpa,\ Primal\ Dawn=1 Zhalfirin\ Commander=1 Zhalfirin\ Crusader=1 Zhalfirin\ Knight=1 @@ -9861,17 +10356,16 @@ Zhur-Taa\ Swine=1 Zodiac\ Monkey=1 Zoetic\ Cavern=1 Zof\ Shade=1 -Zombie\ Apocalypse=1 -Zombie\ Brute=1 +Zombie\ Boa=1 Zombie\ Cannibal=1 Zombie\ Cutthroat=1 Zombie\ Goliath=1 -Zombie\ Infestation=1 Zombie\ Musher=1 -Zombie\ Scavengers=1 +Zombie\ Trailblazer=1 Zombify=1 +Zoologist=1 Zulaport\ Chainmage=1 +Zulaport\ Cutthroat=1 Zulaport\ Enforcer=1 Zur's\ Weirding=1 -Zuran\ Orb=1 Zuran\ Spellcaster=1 diff --git a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java index 8e485c801e6..16f4e618f14 100644 --- a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java +++ b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java @@ -4,11 +4,11 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.mage.plugins.card.dl.sources.CardImageSource; +import org.mage.plugins.card.dl.sources.CardImageUrls; import org.mage.plugins.card.dl.sources.TokensMtgImageSource; import org.mage.plugins.card.images.CardDownloadData; /** - * * @author Quercitron */ @Ignore @@ -18,15 +18,16 @@ public class TokensMtgImageSourceTest { public void generateTokenUrlTest() throws Exception { CardImageSource imageSource = TokensMtgImageSource.instance; - String url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url); + CardImageUrls url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", "")); + Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl); + url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url); + Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url); + Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null, "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url); + Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl); } } diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml index 1cca97c7742..a139eab9600 100644 --- a/Mage.Common/pom.xml +++ b/Mage.Common/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage-common diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index 61a5b2f3831..48683734b53 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -1,4 +1,3 @@ - package mage.utils; import java.io.Serializable; @@ -14,8 +13,8 @@ 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 = 30; - public final static String MAGE_VERSION_MINOR_PATCH = "V2"; + public final static int MAGE_VERSION_PATCH = 31; + public final static String MAGE_VERSION_MINOR_PATCH = "V1"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Common/src/main/java/mage/view/CardsView.java b/Mage.Common/src/main/java/mage/view/CardsView.java index ce01784dd03..2a1264f0ce5 100644 --- a/Mage.Common/src/main/java/mage/view/CardsView.java +++ b/Mage.Common/src/main/java/mage/view/CardsView.java @@ -73,7 +73,7 @@ public class CardsView extends LinkedHashMap { case BATTLEFIELD: sourceObject = game.getPermanent(ability.getSourceId()); if (sourceObject == null) { - sourceObject = (Permanent) game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD); + sourceObject = game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD); } isPermanent = true; break; diff --git a/Mage.Plugins/Mage.Counter.Plugin/pom.xml b/Mage.Plugins/Mage.Counter.Plugin/pom.xml index 96edf662929..a8af62ad9da 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.30 + 1.4.31 mage-counter-plugin diff --git a/Mage.Plugins/Mage.Counter.Plugin/src/main/java/org/mage/plugins/counter/CounterPluginImpl.java b/Mage.Plugins/Mage.Counter.Plugin/src/main/java/org/mage/plugins/counter/CounterPluginImpl.java index 7c7efdf462a..b1d067c3281 100644 --- a/Mage.Plugins/Mage.Counter.Plugin/src/main/java/org/mage/plugins/counter/CounterPluginImpl.java +++ b/Mage.Plugins/Mage.Counter.Plugin/src/main/java/org/mage/plugins/counter/CounterPluginImpl.java @@ -41,6 +41,7 @@ public class CounterPluginImpl implements CounterPlugin { File data = new File(PLUGIN_DATA_FOLDER_PATH + File.separator + DATA_STORAGE_FILE); if (!data.exists()) { try { + data.getParentFile().mkdirs(); data.createNewFile(); } catch (IOException e) { log.error(e.getMessage(), e); diff --git a/Mage.Plugins/pom.xml b/Mage.Plugins/pom.xml index 1bad7059904..19abee5bda1 100644 --- a/Mage.Plugins/pom.xml +++ b/Mage.Plugins/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage-plugins diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml index 99eb5e2de2c..a48379e45c7 100644 --- a/Mage.Server.Console/pom.xml +++ b/Mage.Server.Console/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 org.mage diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml index 5d995e5381b..34ac2c8b537 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.30 + 1.4.31 mage-deck-constructed diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java index 01f1ee9ed26..86a70116a24 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java @@ -1,4 +1,3 @@ - package mage.deck; import java.util.HashMap; @@ -15,6 +14,73 @@ import mage.constants.SetType; */ public class AusHighlander extends Constructed { + public static final Map pointMap = new HashMap(); + + static { + pointMap.put("Ancestral Recall", 4); + pointMap.put("Black Lotus", 4); + pointMap.put("Time Vault", 4); + pointMap.put("Demonic Tutor", 3); + pointMap.put("Imperial Seal", 3); + pointMap.put("Mox Emerald", 3); + pointMap.put("Mox Jet", 3); + pointMap.put("Mox Pearl", 3); + pointMap.put("Mox Ruby", 3); + pointMap.put("Mox Sapphire", 3); + pointMap.put("Sol Ring", 3); + pointMap.put("Time Walk", 3); + pointMap.put("Tinker", 3); + pointMap.put("Vampiric Tutor", 3); + pointMap.put("Yawgmoth’s Will", 3); + pointMap.put("Channel", 2); + pointMap.put("Dig Through Time", 2); + pointMap.put("Library of Alexandria", 2); + pointMap.put("Mana Crypt", 2); + pointMap.put("Mystical Tutor", 2); + pointMap.put("Protean Hulk", 2); + pointMap.put("Skullclamp", 2); + pointMap.put("Strip Mine", 2); + pointMap.put("Tolarian Academy", 2); + pointMap.put("Treasure Cruise", 2); + pointMap.put("Back to Basics", 1); + pointMap.put("Balance", 1); + pointMap.put("Birthing Pod", 1); + pointMap.put("Crop Rotation", 1); + pointMap.put("Dark Petition", 1); + pointMap.put("Enlightened Tutor", 1); + pointMap.put("Fastbond", 1); + pointMap.put("Force of Will", 1); + pointMap.put("Gifts Ungiven", 1); + pointMap.put("Green Sun’s Zenith", 1); + pointMap.put("Hermit Druid", 1); + pointMap.put("Intuition", 1); + pointMap.put("Jace, the Mind Sculptor", 1); + pointMap.put("Karakas", 1); + pointMap.put("Lim-Dul’s Vault", 1); + pointMap.put("Mana Drain", 1); + pointMap.put("Mana Vault", 1); + pointMap.put("Memory Jar", 1); + pointMap.put("Merchant Scroll", 1); + pointMap.put("Mind Twist", 1); + pointMap.put("Mishra’s Workshop", 1); + pointMap.put("Natural Order", 1); + pointMap.put("Oath of Druids", 1); + pointMap.put("Personal Tutor", 1); + pointMap.put("Sensei’s Divining Top", 1); + pointMap.put("Snapcaster Mage", 1); + pointMap.put("Stoneforge Mystic", 1); + pointMap.put("Survival of the Fittest", 1); + pointMap.put("Tainted Pact", 1); + pointMap.put("Time Spiral", 1); + pointMap.put("Timetwister", 1); + pointMap.put("True-Name Nemesis", 1); + pointMap.put("Umezawa’s Jitte", 1); + pointMap.put("Wasteland", 1); + pointMap.put("Wheel of Fortune", 1); + pointMap.put("Worldly Tutor", 1); + pointMap.put("Yawgmoth’s Bargain", 1); + } + public AusHighlander() { this("Australian Highlander"); for (ExpansionSet set : Sets.getInstance().values()) { @@ -82,79 +148,9 @@ public class AusHighlander extends Constructed { int totalPoints = 0; for (Map.Entry entry : counts.entrySet()) { String cn = entry.getKey(); - if (cn.equals("Ancestral Recall") - || cn.equals("Black Lotus") - || cn.equals("Time Vault")) { - totalPoints += 4; - invalid.put(cn, "4 points"); - } - if (cn.equals("Demonic Tutor") - || cn.equals("Imperial Seal") - || cn.equals("Mox Emerald") - || cn.equals("Mox Jet") - || cn.equals("Mox Pearl") - || cn.equals("Mox Ruby") - || cn.equals("Sol Ring") - || cn.equals("Time Walk") - || cn.equals("Tinker") - || cn.equals("Vampiric Tutor") - || cn.equals("Yawgmoth's Will") - || cn.equals("Mox Sapphire")) { - totalPoints += 3; - invalid.put(cn, "3 points"); - } - if (cn.equals("Channel") - || cn.equals("Dig Through Time") - || cn.equals("Library of Alexandria") - || cn.equals("Mana Crypt") - || cn.equals("Mystical Tutor") - || cn.equals("Protean Hulk") - || cn.equals("Skullclamp") - || cn.equals("Strip Mine") - || cn.equals("Tolarian Academy") - || cn.equals("Treasure Cruise")) { - totalPoints += 2; - invalid.put(cn, "2 points"); - } - if (cn.equals("Back to Basics") - || cn.equals("Balance") - || cn.equals("Birthing Pod") - || cn.equals("Crop Rotation") - || cn.equals("Dark Petition") - || cn.equals("Enlightened Tutor") - || cn.equals("Fastbond") - || cn.equals("Force of Will") - || cn.equals("Gifts Ungiven") - || cn.equals("Green Sun's Zenith") - || cn.equals("Hermit Druid") - || cn.equals("Intuition") - || cn.equals("Jace, the Mind Sculptor") - || cn.equals("Karakas") - || cn.equals("Lim-Dul's Vault") - || cn.equals("Mana Drain") - || cn.equals("Mana Vault") - || cn.equals("Memory Jar") - || cn.equals("Merchant Scroll") - || cn.equals("Mind Twist") - || cn.equals("Mishra's Workshop") - || cn.equals("Natural Order") - || cn.equals("Oath of Druids") - || cn.equals("Personal Tutor") - || cn.equals("Sensei's Divining Top") - || cn.equals("Snapcaster Mage") - || cn.equals("Stoneforge Mystic") - || cn.equals("Survival of the Fittest") - || cn.equals("Tainted Pact") - || cn.equals("Time Spiral") - || cn.equals("Timetwister") - || cn.equals("True-Name Nemesis") - || cn.equals("Umezawa's Jitte") - || cn.equals("Wasteland") - || cn.equals("Wheel of Fortune") - || cn.equals("Yawgmoth's Bargain") - || cn.equals("Worldly Tutor")) { - totalPoints += 1; - invalid.put(cn, "1 point"); + if (pointMap.containsKey(cn)) { + totalPoints += pointMap.get(cn); + invalid.put(entry.getKey(), " " + pointMap.get(cn) + " point " + cn); } } if (totalPoints > 7) { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java index bb57ef2f491..7e136506588 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java @@ -1,14 +1,10 @@ - package mage.deck; import java.util.*; import mage.abilities.common.CanBeYourCommanderAbility; import mage.cards.Card; -import mage.cards.ExpansionSet; -import mage.cards.Sets; import mage.cards.decks.Constructed; import mage.cards.decks.Deck; -import mage.constants.SetType; import mage.filter.FilterMana; /** @@ -23,41 +19,11 @@ public class Brawl extends Constructed { super("Brawl"); // Copy of standard sets - GregorianCalendar current = new GregorianCalendar(); - List sets = new ArrayList(Sets.getInstance().values()); - Collections.sort(sets, new Comparator() { - @Override - public int compare(final ExpansionSet lhs, ExpansionSet rhs) { - return lhs.getReleaseDate().after(rhs.getReleaseDate()) ? -1 : 1; - } - }); - int blocksAdded = 0; - int blocksToAdd = 3; - for (Iterator iter = sets.iterator(); iter.hasNext() && blocksAdded < blocksToAdd;) { - ExpansionSet set = iter.next(); - if (set.getSetType() == SetType.CORE || set.getSetType() == SetType.EXPANSION || set.getSetType() == SetType.SUPPLEMENTAL_STANDARD_LEGAL) { // Still adding core sets because of Magic Origins + setCodes.addAll(Standard.makeLegalSets()); - setCodes.add(set.getCode()); - if (set.getReleaseDate().before(current.getTime()) // This stops spoiled sets from counting as "new" blocks - && set.getParentSet() == null - && set.getSetType() == SetType.EXPANSION) { - if (blocksAdded == 0 && !isFallBlock(set)) { // if the most current block is no fall block, 4 blocks are added - blocksToAdd++; - } - blocksAdded++; - } - } - } banned.add("Baral, Chief of Compliance"); banned.add("Smuggler's Copter"); - banned.add("Sorcerers' Spyglass"); - } - - private static boolean isFallBlock(ExpansionSet set) { - Calendar cal = Calendar.getInstance(); - cal.setTime(set.getReleaseDate()); - // Sets from fall block are normally released in September and January - return cal.get(Calendar.MONTH) > 7 || cal.get(Calendar.MONTH) < 2; + banned.add("Sorcerous Spyglass"); } public Brawl(String name) { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java index 0c17e6c2f60..33a0714909e 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java @@ -1,4 +1,3 @@ - package mage.deck; import java.util.HashMap; @@ -15,6 +14,53 @@ import mage.constants.SetType; */ public class CanadianHighlander extends Constructed { + public static final Map pointMap = new HashMap(); + + static { + pointMap.put("Ancestral Recall", 7); + pointMap.put("Balance", 1); + pointMap.put("Birthing Pod", 3); + pointMap.put("Black Lotus", 7); + pointMap.put("Demonic Tutor", 4); + pointMap.put("Dig Through Time", 1); + pointMap.put("Enlightened Tutor", 1); + pointMap.put("Fastbond", 1); + pointMap.put("Flash", 7); + pointMap.put("Gifts Ungiven", 2); + pointMap.put("Hermit Druid", 1); + pointMap.put("Imperial Seal", 1); + pointMap.put("Intuition", 1); + pointMap.put("Library of Alexandria", 1); + pointMap.put("Mana Crypt", 2); + pointMap.put("Mana Drain", 1); + pointMap.put("Mana Vault", 1); + pointMap.put("Merchant Scroll", 1); + pointMap.put("Mind Twist", 1); + pointMap.put("Mox Emerald", 3); + pointMap.put("Mox Jet", 3); + pointMap.put("Mox Pearl", 3); + pointMap.put("Mox Ruby", 3); + pointMap.put("Mox Sapphire", 3); + pointMap.put("Mystical Tutor", 2); + pointMap.put("Natural Order", 4); + pointMap.put("Personal Tutor", 1); + pointMap.put("Protean Hulk", 3); + pointMap.put("Sol Ring", 3); + pointMap.put("Stoneforge Mystic", 1); + pointMap.put("Strip Mine", 2); + pointMap.put("Summoner's Pact", 2); + pointMap.put("Survival of the Fittest", 2); + pointMap.put("Time Vault", 6); + pointMap.put("Time Walk", 6); + pointMap.put("Tinker", 4); + pointMap.put("Tolarian Academy", 1); + pointMap.put("Transmute Artifact", 1); + pointMap.put("Treasure Cruise", 1); + pointMap.put("True-Name Nemesis", 1); + pointMap.put("Umezawa's Jitte", 2); + pointMap.put("Vampiric Tutor", 3); + } + public CanadianHighlander() { this("Canadian Highlander"); for (ExpansionSet set : Sets.getInstance().values()) { @@ -54,74 +100,13 @@ public class CanadianHighlander extends Constructed { } } - int allowedPoints = 10 * (int) Math.floor(deck.getCards().size() / 100.0); + int allowedPoints = 10; int totalPoints = 0; for (Map.Entry entry : counts.entrySet()) { String cn = entry.getKey(); - if (cn.equals("Balance") - || cn.equals("Dig Through Time") - || cn.equals("Doomsday") - || cn.equals("Enlightened Tutor") - || cn.equals("Fastbond") - || cn.equals("Intuition") - || cn.equals("Library of Alexandria") - || cn.equals("Mana Vault") - || cn.equals("Merchant Scroll") - || cn.equals("Mind Twist") - || cn.equals("Personal Tutor") - || cn.equals("Stoneforge Mystic") - || cn.equals("Tainted Pact") - || cn.equals("Tolarian Academy") - || cn.equals("Transmute Artifact") - || cn.equals("Treasure Cruise") - || cn.equals("True-Name Nemesis") - || cn.equals("Worldly Tutor")) { - totalPoints += 1; - invalid.put(entry.getKey(), " 1 point " + cn); - } - if (cn.equals("Gifts Ungiven") - || cn.equals("Hermit Druid") - || cn.equals("Imperial Seal") - || cn.equals("Mana Crypt") - || cn.equals("Mystical Tutor") - || cn.equals("Strip Mine") - || cn.equals("Summoner's Pact") - || cn.equals("Survival of the Fittest") - || cn.equals("Umezawa's Jitte")) { - totalPoints += 2; - invalid.put(entry.getKey(), " 2 points " + cn); - } - if (cn.equals("Birthing Pod") - || cn.equals("Mox Emerald") - || cn.equals("Mox Jet") - || cn.equals("Mox Pearl") - || cn.equals("Mox Ruby") - || cn.equals("Mox Sapphire") - || cn.equals("Protean Hulk") - || cn.equals("Sol Ring") - || cn.equals("Vampiric Tutor")) { - totalPoints += 3; - invalid.put(entry.getKey(), " 3 points " + cn); - } - if (cn.equals("Demonic Tutor") - || cn.equals("Tinker")) { - totalPoints += 4; - invalid.put(entry.getKey(), " 4 points " + cn); - } - if (cn.equals("Natural Order") - || cn.equals("Time Walk")) { - totalPoints += 5; - invalid.put(entry.getKey(), " 5 points " + cn); - } - if (cn.equals("Ancestral Recall") - || cn.equals("Time Vault")) { - totalPoints += 6; - invalid.put(entry.getKey(), " 6 points " + cn); - } - if (cn.equals("Black Lotus") - || cn.equals("Flash")) { - totalPoints += 7; - invalid.put(entry.getKey(), " 7 points " + cn); + if (pointMap.containsKey(cn)) { + totalPoints += pointMap.get(cn); + invalid.put(entry.getKey(), " " + pointMap.get(cn) + " point " + cn); } } if (totalPoints > allowedPoints) { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Commander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Commander.java index 81e4030d252..439e7bf928e 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Commander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Commander.java @@ -1,4 +1,3 @@ - package mage.deck; import java.util.*; @@ -23,6 +22,7 @@ import mage.filter.FilterMana; public class Commander extends Constructed { protected List bannedCommander = new ArrayList<>(); + protected boolean partnerAllowed = true; public Commander() { this("Commander"); @@ -105,6 +105,9 @@ public class Commander extends Constructed { } if (deck.getSideboard().size() < 1 || deck.getSideboard().size() > 2) { + if ((deck.getSideboard().size() > 1 && !partnerAllowed)) { + invalid.put("Commander", "You may only have one commander"); + } invalid.put("Commander", "Sideboard must contain only the commander(s)"); valid = false; } else { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/FreeformCommander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/FreeformCommander.java index 279db83346c..14811d576c7 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/FreeformCommander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/FreeformCommander.java @@ -20,7 +20,6 @@ public class FreeformCommander extends Constructed { protected List bannedCommander = new ArrayList<>(); private static final Map pdAllowed = new HashMap<>(); - private static boolean setupAllowed = false; public FreeformCommander() { this("Freeform Commander"); @@ -43,7 +42,6 @@ public class FreeformCommander extends Constructed { valid = false; } - List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes")); Map counts = new HashMap<>(); countCards(counts, deck.getCards()); countCards(counts, deck.getSideboard()); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java index c2e9a7e7a62..90f4ee51ba8 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java @@ -1,4 +1,3 @@ - package mage.deck; import mage.cards.ExpansionSet; @@ -32,6 +31,7 @@ public class Legacy extends Constructed { banned.add("Chaos Orb"); banned.add("Contract from Below"); banned.add("Darkpact"); + banned.add("Deathrite Shaman"); banned.add("Demonic Attorney"); banned.add("Demonic Consultation"); banned.add("Demonic Tutor"); @@ -42,6 +42,7 @@ public class Legacy extends Constructed { banned.add("Fastbond"); banned.add("Flash"); banned.add("Frantic Search"); + banned.add("Gitaxian Probe"); banned.add("Goblin Recruiter"); banned.add("Gush"); banned.add("Hermit Druid"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/MTGO1v1Commander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/MTGO1v1Commander.java index 2d1f9ffb910..511d0d3f0e0 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/MTGO1v1Commander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/MTGO1v1Commander.java @@ -1,4 +1,3 @@ - package mage.deck; /** @@ -9,70 +8,49 @@ public class MTGO1v1Commander extends Commander { public MTGO1v1Commander() { super("MTGO 1v1 Commander"); + partnerAllowed = false; + banned.add("Ancestral Recall"); - banned.add("Ancient Tomb"); banned.add("Back to Basics"); banned.add("Balance"); banned.add("Baral, Chief of Compliance"); banned.add("Black Lotus"); banned.add("Braids, Cabal Minion"); - banned.add("Brainstorm"); banned.add("Channel"); - banned.add("Chrome Mox"); banned.add("Derevi, Empyrial Tactician"); - banned.add("Demonic Tutor"); - banned.add("Dig Through Time"); + banned.add("Doomsday"); banned.add("Edgar Markov"); banned.add("Edric, Spymaster of Trest"); banned.add("Emrakul, the Aeons Torn"); - banned.add("Enlightened Tutor"); - banned.add("Entomb"); + banned.add("Erayo, Soratami Ascendant"); banned.add("Fastbond"); banned.add("Food Chain"); - banned.add("Gaea's Cradle"); banned.add("Gifts Ungiven"); banned.add("Hermit Druid"); banned.add("Humility"); - banned.add("Imperial Seal"); banned.add("Karakas"); banned.add("Library of Alexandria"); - banned.add("Mana Crypt"); - banned.add("Mana Drain"); - banned.add("Mana Vault"); banned.add("Mind Twist"); banned.add("Moat"); - banned.add("Mox Diamond"); banned.add("Mox Emerald"); banned.add("Mox Jet"); banned.add("Mox Pearl"); banned.add("Mox Ruby"); banned.add("Mox Sapphire"); - banned.add("Mystical Tutor"); banned.add("Natural Order"); - banned.add("Necropotence"); banned.add("Oath of Druids"); - banned.add("Ponder"); - banned.add("Preordain"); banned.add("Rofellos, Llanowar Emissary"); + banned.add("Strip Mine"); banned.add("Sensei's Divining Top"); banned.add("Serra Ascendant"); - banned.add("Sol Ring"); - banned.add("Strip Mine"); banned.add("Survival of the Fittest"); banned.add("Sylvan Library"); - banned.add("Sylvan Tutor"); banned.add("The Tabernacle at Pendrell Vale"); banned.add("Time Vault"); banned.add("Time Walk"); banned.add("Tinker"); banned.add("Tolarian Academy"); - banned.add("Treachery"); - banned.add("Treasure Cruise"); - banned.add("Vial Smasher the Fierce"); - banned.add("Vampiric Tutor"); banned.add("Winter Orb"); - banned.add("Wordly Tutor"); - banned.add("Yamgmoth's Bargain"); banned.add("Zur the Enchanter"); } } diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java index 644c67f2f6d..2e2098244a1 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java @@ -1,12 +1,11 @@ - package mage.deck; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.GregorianCalendar; -import java.util.Iterator; import java.util.List; import mage.cards.ExpansionSet; import mage.cards.Sets; @@ -21,31 +20,9 @@ public class Standard extends Constructed { public Standard() { super("Constructed - Standard"); - GregorianCalendar current = new GregorianCalendar(); - List sets = new ArrayList(Sets.getInstance().values()); - Collections.sort(sets, new Comparator() { - @Override - public int compare(final ExpansionSet lhs, ExpansionSet rhs) { - return lhs.getReleaseDate().after(rhs.getReleaseDate()) ? -1 : 1; - } - }); - int blocksAdded = 0; - int blocksToAdd = 3; - for (Iterator iter = sets.iterator(); iter.hasNext() && blocksAdded < blocksToAdd;) { - ExpansionSet set = iter.next(); - if (set.getSetType() == SetType.CORE || set.getSetType() == SetType.EXPANSION || set.getSetType() == SetType.SUPPLEMENTAL_STANDARD_LEGAL) { // Still adding core sets because of Magic Origins - setCodes.add(set.getCode()); - if (set.getReleaseDate().before(current.getTime()) // This stops spoiled sets from counting as "new" blocks - && set.getParentSet() == null - && set.getSetType() == SetType.EXPANSION) { - if (blocksAdded == 0 && !isFallBlock(set)) { // if the most current block is no fall block, 4 blocks are added - blocksToAdd++; - } - blocksAdded++; - } - } - } + setCodes.addAll(makeLegalSets()); + banned.add("Attune with Aether"); // since 2018-01-15 banned.add("Aetherworks Marvel"); banned.add("Felidar Guardian"); @@ -55,10 +32,49 @@ public class Standard extends Constructed { banned.add("Smuggler's Copter"); } - private static boolean isFallBlock(ExpansionSet set) { + private static boolean isFallSet(ExpansionSet set) { Calendar cal = Calendar.getInstance(); cal.setTime(set.getReleaseDate()); - // Sets from fall block are normally released in September and January - return cal.get(Calendar.MONTH) > 7 || cal.get(Calendar.MONTH) < 2; + // Fall sets are normally released during or after September + return set.getSetType() == SetType.EXPANSION + && (cal.get(Calendar.MONTH) > 7); + } + + public static List makeLegalSets() { + List codes = new ArrayList(); + GregorianCalendar current = new GregorianCalendar(); + List sets = new ArrayList(Sets.getInstance().values()); + Collections.sort(sets, new Comparator() { + @Override + public int compare(final ExpansionSet lhs, ExpansionSet rhs) { + return lhs.getReleaseDate().after(rhs.getReleaseDate()) ? -1 : 1; + } + }); + int fallSetsAdded = 0; + Date earliestDate = null; + // Get the second most recent fall set that's been released. + for (ExpansionSet set : sets) { + if (set.getReleaseDate().after(current.getTime())) { + continue; + } + if (isFallSet(set)) { + fallSetsAdded++; + if (fallSetsAdded == 2) { + earliestDate = set.getReleaseDate(); + break; + } + } + } + // Get all sets released on or after the second most recent fall set's release + for (ExpansionSet set : sets) { + if ((set.getSetType() == SetType.CORE + || set.getSetType() == SetType.EXPANSION + || set.getSetType() == SetType.SUPPLEMENTAL_STANDARD_LEGAL) + && !set.getReleaseDate().before(earliestDate)) { +// && !set.getReleaseDate().after(current.getTime()))) { + codes.add(set.getCode()); + } + } + return codes; } } diff --git a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml index 78fd34bf6c4..831c92012e6 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.30 + 1.4.31 mage-deck-limited diff --git a/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml index 0b1a9a5c22e..be720b6a91e 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.30 + 1.4.31 mage-game-brawlduel diff --git a/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java b/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java index 1650d6fb20f..e0a56eb0e23 100644 --- a/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java +++ b/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java @@ -16,7 +16,7 @@ public class BrawlDuelMatch extends MatchImpl { @Override public void startGame() throws GameException { - int startLife = 20; + int startLife = 25; boolean alsoHand = true; BrawlDuel game = new BrawlDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife); game.setCheckCommanderDamage(false); diff --git a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml index 2d4503d4ea9..45666026043 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.30 + 1.4.31 mage-game-brawlfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml index 6f5ed897271..5b32376a59e 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.30 + 1.4.31 mage-game-canadianhighlanderduel diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml index 8058f31e8b6..3bc9525794c 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.30 + 1.4.31 mage-game-commanderduel diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml index c1e880af349..1888b3a1fb6 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.30 + 1.4.31 mage-game-commanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml index a594fc43ba2..239c59dcdf3 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.30 + 1.4.31 mage-game-freeforall diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml index f470d91e355..eaa55ae4e9c 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.30 + 1.4.31 mage-game-freeformcommanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml index dd2baee2fc8..e4ec5b48a76 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.30 + 1.4.31 mage-game-momirduel diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml index 73bd0da03f0..e17bfe1289a 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.30 + 1.4.31 mage-game-momirfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml index 47296e7410c..60538dc66c3 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.30 + 1.4.31 mage-game-pennydreadfulcommanderfreeforall diff --git a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml index dfab44f5c3e..111fedc13fb 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.30 + 1.4.31 mage-game-tinyleadersduel diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml index a01797f1c01..5d5ba7eb623 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.30 + 1.4.31 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 835f1aa271d..75c0e758224 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.30 + 1.4.31 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 b85644b4eed..9f8a8b0e53d 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.30 + 1.4.31 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 05a410dd3a6..f38270bec6f 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 @@ -136,7 +136,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { sb.setLength(0); sb.append("-> Permanents: ["); for (Permanent permanent : game.getBattlefield().getAllPermanents()) { - if (permanent.getOwnerId().equals(player.getId())) { + if (permanent.isOwnedBy(player.getId())) { sb.append(permanent.getName()); if (permanent.isTapped()) { sb.append("(tapped)"); @@ -254,7 +254,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { } else if (stepFinished) { logger.debug("Step finished"); int testScore = GameStateEvaluator2.evaluate(playerId, game); - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { if (testScore < currentScore) { // if score at end of step is worse than original score don't check further //logger.debug("Add Action -- abandoning check, no immediate benefit"); diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java index a9d0f29657e..628472299c1 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java @@ -54,7 +54,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { pass(game); return false; case PRECOMBAT_MAIN: - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { printOutState(game); if (actions.isEmpty()) { logger.info("Sim Calculate pre combat actions ----------------------------------------------------- "); diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml index d8b40b7034b..81f988b7341 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.30 + 1.4.31 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 e5dd0c6b0ea..8362963995a 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 @@ -987,7 +987,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { private boolean priorityPlay(Game game) { UUID opponentId = game.getOpponents(playerId).iterator().next(); - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { if (game.isMainPhase() && game.getStack().isEmpty()) { playLand(game); } diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml index bacd02de913..d8a75c7fde3 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.30 + 1.4.31 mage-player-ai-mcts diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java index 53b6533a58f..257d3adb828 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java @@ -348,7 +348,7 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player { thinkTime = maxThinkTime / 2; } } - else if (game.getActivePlayerId().equals(playerId) && (curStep == PhaseStep.PRECOMBAT_MAIN || curStep == PhaseStep.POSTCOMBAT_MAIN) && game.getStack().isEmpty()) { + else if (game.isActivePlayer(playerId) && (curStep == PhaseStep.PRECOMBAT_MAIN || curStep == PhaseStep.POSTCOMBAT_MAIN) && game.getStack().isEmpty()) { if (nodeSizeRatio < THINK_MIN_RATIO) { thinkTime = maxThinkTime; } diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml index a8c6839a985..1cc373afd2b 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.30 + 1.4.31 mage-player-aiminimax diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java index 52ceb958dba..28e8f8e0125 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java @@ -50,7 +50,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { pass(game); return false; case PRECOMBAT_MAIN: - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { if (actions.isEmpty()) { calculatePreCombatActions(game); } @@ -64,7 +64,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { pass(game); return false; case DECLARE_ATTACKERS: - if (!game.getActivePlayerId().equals(playerId)) { + if (!game.isActivePlayer(playerId)) { if (actions.isEmpty()) { calculatePreCombatActions(game); } @@ -81,7 +81,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { pass(game); return false; case POSTCOMBAT_MAIN: - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { if (actions.isEmpty()) { calculatePostCombatActions(game); } @@ -184,7 +184,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { else if (stepFinished) { logger.debug(indent(node.depth) + "step finished"); int testScore = GameStateEvaluator.evaluate(playerId, game); - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { if (testScore < currentScore) { // if score at end of step is worse than original score don't check further logger.debug(indent(node.depth) + "simulating -- abandoning check, no immediate benefit"); diff --git a/Mage.Server.Plugins/Mage.Player.Human/pom.xml b/Mage.Server.Plugins/Mage.Player.Human/pom.xml index 633eae49c08..b295f64ad4d 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.30 + 1.4.31 mage-player-human diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index ab2848376dc..a8122e52b4f 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -341,8 +341,18 @@ public class HumanPlayer extends PlayerImpl { replacementEffectChoice.getChoices().clear(); replacementEffectChoice.setKeyChoices(rEffects); + + // Check if there are different ones + int differentChoices = 0; + String lastChoice = ""; + for (String value : replacementEffectChoice.getKeyChoices().values()) { + if (!lastChoice.equalsIgnoreCase(value)) { + lastChoice = value; + differentChoices++; + } + } - while (!abort) { + while (!abort && differentChoices > 1) { updateGameStatePriority("chooseEffect", game); prepareForResponse(game); if (!isExecutingMacro()) { @@ -1943,7 +1953,7 @@ public class HumanPlayer extends PlayerImpl { if (userData.confirmEmptyManaPool() && game.getStack().isEmpty() && getManaPool().count() > 0) { String activePlayerText; - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { activePlayerText = "Your turn"; } else { activePlayerText = game.getPlayer(game.getActivePlayerId()).getName() + "'s turn"; diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml index c51329ccda2..f3cecab6e5f 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.30 + 1.4.31 mage-tournament-boosterdraft diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/VintageCubeJune2018.java b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/VintageCubeJune2018.java new file mode 100644 index 00000000000..ff41043da7f --- /dev/null +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/VintageCubeJune2018.java @@ -0,0 +1,555 @@ +package mage.tournament.cubes; + +import mage.game.draft.DraftCube; + +/** + * + * @author TheELk801 + */ +public class VintageCubeJune2018 extends DraftCube { + + public VintageCubeJune2018() { + super("MTGO Vintage Cube June 2018"); + + cubeCards.add(new DraftCube.CardIdentity("Abbot of Keral Keep", "")); + cubeCards.add(new DraftCube.CardIdentity("Abrade", "")); + cubeCards.add(new DraftCube.CardIdentity("Abrupt Decay", "")); + cubeCards.add(new DraftCube.CardIdentity("Academy Ruins", "")); + cubeCards.add(new DraftCube.CardIdentity("Acidic Slime", "")); + cubeCards.add(new DraftCube.CardIdentity("Adanto Vanguard", "")); + cubeCards.add(new DraftCube.CardIdentity("Ajani Vengeant", "")); + cubeCards.add(new DraftCube.CardIdentity("Ancestral Recall", "")); + cubeCards.add(new DraftCube.CardIdentity("Ancestral Vision", "")); + cubeCards.add(new DraftCube.CardIdentity("Ancient Grudge", "")); + cubeCards.add(new DraftCube.CardIdentity("Ancient Stirrings", "")); + cubeCards.add(new DraftCube.CardIdentity("Ancient Tomb", "")); + cubeCards.add(new DraftCube.CardIdentity("Angel of Invention", "")); + cubeCards.add(new DraftCube.CardIdentity("Angel of Sanctions", "")); + cubeCards.add(new DraftCube.CardIdentity("Angel of Serenity", "")); + cubeCards.add(new DraftCube.CardIdentity("Anguished Unmaking", "")); + cubeCards.add(new DraftCube.CardIdentity("Animate Dead", "")); + cubeCards.add(new DraftCube.CardIdentity("Arbor Elf", "")); + cubeCards.add(new DraftCube.CardIdentity("Archangel of Thune", "")); + cubeCards.add(new DraftCube.CardIdentity("Arguel's Blood Fast", "")); + cubeCards.add(new DraftCube.CardIdentity("Arid Mesa", "")); + cubeCards.add(new DraftCube.CardIdentity("Armageddon", "")); + cubeCards.add(new DraftCube.CardIdentity("Ashiok, Nightmare Weaver", "")); + cubeCards.add(new DraftCube.CardIdentity("Augur of Bolas", "")); + cubeCards.add(new DraftCube.CardIdentity("Avacyn's Pilgrim", "")); + cubeCards.add(new DraftCube.CardIdentity("Avalanche Riders", "")); + cubeCards.add(new DraftCube.CardIdentity("Avenger of Zendikar", "")); + cubeCards.add(new DraftCube.CardIdentity("Awakening Zone", "")); + cubeCards.add(new DraftCube.CardIdentity("Azorius Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Badlands", "")); + cubeCards.add(new DraftCube.CardIdentity("Balance", "")); + cubeCards.add(new DraftCube.CardIdentity("Baleful Strix", "")); + cubeCards.add(new DraftCube.CardIdentity("Baneslayer Angel", "")); + cubeCards.add(new DraftCube.CardIdentity("Banisher Priest", "")); + cubeCards.add(new DraftCube.CardIdentity("Banishing Light", "")); + cubeCards.add(new DraftCube.CardIdentity("Basalt Monolith", "")); + cubeCards.add(new DraftCube.CardIdentity("Batterskull", "")); + cubeCards.add(new DraftCube.CardIdentity("Bayou", "")); + cubeCards.add(new DraftCube.CardIdentity("Bazaar of Baghdad", "")); + cubeCards.add(new DraftCube.CardIdentity("Beast Within", "")); + cubeCards.add(new DraftCube.CardIdentity("Benalish Marshal", "")); + cubeCards.add(new DraftCube.CardIdentity("Birds of Paradise", "")); + cubeCards.add(new DraftCube.CardIdentity("Bitterblossom", "")); + cubeCards.add(new DraftCube.CardIdentity("Black Lotus", "")); + cubeCards.add(new DraftCube.CardIdentity("Blackcleave Cliffs", "")); + cubeCards.add(new DraftCube.CardIdentity("Blade Splicer", "")); + cubeCards.add(new DraftCube.CardIdentity("Blightsteel Colossus", "")); + cubeCards.add(new DraftCube.CardIdentity("Blink of an Eye", "")); + cubeCards.add(new DraftCube.CardIdentity("Blood Crypt", "")); + cubeCards.add(new DraftCube.CardIdentity("Bloodbraid Elf", "")); + cubeCards.add(new DraftCube.CardIdentity("Bloodstained Mire", "")); + cubeCards.add(new DraftCube.CardIdentity("Blooming Marsh", "")); + cubeCards.add(new DraftCube.CardIdentity("Bone Shredder", "")); + cubeCards.add(new DraftCube.CardIdentity("Bonfire of the Damned", "")); + cubeCards.add(new DraftCube.CardIdentity("Boros Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Botanical Sanctum", "")); + cubeCards.add(new DraftCube.CardIdentity("Braids, Cabal Minion", "")); + cubeCards.add(new DraftCube.CardIdentity("Brain Freeze", "")); + cubeCards.add(new DraftCube.CardIdentity("Brain Maggot", "")); + cubeCards.add(new DraftCube.CardIdentity("Brainstorm", "")); + cubeCards.add(new DraftCube.CardIdentity("Breeding Pool", "")); + cubeCards.add(new DraftCube.CardIdentity("Bribery", "")); + cubeCards.add(new DraftCube.CardIdentity("Brimaz, King of Oreskos", "")); + cubeCards.add(new DraftCube.CardIdentity("Bring to Light", "")); + cubeCards.add(new DraftCube.CardIdentity("Buried Alive", "")); + cubeCards.add(new DraftCube.CardIdentity("Burning of Xinye", "")); + cubeCards.add(new DraftCube.CardIdentity("Burst Lightning", "")); + cubeCards.add(new DraftCube.CardIdentity("Cabal Ritual", "")); + cubeCards.add(new DraftCube.CardIdentity("Cast Down", "")); + cubeCards.add(new DraftCube.CardIdentity("Cast Out", "")); + cubeCards.add(new DraftCube.CardIdentity("Celestial Colonnade", "")); + cubeCards.add(new DraftCube.CardIdentity("Chain Lightning", "")); + cubeCards.add(new DraftCube.CardIdentity("Chandra, Flamecaller", "")); + cubeCards.add(new DraftCube.CardIdentity("Chandra, Pyromaster", "")); + cubeCards.add(new DraftCube.CardIdentity("Chandra, Torch of Defiance", "")); + cubeCards.add(new DraftCube.CardIdentity("Channel", "")); + cubeCards.add(new DraftCube.CardIdentity("Char", "")); + cubeCards.add(new DraftCube.CardIdentity("Chart a Course", "")); + cubeCards.add(new DraftCube.CardIdentity("Chrome Mox", "")); + cubeCards.add(new DraftCube.CardIdentity("Coalition Relic", "")); + cubeCards.add(new DraftCube.CardIdentity("Coercive Portal", "")); + cubeCards.add(new DraftCube.CardIdentity("Commit // Memory", "")); + cubeCards.add(new DraftCube.CardIdentity("Compulsive Research", "")); + cubeCards.add(new DraftCube.CardIdentity("Concealed Courtyard", "")); + cubeCards.add(new DraftCube.CardIdentity("Consecrated Sphinx", "")); + cubeCards.add(new DraftCube.CardIdentity("Control Magic", "")); + cubeCards.add(new DraftCube.CardIdentity("Copperline Gorge", "")); + cubeCards.add(new DraftCube.CardIdentity("Corpse Dance", "")); + cubeCards.add(new DraftCube.CardIdentity("Council's Judgment", "")); + cubeCards.add(new DraftCube.CardIdentity("Counterspell", "")); + cubeCards.add(new DraftCube.CardIdentity("Courser of Kruphix", "")); + cubeCards.add(new DraftCube.CardIdentity("Craterhoof Behemoth", "")); + cubeCards.add(new DraftCube.CardIdentity("Creeping Tar Pit", "")); + cubeCards.add(new DraftCube.CardIdentity("Crucible of Worlds", "")); + cubeCards.add(new DraftCube.CardIdentity("Cryptic Command", "")); + cubeCards.add(new DraftCube.CardIdentity("Dack Fayden", "")); + cubeCards.add(new DraftCube.CardIdentity("Damnation", "")); + cubeCards.add(new DraftCube.CardIdentity("Daretti, Scrap Savant", "")); + cubeCards.add(new DraftCube.CardIdentity("Dark Confidant", "")); + cubeCards.add(new DraftCube.CardIdentity("Dark Petition", "")); + cubeCards.add(new DraftCube.CardIdentity("Dark Ritual", "")); + cubeCards.add(new DraftCube.CardIdentity("Darkslick Shores", "")); + cubeCards.add(new DraftCube.CardIdentity("Day of Judgment", "")); + cubeCards.add(new DraftCube.CardIdentity("Daze", "")); + cubeCards.add(new DraftCube.CardIdentity("Deathrite Shaman", "")); + cubeCards.add(new DraftCube.CardIdentity("Deceiver Exarch", "")); + cubeCards.add(new DraftCube.CardIdentity("Declaration in Stone", "")); + cubeCards.add(new DraftCube.CardIdentity("Delver of Secrets", "")); + cubeCards.add(new DraftCube.CardIdentity("Demonic Tutor", "")); + cubeCards.add(new DraftCube.CardIdentity("Demonlord Belzenlok", "")); + cubeCards.add(new DraftCube.CardIdentity("Den Protector", "")); + cubeCards.add(new DraftCube.CardIdentity("Deranged Hermit", "")); + cubeCards.add(new DraftCube.CardIdentity("Desperate Ritual", "")); + cubeCards.add(new DraftCube.CardIdentity("Dig Through Time", "")); + cubeCards.add(new DraftCube.CardIdentity("Dimir Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Dire Fleet Daredevil", "")); + cubeCards.add(new DraftCube.CardIdentity("Disenchant", "")); + cubeCards.add(new DraftCube.CardIdentity("Dismember", "")); + cubeCards.add(new DraftCube.CardIdentity("Dissenter's Deliverance", "")); + cubeCards.add(new DraftCube.CardIdentity("Dragonlord Atarka", "")); + cubeCards.add(new DraftCube.CardIdentity("Dragonlord Dromoka", "")); + cubeCards.add(new DraftCube.CardIdentity("Dragonlord Ojutai", "")); + cubeCards.add(new DraftCube.CardIdentity("Dreadbore", "")); + cubeCards.add(new DraftCube.CardIdentity("Dualcaster Mage", "")); + cubeCards.add(new DraftCube.CardIdentity("Duplicant", "")); + cubeCards.add(new DraftCube.CardIdentity("Duress", "")); + cubeCards.add(new DraftCube.CardIdentity("Edric, Spymaster of Trest", "")); + cubeCards.add(new DraftCube.CardIdentity("Eidolon of the Great Revel", "")); + cubeCards.add(new DraftCube.CardIdentity("Electrolyze", "")); + cubeCards.add(new DraftCube.CardIdentity("Elesh Norn, Grand Cenobite", "")); + cubeCards.add(new DraftCube.CardIdentity("Elspeth, Knight-Errant", "")); + cubeCards.add(new DraftCube.CardIdentity("Elspeth, Sun's Champion", "")); + cubeCards.add(new DraftCube.CardIdentity("Elves of Deep Shadow", "")); + cubeCards.add(new DraftCube.CardIdentity("Elvish Mystic", "")); + cubeCards.add(new DraftCube.CardIdentity("Emeria Angel", "")); + cubeCards.add(new DraftCube.CardIdentity("Empty the Warrens", "")); + cubeCards.add(new DraftCube.CardIdentity("Emrakul, the Aeons Torn", "")); + cubeCards.add(new DraftCube.CardIdentity("Emrakul, the Promised End", "")); + cubeCards.add(new DraftCube.CardIdentity("Enlightened Tutor", "")); + cubeCards.add(new DraftCube.CardIdentity("Entomb", "")); + cubeCards.add(new DraftCube.CardIdentity("Eternal Witness", "")); + cubeCards.add(new DraftCube.CardIdentity("Eureka", "")); + cubeCards.add(new DraftCube.CardIdentity("Everflowing Chalice", "")); + cubeCards.add(new DraftCube.CardIdentity("Exhume", "")); + cubeCards.add(new DraftCube.CardIdentity("Exquisite Firecraft", "")); + cubeCards.add(new DraftCube.CardIdentity("Fact or Fiction", "")); + cubeCards.add(new DraftCube.CardIdentity("Faithless Looting", "")); + cubeCards.add(new DraftCube.CardIdentity("Falkenrath Gorger", "")); + cubeCards.add(new DraftCube.CardIdentity("Fastbond", "")); + cubeCards.add(new DraftCube.CardIdentity("Fatal Push", "")); + cubeCards.add(new DraftCube.CardIdentity("Fauna Shaman", "")); + cubeCards.add(new DraftCube.CardIdentity("Field of Ruin", "")); + cubeCards.add(new DraftCube.CardIdentity("Fiend Hunter", "")); + cubeCards.add(new DraftCube.CardIdentity("Fiery Confluence", "")); + cubeCards.add(new DraftCube.CardIdentity("Figure of Destiny", "")); + cubeCards.add(new DraftCube.CardIdentity("Fire // Ice", "")); + cubeCards.add(new DraftCube.CardIdentity("Fireblast", "")); + cubeCards.add(new DraftCube.CardIdentity("Firebolt", "")); + cubeCards.add(new DraftCube.CardIdentity("Firedrinker Satyr", "")); + cubeCards.add(new DraftCube.CardIdentity("Flametongue Kavu", "")); + cubeCards.add(new DraftCube.CardIdentity("Flickerwisp", "")); + cubeCards.add(new DraftCube.CardIdentity("Flooded Strand", "")); + cubeCards.add(new DraftCube.CardIdentity("Force Spike", "")); + cubeCards.add(new DraftCube.CardIdentity("Force of Will", "")); + cubeCards.add(new DraftCube.CardIdentity("Frantic Search", "")); + cubeCards.add(new DraftCube.CardIdentity("Freyalise, Llanowar's Fury", "")); + cubeCards.add(new DraftCube.CardIdentity("Frost Titan", "")); + cubeCards.add(new DraftCube.CardIdentity("Fyndhorn Elves", "")); + cubeCards.add(new DraftCube.CardIdentity("Gaea's Cradle", "")); + cubeCards.add(new DraftCube.CardIdentity("Garruk Relentless", "")); + cubeCards.add(new DraftCube.CardIdentity("Garruk Wildspeaker", "")); + cubeCards.add(new DraftCube.CardIdentity("Garruk, Primal Hunter", "")); + cubeCards.add(new DraftCube.CardIdentity("Geist of Saint Traft", "")); + cubeCards.add(new DraftCube.CardIdentity("Genesis Wave", "")); + cubeCards.add(new DraftCube.CardIdentity("Gideon Jura", "")); + cubeCards.add(new DraftCube.CardIdentity("Gideon of the Trials", "")); + cubeCards.add(new DraftCube.CardIdentity("Gideon, Ally of Zendikar", "")); + cubeCards.add(new DraftCube.CardIdentity("Gifts Ungiven", "")); + cubeCards.add(new DraftCube.CardIdentity("Gilded Lotus", "")); + cubeCards.add(new DraftCube.CardIdentity("Gitaxian Probe", "")); + cubeCards.add(new DraftCube.CardIdentity("Glen Elendra Archmage", "")); + cubeCards.add(new DraftCube.CardIdentity("Glorybringer", "")); + cubeCards.add(new DraftCube.CardIdentity("Go for the Throat", "")); + cubeCards.add(new DraftCube.CardIdentity("Goblin Chainwhirler", "")); + cubeCards.add(new DraftCube.CardIdentity("Goblin Dark-Dwellers", "")); + cubeCards.add(new DraftCube.CardIdentity("Goblin Guide", "")); + cubeCards.add(new DraftCube.CardIdentity("Goblin Welder", "")); + cubeCards.add(new DraftCube.CardIdentity("Godless Shrine", "")); + cubeCards.add(new DraftCube.CardIdentity("Golgari Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Gonti, Lord of Luxury", "")); + cubeCards.add(new DraftCube.CardIdentity("Grave Titan", "")); + cubeCards.add(new DraftCube.CardIdentity("Green Sun's Zenith", "")); + cubeCards.add(new DraftCube.CardIdentity("Grim Lavamancer", "")); + cubeCards.add(new DraftCube.CardIdentity("Grim Monolith", "")); + cubeCards.add(new DraftCube.CardIdentity("Grim Tutor", "")); + cubeCards.add(new DraftCube.CardIdentity("Griselbrand", "")); + cubeCards.add(new DraftCube.CardIdentity("Gruul Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Gush", "")); + cubeCards.add(new DraftCube.CardIdentity("Hallowed Fountain", "")); + cubeCards.add(new DraftCube.CardIdentity("Hangarback Walker", "")); + cubeCards.add(new DraftCube.CardIdentity("Harmonize", "")); + cubeCards.add(new DraftCube.CardIdentity("Hazoret the Fervent", "")); + cubeCards.add(new DraftCube.CardIdentity("Heartbeat of Spring", "")); + cubeCards.add(new DraftCube.CardIdentity("Hellrider", "")); + cubeCards.add(new DraftCube.CardIdentity("Hero of Bladehold", "")); + cubeCards.add(new DraftCube.CardIdentity("Hero's Downfall", "")); + cubeCards.add(new DraftCube.CardIdentity("High Tide", "")); + cubeCards.add(new DraftCube.CardIdentity("Hissing Quagmire", "")); + cubeCards.add(new DraftCube.CardIdentity("History of Benalia", "")); + cubeCards.add(new DraftCube.CardIdentity("Honor of the Pure", "")); + cubeCards.add(new DraftCube.CardIdentity("Hostage Taker", "")); + cubeCards.add(new DraftCube.CardIdentity("Huntmaster of the Fells", "")); + cubeCards.add(new DraftCube.CardIdentity("Hymn to Tourach", "")); + cubeCards.add(new DraftCube.CardIdentity("Hypnotic Specter", "")); + cubeCards.add(new DraftCube.CardIdentity("Imperial Recruiter", "")); + cubeCards.add(new DraftCube.CardIdentity("Imperial Seal", "")); + cubeCards.add(new DraftCube.CardIdentity("Impulse", "")); + cubeCards.add(new DraftCube.CardIdentity("Incinerate", "")); + cubeCards.add(new DraftCube.CardIdentity("Inferno Titan", "")); + cubeCards.add(new DraftCube.CardIdentity("Inkwell Leviathan", "")); + cubeCards.add(new DraftCube.CardIdentity("Inquisition of Kozilek", "")); + cubeCards.add(new DraftCube.CardIdentity("Inspiring Vantage", "")); + cubeCards.add(new DraftCube.CardIdentity("Iona, Shield of Emeria", "")); + cubeCards.add(new DraftCube.CardIdentity("Izzet Charm", "")); + cubeCards.add(new DraftCube.CardIdentity("Izzet Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Jace Beleren", "")); + cubeCards.add(new DraftCube.CardIdentity("Jace, Architect of Thought", "")); + cubeCards.add(new DraftCube.CardIdentity("Jace, Vryn's Prodigy", "")); + cubeCards.add(new DraftCube.CardIdentity("Jace, the Mind Sculptor", "")); + cubeCards.add(new DraftCube.CardIdentity("Jackal Pup", "")); + cubeCards.add(new DraftCube.CardIdentity("Jadelight Ranger", "")); + cubeCards.add(new DraftCube.CardIdentity("Jhoira, Weatherlight Captain", "")); + cubeCards.add(new DraftCube.CardIdentity("Joraga Treespeaker", "")); + cubeCards.add(new DraftCube.CardIdentity("Karakas", "")); + cubeCards.add(new DraftCube.CardIdentity("Karn Liberated", "")); + cubeCards.add(new DraftCube.CardIdentity("Karn, Scion of Urza", "")); + cubeCards.add(new DraftCube.CardIdentity("Kiki-Jiki, Mirror Breaker", "")); + cubeCards.add(new DraftCube.CardIdentity("Kitchen Finks", "")); + cubeCards.add(new DraftCube.CardIdentity("Kitesail Freebooter", "")); + cubeCards.add(new DraftCube.CardIdentity("Knight of the White Orchi", "")); + cubeCards.add(new DraftCube.CardIdentity("Kolaghan's Command", "")); + cubeCards.add(new DraftCube.CardIdentity("Koth of the Hammer", "")); + cubeCards.add(new DraftCube.CardIdentity("Kozilek, Butcher of Truth", "")); + cubeCards.add(new DraftCube.CardIdentity("Kuldotha Forgemaster", "")); + cubeCards.add(new DraftCube.CardIdentity("Kytheon, Hero of Akros", "")); + cubeCards.add(new DraftCube.CardIdentity("Land Tax", "")); + cubeCards.add(new DraftCube.CardIdentity("Lavaclaw Reaches", "")); + cubeCards.add(new DraftCube.CardIdentity("Legion's Landing", "")); + cubeCards.add(new DraftCube.CardIdentity("Leonin Relic-Warder", "")); + cubeCards.add(new DraftCube.CardIdentity("Leovold, Emissary of Trest", "")); + cubeCards.add(new DraftCube.CardIdentity("Leyline of Sanctity", "")); + cubeCards.add(new DraftCube.CardIdentity("Library of Alexandria", "")); + cubeCards.add(new DraftCube.CardIdentity("Lightning Bolt", "")); + cubeCards.add(new DraftCube.CardIdentity("Lightning Greaves", "")); + cubeCards.add(new DraftCube.CardIdentity("Lightning Helix", "")); + cubeCards.add(new DraftCube.CardIdentity("Lightning Strike", "")); + cubeCards.add(new DraftCube.CardIdentity("Liliana of the Veil", "")); + cubeCards.add(new DraftCube.CardIdentity("Liliana, Death's Majesty", "")); + cubeCards.add(new DraftCube.CardIdentity("Lingering Souls", "")); + cubeCards.add(new DraftCube.CardIdentity("Linvala, Keeper of Silence", "")); + cubeCards.add(new DraftCube.CardIdentity("Lion's Eye Diamond", "")); + cubeCards.add(new DraftCube.CardIdentity("Living Death", "")); + cubeCards.add(new DraftCube.CardIdentity("Llanowar Elves", "")); + cubeCards.add(new DraftCube.CardIdentity("Lodestone Golem", "")); + cubeCards.add(new DraftCube.CardIdentity("Looter il-Kor", "")); + cubeCards.add(new DraftCube.CardIdentity("Lotus Bloom", "")); + cubeCards.add(new DraftCube.CardIdentity("Lotus Cobra", "")); + cubeCards.add(new DraftCube.CardIdentity("Lotus Petal", "")); + cubeCards.add(new DraftCube.CardIdentity("Lumbering Falls", "")); + cubeCards.add(new DraftCube.CardIdentity("Lyra Dawnbringer", "")); + cubeCards.add(new DraftCube.CardIdentity("Maelstrom Pulse", "")); + cubeCards.add(new DraftCube.CardIdentity("Magma Jet", "")); + cubeCards.add(new DraftCube.CardIdentity("Magus of the Moon", "")); + cubeCards.add(new DraftCube.CardIdentity("Makeshift Mannequin", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Confluence", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Crypt", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Drain", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Flare", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Leak", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Tithe", "")); + cubeCards.add(new DraftCube.CardIdentity("Mana Vault", "")); + cubeCards.add(new DraftCube.CardIdentity("Manglehorn", "")); + cubeCards.add(new DraftCube.CardIdentity("Manic Vandal", "")); + cubeCards.add(new DraftCube.CardIdentity("Marsh Flats", "")); + cubeCards.add(new DraftCube.CardIdentity("Massacre Wurm", "")); + cubeCards.add(new DraftCube.CardIdentity("Master of the Wild Hunt", "")); + cubeCards.add(new DraftCube.CardIdentity("Maze of Ith", "")); + cubeCards.add(new DraftCube.CardIdentity("Memory Jar", "")); + cubeCards.add(new DraftCube.CardIdentity("Mesmeric Fiend", "")); + cubeCards.add(new DraftCube.CardIdentity("Metalworker", "")); + cubeCards.add(new DraftCube.CardIdentity("Mind Twist", "")); + cubeCards.add(new DraftCube.CardIdentity("Mind's Desire", "")); + cubeCards.add(new DraftCube.CardIdentity("Mindslaver", "")); + cubeCards.add(new DraftCube.CardIdentity("Mirari's Wake", "")); + cubeCards.add(new DraftCube.CardIdentity("Mirran Crusader", "")); + cubeCards.add(new DraftCube.CardIdentity("Mishra's Factory", "")); + cubeCards.add(new DraftCube.CardIdentity("Mishra's Workshop", "")); + cubeCards.add(new DraftCube.CardIdentity("Misty Rainforest", "")); + cubeCards.add(new DraftCube.CardIdentity("Mizzium Mortars", "")); + cubeCards.add(new DraftCube.CardIdentity("Moat", "")); + cubeCards.add(new DraftCube.CardIdentity("Monastery Mentor", "")); + cubeCards.add(new DraftCube.CardIdentity("Monastery Swiftspear", "")); + cubeCards.add(new DraftCube.CardIdentity("Mother of Runes", "")); + cubeCards.add(new DraftCube.CardIdentity("Mox Diamond", "")); + cubeCards.add(new DraftCube.CardIdentity("Mox Emerald", "")); + cubeCards.add(new DraftCube.CardIdentity("Mox Jet", "")); + cubeCards.add(new DraftCube.CardIdentity("Mox Pearl", "")); + cubeCards.add(new DraftCube.CardIdentity("Mox Ruby", "")); + cubeCards.add(new DraftCube.CardIdentity("Mox Sapphire", "")); + cubeCards.add(new DraftCube.CardIdentity("Mulldrifter", "")); + cubeCards.add(new DraftCube.CardIdentity("Murderous Cut", "")); + cubeCards.add(new DraftCube.CardIdentity("Mutavault", "")); + cubeCards.add(new DraftCube.CardIdentity("Myr Battlesphere", "")); + cubeCards.add(new DraftCube.CardIdentity("Mystic Confluence", "")); + cubeCards.add(new DraftCube.CardIdentity("Mystic Snake", "")); + cubeCards.add(new DraftCube.CardIdentity("Mystical Tutor", "")); + cubeCards.add(new DraftCube.CardIdentity("Nahiri, the Harbinger", "")); + cubeCards.add(new DraftCube.CardIdentity("Natural Order", "")); + cubeCards.add(new DraftCube.CardIdentity("Nature's Claim", "")); + cubeCards.add(new DraftCube.CardIdentity("Necromancy", "")); + cubeCards.add(new DraftCube.CardIdentity("Necropotence", "")); + cubeCards.add(new DraftCube.CardIdentity("Needle Spires", "")); + cubeCards.add(new DraftCube.CardIdentity("Nekrataal", "")); + cubeCards.add(new DraftCube.CardIdentity("Nevinyrral's Disk", "")); + cubeCards.add(new DraftCube.CardIdentity("Nezumi Graverobber", "")); + cubeCards.add(new DraftCube.CardIdentity("Nezumi Shortfang", "")); + cubeCards.add(new DraftCube.CardIdentity("Nicol Bolas, Planeswalker", "")); + cubeCards.add(new DraftCube.CardIdentity("Nissa, Worldwaker", "")); + cubeCards.add(new DraftCube.CardIdentity("Noble Hierarch", "")); + cubeCards.add(new DraftCube.CardIdentity("Noxious Gearhulk", "")); + cubeCards.add(new DraftCube.CardIdentity("Nykthos, Shrine to Nyx", "")); + cubeCards.add(new DraftCube.CardIdentity("Oath of Druids", "")); + cubeCards.add(new DraftCube.CardIdentity("Oath of Nissa", "")); + cubeCards.add(new DraftCube.CardIdentity("Oblivion Ring", "")); + cubeCards.add(new DraftCube.CardIdentity("Olivia Voldaren", "")); + cubeCards.add(new DraftCube.CardIdentity("Oona's Prowler", "")); + cubeCards.add(new DraftCube.CardIdentity("Ophiomancer", "")); + cubeCards.add(new DraftCube.CardIdentity("Opposition", "")); + cubeCards.add(new DraftCube.CardIdentity("Oracle of Mul Daya", "")); + cubeCards.add(new DraftCube.CardIdentity("Orzhov Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Overgrown Tomb", "")); + cubeCards.add(new DraftCube.CardIdentity("Pack Rat", "")); + cubeCards.add(new DraftCube.CardIdentity("Painful Truths", "")); + cubeCards.add(new DraftCube.CardIdentity("Palinchron", "")); + cubeCards.add(new DraftCube.CardIdentity("Parallax Wave", "")); + cubeCards.add(new DraftCube.CardIdentity("Path to Exile", "")); + cubeCards.add(new DraftCube.CardIdentity("Pentad Prism", "")); + cubeCards.add(new DraftCube.CardIdentity("Pernicious Deed", "")); + cubeCards.add(new DraftCube.CardIdentity("Pestermite", "")); + cubeCards.add(new DraftCube.CardIdentity("Phantasmal Image", "")); + cubeCards.add(new DraftCube.CardIdentity("Phyrexian Metamorph", "")); + cubeCards.add(new DraftCube.CardIdentity("Phyrexian Revoker", "")); + cubeCards.add(new DraftCube.CardIdentity("Plateau", "")); + cubeCards.add(new DraftCube.CardIdentity("Polluted Delta", "")); + cubeCards.add(new DraftCube.CardIdentity("Polukranos, World Eater", "")); + cubeCards.add(new DraftCube.CardIdentity("Ponder", "")); + cubeCards.add(new DraftCube.CardIdentity("Porcelain Legionnaire", "")); + cubeCards.add(new DraftCube.CardIdentity("Preordain", "")); + cubeCards.add(new DraftCube.CardIdentity("Primal Command", "")); + cubeCards.add(new DraftCube.CardIdentity("Primeval Titan", "")); + cubeCards.add(new DraftCube.CardIdentity("Progenitus", "")); + cubeCards.add(new DraftCube.CardIdentity("Putrid Imp", "")); + cubeCards.add(new DraftCube.CardIdentity("Pyretic Ritual", "")); + cubeCards.add(new DraftCube.CardIdentity("Qasali Pridemage", "")); + cubeCards.add(new DraftCube.CardIdentity("Raging Ravine", "")); + cubeCards.add(new DraftCube.CardIdentity("Rakdos Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Rakdos's Return", "")); + cubeCards.add(new DraftCube.CardIdentity("Ravages of War", "")); + cubeCards.add(new DraftCube.CardIdentity("Ravenous Chupacabra", "")); + cubeCards.add(new DraftCube.CardIdentity("Razorverge Thicket", "")); + cubeCards.add(new DraftCube.CardIdentity("Reanimate", "")); + cubeCards.add(new DraftCube.CardIdentity("Reclamation Sage", "")); + cubeCards.add(new DraftCube.CardIdentity("Recruiter of the Guard", "")); + cubeCards.add(new DraftCube.CardIdentity("Recurring Nightmare", "")); + cubeCards.add(new DraftCube.CardIdentity("Regrowth", "")); + cubeCards.add(new DraftCube.CardIdentity("Rekindling Phoenix", "")); + cubeCards.add(new DraftCube.CardIdentity("Remand", "")); + cubeCards.add(new DraftCube.CardIdentity("Repeal", "")); + cubeCards.add(new DraftCube.CardIdentity("Restoration Angel", "")); + cubeCards.add(new DraftCube.CardIdentity("Reveillark", "")); + cubeCards.add(new DraftCube.CardIdentity("Rift Bolt", "")); + cubeCards.add(new DraftCube.CardIdentity("Riftwing Cloudskate", "")); + cubeCards.add(new DraftCube.CardIdentity("Rishadan Port", "")); + cubeCards.add(new DraftCube.CardIdentity("Rishkar, Peema Renegade", "")); + cubeCards.add(new DraftCube.CardIdentity("Rite of Flame", "")); + cubeCards.add(new DraftCube.CardIdentity("Rofellos, Llanowar Emissary", "")); + cubeCards.add(new DraftCube.CardIdentity("Sacred Foundry", "")); + cubeCards.add(new DraftCube.CardIdentity("Sakura-Tribe Elder", "")); + cubeCards.add(new DraftCube.CardIdentity("Savannah", "")); + cubeCards.add(new DraftCube.CardIdentity("Scalding Tarn", "")); + cubeCards.add(new DraftCube.CardIdentity("Scavenging Ooze", "")); + cubeCards.add(new DraftCube.CardIdentity("Scrubland", "")); + cubeCards.add(new DraftCube.CardIdentity("Seachrome Coast", "")); + cubeCards.add(new DraftCube.CardIdentity("Search for Azcanta", "")); + cubeCards.add(new DraftCube.CardIdentity("Search for Tomorrow", "")); + cubeCards.add(new DraftCube.CardIdentity("Searing Spear", "")); + cubeCards.add(new DraftCube.CardIdentity("Seething Song", "")); + cubeCards.add(new DraftCube.CardIdentity("Selesnya Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Selfless Spirit", "")); + cubeCards.add(new DraftCube.CardIdentity("Sensei's Divining Top", "")); + cubeCards.add(new DraftCube.CardIdentity("Shallow Grave", "")); + cubeCards.add(new DraftCube.CardIdentity("Shambling Vent", "")); + cubeCards.add(new DraftCube.CardIdentity("Shardless Agent", "")); + cubeCards.add(new DraftCube.CardIdentity("Shelldock Isle", "")); + cubeCards.add(new DraftCube.CardIdentity("Sheoldred, Whispering One", "")); + cubeCards.add(new DraftCube.CardIdentity("Show and Tell", "")); + cubeCards.add(new DraftCube.CardIdentity("Shriekmaw", "")); + cubeCards.add(new DraftCube.CardIdentity("Shrine of Burning Rage", "")); + cubeCards.add(new DraftCube.CardIdentity("Siege-Gang Commander", "")); + cubeCards.add(new DraftCube.CardIdentity("Silverblade Paladin", "")); + cubeCards.add(new DraftCube.CardIdentity("Simic Signet", "")); + cubeCards.add(new DraftCube.CardIdentity("Skullclamp", "")); + cubeCards.add(new DraftCube.CardIdentity("Skymarcher Aspirant", "")); + cubeCards.add(new DraftCube.CardIdentity("Smokestack", "")); + cubeCards.add(new DraftCube.CardIdentity("Smuggler's Copter", "")); + cubeCards.add(new DraftCube.CardIdentity("Snapcaster Mage", "")); + cubeCards.add(new DraftCube.CardIdentity("Sneak Attack", "")); + cubeCards.add(new DraftCube.CardIdentity("Sol Ring", "")); + cubeCards.add(new DraftCube.CardIdentity("Solemn Simulacrum", "")); + cubeCards.add(new DraftCube.CardIdentity("Song of the Dryads", "")); + cubeCards.add(new DraftCube.CardIdentity("Sorcerous Spyglass", "")); + cubeCards.add(new DraftCube.CardIdentity("Soulfire Grand Master", "")); + cubeCards.add(new DraftCube.CardIdentity("Sower of Temptation", "")); + cubeCards.add(new DraftCube.CardIdentity("Spear of Heliod", "")); + cubeCards.add(new DraftCube.CardIdentity("Spectral Procession", "")); + cubeCards.add(new DraftCube.CardIdentity("Spell Pierce", "")); + cubeCards.add(new DraftCube.CardIdentity("Spellskite", "")); + cubeCards.add(new DraftCube.CardIdentity("Sphinx of the Steel Wind", "")); + cubeCards.add(new DraftCube.CardIdentity("Sphinx's Revelation", "")); + cubeCards.add(new DraftCube.CardIdentity("Spirebluff Canal", "")); + cubeCards.add(new DraftCube.CardIdentity("Splinter Twin", "")); + cubeCards.add(new DraftCube.CardIdentity("Steam Vents", "")); + cubeCards.add(new DraftCube.CardIdentity("Stirring Wildwood", "")); + cubeCards.add(new DraftCube.CardIdentity("Stomping Ground", "")); + cubeCards.add(new DraftCube.CardIdentity("Stoneforge Mystic", "")); + cubeCards.add(new DraftCube.CardIdentity("Stormbreath Dragon", "")); + cubeCards.add(new DraftCube.CardIdentity("Strip Mine", "")); + cubeCards.add(new DraftCube.CardIdentity("Student of Warfare", "")); + cubeCards.add(new DraftCube.CardIdentity("Sulfuric Vortex", "")); + cubeCards.add(new DraftCube.CardIdentity("Sun Titan", "")); + cubeCards.add(new DraftCube.CardIdentity("Sundering Titan", "")); + cubeCards.add(new DraftCube.CardIdentity("Supreme Verdict", "")); + cubeCards.add(new DraftCube.CardIdentity("Survival of the Fittest", "")); + cubeCards.add(new DraftCube.CardIdentity("Sweltering Suns", "")); + cubeCards.add(new DraftCube.CardIdentity("Sword of Body and Mind", "")); + cubeCards.add(new DraftCube.CardIdentity("Sword of Feast and Famine", "")); + cubeCards.add(new DraftCube.CardIdentity("Sword of Fire and Ice", "")); + cubeCards.add(new DraftCube.CardIdentity("Sword of Light and Shadow", "")); + cubeCards.add(new DraftCube.CardIdentity("Sword of War and Peace", "")); + cubeCards.add(new DraftCube.CardIdentity("Swords to Plowshares", "")); + cubeCards.add(new DraftCube.CardIdentity("Sylvan Caryatid", "")); + cubeCards.add(new DraftCube.CardIdentity("Sylvan Library", "")); + cubeCards.add(new DraftCube.CardIdentity("Taiga", "")); + cubeCards.add(new DraftCube.CardIdentity("Tamiyo, the Moon Sage", "")); + cubeCards.add(new DraftCube.CardIdentity("Tangle Wire", "")); + cubeCards.add(new DraftCube.CardIdentity("Tarmogoyf", "")); + cubeCards.add(new DraftCube.CardIdentity("Tasigur, the Golden Fang", "")); + cubeCards.add(new DraftCube.CardIdentity("Teferi, Hero of Dominaria", "")); + cubeCards.add(new DraftCube.CardIdentity("Temple Garden", "")); + cubeCards.add(new DraftCube.CardIdentity("Tendrils of Agony", "")); + cubeCards.add(new DraftCube.CardIdentity("Terastodon", "")); + cubeCards.add(new DraftCube.CardIdentity("Terminate", "")); + cubeCards.add(new DraftCube.CardIdentity("Tezzeret the Seeker", "")); + cubeCards.add(new DraftCube.CardIdentity("Tezzeret, Agent of Bolas", "")); + cubeCards.add(new DraftCube.CardIdentity("Thalia, Guardian of Thraben", "")); + cubeCards.add(new DraftCube.CardIdentity("The Abyss", "")); + cubeCards.add(new DraftCube.CardIdentity("The Scarab God", "")); + cubeCards.add(new DraftCube.CardIdentity("Thing in the Ice", "")); + cubeCards.add(new DraftCube.CardIdentity("Thirst for Knowledge", "")); + cubeCards.add(new DraftCube.CardIdentity("Thoughtseize", "")); + cubeCards.add(new DraftCube.CardIdentity("Thragtusk", "")); + cubeCards.add(new DraftCube.CardIdentity("Thran Dynamo", "")); + cubeCards.add(new DraftCube.CardIdentity("Thrashing Brontodon", "")); + cubeCards.add(new DraftCube.CardIdentity("Through the Breach", "")); + cubeCards.add(new DraftCube.CardIdentity("Thrun, the Last Troll", "")); + cubeCards.add(new DraftCube.CardIdentity("Thundermaw Hellkite", "")); + cubeCards.add(new DraftCube.CardIdentity("Tidehollow Sculler", "")); + cubeCards.add(new DraftCube.CardIdentity("Time Spiral", "")); + cubeCards.add(new DraftCube.CardIdentity("Time Walk", "")); + cubeCards.add(new DraftCube.CardIdentity("Timely Reinforcements", "")); + cubeCards.add(new DraftCube.CardIdentity("Timetwister", "")); + cubeCards.add(new DraftCube.CardIdentity("Tinker", "")); + cubeCards.add(new DraftCube.CardIdentity("Tolarian Academy", "")); + cubeCards.add(new DraftCube.CardIdentity("Tooth and Nail", "")); + cubeCards.add(new DraftCube.CardIdentity("Torrential Gearhulk", "")); + cubeCards.add(new DraftCube.CardIdentity("Toxic Deluge", "")); + cubeCards.add(new DraftCube.CardIdentity("Treachery", "")); + cubeCards.add(new DraftCube.CardIdentity("Treasure Cruise", "")); + cubeCards.add(new DraftCube.CardIdentity("Trinket Mage", "")); + cubeCards.add(new DraftCube.CardIdentity("Tropical Island", "")); + cubeCards.add(new DraftCube.CardIdentity("True-Name Nemesis", "")); + cubeCards.add(new DraftCube.CardIdentity("Trygon Predator", "")); + cubeCards.add(new DraftCube.CardIdentity("Tundra", "")); + cubeCards.add(new DraftCube.CardIdentity("Turnabout", "")); + cubeCards.add(new DraftCube.CardIdentity("Ugin, the Spirit Dragon", "")); + cubeCards.add(new DraftCube.CardIdentity("Ulamog, the Ceaseless Hunger", "")); + cubeCards.add(new DraftCube.CardIdentity("Ulamog, the Infinite Gyre", "")); + cubeCards.add(new DraftCube.CardIdentity("Ultimate Price", "")); + cubeCards.add(new DraftCube.CardIdentity("Umezawa's Jitte", "")); + cubeCards.add(new DraftCube.CardIdentity("Unburial Rites", "")); + cubeCards.add(new DraftCube.CardIdentity("Underground Sea", "")); + cubeCards.add(new DraftCube.CardIdentity("Unexpectedly Absent", "")); + cubeCards.add(new DraftCube.CardIdentity("Upheaval", "")); + cubeCards.add(new DraftCube.CardIdentity("Urborg, Tomb of Yawgmoth", "")); + cubeCards.add(new DraftCube.CardIdentity("Vampire Nighthawk", "")); + cubeCards.add(new DraftCube.CardIdentity("Vampiric Tutor", "")); + cubeCards.add(new DraftCube.CardIdentity("Vedalken Shackles", "")); + cubeCards.add(new DraftCube.CardIdentity("Vendilion Clique", "")); + cubeCards.add(new DraftCube.CardIdentity("Venser, Shaper Savant", "")); + cubeCards.add(new DraftCube.CardIdentity("Verdant Catacombs", "")); + cubeCards.add(new DraftCube.CardIdentity("Verdurous Gearhulk", "")); + cubeCards.add(new DraftCube.CardIdentity("Vindicate", "")); + cubeCards.add(new DraftCube.CardIdentity("Voice of Resurgence", "")); + cubeCards.add(new DraftCube.CardIdentity("Volcanic Island", "")); + cubeCards.add(new DraftCube.CardIdentity("Vraska's Contempt", "")); + cubeCards.add(new DraftCube.CardIdentity("Vraska, Relic Seeker", "")); + cubeCards.add(new DraftCube.CardIdentity("Walking Ballista", "")); + cubeCards.add(new DraftCube.CardIdentity("Wall of Blossoms", "")); + cubeCards.add(new DraftCube.CardIdentity("Wall of Omens", "")); + cubeCards.add(new DraftCube.CardIdentity("Wall of Roots", "")); + cubeCards.add(new DraftCube.CardIdentity("Wandering Fumarole", "")); + cubeCards.add(new DraftCube.CardIdentity("Wasteland", "")); + cubeCards.add(new DraftCube.CardIdentity("Watery Grave", "")); + cubeCards.add(new DraftCube.CardIdentity("Wear // Tear", "")); + cubeCards.add(new DraftCube.CardIdentity("Wheel of Fortune", "")); + cubeCards.add(new DraftCube.CardIdentity("Wildfire", "")); + cubeCards.add(new DraftCube.CardIdentity("Windswept Heath", "")); + cubeCards.add(new DraftCube.CardIdentity("Winter Orb", "")); + cubeCards.add(new DraftCube.CardIdentity("Wooded Foothills", "")); + cubeCards.add(new DraftCube.CardIdentity("Woodfall Primus", "")); + cubeCards.add(new DraftCube.CardIdentity("Worn Powerstone", "")); + cubeCards.add(new DraftCube.CardIdentity("Wrath of God", "")); + cubeCards.add(new DraftCube.CardIdentity("Wurmcoil Engine", "")); + cubeCards.add(new DraftCube.CardIdentity("Xenagos, the Reveler", "")); + cubeCards.add(new DraftCube.CardIdentity("Yavimaya Elder", "")); + cubeCards.add(new DraftCube.CardIdentity("Yawgmoth's Bargain", "")); + cubeCards.add(new DraftCube.CardIdentity("Yawgmoth's Will", "")); + cubeCards.add(new DraftCube.CardIdentity("Young Pyromancer", "")); + cubeCards.add(new DraftCube.CardIdentity("Zealous Conscripts", "")); + cubeCards.add(new DraftCube.CardIdentity("Zurgo Bellstriker", "")); + } +} diff --git a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml index 9d7a35c808e..bec51f060af 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.30 + 1.4.31 mage-tournament-constructed diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml index 1ee73bd18e6..b9aab5d4f47 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.30 + 1.4.31 mage-tournament-sealed diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index 46611f0d337..a3ac123d038 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage-server-plugins diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 01a85130846..6ee934ff18f 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -133,6 +133,7 @@ + diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 3f11bd456b1..ef2b5d1b81a 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage-server diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index b3716c92f87..40a2f3ad72c 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -127,6 +127,7 @@ + diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 78ce2b7dc5b..a9593816c70 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -1,4 +1,3 @@ - package mage.server.game; import java.io.*; @@ -1149,7 +1148,7 @@ public class GameController implements GameCallback { sb.append(state.getTurnMods()); sb.append("
getTurnNum: "); sb.append(state.getTurnNum()); - + sb.append("
Using plane chase?:" + state.isPlaneChase()); if (state.isPlaneChase()) { Plane currentPlane = state.getCurrentPlane(); @@ -1157,7 +1156,7 @@ public class GameController implements GameCallback { sb.append("
Current plane:" + currentPlane.getName()); } } - + sb.append("
Future Timeout:"); if (futureTimeout != null) { sb.append("Cancelled?="); @@ -1188,8 +1187,13 @@ public class GameController implements GameCallback { sb.append("
Active player is: "); sb.append(game.getPlayer(state.getActivePlayerId()).getName()); + PassAbility pass = new PassAbility(); if (game.getPlayer(state.getActivePlayerId()).hasLeft()) { + Player p = game.getPlayer(state.getActivePlayerId()); + if (p != null) { + p.concede(game); + } Phase currentPhase = game.getPhase(); if (currentPhase != null) { currentPhase.getStep().skipStep(game, state.getActivePlayerId()); @@ -1204,6 +1208,10 @@ public class GameController implements GameCallback { sb.append("
getChoosingPlayerId: "); if (state.getChoosingPlayerId() != null) { if (game.getPlayer(state.getChoosingPlayerId()).hasLeft()) { + Player p = game.getPlayer(state.getChoosingPlayerId()); + if (p != null) { + p.concede(game); + } Phase currentPhase = game.getPhase(); if (currentPhase != null && !fixedAlready) { currentPhase.getStep().endStep(game, state.getActivePlayerId()); @@ -1218,7 +1226,11 @@ public class GameController implements GameCallback { sb.append("
Player with Priority is: "); if (state.getPriorityPlayerId() != null) { - if (game.getPlayer(state.getPriorityPlayerId()).hasLeft()) { + if (game.getPlayer(state.getPriorityPlayerId()).hasLeft()) { + Player p = game.getPlayer(state.getPriorityPlayerId()); + if (p != null) { + p.concede(game); + } Phase currentPhase = game.getPhase(); if (currentPhase != null && !fixedAlready) { currentPhase.getStep().skipStep(game, state.getActivePlayerId()); @@ -1228,7 +1240,7 @@ public class GameController implements GameCallback { } sb.append(game.getPlayer(state.getPriorityPlayerId()).getName()); sb.append(""); - } + } sb.append("
Future Timeout:"); if (futureTimeout != null) { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java index 135bcac1ee7..12bf551a7b2 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentFactory.java @@ -40,7 +40,7 @@ public enum TournamentFactory { Map setInfo = new LinkedHashMap<>(); for (String setCode: options.getLimitedOptions().getSetCodes()) { tournament.getSets().add(Sets.findSet(setCode)); - int count = setInfo.containsKey(setCode) ? setInfo.get(setCode) : 0; + int count = setInfo.getOrDefault(setCode, 0); setInfo.put(setCode, count + 1); } tournament.getOptions().getLimitedOptions().setNumberBoosters(tournament.getTournamentType().getNumBoosters()); diff --git a/Mage.Server/src/main/resources/mage/deck/pennydreadful.properties b/Mage.Server/src/main/resources/mage/deck/pennydreadful.properties index c85cbd63c55..21b36851790 100644 --- a/Mage.Server/src/main/resources/mage/deck/pennydreadful.properties +++ b/Mage.Server/src/main/resources/mage/deck/pennydreadful.properties @@ -1,39 +1,38 @@ -Abandon\ Hope=1 Abandon\ Reason=1 +Abandoned\ Outpost=1 +Abandoned\ Sarcophagus=1 Abattoir\ Ghoul=1 -Abbey\ Gargoyles=1 +Abduction=1 Aberrant\ Researcher=1 Abhorrent\ Overlord=1 +Abnormal\ Endurance=1 Abomination\ of\ Gudul=1 -Aboshan,\ Cephalid\ Emperor=1 +Aboshan's\ Desire=1 About\ Face=1 -Absolute\ Law=1 Absolver\ Thrull=1 Absorb\ Vis=1 Abstruse\ Interference=1 -Abuna\ Acolyte=1 +Abuna's\ Chant=1 Abundant\ Maw=1 Abyssal\ Horror=1 Abyssal\ Nocturnus=1 Abyssal\ Specter=1 -Abzan\ Advantage=1 Abzan\ Ascendancy=1 Abzan\ Banner=1 Abzan\ Battle\ Priest=1 -Abzan\ Beastmaster=1 Abzan\ Charm=1 Abzan\ Falconer=1 Abzan\ Guide=1 -Abzan\ Kin-Guard=1 Abzan\ Runemark=1 -Abzan\ Skycaptain=1 +Academy\ Drake=1 Academy\ Elite=1 +Academy\ Journeymage=1 Academy\ Raider=1 Academy\ Researchers=1 +Accelerate=1 Accomplished\ Automaton=1 Accorder's\ Shield=1 Accorder\ Paladin=1 -Accursed\ Centaur=1 Accursed\ Horde=1 Accursed\ Spirit=1 Accursed\ Witch=1 @@ -41,15 +40,18 @@ Acid-Spewer\ Dragon=1 Acid\ Web\ Spider=1 Acidic\ Sliver=1 Acolyte's\ Reward=1 +Acolyte\ of\ Xathrid=1 Acolyte\ of\ the\ Inferno=1 Acquire=1 -Acridian=1 Acrobatic\ Maneuver=1 Act\ of\ Aggression=1 Act\ of\ Heroism=1 Act\ of\ Treason=1 Act\ on\ Impulse=1 +Active\ Volcano=1 +Adamant\ Will=1 Adamaro,\ First\ to\ Desire=1 +Adanto\ Vanguard=1 Adaptive\ Snapjaw=1 Adarkar\ Sentinel=1 Adarkar\ Valkyrie=1 @@ -65,9 +67,10 @@ Advice\ from\ the\ Fae=1 Advocate\ of\ the\ Beast=1 Aegis\ Angel=1 Aegis\ Automaton=1 -Aegis\ of\ Honor=1 Aeolipile=1 Aeon\ Chronicler=1 +Aerial\ Caravan=1 +Aerial\ Engineer=1 Aerial\ Formation=1 Aerial\ Guide=1 Aerial\ Maneuver=1 @@ -83,16 +86,14 @@ Aeronaut\ Admiral=1 Aeronaut\ Tinkerer=1 Aesthir\ Glider=1 Aether\ Adept=1 -Aether\ Charge=1 Aether\ Chaser=1 Aether\ Figment=1 -Aether\ Flash=1 Aether\ Herder=1 Aether\ Inspector=1 -Aether\ Meltdown=1 Aether\ Membrane=1 Aether\ Mutation=1 Aether\ Poisoner=1 +Aether\ Shockwave=1 Aether\ Snap=1 Aether\ Spellbomb=1 Aether\ Sting=1 @@ -103,31 +104,30 @@ Aether\ Tide=1 Aether\ Tradewinds=1 Aetherborn\ Marauder=1 Aethergeode\ Miner=1 -Aetherize=1 Aetherling=1 Aethermage's\ Touch=1 Aetherplasm=1 +Aethershield\ Artificer=1 Aethersnipe=1 Aethersquall\ Ancient=1 Aetherstorm\ Roc=1 Aetherstream\ Leopard=1 +Aethertide\ Whale=1 Aethertorch\ Renegade=1 Aethertow=1 -Affa\ Guard\ Hound=1 +Aetherwind\ Basker=1 Affa\ Protector=1 Afflict=1 Afflicted\ Deserter=1 Afterlife=1 Aftershock=1 Agadeem\ Occultist=1 -Ageless\ Entity=1 -Ageless\ Sentinels=1 -Agent\ of\ Erebos=1 Agent\ of\ Horizons=1 Agent\ of\ Masks=1 Agent\ of\ the\ Fates=1 Aggressive\ Urge=1 Agility=1 +Agonizing\ Demise=1 Agonizing\ Memories=1 Agony\ Warp=1 Agoraphobia=1 @@ -137,29 +137,31 @@ Aid\ from\ the\ Cowl=1 Aim\ High=1 Ainok\ Artillerist=1 Ainok\ Bond-Kin=1 -Ainok\ Guide=1 Ainok\ Tracker=1 +Air\ Bladder=1 Air\ Elemental=1 Air\ Servant=1 Airborne\ Aid=1 Airdrop\ Aeronauts=1 -Airdrop\ Condor=1 -Ajani's\ Chosen=1 Ajani's\ Mantra=1 Ajani's\ Sunstriker=1 Akki\ Avalanchers=1 Akki\ Blizzard-Herder=1 +Akki\ Drillmaster=1 Akki\ Lavarunner=1 +Akki\ Raider=1 Akki\ Rockspeaker=1 -Akki\ Underling=1 Akki\ Underminer=1 +Akoum\ Battlesinger=1 Akoum\ Boulderfoot=1 -Akoum\ Firebird=1 Akoum\ Flameseeker=1 Akoum\ Hellkite=1 Akoum\ Stonewaker=1 +Akrasan\ Squire=1 Akroan\ Conscriptor=1 +Akroan\ Crusader=1 Akroan\ Hoplite=1 +Akroan\ Horse=1 Akroan\ Jailer=1 Akroan\ Line\ Breaker=1 Akroan\ Mastiff=1 @@ -168,10 +170,9 @@ Akroan\ Sergeant=1 Akroma's\ Blessing=1 Akroma's\ Devoted=1 Akron\ Legionnaire=1 -Akuta,\ Born\ of\ Ash=1 +Aku\ Djinn=1 Alabaster\ Kirin=1 -Alabaster\ Mage=1 -Alabaster\ Potion=1 +Alabaster\ Wall=1 Alaborn\ Musketeer=1 Alaborn\ Trooper=1 Aladdin's\ Ring=1 @@ -179,19 +180,16 @@ Alarum=1 Albino\ Troll=1 Alchemist's\ Apprentice=1 Alchemist's\ Greeting=1 -Alchemist's\ Vial=1 -Alchor's\ Tomb=1 -Alesha's\ Vanguard=1 +Aleatory=1 Algae\ Gharial=1 Alhammarret,\ High\ Arbiter=1 Aligned\ Hedron\ Network=1 Alive\ //\ Well=1 All\ Suns'\ Dawn=1 -Allay=1 Alley\ Evasion=1 Alley\ Strangler=1 Allied\ Reinforcements=1 -Allied\ Strategies=1 +Alloy\ Golem=1 Alloy\ Myr=1 Alluring\ Scent=1 Alluring\ Siren=1 @@ -201,9 +199,8 @@ Alms\ Beast=1 Alms\ of\ the\ Vein=1 Alpha\ Authority=1 Alpha\ Brawl=1 +Alpha\ Kavu=1 Alpha\ Myr=1 -Alpha\ Status=1 -Alpha\ Tyrranax=1 Alpine\ Grizzly=1 Altac\ Bloodseeker=1 Altar's\ Reap=1 @@ -212,17 +209,21 @@ Altar\ of\ Shadows=1 Altar\ of\ the\ Brood=1 Altar\ of\ the\ Lost=1 Altered\ Ego=1 +Always\ Watching=1 +Amaranthine\ Wall=1 Amass\ the\ Components=1 +Ambassador\ Laquatus=1 Ambassador\ Oak=1 Ambitious\ Aetherborn=1 Ambuscade=1 Ambuscade\ Shaman=1 -Ambush\ Commander=1 Ambush\ Krotiq=1 Ambush\ Party=1 Ambush\ Viper=1 +Amnesia=1 Amoeboid\ Changeling=1 Amok=1 +Amphibious\ Kavu=1 Amphin\ Cutthroat=1 Amphin\ Pathmage=1 Ampryn\ Tactician=1 @@ -232,49 +233,55 @@ Amrou\ Seekers=1 Amugaba=1 Amulet\ of\ Kroog=1 Ana\ Battlemage=1 +Ana\ Disciple=1 +Ana\ Sanctuary=1 +Anaba\ Ancestor=1 Anaba\ Shaman=1 Anaba\ Spirit\ Crafter=1 Anaconda=1 +Anarchist=1 Anathemancer=1 -Anavolver=1 Anax\ and\ Cymede=1 +Ancestor's\ Chosen=1 Ancestor's\ Prophet=1 Ancestral\ Memories=1 -Ancestral\ Statue=1 +Ancestral\ Tribute=1 Ancestral\ Vengeance=1 Anchor\ to\ the\ Aether=1 Ancient\ Amphitheater=1 +Ancient\ Animus=1 Ancient\ Brontodon=1 Ancient\ Carp=1 Ancient\ Crab=1 Ancient\ Hellkite=1 -Ancient\ Hydra=1 -Ancient\ Ooze=1 +Ancient\ Kavu=1 Ancient\ Runes=1 Ancient\ Silverback=1 Andradite\ Leech=1 Angel's\ Feather=1 +Angel's\ Herald=1 Angel's\ Mercy=1 Angel's\ Tomb=1 Angel's\ Trumpet=1 Angel\ of\ Condemnation=1 Angel\ of\ Deliverance=1 +Angel\ of\ Despair=1 Angel\ of\ Flight\ Alabaster=1 Angel\ of\ Fury=1 -Angel\ of\ Glory's\ Rise=1 Angel\ of\ Light=1 Angel\ of\ Mercy=1 Angel\ of\ Renewal=1 +Angel\ of\ Retribution=1 Angel\ of\ Salvation=1 +Angel\ of\ the\ Dawn=1 Angel\ of\ the\ God-Pharaoh=1 +Angelfire\ Crusader=1 Angelheart\ Vial=1 -Angelic\ Accord=1 Angelic\ Arbiter=1 Angelic\ Armaments=1 Angelic\ Benediction=1 Angelic\ Blessing=1 Angelic\ Captain=1 -Angelic\ Chorus=1 Angelic\ Curator=1 Angelic\ Edict=1 Angelic\ Favor=1 @@ -287,13 +294,14 @@ Angelic\ Shield=1 Angelic\ Skirmisher=1 Angelic\ Voices=1 Angelic\ Wall=1 +Angelsong=1 Angler\ Drake=1 Angrath's\ Marauders=1 Angry\ Mob=1 Animal\ Boneyard=1 Animal\ Magnetism=1 Animate\ Artifact=1 -Animate\ Dead=1 +Animate\ Land=1 Animate\ Wall=1 Animation\ Module=1 Animist's\ Awakening=1 @@ -308,19 +316,21 @@ Anointed\ Deacon=1 Anointer\ Priest=1 Anointer\ of\ Champions=1 Ant\ Queen=1 -Antagonism=1 -Anthousa,\ Setessan\ Hero=1 -Anthroplasm=1 +Anthem\ of\ Rakdos=1 Anticipate=1 Antler\ Skulkin=1 +Anurid\ Barkripper=1 +Anurid\ Brushhopper=1 Anurid\ Murkdiver=1 Anurid\ Scavenger=1 +Anurid\ Swarmsnapper=1 Anvilwrought\ Raptor=1 -Apathy=1 +Apes\ of\ Rath=1 Aphetto\ Dredging=1 Aphetto\ Exterminator=1 Aphetto\ Vulture=1 Aphotic\ Wisps=1 +Apocalypse\ Demon=1 Apocalypse\ Hydra=1 Apothecary\ Geist=1 Apothecary\ Initiate=1 @@ -328,21 +338,23 @@ Appeal\ //\ Authority=1 Appetite\ for\ Brains=1 Appetite\ for\ the\ Unnatural=1 Apprentice\ Wizard=1 +Approach\ of\ the\ Second\ Sun=1 Aquamoeba=1 -Aquamorph\ Entity=1 Aquastrand\ Spider=1 Aquatic\ Incursion=1 Aquitect's\ Will=1 Araba\ Mothrider=1 -Arachnoid=1 Arachnus\ Spinner=1 Arachnus\ Web=1 Aradara\ Express=1 Arashi,\ the\ Sky\ Asunder=1 +Arashin\ Cleric=1 +Arashin\ Sovereign=1 Arashin\ War\ Beast=1 Arbalest\ Elite=1 Arbiter\ of\ Knollridge=1 Arbiter\ of\ the\ Ideal=1 +Arbor\ Armament=1 Arbor\ Colossus=1 Arborback\ Stomper=1 Arc-Slogger=1 @@ -350,23 +362,25 @@ Arc\ Blade=1 Arc\ Lightning=1 Arc\ Runner=1 Arc\ Trail=1 -Arcades\ Sabboth=1 Arcane\ Adaptation=1 -Arcane\ Melee=1 +Arcane\ Flight=1 +Arcane\ Sanctum=1 Arcane\ Spyglass=1 +Arcane\ Teachings=1 +Arcanis\ the\ Omnipotent=1 Arcbound\ Bruiser=1 Arcbound\ Crusher=1 Arcbound\ Fiend=1 Arcbound\ Hybrid=1 Arcbound\ Lancer=1 Arcbound\ Overseer=1 -Arcbound\ Slith=1 +Arcbound\ Reclaimer=1 Arcbound\ Stinger=1 Arcbound\ Wanderer=1 -Arcbound\ Worker=1 -Archangel=1 +Archaeological\ Dig=1 Archdemon\ of\ Unx=1 Archers'\ Parapet=1 +Archers\ of\ Qarsi=1 Archery\ Training=1 Archetype\ of\ Aggression=1 Archetype\ of\ Courage=1 @@ -379,67 +393,75 @@ Archmage\ Ascension=1 Archon\ of\ Justice=1 Archon\ of\ Redemption=1 Archon\ of\ the\ Triumvirate=1 -Archwing\ Dragon=1 +Archweaver=1 Arctic\ Aven=1 -Arctic\ Merfolk=1 Arctic\ Nishoba=1 Arctic\ Wolves=1 Ardent\ Militia=1 Ardent\ Recruit=1 +Ardent\ Soldier=1 Arena\ Athlete=1 Argent\ Mutation=1 Argent\ Sphinx=1 +Argivian\ Blacksmith=1 +Argivian\ Restoration=1 Argothian\ Pixies=1 Argothian\ Swine=1 Argothian\ Treefolk=1 Ark\ of\ Blight=1 -Arm\ with\ Aether=1 +Armageddon\ Clock=1 Armament\ Corps=1 Armament\ Master=1 Armament\ of\ Nyx=1 Armed\ //\ Dangerous=1 Armed\ Response=1 -Armistice=1 +Armillary\ Sphere=1 Armor\ Sliver=1 Armor\ Thrull=1 +Armor\ of\ Faith=1 +Armor\ of\ Thorns=1 Armorcraft\ Judge=1 Armored\ Ascension=1 Armored\ Cancrix=1 Armored\ Griffin=1 Armored\ Pegasus=1 Armored\ Skaab=1 -Armored\ Transport=1 +Armored\ Warhorse=1 Armored\ Wolf-Rider=1 Armorer\ Guildmage=1 -Armory\ Guard=1 Armory\ of\ Iroas=1 Arms\ Dealer=1 -Army\ Ants=1 Arrest=1 Arrogant\ Bloodlord=1 -Arrogant\ Wurm=1 Arrow\ Storm=1 +Arrows\ of\ Justice=1 Arsenal\ Thresher=1 Arterial\ Flow=1 -Artful\ Maneuver=1 +Artifact\ Blast=1 +Artificer's\ Assistant=1 Artificer's\ Epiphany=1 Artificer's\ Hex=1 +Artificial\ Evolution=1 Artillerize=1 Artisan's\ Sorrow=1 Artisan\ of\ Forms=1 Artisan\ of\ Kozilek=1 +Arvad\ the\ Cursed=1 +Aryel,\ Knight\ of\ Windgrace=1 +Ascendant\ Evincar=1 Ascended\ Lawmage=1 -Ascending\ Aven=1 +Ash\ Zealot=1 Asha's\ Favor=1 -Ashcloud\ Phoenix=1 Ashcoat\ Bear=1 Ashen\ Firebeast=1 Ashen\ Ghoul=1 +Ashen\ Monstrosity=1 Ashenmoor\ Cohort=1 Ashenmoor\ Gouger=1 Ashes\ of\ the\ Fallen=1 Ashiok's\ Adept=1 Ashling's\ Prerogative=1 +Ashling,\ the\ Extinguisher=1 Ashling\ the\ Pilgrim=1 Ashnod's\ Cylix=1 Ashnod's\ Transmogrant=1 @@ -448,48 +470,48 @@ Aspect\ of\ Mongoose=1 Asphodel\ Wanderer=1 Asphyxiate=1 Aspiring\ Aeronaut=1 +Assassin's\ Strike=1 Assassinate=1 Assault\ //\ Battery=1 Assault\ Griffin=1 Assault\ Zeppelid=1 -Assemble\ the\ Legion=1 Assembled\ Alphas=1 -Assembly-Worker=1 Assert\ Authority=1 -Astral\ Cornucopia=1 Astral\ Slide=1 Astral\ Steel=1 Astrolabe=1 +Asylum\ Visitor=1 +Atarka\ Efreet=1 Atarka\ Monument=1 Atarka\ Pummeler=1 +Atogatog=1 Attended\ Knight=1 +Attune\ with\ Aether=1 Atzocan\ Archer=1 Atzocan\ Seer=1 Audacious\ Infiltrator=1 Auger\ Spree=1 Augmenting\ Automaton=1 Augur\ il-Vec=1 -Augury\ Adept=1 Augury\ Owl=1 -Auntie's\ Hovel=1 Auntie's\ Snitch=1 Aura\ Barbs=1 +Aura\ Extraction=1 Aura\ Finesse=1 -Aura\ Fracture=1 +Aura\ Graft=1 Auramancer's\ Guise=1 Auramancer=1 -Auratog=1 Auratouched\ Mage=1 -Auriok\ Bladewarden=1 Auriok\ Edgewright=1 Auriok\ Glaivemaster=1 -Auriok\ Replica=1 Auriok\ Salvagers=1 +Auriok\ Steelshaper=1 Auriok\ Sunchaser=1 Auriok\ Survivors=1 -Aurochs=1 +Auriok\ Transfixer=1 +Auriok\ Windwalker=1 Aurora\ Eidolon=1 -Aurora\ Griffin=1 +Auspicious\ Ancestor=1 Autochthon\ Wurm=1 Autumn's\ Veil=1 Autumn\ Willow=1 @@ -500,13 +522,14 @@ Avacyn's\ Pilgrim=1 Avacyn,\ Guardian\ Angel=1 Avacynian\ Missionaries=1 Avacynian\ Priest=1 -Avalanche\ Tusker=1 Avarax=1 Avarice\ Amulet=1 Avarice\ Totem=1 Avatar\ of\ Might=1 +Aven\ Archer=1 Aven\ Augur=1 Aven\ Battle\ Priest=1 +Aven\ Brigadier=1 Aven\ Cloudchaser=1 Aven\ Envoy=1 Aven\ Farseer=1 @@ -516,34 +539,41 @@ Aven\ Flock=1 Aven\ Initiate=1 Aven\ Liberator=1 Aven\ Mimeomancer=1 +Aven\ Mindcensor=1 Aven\ Redeemer=1 Aven\ Reedstalker=1 Aven\ Riftwatcher=1 +Aven\ Sentry=1 Aven\ Shrine=1 -Aven\ Skirmisher=1 Aven\ Smokeweaver=1 Aven\ Squire=1 Aven\ Sunstriker=1 Aven\ Surveyor=1 Aven\ Tactician=1 +Aven\ Trailblazer=1 +Aven\ Trooper=1 +Aven\ Warcraft=1 +Aven\ Warhawk=1 Aven\ Wind\ Guide=1 +Aven\ Wind\ Mage=1 Aven\ Windreader=1 Aven\ of\ Enduring\ Hope=1 Avenging\ Angel=1 Avenging\ Arrow=1 -Avenging\ Druid=1 Avian\ Changeling=1 Aviary\ Mechanic=1 +Aviation\ Pioneer=1 +Avizoa=1 +Avoid\ Fate=1 Awaken\ the\ Ancient=1 Awaken\ the\ Bear=1 Awakened\ Amalgam=1 Awakener\ Druid=1 Awe\ Strike=1 Awe\ for\ the\ Guilds=1 -Axebane\ Guardian=1 Axebane\ Stag=1 -Axegrinder\ Giant=1 Axelrod\ Gunnarson=1 +Ayli,\ Eternal\ Pilgrim=1 Aysen\ Bureaucrats=1 Aysen\ Crusader=1 Ayumi,\ the\ Last\ Visitor=1 @@ -559,13 +589,13 @@ Azorius\ Guildmage=1 Azorius\ Herald=1 Azorius\ Justiciar=1 Azorius\ Keyrune=1 -Azorius\ Ploy=1 +Azure\ Drake=1 Azure\ Mage=1 Back\ from\ the\ Brink=1 -Back\ to\ Nature=1 -Backlash=1 Backwoods\ Survivalists=1 Bad\ River=1 +Baffling\ End=1 +Baird,\ Steward\ of\ Argive=1 Baku\ Altar=1 Bala\ Ged\ Scorpion=1 Bala\ Ged\ Thief=1 @@ -573,8 +603,7 @@ Balance\ of\ Power=1 Balduvian\ Barbarians=1 Balduvian\ Conjurer=1 Balduvian\ Dead=1 -Balduvian\ Frostwaker=1 -Balduvian\ Horde=1 +Balduvian\ Fallen=1 Balduvian\ Rage=1 Balduvian\ Warlord=1 Baleful\ Ammit=1 @@ -582,68 +611,68 @@ Baleful\ Eidolon=1 Baleful\ Force=1 Baleful\ Stare=1 Ballista\ Charger=1 -Ballista\ Squad=1 Balloon\ Peddler=1 Ballynock\ Cohort=1 Ballynock\ Trapper=1 -Ballyrush\ Banneret=1 Baloth\ Cage\ Trap=1 +Baloth\ Gorger=1 Baloth\ Null=1 Baloth\ Pup=1 Baloth\ Woodcrasher=1 Balshan\ Beguiler=1 +Balshan\ Collaborator=1 +Balshan\ Griffin=1 Balustrade\ Spy=1 Bamboozle=1 Bandage=1 Bane\ Alley\ Broker=1 Bane\ of\ Bala\ Ged=1 Baneful\ Omen=1 -Banewasp\ Affliction=1 Banewhip\ Punisher=1 +Banisher\ Priest=1 Banishing\ Stroke=1 Banishment\ Decree=1 Banners\ Raised=1 Banshee's\ Blade=1 Banshee=1 -Banshee\ of\ the\ Dread\ Choir=1 -Bant\ Battlemage=1 Bant\ Sojourners=1 Bar\ the\ Door=1 +Barbarian\ Bully=1 +Barbarian\ Riftcutter=1 +Barbed-Back\ Wurm=1 +Barbed\ Battlegear=1 Barbed\ Lightning=1 Barbed\ Sextant=1 Barbed\ Shocker=1 Barbed\ Sliver=1 +Barbed\ Wire=1 Barishi=1 Barkhide\ Mauler=1 Barkshell\ Blessing=1 Barktooth\ Warbeard=1 Barl's\ Cage=1 -Barony\ Vampire=1 Barrage\ Ogre=1 Barrage\ Tyrant=1 Barrage\ of\ Boulders=1 -Barrage\ of\ Expendables=1 +Barrel\ Down\ Sokenzan=1 Barren\ Glory=1 Barrenton\ Cragtreads=1 +Barrenton\ Medic=1 Barricade\ Breaker=1 Barrin's\ Codex=1 -Bartel\ Runeaxe=1 -Barter\ in\ Blood=1 +Barrin's\ Unmaking=1 Basal\ Sliver=1 Basal\ Thrull=1 Basalt\ Gargoyle=1 Basandra,\ Battle\ Seraph=1 +Bash\ to\ Bits=1 Basilica\ Guards=1 Basilica\ Screecher=1 -Basking\ Rootwalla=1 Bassara\ Tower\ Archer=1 Bastion\ Enforcer=1 Bastion\ Inventor=1 Bastion\ Mastodon=1 -Bathe\ in\ Dragonfire=1 Bathe\ in\ Light=1 -Baton\ of\ Courage=1 -Battered\ Golem=1 Batterhorn=1 Battering\ Craghorn=1 Battering\ Krasis=1 @@ -651,16 +680,16 @@ Battering\ Sliver=1 Battering\ Wurm=1 Battle-Mad\ Ronin=1 Battle-Rattle\ Shaman=1 -Battle\ Brawler=1 Battle\ Hurda=1 Battle\ Mastery=1 +Battle\ Screech=1 Battle\ Sliver=1 Battle\ Squadron=1 Battle\ of\ Wits=1 Battlefield\ Medic=1 +Battlefield\ Percher=1 Battlefield\ Scavenger=1 Battlefield\ Thaumaturge=1 -Battleflight\ Eagle=1 Battlefront\ Krushok=1 Battlegate\ Mimic=1 Battlegrace\ Angel=1 @@ -671,26 +700,32 @@ Battlewand\ Oak=1 Battlewise\ Hoplite=1 Battlewise\ Valor=1 Batwing\ Brume=1 +Bay\ Falcon=1 Bayou\ Dragonfly=1 -Bazaar\ Krovod=1 -Bazaar\ Trader=1 -Beacon\ Behemoth=1 Beacon\ Hawk=1 Beacon\ of\ Destiny=1 Beacon\ of\ Destruction=1 Beacon\ of\ Immortality=1 +Beacon\ of\ Unrest=1 Bear's\ Companion=1 Bearer\ of\ Silence=1 Bearer\ of\ the\ Heavens=1 +Bearscape=1 +Beast\ Attack=1 +Beast\ Hunt=1 +Beast\ of\ Burden=1 Beastbreaker\ of\ Bala\ Ged=1 Beastcaller\ Savant=1 -Beastmaster's\ Magemark=1 +Beckon\ Apparition=1 +Bedlam=1 Bee\ Sting=1 Beetleback\ Chief=1 Beetleform\ Mage=1 -Befoul=1 +Befuddle=1 +Behemoth's\ Herald=1 Behemoth\ Sledge=1 Behind\ the\ Scenes=1 +Belbe's\ Percher=1 Belfry\ Spirit=1 Belligerent\ Brontodon=1 Belligerent\ Hatchling=1 @@ -706,36 +741,42 @@ Belltower\ Sphinx=1 Beloved\ Chaplain=1 Benalish\ Cavalry=1 Benalish\ Commander=1 +Benalish\ Emissary=1 +Benalish\ Heralds=1 Benalish\ Hero=1 +Benalish\ Honor\ Guard=1 +Benalish\ Knight=1 +Benalish\ Lancer=1 +Benalish\ Missionary=1 Benalish\ Trapper=1 Benalish\ Veteran=1 Beneath\ the\ Sands=1 Benediction\ of\ Moons=1 Benefaction\ of\ Rhonas=1 Benevolent\ Ancestor=1 +Benevolent\ Bodyguard=1 Benthic\ Behemoth=1 +Benthic\ Djinn=1 Benthic\ Explorers=1 Benthic\ Giant=1 Benthic\ Infiltrator=1 Bereavement=1 +Berserk\ Murlodont=1 +Berserkers\ of\ Blood\ Ridge=1 Bestial\ Menace=1 -Betrayal\ of\ Flesh=1 -Betrothed\ of\ Fire=1 Bewilder=1 Bident\ of\ Thassa=1 +Bile\ Blight=1 Bile\ Urchin=1 Binding\ Agony=1 -Binding\ Grasp=1 Binding\ Mummy=1 Biomantic\ Mastery=1 Biomass\ Mutation=1 Bioplasm=1 -Biorhythm=1 Bioshift=1 Biovisionary=1 Birthing\ Hulk=1 Bishop's\ Soldier=1 -Bishop\ of\ Binding=1 Bishop\ of\ Rebirth=1 Bishop\ of\ the\ Bloodstained=1 Biting\ Rain=1 @@ -745,17 +786,18 @@ Bitterblade\ Warrior=1 Bitterbow\ Sharpshooters=1 Bitterheart\ Witch=1 Bituminous\ Blast=1 -Black\ Cat=1 Black\ Knight=1 Black\ Oak\ of\ Odunos=1 Black\ Poplar\ Shaman=1 +Blackblade\ Reforged=1 Blackcleave\ Goblin=1 Blade-Tribe\ Berserkers=1 -Blade\ of\ the\ Sixth\ Pride=1 Bladed\ Bracers=1 Bladed\ Pinions=1 +Bladed\ Sentinel=1 Blades\ of\ Velis\ Vel=1 Bladetusk\ Boar=1 +Bladewing's\ Thrall=1 Blanchwood\ Armor=1 Blanchwood\ Treefolk=1 Blast\ of\ Genius=1 @@ -764,21 +806,23 @@ Blastoderm=1 Blaze=1 Blaze\ Commando=1 Blaze\ of\ Glory=1 +Blazethorn\ Scarecrow=1 Blazing\ Blade\ Askari=1 Blazing\ Hellhound=1 Blazing\ Hope=1 Blazing\ Specter=1 Blazing\ Torch=1 -Blazing\ Volley=1 Bleak\ Coven\ Vampires=1 Blessed\ Breath=1 +Blessed\ Light=1 Blessed\ Orator=1 +Blessed\ Reincarnation=1 Blessed\ Reversal=1 Blessed\ Spirits=1 Blessing=1 +Blessing\ of\ Belzenlok=1 Blessing\ of\ Leeches=1 Blessing\ of\ the\ Nephilim=1 -Blessings\ of\ Nature=1 Blight\ Herder=1 Blight\ Keeper=1 Blight\ Sickle=1 @@ -787,16 +831,17 @@ Blighted\ Bat=1 Blighted\ Cataract=1 Blighted\ Fen=1 Blighted\ Gorge=1 +Blighted\ Shaman=1 Blighted\ Steppe=1 Blighted\ Woodland=1 -Blightsoil\ Druid=1 Blightspeaker=1 Blightwidow=1 -Blind-Spot\ Giant=1 Blind\ Creeper=1 +Blind\ Fury=1 Blind\ Hunter=1 -Blind\ Phantasm=1 Blind\ Zealot=1 +Blind\ with\ Anger=1 +Blinding\ Angel=1 Blinding\ Beam=1 Blinding\ Drone=1 Blinding\ Flare=1 @@ -807,10 +852,14 @@ Blinding\ Powder=1 Blinding\ Souleater=1 Blinding\ Spray=1 Blinking\ Spirit=1 +Blinkmoth\ Infusion=1 +Blinkmoth\ Urn=1 Blinkmoth\ Well=1 +Blister\ Beetle=1 Blistercoil\ Weird=1 Blistergrub=1 Blistering\ Barrier=1 +Blistering\ Dieflyn=1 Blisterpod=1 Blitz\ Hellion=1 Blizzard\ Elemental=1 @@ -819,10 +868,11 @@ Bloated\ Toad=1 Blockade\ Runner=1 Blockbuster=1 Blood-Chin\ Fanatic=1 -Blood-Chin\ Rager=1 Blood-Cursed\ Knight=1 Blood\ Bairn=1 Blood\ Celebrant=1 +Blood\ Clock=1 +Blood\ Cultist=1 Blood\ Frenzy=1 Blood\ Funnel=1 Blood\ Host=1 @@ -836,17 +886,20 @@ Blood\ Seeker=1 Blood\ Speaker=1 Blood\ Tithe=1 Blood\ Tribute=1 -Blood\ Tyrant=1 +Blood\ Vassal=1 Bloodbond\ March=1 Bloodbond\ Vampire=1 Bloodbriar=1 +Bloodcrazed\ Goblin=1 Bloodcrazed\ Hoplite=1 Bloodcrazed\ Neonate=1 -Bloodcrazed\ Paladin=1 Bloodcurdler=1 +Bloodfire\ Colossus=1 Bloodfire\ Dwarf=1 Bloodfire\ Enforcers=1 Bloodfire\ Expert=1 +Bloodfire\ Infusion=1 +Bloodfire\ Kavu=1 Bloodfire\ Mentor=1 Bloodfray\ Giant=1 Bloodgift\ Demon=1 @@ -854,57 +907,71 @@ Bloodhall\ Ooze=1 Bloodhall\ Priest=1 Bloodhunter\ Bat=1 Bloodhusk\ Ritualist=1 +Bloodied\ Ghost=1 Bloodletter\ Quill=1 +Bloodline\ Keeper=1 Bloodline\ Shaman=1 Bloodlust\ Inciter=1 Bloodmad\ Vampire=1 Bloodmark\ Mentor=1 -Bloodpyre\ Elemental=1 Bloodrage\ Brawler=1 Bloodrage\ Vampire=1 Bloodrite\ Invoker=1 Bloodrock\ Cyclops=1 Bloodscale\ Prowler=1 Bloodscent=1 -Bloodshot\ Cyclops=1 -Bloodsoaked\ Champion=1 +Bloodshed\ Fever=1 +Bloodshot\ Trainee=1 Bloodstoke\ Howler=1 Bloodstone\ Cameo=1 +Bloodstone\ Goblin=1 +Bloodtallow\ Candle=1 Bloodthirsty\ Ogre=1 Bloodthorn\ Taunter=1 Bloodthrone\ Vampire=1 Bloodwater\ Entity=1 Blossom\ Dryad=1 +Blossoming\ Wreath=1 Blowfly\ Infestation=1 Bludgeon\ Brawl=1 Blunt\ the\ Assault=1 Blur\ of\ Blades=1 Blustersquall=1 +Boa\ Constrictor=1 Boar\ Umbra=1 +Board\ the\ Weatherlight=1 Body\ of\ Jukai=1 Bog-Strider\ Ash=1 +Bog\ Down=1 +Bog\ Elemental=1 +Bog\ Gnarr=1 Bog\ Hoodlums=1 Bog\ Imp=1 +Bog\ Initiate=1 Bog\ Raiders=1 Bog\ Serpent=1 -Bog\ Smugglers=1 Bog\ Tatters=1 Bog\ Wraith=1 +Bog\ Wreckage=1 +Bogardan\ Firefiend=1 +Bogardan\ Hellkite=1 +Bogardan\ Lancer=1 Bogardan\ Phoenix=1 Bogbrew\ Witch=1 Boggart\ Arsonists=1 Boggart\ Birth\ Rite=1 Boggart\ Brute=1 -Boggart\ Forager=1 -Boggart\ Harbinger=1 -Boggart\ Loggers=1 Boggart\ Mob=1 -Boggart\ Ram-Gang=1 Boggart\ Shenanigans=1 +Bogstomper=1 +Boiling\ Blood=1 Boiling\ Earth=1 +Boiling\ Seas=1 Bojuka\ Brigand=1 +Bola\ Warrior=1 Bold\ Defense=1 Bold\ Impaler=1 +Boldwyr\ Heavyweights=1 Boldwyr\ Intimidator=1 Bolt\ of\ Keranos=1 Boltwing\ Marauder=1 @@ -918,35 +985,35 @@ Bonded\ Fetch=1 Bonded\ Horncrest=1 Bonds\ of\ Faith=1 Bonds\ of\ Mortality=1 -Bonds\ of\ Quicksilver=1 Bone\ Flute=1 -Bone\ Harvest=1 +Bone\ Picker=1 Bone\ Saw=1 Bone\ Splinters=1 Bone\ to\ Ash=1 -Bonebreaker\ Giant=1 Bonehoard=1 Boneknitter=1 +Boneshard\ Slasher=1 Bonesplitter\ Sliver=1 Bonethorn\ Valesk=1 Boneyard\ Wurm=1 +Bontu's\ Monument=1 Booby\ Trap=1 +Book\ Burning=1 Book\ of\ Rass=1 Boon\ Satyr=1 Boon\ of\ Emrakul=1 Boon\ of\ Erebos=1 Boonweaver\ Giant=1 +Borborygmos=1 Borderland\ Behemoth=1 Borderland\ Marauder=1 Borderland\ Minotaur=1 Borderland\ Ranger=1 Boreal\ Centaur=1 Boreal\ Griffin=1 -Boris\ Devilboon=1 Boros\ Battleshaper=1 Boros\ Cluestone=1 Boros\ Elite=1 -Boros\ Fury-Shield=1 Boros\ Guildgate=1 Boros\ Guildmage=1 Boros\ Keyrune=1 @@ -957,36 +1024,31 @@ Boros\ Swiftblade=1 Borrowed\ Grace=1 Borrowed\ Hostility=1 Borrowed\ Malevolence=1 -Borrowing\ 100,000\ Arrows=1 Bosh,\ Iron\ Golem=1 +Bosk\ Banneret=1 Bottle\ Gnomes=1 Bottled\ Cloister=1 -Boulder\ Salvo=1 Boulderfall=1 -Bouncing\ Beebles=1 Bound\ //\ Determined=1 Bound\ by\ Moonsilver=1 Bound\ in\ Silence=1 Bounding\ Krasis=1 Bounteous\ Kirin=1 -Bounty\ of\ the\ Luxa=1 Bow\ of\ Nylea=1 Bower\ Passage=1 Brace\ for\ Impact=1 -Braids,\ Conjurer\ Adept=1 -Braidwood\ Sextant=1 +Braids,\ Cabal\ Minion=1 +Braidwood\ Cup=1 Brain\ Freeze=1 Brain\ Gorgers=1 -Brain\ Maggot=1 Brain\ Pry=1 Brain\ Weevil=1 Brain\ in\ a\ Jar=1 Brainbite=1 Brainspoil=1 +Bramble\ Creeper=1 Bramble\ Elemental=1 -Bramblecrush=1 Bramblesnap=1 -Bramblewood\ Paragon=1 Branching\ Bolt=1 Branded\ Brawlers=1 Brass's\ Bounty=1 @@ -994,29 +1056,31 @@ Brass-Talon\ Chimera=1 Brass\ Gnat=1 Brass\ Herald=1 Brass\ Man=1 +Brass\ Secretary=1 Brass\ Squire=1 -Brassclaw\ Orcs=1 -Bravado=1 Brave\ the\ Sands=1 +Brawl-Bash\ Ogre=1 Brawler's\ Plate=1 Brawn=1 Brazen\ Buccaneers=1 Brazen\ Freebooter=1 Brazen\ Scourge=1 Brazen\ Wolves=1 -Breach=1 +Breaching\ Hippocamp=1 Break\ Asunder=1 Break\ Open=1 Break\ of\ Day=1 Breaker\ of\ Armies=1 +Breaking\ Point=1 +Breaking\ Wave=1 Breakneck\ Rider=1 -Breath\ of\ Darigaaz=1 Breath\ of\ Fury=1 Breath\ of\ Life=1 Breath\ of\ Malfegor=1 +Breathstealer=1 Bred\ for\ the\ Hunt=1 Breeding\ Pit=1 -Breezekeeper=1 +Briar\ Patch=1 Briarberry\ Cohort=1 Briarbridge\ Patrol=1 Briarhorn=1 @@ -1029,24 +1093,23 @@ Brighthearth\ Banneret=1 Brigid,\ Hero\ of\ Kinsbaile=1 Brilliant\ Halo=1 Brilliant\ Spectrum=1 -Brilliant\ Ultimatum=1 -Brimstone\ Dragon=1 Brimstone\ Mage=1 -Brimstone\ Volley=1 Brindle\ Boar=1 Brine\ Elemental=1 Brine\ Seer=1 Brine\ Shaman=1 -Bring\ Low=1 +Bring\ to\ Light=1 +Bringer\ of\ the\ Blue\ Dawn=1 Bringer\ of\ the\ Green\ Dawn=1 Bringer\ of\ the\ Red\ Dawn=1 Brink\ of\ Disaster=1 Brink\ of\ Madness=1 Brion\ Stoutarm=1 +Bristling\ Boar=1 Brittle\ Effigy=1 Broken\ Ambitions=1 +Broken\ Bond=1 Broken\ Concentration=1 -Broken\ Fall=1 Broken\ Visage=1 Bronze\ Bombshell=1 Bronze\ Horse=1 @@ -1057,6 +1120,7 @@ Brood\ Butcher=1 Brood\ Keeper=1 Brood\ Monitor=1 Brood\ of\ Cockroaches=1 +Broodbirth\ Viper=1 Broodhatch\ Nantuko=1 Broodhunter\ Wurm=1 Broodmate\ Dragon=1 @@ -1064,32 +1128,24 @@ Broodstar=1 Broodwarden=1 Brothers\ Yamazaki=1 Brothers\ of\ Fire=1 -Browbeat=1 Brown\ Ouphe=1 Browse=1 -Bruna,\ the\ Fading\ Light=1 Brush\ with\ Death=1 -Brutal\ Deceiver=1 Brutal\ Expulsion=1 Brutalizer\ Exarch=1 Brute\ Force=1 Brute\ Strength=1 Bubbling\ Cauldron=1 Buccaneer's\ Bravado=1 -Budoka\ Gardener=1 Builder's\ Blessing=1 Built\ to\ Last=1 Built\ to\ Smash=1 Bull\ Aurochs=1 -Bull\ Cerodon=1 -Bull\ Elephant=1 Bull\ Hippo=1 Bull\ Rush=1 Bullwhip=1 -Bulwark=1 Buoyancy=1 -Burden\ of\ Guilt=1 -Buried\ Alive=1 +Burden\ of\ Greed=1 Burn\ Away=1 Burn\ from\ Within=1 Burn\ the\ Impure=1 @@ -1099,10 +1155,10 @@ Burning-Tree\ Bloodscale=1 Burning\ Anger=1 Burning\ Earth=1 Burning\ Oil=1 -Burning\ Shield\ Askari=1 +Burning\ Palm\ Efreet=1 Burning\ Sun's\ Avatar=1 Burning\ Vengeance=1 -Burnout=1 +Burning\ of\ Xinye=1 Burr\ Grafter=1 Burrenton\ Bombardier=1 Burrenton\ Shield-Bearers=1 @@ -1120,34 +1176,42 @@ Bygone\ Bishop=1 Byway\ Courier=1 Cabal\ Archon=1 Cabal\ Conditioning=1 +Cabal\ Evangel=1 Cabal\ Executioner=1 -Cabal\ Interrogator=1 +Cabal\ Inquisitor=1 +Cabal\ Paladin=1 Cabal\ Patriarch=1 -Cabal\ Ritual=1 Cabal\ Shrine=1 +Cabal\ Surgeon=1 +Cabal\ Torturer=1 Cache\ Raiders=1 -Cached\ Defenses=1 Cackling\ Counterpart=1 -Cackling\ Fiend=1 Cackling\ Flames=1 Cackling\ Imp=1 +Cackling\ Witch=1 Cacophodon=1 Cadaver\ Imp=1 +Cadaverous\ Knight=1 Cage\ of\ Hands=1 +Cagemail=1 Cairn\ Wanderer=1 Calciderm=1 Calciform\ Pools=1 Calcite\ Snapper=1 Calculated\ Dismissal=1 Caldera\ Hellion=1 +Caldera\ Kavu=1 Caldera\ Lake=1 +Caligo\ Skin-Witch=1 Call\ for\ Blood=1 Call\ for\ Unity=1 Call\ of\ the\ Conclave=1 Call\ of\ the\ Full\ Moon=1 Call\ of\ the\ Herd=1 Call\ of\ the\ Nightwing=1 +Call\ of\ the\ Wild=1 Call\ the\ Bloodline=1 +Call\ the\ Cavalry=1 Call\ the\ Gatewatch=1 Call\ the\ Scions=1 Call\ the\ Skybreaker=1 @@ -1157,50 +1221,49 @@ Call\ to\ Heel=1 Call\ to\ Mind=1 Call\ to\ Serve=1 Call\ to\ the\ Feast=1 +Call\ to\ the\ Grave=1 Call\ to\ the\ Kindred=1 +Caller\ of\ Gales=1 Caller\ of\ the\ Pack=1 -Callous\ Giant=1 +Callous\ Oppressor=1 Callow\ Jushi=1 +Caltrops=1 Campaign\ of\ Vengeance=1 Canal\ Monitor=1 Cancel=1 -Candles'\ Glow=1 Candles\ of\ Leng=1 Canker\ Abomination=1 Cankerous\ Thirst=1 Cannibalize=1 +Canopy\ Claws=1 Canopy\ Cover=1 Canopy\ Crawler=1 Canopy\ Gorger=1 Canopy\ Spider=1 -Cantivore=1 +Canyon\ Drake=1 Canyon\ Lurkers=1 Canyon\ Minotaur=1 Canyon\ Wildcat=1 Capashen\ Knight=1 -Capashen\ Standard=1 +Capashen\ Templar=1 Capashen\ Unicorn=1 Capricious\ Efreet=1 Captain's\ Call=1 Captain's\ Claws=1 Captain's\ Hook=1 +Captain's\ Maneuver=1 Captain\ of\ the\ Mists=1 Captivating\ Crew=1 -Captivating\ Glance=1 +Captive\ Flame=1 Captured\ Sunlight=1 -Captured\ by\ the\ Consulate=1 -Carapace=1 Caravan\ Escort=1 Caravan\ Hurda=1 -Caravan\ Vigil=1 Carbonize=1 Careful\ Consideration=1 Caregiver=1 Caress\ of\ Phyrexia=1 -Caribou\ Range=1 Carnage\ Altar=1 Carnage\ Gladiator=1 -Carnage\ Wurm=1 Carnassid=1 Carnifex\ Demon=1 Carnival\ Hellsteed=1 @@ -1208,37 +1271,40 @@ Carnivorous\ Moss-Beast=1 Carnivorous\ Plant=1 Carom=1 Carrier\ Thrall=1 -Carrion\ Ants=1 Carrion\ Beetles=1 Carrion\ Call=1 -Carrion\ Crow=1 Carrion\ Rats=1 Carrion\ Screecher=1 Carrion\ Thrash=1 +Carrion\ Wall=1 +Carrion\ Wurm=1 +Cartel\ Aristocrat=1 Cartographer=1 Cartouche\ of\ Ambition=1 +Cartouche\ of\ Knowledge=1 Cartouche\ of\ Strength=1 -Cartouche\ of\ Zeal=1 Carven\ Caryatid=1 Cascading\ Cataracts=1 Cast\ into\ Darkness=1 Castle=1 +Castle\ Raptors=1 Cat\ Burglar=1 Catacomb\ Sifter=1 Catacomb\ Slug=1 Catalog=1 -Catapult\ Squad=1 +Catalyst\ Elemental=1 Catch\ //\ Release=1 -Cateran\ Brute=1 -Cateran\ Persuader=1 +Cateran\ Kidnappers=1 +Cateran\ Summons=1 Caterwauling\ Boggart=1 Cathar's\ Companion=1 Cathar's\ Shield=1 Cathartic\ Adept=1 Cathedral\ Membrane=1 -Cathedral\ Sanctifier=1 +Cathedral\ of\ War=1 Cathodion=1 Caught\ in\ the\ Brights=1 +Caustic\ Caterpillar=1 Caustic\ Crawler=1 Caustic\ Hound=1 Caustic\ Rain=1 @@ -1246,58 +1312,74 @@ Caustic\ Tar=1 Cautery\ Sliver=1 Cavalry\ Master=1 Cavalry\ Pegasus=1 +Cave\ Sense=1 Cave\ Tiger=1 Cavern\ Crawler=1 Cavern\ Lampad=1 Cavern\ Thoctar=1 +Cease-Fire=1 Ceaseless\ Searblades=1 +Celestial\ Ancient=1 Celestial\ Archon=1 Celestial\ Crusader=1 Celestial\ Dawn=1 Celestial\ Flare=1 +Celestial\ Kirin=1 Celestial\ Mantle=1 Celestial\ Sword=1 Cellar\ Door=1 Cemetery\ Puca=1 -Cemetery\ Reaper=1 Cemetery\ Recruitment=1 +Cenn's\ Enlistment=1 Cenn's\ Heir=1 Cenn's\ Tactician=1 Centaur's\ Herald=1 Centaur\ Archer=1 Centaur\ Battlemaster=1 +Centaur\ Chieftain=1 Centaur\ Courser=1 Centaur\ Glade=1 Centaur\ Healer=1 Centaur\ Omenreader=1 -Centaur\ Safeguard=1 +Centaur\ Rootcaster=1 Center\ Soul=1 -Cephalid\ Constable=1 -Cephalid\ Pathmage=1 +Cephalid\ Aristocrat=1 +Cephalid\ Broker=1 +Cephalid\ Illusionist=1 +Cephalid\ Inkshrouder=1 +Cephalid\ Looter=1 Cephalid\ Retainer=1 Cephalid\ Sage=1 +Cephalid\ Scout=1 +Cephalid\ Shrine=1 Cerebral\ Eruption=1 Cerebral\ Vortex=1 +Ceremonial\ Guard=1 +Cerodon\ Yearling=1 Certain\ Death=1 Cerulean\ Sphinx=1 -Cerulean\ Wisps=1 +Cerulean\ Wyvern=1 Cessation=1 -Cetavolver=1 -Chain\ of\ Acid=1 +Ceta\ Disciple=1 +Ceta\ Sanctuary=1 Chain\ of\ Plasma=1 Chain\ of\ Silence=1 Chainbreaker=1 Chained\ Throatseeker=1 -Chalice\ of\ Life=1 +Chained\ to\ the\ Rocks=1 +Chainer's\ Torment=1 +Chainflinger=1 Chamber\ of\ Manipulation=1 +Chambered\ Nautilus=1 Chameleon\ Blur=1 Champion's\ Drake=1 Champion\ Lancer=1 Champion\ of\ Arashin=1 Champion\ of\ Dusk=1 Champion\ of\ Rhonas=1 +Champion\ of\ the\ Flame=1 Chancellor\ of\ the\ Dross=1 -Chancellor\ of\ the\ Spires=1 +Chancellor\ of\ the\ Forge=1 Chandra's\ Fury=1 Chandra's\ Ignition=1 Chandra's\ Outrage=1 @@ -1305,6 +1387,7 @@ Chandra's\ Phoenix=1 Chandra's\ Pyrohelix=1 Chandra's\ Revolution=1 Chandra's\ Spitfire=1 +Chandra\ Nalaar=1 Change\ of\ Heart=1 Changeling\ Berserker=1 Changeling\ Hero=1 @@ -1312,61 +1395,66 @@ Changeling\ Sentinel=1 Changeling\ Titan=1 Channel\ Harm=1 Channel\ the\ Suns=1 +Channeler\ Initiate=1 Chant\ of\ Vitu-Ghazi=1 Chaos\ Charm=1 Chaos\ Imps=1 Chaos\ Maw=1 Chaotic\ Backlash=1 Chaplain's\ Blessing=1 -Char-Rumbler=1 Char=1 +Charge=1 Charge\ Across\ the\ Araba=1 Charging\ Badger=1 -Charging\ Cinderhorn=1 Charging\ Griffin=1 Charging\ Monstrosaur=1 +Charging\ Paladin=1 Charging\ Rhino=1 Charging\ Slateback=1 Charging\ Tuskodon=1 -Chariot\ of\ Victory=1 -Chariot\ of\ the\ Sun=1 -Charm\ Peddler=1 Charmbreaker\ Devils=1 -Charnelhoard\ Wurm=1 +Charmed\ Griffin=1 Chartooth\ Cougar=1 Chasm\ Drake=1 Chasm\ Guide=1 +Chastise=1 Chemister's\ Trick=1 Cherished\ Hatchling=1 Chief\ of\ the\ Edge=1 Chief\ of\ the\ Foundry=1 Chief\ of\ the\ Scale=1 -Child\ of\ Gaea=1 +Chieftain\ en-Dal=1 Child\ of\ Night=1 -Child\ of\ Thorns=1 +Childhood\ Horror=1 Children\ of\ Korlis=1 +Chill\ Haunting=1 Chill\ of\ Foreboding=1 +Chill\ to\ the\ Bone=1 Chilling\ Grasp=1 Chilling\ Shade=1 +Chime\ of\ Night=1 Chimeric\ Coils=1 Chimeric\ Egg=1 Chimeric\ Idol=1 Chimeric\ Mass=1 Chimeric\ Staff=1 -Chimney\ Imp=1 Chisei,\ Heart\ of\ Oceans=1 Chitinous\ Cloak=1 Chlorophant=1 +Cho-Arrim\ Legate=1 Cho-Manno,\ Revolutionary=1 Choice\ of\ Damnations=1 Choking\ Fumes=1 Choking\ Restraints=1 +Choking\ Tethers=1 Chorus\ of\ Might=1 +Chorus\ of\ the\ Conclave=1 Chorus\ of\ the\ Tides=1 Chosen\ by\ Heliod=1 Chosen\ of\ Markov=1 +Chrome\ Steed=1 Chromescale\ Drake=1 -Chromeshell\ Crab=1 +Chromium=1 Chronatog\ Totem=1 Chronic\ Flooding=1 Chronicler\ of\ Heroes=1 @@ -1376,33 +1464,28 @@ Chronosavant=1 Chronostutter=1 Chronozoa=1 Chub\ Toad=1 +Churning\ Eddy=1 Cinder\ Barrens=1 +Cinder\ Cloud=1 Cinder\ Crawler=1 Cinder\ Elemental=1 -Cinder\ Hellion=1 -Cinder\ Marsh=1 Cinder\ Pyromancer=1 Cinder\ Seer=1 Cinder\ Shade=1 -Cinder\ Storm=1 -Cinder\ Wall=1 Cinderhaze\ Wretch=1 Circle\ of\ Affliction=1 Circle\ of\ Elders=1 Circle\ of\ Flame=1 Circle\ of\ Protection:\ Artifacts=1 -Circle\ of\ Protection:\ Black=1 Circle\ of\ Protection:\ Shadow=1 Circle\ of\ Protection:\ White=1 Circle\ of\ Solace=1 Circling\ Vultures=1 Circu,\ Dimir\ Lobotomist=1 -Circular\ Logic=1 Citadel\ Castellan=1 -Citanul\ Centaurs=1 Citanul\ Druid=1 +Citanul\ Flute=1 Citanul\ Woodreaders=1 -City\ in\ a\ Bottle=1 Civic\ Guildmage=1 Civic\ Saber=1 Civic\ Wayfinder=1 @@ -1414,15 +1497,15 @@ Clarion\ Ultimatum=1 Clash\ of\ Realities=1 Clash\ of\ Wills=1 Claustrophobia=1 -Claws\ of\ Gix=1 Claws\ of\ Valakut=1 -Claws\ of\ Wirewood=1 Clay\ Statue=1 +Cleanse=1 Cleansing\ Beam=1 +Cleansing\ Meditation=1 Cleansing\ Ray=1 +Clear=1 Clear\ Shot=1 Clear\ a\ Path=1 -Clearwater\ Goblet=1 Clergy\ en-Vec=1 Cleric\ of\ the\ Forward\ Order=1 Clickslither=1 @@ -1434,30 +1517,28 @@ Clinging\ Anemones=1 Clinging\ Mists=1 Clip\ Wings=1 Cloak\ and\ Dagger=1 -Cloak\ of\ Confusion=1 -Cloak\ of\ Invisibility=1 Cloak\ of\ Mists=1 Cloaked\ Siren=1 Clock\ of\ Omens=1 Clockspinning=1 Clockwork\ Avian=1 -Clockwork\ Beast=1 Clockwork\ Beetle=1 +Clockwork\ Condor=1 Clockwork\ Dragon=1 Clockwork\ Gnomes=1 Clockwork\ Hydra=1 -Clockwork\ Steed=1 -Clockwork\ Swarm=1 Cloistered\ Youth=1 Clone=1 Clone\ Shell=1 +Close\ Quarters=1 +Clot\ Sliver=1 Cloud\ Crusader=1 -Cloud\ Djinn=1 Cloud\ Dragon=1 Cloud\ Elemental=1 Cloud\ Manta=1 Cloud\ Spirit=1 Cloud\ Sprite=1 +Cloud\ of\ Faeries=1 Cloudblazer=1 Cloudchaser\ Kestrel=1 Cloudcrest\ Lake=1 @@ -1467,18 +1548,21 @@ Cloudheath\ Drake=1 Cloudhoof\ Kirin=1 Cloudpost=1 Cloudreach\ Cavalry=1 +Cloudreader\ Sphinx=1 Cloudseeder=1 +Cloudshift=1 Cloudskate=1 -Cloudthresher=1 Cloven\ Casting=1 Clutch\ of\ Currents=1 Clutch\ of\ Undeath=1 Clutch\ of\ the\ Undercity=1 Coal\ Golem=1 Coal\ Stoker=1 +Coalition\ Flag=1 Coalition\ Victory=1 Coast\ Watcher=1 Coastal\ Discovery=1 +Coastal\ Drake=1 Coastal\ Hornclaw=1 Coat\ with\ Venom=1 Coax\ from\ the\ Blind\ Eternities=1 @@ -1487,26 +1571,30 @@ Cobblebrute=1 Cobbled\ Wings=1 Cobra\ Trap=1 Cockatrice=1 +Codex\ Shredder=1 Coerced\ Confession=1 Coercion=1 Cognivore=1 Cogwork\ Assembler=1 Cogworker's\ Puzzleknot=1 Coiled\ Tinviper=1 -Coiling\ Oracle=1 +Coiling\ Woodworm=1 +Coils\ of\ the\ Medusa=1 +Cold-Water\ Snapper=1 Colfenor's\ Plans=1 Colfenor's\ Urn=1 Collective\ Blessing=1 +Collective\ Defiance=1 Collective\ Effort=1 Colos\ Yearling=1 Colossal\ Dreadmaw=1 Colossal\ Heroics=1 +Colossal\ Might=1 Colossal\ Whale=1 Colossapede=1 Colossus\ of\ Akros=1 Colossus\ of\ Sardia=1 Coma\ Veil=1 -Combat\ Medic=1 Combust=1 Commander's\ Authority=1 Commander\ Greven\ il-Vec=1 @@ -1519,10 +1607,10 @@ Comparative\ Analysis=1 Compelling\ Argument=1 Compelling\ Deterrence=1 Complete\ Disregard=1 +Complex\ Automaton=1 +Complicate=1 Composite\ Golem=1 -Compost=1 Compulsory\ Rest=1 -Concentrate=1 Concerted\ Effort=1 Conclave's\ Blessing=1 Conclave\ Equenaut=1 @@ -1532,21 +1620,20 @@ Concordia\ Pegasus=1 Conduit\ of\ Ruin=1 Conduit\ of\ Storms=1 Cone\ of\ Flame=1 +Confessor=1 Confirm\ Suspicions=1 Confiscate=1 +Confiscation\ Coup=1 Confront\ the\ Unknown=1 -Confusion\ in\ the\ Ranks=1 Congregate=1 Congregation\ at\ Dawn=1 -Conifer\ Strider=1 Conjured\ Currency=1 +Conjurer's\ Ban=1 Conquer=1 Conquering\ Manticore=1 -Conqueror's\ Galleon=1 Conqueror's\ Pledge=1 Consecrate\ Land=1 Consecrated\ by\ Blood=1 -Consign\ //\ Oblivion=1 Consign\ to\ Dream=1 Consign\ to\ Dust=1 Constricting\ Sliver=1 @@ -1559,14 +1646,16 @@ Consulate\ Surveillance=1 Consulate\ Turret=1 Consult\ the\ Necrosages=1 Consume\ Spirit=1 +Consume\ Strength=1 Consume\ the\ Meek=1 +Consuming\ Aberration=1 Consuming\ Bonfire=1 Consuming\ Ferocity=1 Consuming\ Fervor=1 Consuming\ Sinkhole=1 Consuming\ Vortex=1 Consumptive\ Goo=1 -Contagion\ Engine=1 +Contagion\ Clasp=1 Contagious\ Nim=1 Containment\ Membrane=1 Contaminated\ Bond=1 @@ -1577,30 +1666,26 @@ Contingency\ Plan=1 Contraband\ Kingpin=1 Contract\ Killing=1 Contradict=1 +Control\ Magic=1 Controvert=1 Conundrum\ Sphinx=1 -Convalescence=1 Convalescent\ Care=1 Conversion\ Chamber=1 Convicted\ Killer=1 Conviction=1 Convincing\ Mirage=1 Convolute=1 -Convulsing\ Licid=1 Coordinated\ Assault=1 Coordinated\ Barrage=1 Copper\ Carapace=1 Copper\ Myr=1 +Copper\ Tablet=1 Copperhoof\ Vorrac=1 Copperhorn\ Scout=1 -Coral\ Atoll=1 Coral\ Barrier=1 Coral\ Eel=1 -Coral\ Fighters=1 -Coral\ Helm=1 Coral\ Merfolk=1 Coral\ Trickster=1 -Coralhelm\ Commander=1 Coralhelm\ Guide=1 Core\ Prowler=1 Corpse\ Blockade=1 @@ -1608,14 +1693,17 @@ Corpse\ Churn=1 Corpse\ Connoisseur=1 Corpse\ Cur=1 Corpse\ Hauler=1 +Corpse\ Lunge=1 Corpse\ Traders=1 Corpsehatch=1 Corpsejack\ Menace=1 -Corpulent\ Corpse=1 +Corpseweft=1 Corrosive\ Gale=1 Corrosive\ Mentor=1 +Corrosive\ Ooze=1 Corrupt=1 Corrupt\ Eunuchs=1 +Corrupt\ Official=1 Corrupted\ Conscience=1 Corrupted\ Crossroads=1 Corrupted\ Grafstone=1 @@ -1623,26 +1711,29 @@ Corrupted\ Harvester=1 Corrupted\ Resolve=1 Corrupted\ Roots=1 Corrupted\ Zendikon=1 +Corrupting\ Licid=1 Cosi's\ Ravager=1 -Cosi's\ Trickster=1 Cosmic\ Horror=1 -Cosmic\ Larva=1 Costly\ Plunder=1 +Council\ of\ the\ Absolute=1 Counsel\ of\ the\ Soratami=1 Counterbore=1 Counterflux=1 Counterlash=1 Countermand=1 +Countervailing\ Winds=1 Countless\ Gears\ Renegade=1 +Countryside\ Crusher=1 Courageous\ Outrider=1 Courier's\ Capsule=1 Courier\ Griffin=1 -Courier\ Hawk=1 Coursers'\ Accord=1 Court\ Archers=1 Court\ Homunculus=1 Court\ Hussar=1 Court\ Street\ Denizen=1 +Courtly\ Provocateur=1 +Covenant\ of\ Blood=1 Covenant\ of\ Minds=1 Cover\ of\ Winter=1 Cowardice=1 @@ -1653,7 +1744,7 @@ Crab\ Umbra=1 Crabapple\ Cohort=1 Crackdown\ Construct=1 Crackleburr=1 -Crackling\ Doom=1 +Crackling\ Club=1 Crackling\ Perimeter=1 Crackling\ Triton=1 Cradle\ Guard=1 @@ -1665,56 +1756,62 @@ Crafty\ Pathmage=1 Crag\ Puca=1 Cragganwick\ Cremator=1 Cranial\ Archive=1 -Crash=1 +Cranial\ Extraction=1 Crash\ Landing=1 Crash\ Through=1 Crash\ of\ Rhinos=1 Crash\ the\ Ramparts=1 +Crashing\ Boars=1 +Crashing\ Centaur=1 Crashing\ Tide=1 Crater's\ Claws=1 Crater\ Elemental=1 Crater\ Hellion=1 Craterize=1 Craven\ Giant=1 -Craw\ Giant=1 Craw\ Wurm=1 Crawling\ Filth=1 Crawling\ Sensation=1 +Crazed\ Armodon=1 Crazed\ Goblin=1 +Creakwood\ Ghoul=1 Cream\ of\ the\ Crop=1 -Creeperhulk=1 Creeping\ Dread=1 Creeping\ Mold=1 Creeping\ Renaissance=1 Creepy\ Doll=1 Cremate=1 Crescendo\ of\ War=1 +Crested\ Craghorn=1 Crested\ Herdcaller=1 Crib\ Swap=1 -Crime\ //\ Punishment=1 +Crimson\ Hellkite=1 Crimson\ Mage=1 Crimson\ Manticore=1 Crimson\ Muckwader=1 Crimson\ Roc=1 +Crimson\ Wisps=1 Crippling\ Blight=1 Crippling\ Chill=1 Crocanura=1 Crocodile\ of\ the\ Crossing=1 Crookclaw\ Transmuter=1 Crop\ Sigil=1 +Crosis's\ Attendant=1 Crossbow\ Ambush=1 Crossbow\ Infantry=1 Crossroads\ Consecrator=1 +Crosstown\ Courier=1 Crossway\ Vampire=1 Crosswinds=1 Crovax,\ Ascendant\ Hero=1 +Crovax\ the\ Cursed=1 Crow\ of\ Dark\ Tidings=1 Crowd's\ Favor=1 Crowd\ of\ Cinders=1 Crown\ of\ Ascension=1 -Crown\ of\ Awe=1 -Crown\ of\ Convergence=1 Crown\ of\ Empires=1 +Crown\ of\ Flames=1 Crown\ of\ Fury=1 Crown\ of\ Suspicion=1 Crown\ of\ Vigor=1 @@ -1729,18 +1826,19 @@ Cruel\ Finality=1 Cruel\ Revival=1 Cruel\ Sadist=1 Crumble=1 -Crumbling\ Colossus=1 Crumbling\ Vestige=1 Crusader\ of\ Odric=1 +Crush=1 Crush\ Underfoot=1 Crusher\ Zendikon=1 Crushing\ Canopy=1 +Crushing\ Pain=1 Crushing\ Vines=1 Cry\ of\ Contrition=1 Cryoclasm=1 Crypsis=1 Crypt\ Champion=1 -Crypt\ Creeper=1 +Crypt\ Cobra=1 Crypt\ Ripper=1 Crypt\ of\ the\ Eternals=1 Cryptborn\ Horror=1 @@ -1748,43 +1846,43 @@ Cryptic\ Annelid=1 Cryptic\ Cruiser=1 Cryptic\ Serpent=1 Cryptolith\ Fragment=1 -Cryptoplasm=1 Cryptwailing=1 Crystal\ Ball=1 -Crystal\ Golem=1 Crystal\ Rod=1 Crystal\ Seer=1 Crystal\ Shard=1 Crystal\ Spray=1 Crystalline\ Nautilus=1 +Crystallization=1 Cudgel\ Troll=1 Culling\ Dais=1 Culling\ Drone=1 Culling\ Mark=1 +Culling\ Scales=1 Culling\ Sun=1 Cult\ of\ the\ Waxing\ Moon=1 -Cultbrand\ Cinder=1 Cultist's\ Staff=1 Cultivator's\ Caravan=1 Cultivator\ Drone=1 Cultivator\ of\ Blades=1 Cumber\ Stone=1 -Cunning=1 +Cunning\ Bandit=1 Cunning\ Breezedancer=1 Cunning\ Lethemancer=1 Cunning\ Sparkmage=1 Cunning\ Strike=1 Cunning\ Survivor=1 +Curator's\ Ward=1 +Curator\ of\ Mysteries=1 Curio\ Vendor=1 Curiosity=1 Curious\ Homunculus=1 -Curse\ of\ Bloodletting=1 -Curse\ of\ Echoes=1 -Curse\ of\ Misfortunes=1 +Curse\ of\ Death's\ Hold=1 Curse\ of\ Oblivion=1 Curse\ of\ Stalked\ Prey=1 Curse\ of\ Thirst=1 Curse\ of\ Wizardry=1 +Curse\ of\ the\ Cabal=1 Curse\ of\ the\ Nightly\ Hunt=1 Curse\ of\ the\ Swine=1 Cursebreak=1 @@ -1793,59 +1891,59 @@ Cursed\ Minotaur=1 Cursed\ Monstrosity=1 Cursed\ Rack=1 Cursed\ Scroll=1 +Curtain\ of\ Light=1 Custodi\ Soulbinders=1 Custodian\ of\ the\ Trove=1 Cut\ the\ Earthly\ Bond=1 Cut\ the\ Tethers=1 Cutthroat\ Maneuver=1 Cutthroat\ il-Dal=1 -Cyclical\ Evolution=1 +Cycle\ of\ Life=1 Cyclone\ Sire=1 Cyclopean\ Giant=1 Cyclopean\ Mummy=1 Cyclopean\ Snare=1 -Cyclopean\ Tomb=1 Cyclops\ Gladiator=1 +Cyclops\ Tyrant=1 Cyclops\ of\ Eternal\ Fury=1 Cyclops\ of\ One-Eyed\ Pass=1 -Cylian\ Elf=1 -Cylian\ Sunsinger=1 Cystbearer=1 Cytoplast\ Manipulator=1 Cytoplast\ Root-Kin=1 Cytoshape=1 Cytospawn\ Shambler=1 -D'Avenant\ Archer=1 -D'Avenant\ Healer=1 +D'Avenant\ Trapper=1 Dack's\ Duplicate=1 Dagger\ of\ the\ Worthy=1 Daggerback\ Basilisk=1 +Daggerclaw\ Imp=1 Daggerdrome\ Imp=1 Daily\ Regimen=1 Dakmor\ Lancer=1 -Dakmor\ Plague=1 Dakra\ Mystic=1 Dampen\ Thought=1 Dampening\ Pulse=1 -Damping\ Engine=1 Damping\ Matrix=1 -Dance\ of\ Many=1 Dance\ of\ Shadows=1 Dance\ of\ the\ Skywise=1 Dance\ with\ Devils=1 Dancing\ Scimitar=1 -Dandan=1 +Dandn=1 Daraja\ Griffin=1 +Darba=1 Daredevil\ Dragster=1 -Darigaaz's\ Charm=1 +Darigaaz's\ Attendant=1 +Darigaaz's\ Caldera=1 Daring\ Apprentice=1 +Daring\ Archaeologist=1 Daring\ Buccaneer=1 Daring\ Demolition=1 +Daring\ Leap=1 Daring\ Saboteur=1 Daring\ Skyjek=1 Daring\ Sleuth=1 -Daring\ Thief=1 Dark\ Banishing=1 +Dark\ Bargain=1 Dark\ Betrayal=1 Dark\ Dabbling=1 Dark\ Favor=1 @@ -1856,27 +1954,25 @@ Dark\ Intimations=1 Dark\ Nourishment=1 Dark\ Privilege=1 Dark\ Revenant=1 -Dark\ Salvation=1 +Dark\ Supplicant=1 Dark\ Temper=1 Dark\ Tutelage=1 Dark\ Withering=1 +Darkheart\ Sliver=1 Darkling\ Stalker=1 -Darklit\ Gargoyle=1 +Darkslick\ Drake=1 Darksteel\ Axe=1 Darksteel\ Brute=1 Darksteel\ Gargoyle=1 -Darksteel\ Juggernaut=1 Darksteel\ Myr=1 -Darksteel\ Relic=1 +Darksteel\ Pendant=1 Darksteel\ Sentinel=1 Darkthicket\ Wolf=1 Darkwatch\ Elves=1 -Daru\ Cavalier=1 +Darkwater\ Egg=1 Daru\ Encampment=1 -Daru\ Healer=1 Daru\ Lancer=1 -Daru\ Sanctifier=1 -Daru\ Stinger=1 +Daru\ Mender=1 Dash\ Hopes=1 Dauntless\ Aven=1 Dauntless\ Cathar=1 @@ -1884,35 +1980,38 @@ Dauntless\ Dourbark=1 Dauntless\ Onslaught=1 Dauntless\ River\ Marshal=1 Dauthi\ Cutthroat=1 -Dauthi\ Embrace=1 Dauthi\ Jackal=1 Dauthi\ Marauder=1 -Dauthi\ Mercenary=1 Dauthi\ Mindripper=1 Dauthi\ Trapper=1 Dauthi\ Warlord=1 Dawn's\ Reflection=1 +Dawn\ Elemental=1 Dawn\ Gryff=1 Dawn\ to\ Dusk=1 Dawnbringer\ Charioteers=1 Dawnfeather\ Eagle=1 +Dawnglare\ Invoker=1 Dawnglow\ Infusion=1 Dawning\ Purist=1 Dawnray\ Archer=1 Dawnstrike\ Paladin=1 Dawntreader\ Elk=1 Daxos\ of\ Meletis=1 -Day\ of\ Destiny=1 Day\ of\ the\ Dragons=1 +Daybreak\ Chaplain=1 Daybreak\ Ranger=1 Dazzling\ Beauty=1 Dazzling\ Ramparts=1 Dazzling\ Reflection=1 +Dead-Iron\ Sledge=1 Dead\ //\ Gone=1 Dead\ Drop=1 Dead\ Man's\ Chest=1 Dead\ Reveler=1 +Dead\ Ringers=1 Dead\ Weight=1 +Deadapult=1 Deadbridge\ Goliath=1 Deadbridge\ Shaman=1 Deadeye\ Brawler=1 @@ -1923,112 +2022,128 @@ Deadeye\ Rig-Hauler=1 Deadeye\ Tormentor=1 Deadlock\ Trap=1 Deadly\ Allure=1 +Deadly\ Designs=1 +Deadly\ Grub=1 Deadly\ Insect=1 Deadly\ Recluse=1 Deadly\ Wanderings=1 -Deadwood\ Treefolk=1 Dearly\ Departed=1 -Death's-Head\ Buzzard=1 Death's\ Approach=1 Death's\ Duet=1 Death's\ Presence=1 Death-Hood\ Cobra=1 Death\ Bomb=1 -Death\ Charmer=1 Death\ Cultist=1 Death\ Denied=1 Death\ Frenzy=1 Death\ Grasp=1 Death\ Match=1 -Death\ Mutation=1 +Death\ Pit\ Offering=1 Death\ Pits\ of\ Rath=1 Death\ Pulse=1 Death\ Rattle=1 Death\ Stroke=1 -Death\ Watch=1 Death\ Wind=1 Death\ by\ Dragons=1 Death\ of\ a\ Thousand\ Stings=1 Deathbellow\ Raider=1 -Deathbringer\ Regent=1 +Deathbloom\ Thallid=1 +Deathbringer\ Thoctar=1 Deathcap\ Cultivator=1 +Deathcoil\ Wurm=1 Deathcult\ Rogue=1 Deathforge\ Shaman=1 Deathgaze\ Cockatrice=1 -Deathknell\ Kami=1 +Deathgazer=1 +Deathgreeter=1 Deathless\ Ancient=1 +Deathless\ Angel=1 Deathless\ Behemoth=1 Deathmark=1 Deathmark\ Prelate=1 +Deathmask\ Nezumi=1 Deathreap\ Ritual=1 -Deathrender=1 Deathspore\ Thallid=1 Debilitating\ Injury=1 Debtor's\ Pulpit=1 +Debtors'\ Knell=1 +Decaying\ Soil=1 Deceiver\ of\ Form=1 Decimator\ Beetle=1 -Decimator\ Web=1 Decision\ Paralysis=1 -Declaration\ of\ Naught=1 +Declare\ Dominance=1 Decoction\ Module=1 Decommission=1 Decompose=1 +Decomposition=1 Deconstruct=1 Decorated\ Griffin=1 Deem\ Worthy=1 Deep-Sea\ Kraken=1 Deep-Sea\ Terror=1 Deep-Slumber\ Titan=1 -Deep\ Spawn=1 +Deep\ Freeze=1 +Deep\ Reconnaissance=1 Deepcavern\ Imp=1 Deepchannel\ Mentor=1 Deepfathom\ Skulker=1 +Deepfire\ Elemental=1 Deeproot\ Warrior=1 +Deeproot\ Waters=1 +Deeptread\ Merrow=1 Deepwater\ Hypnotist=1 +Deepwood\ Ghoul=1 +Deepwood\ Legate=1 +Deepwood\ Tantiv=1 Deepwood\ Wolverine=1 -Defang=1 Defeat=1 Defend\ the\ Hearth=1 -Defender\ of\ Chaos=1 +Defender\ en-Vec=1 Defender\ of\ Law=1 Defender\ of\ the\ Order=1 Defensive\ Formation=1 Defensive\ Maneuvers=1 -Defensive\ Stance=1 Defiant\ Bloodlord=1 Defiant\ Elf=1 Defiant\ Greatmaw=1 Defiant\ Khenra=1 Defiant\ Ogre=1 Defiant\ Salvager=1 -Defiant\ Vanguard=1 +Defiant\ Strike=1 +Defiling\ Tears=1 Deflection=1 +Deft\ Dismissal=1 Deft\ Duelist=1 Deftblade\ Elite=1 Defy\ Death=1 +Defy\ Gravity=1 Dega\ Sanctuary=1 -Degavolver=1 Deglamer=1 Dehydration=1 Deicide=1 -Delaying\ Shield=1 Delirium\ Skeins=1 -Deluge=1 -Dementia\ Bat=1 +Delusions\ of\ Mediocrity=1 +Dematerialize=1 Dementia\ Sliver=1 Demolish=1 Demolition\ Stomper=1 Demon's\ Grasp=1 +Demon's\ Herald=1 Demon's\ Horn=1 Demon's\ Jester=1 Demonfire=1 Demonic\ Appetite=1 +Demonic\ Collusion=1 +Demonic\ Consultation=1 Demonic\ Taskmaster=1 Demonic\ Torment=1 +Demonic\ Vigor=1 Demonmail\ Hauberk=1 Demonspine\ Whip=1 +Demoralize=1 Demystify=1 Denizen\ of\ the\ Deep=1 +Dense\ Canopy=1 Deny\ Existence=1 Deny\ Reality=1 Depala,\ Pilot\ Exemplar=1 @@ -2038,110 +2153,110 @@ Deranged\ Assistant=1 Deranged\ Hermit=1 Deranged\ Outcast=1 Deranged\ Whelp=1 -Descendant\ of\ Kiyomaro=1 +Dermoplasm=1 Descendant\ of\ Soramaro=1 -Desecration\ Demon=1 +Descent\ into\ Madness=1 +Desecrated\ Earth=1 Desecration\ Elemental=1 Desecration\ Plague=1 Desecrator\ Hag=1 Desert's\ Hold=1 +Desert=1 Desert\ Cerodon=1 +Desert\ Twister=1 Desert\ of\ the\ Fervent=1 Desert\ of\ the\ Glorified=1 Desert\ of\ the\ Indomitable=1 Desert\ of\ the\ Mindful=1 Desert\ of\ the\ True=1 Deserter's\ Quarters=1 -Desolation=1 Desolation\ Giant=1 Desolation\ Twin=1 Desperate\ Castaways=1 Desperate\ Charge=1 +Desperate\ Gambit=1 Desperate\ Ravings=1 Desperate\ Sentry=1 Desperate\ Stand=1 Despise=1 Despoiler\ of\ Souls=1 -Despondency=1 Destined\ //\ Lead=1 Destroy\ the\ Evidence=1 +Destructive\ Force=1 Destructive\ Tampering=1 +Destructive\ Urge=1 Detainment\ Spell=1 -Detonate=1 -Detritivore=1 -Devastating\ Summons=1 Deviant\ Glee=1 Devil's\ Play=1 Devils'\ Playground=1 Devilthorn\ Fox=1 Devoted\ Crop-Mate=1 -Devoted\ Retainer=1 Devotee\ of\ Strength=1 Devour\ in\ Flames=1 +Devour\ in\ Shadow=1 Devouring\ Greed=1 Devouring\ Light=1 Devouring\ Rage=1 +Devouring\ Strossus=1 Devouring\ Swarm=1 Devout\ Chaplain=1 +Devout\ Harpist=1 +Devout\ Lightcaster=1 Devout\ Witness=1 Dewdrop\ Spy=1 Dhund\ Operative=1 -Diabolic\ Machine=1 Diabolic\ Revelation=1 Diabolic\ Tutor=1 Diabolic\ Vision=1 -Dichotomancy=1 -Dictate\ of\ Karametra=1 -Dictate\ of\ the\ Twin\ Gods=1 +Diamond\ Faerie=1 Die\ Young=1 +Diligent\ Excavator=1 Diluvian\ Primordial=1 Dimensional\ Breach=1 Dimensional\ Infiltrator=1 Diminish=1 -Diminishing\ Returns=1 +Dimir\ Charm=1 Dimir\ Cluestone=1 Dimir\ Cutpurse=1 -Dimir\ Guildgate=1 Dimir\ Guildmage=1 Dimir\ House\ Guard=1 Dimir\ Infiltrator=1 Dimir\ Keyrune=1 Dimir\ Machinations=1 -Dimir\ Signet=1 Din\ of\ the\ Fireherd=1 Dingus\ Egg=1 -Dingus\ Staff=1 Dinosaur\ Hunter=1 Dinosaur\ Stampede=1 Dinrova\ Horror=1 Diplomacy\ of\ the\ Wastes=1 +Diplomatic\ Escort=1 Dire\ Fleet\ Captain=1 Dire\ Fleet\ Hoarder=1 Dire\ Fleet\ Interloper=1 Dire\ Fleet\ Neckbreaker=1 Dire\ Undercurrents=1 -Diregraf\ Ghoul=1 -Dirtwater\ Wraith=1 +Diregraf\ Colossus=1 +Diregraf\ Escort=1 +Dirge\ of\ Dread=1 +Dirty\ Wererat=1 Disappear=1 Disappearing\ Act=1 Disarm=1 Disaster\ Radius=1 -Disciple\ of\ Deceit=1 Disciple\ of\ Grace=1 Disciple\ of\ Griselbrand=1 -Disciple\ of\ Law=1 +Disciple\ of\ Kangee=1 Disciple\ of\ Malice=1 Disciple\ of\ Phenax=1 Disciple\ of\ Tevesh\ Szat=1 Disciple\ of\ the\ Old\ Ways=1 -Discombobulate=1 +Disciple\ of\ the\ Ring=1 Discordant\ Dirge=1 -Disdainful\ Stroke=1 +Discordant\ Spirit=1 Disease\ Carriers=1 Disembowel=1 -Disempower=1 Disentomb=1 -Disharmony=1 +Disintegrate=1 Dismal\ Failure=1 Dismantle=1 Dismiss\ into\ Dream=1 @@ -2149,17 +2264,16 @@ Disorder=1 Disowned\ Ancestor=1 Dispeller's\ Capsule=1 Dispense\ Justice=1 -Dispersal\ Shield=1 Dispersal\ Technician=1 Disperse=1 +Dispersing\ Orb=1 Displace=1 Displacement\ Wave=1 -Display\ of\ Dominance=1 Disposal\ Mummy=1 Dispossess=1 Disrupting\ Scepter=1 -Disruption\ Aura=1 Disruptive\ Pitmage=1 +Disruptive\ Student=1 Dissension\ in\ the\ Ranks=1 Dissenter's\ Deliverance=1 Dissipate=1 @@ -2168,14 +2282,14 @@ Dissolve=1 Distant\ Memories=1 Distemper\ of\ the\ Blood=1 Distended\ Mindbender=1 -Distorting\ Lens=1 -Disturbed\ Burial=1 -Dive\ Bomber=1 +Distorting\ Wake=1 +Disturbing\ Plot=1 Dive\ Down=1 Divebomber\ Griffin=1 Divergent\ Growth=1 +Diversionary\ Tactics=1 +Divest=1 Divination=1 -Divine\ Congregation=1 Divine\ Deflection=1 Divine\ Favor=1 Divine\ Offering=1 @@ -2183,7 +2297,8 @@ Divine\ Reckoning=1 Divine\ Transformation=1 Divine\ Verdict=1 Diviner's\ Wand=1 -Dizzy\ Spell=1 +Diviner\ Spirit=1 +Diving\ Griffin=1 Dizzying\ Gaze=1 Djeru's\ Renunciation=1 Djeru's\ Resolve=1 @@ -2194,36 +2309,38 @@ Docent\ of\ Perfection=1 Dodecapod=1 Dogged\ Hunter=1 Dogpile=1 +Dolmen\ Gate=1 Domesticated\ Hydra=1 Domestication=1 -Dominaria's\ Judgment=1 Dominator\ Drone=1 -Domineer=1 Dong\ Zhou,\ the\ Tyrant=1 Doom\ Cannon=1 Doomed\ Dissenter=1 +Doomed\ Necromancer=1 Doomgape=1 Doomwake\ Giant=1 Door\ to\ Nothingness=1 Doorkeeper=1 Dormant\ Gomazoa=1 Dormant\ Sliver=1 -Dormant\ Volcano=1 Dosan's\ Oldest\ Chant=1 Double\ Negative=1 -Doubling\ Chant=1 Doubtless\ One=1 Douse\ in\ Gloom=1 Down\ //\ Dirty=1 +Downdraft=1 Downpour=1 Downsize=1 +Dowsing\ Shaman=1 +Dracoplasm=1 Drag\ Down=1 Drag\ Under=1 +Dragon's\ Eye\ Savants=1 Dragon's\ Eye\ Sentry=1 +Dragon's\ Herald=1 Dragon-Scarred\ Bear=1 Dragon-Style\ Twins=1 Dragon\ Appeasement=1 -Dragon\ Arch=1 Dragon\ Bell\ Monk=1 Dragon\ Blood=1 Dragon\ Egg=1 @@ -2241,66 +2358,74 @@ Dragonlord's\ Prerogative=1 Dragonlord's\ Servant=1 Dragonrage=1 Dragonscale\ Boon=1 -Dragonscale\ General=1 Dragonshift=1 Dragonsoul\ Knight=1 -Dragonstorm=1 +Dragonstalker=1 Drain\ the\ Well=1 Draining\ Whelk=1 Drainpipe\ Vermin=1 Drake-Skull\ Cameo=1 Drake\ Familiar=1 Drake\ Hatchling=1 +Drake\ Haven=1 Drake\ Umbra=1 Drakestown\ Forgotten=1 +Drakewing\ Krasis=1 Dralnu's\ Pet=1 +Dralnu,\ Lich\ Lord=1 Dramatic\ Rescue=1 Dramatic\ Reversal=1 Drana's\ Chosen=1 Drana's\ Emissary=1 -Drana,\ Kalastria\ Bloodchief=1 Drastic\ Revelation=1 Dread=1 Dread\ Defiler=1 Dread\ Drone=1 Dread\ Reaper=1 -Dread\ Return=1 Dread\ Slag=1 -Dread\ Slaver=1 Dread\ Specter=1 +Dread\ Warlock=1 Dread\ Wight=1 Dreadbringer\ Lampads=1 -Dreadship\ Reef=1 Dreadwaters=1 Dreadwing=1 Dream's\ Grip=1 -Dream\ Cache=1 Dream\ Chisel=1 Dream\ Fighter=1 +Dream\ Leash=1 Dream\ Prowler=1 +Dream\ Salvage=1 Dream\ Thief=1 Dream\ Tides=1 Dream\ Twist=1 +Dreamborn\ Muse=1 +Dreamcaller\ Siren=1 Dreamcatcher=1 Dreampod\ Druid=1 Dreams\ of\ the\ Dead=1 Dreamscape\ Artist=1 Dreamspoiler\ Witches=1 +Dreamstealer=1 +Dreamstone\ Hedron=1 +Dreamwinder=1 Dreg\ Mangler=1 Dreg\ Reaver=1 +Dregs\ of\ Sorrow=1 Dregscape\ Zombie=1 Drekavac=1 Drelnoch=1 Drift\ of\ the\ Dead=1 +Drifter\ il-Dal=1 Drifting\ Shade=1 Drill-Skimmer=1 Drinker\ of\ Sorrow=1 +Dripping-Tongue\ Zubera=1 Dripping\ Dead=1 Driven\ //\ Despair=1 Driver\ of\ the\ Dead=1 Drogskol\ Cavalry=1 Drogskol\ Shieldmate=1 -Dromad\ Purebred=1 +Dromar's\ Attendant=1 Dromoka's\ Gift=1 Dromoka\ Captain=1 Dromoka\ Dunecaster=1 @@ -2317,6 +2442,7 @@ Dross\ Hopper=1 Dross\ Prowler=1 Dross\ Scorpion=1 Drove\ of\ Elves=1 +Drover\ of\ the\ Mighty=1 Drown\ in\ Filth=1 Drowned=1 Drowned\ Rusalka=1 @@ -2328,25 +2454,26 @@ Drownyard\ Explorers=1 Drownyard\ Temple=1 Drudge\ Beetle=1 Drudge\ Reavers=1 +Drudge\ Sentinel=1 Drudge\ Skeletons=1 +Druid's\ Call=1 Druid's\ Deliverance=1 Druid's\ Familiar=1 +Druid\ Lyrist=1 +Druid\ of\ the\ Anima=1 Druid\ of\ the\ Cowl=1 Druidic\ Satchel=1 Drumhunter=1 Drunau\ Corpse\ Trawler=1 Dry\ Spell=1 Dryad's\ Caress=1 -Dryad's\ Favor=1 Dryad\ Sophisticate=1 -Dual\ Casting=1 Dual\ Shot=1 +Dub=1 Dubious\ Challenge=1 Duct\ Crawler=1 -Due\ Respect=1 Duergar\ Assailant=1 Duergar\ Cave-Guard=1 -Duergar\ Hedge-Mage=1 Duergar\ Mine-Captain=1 Dukhara\ Peafowl=1 Dukhara\ Scavenger=1 @@ -2358,6 +2485,7 @@ Dunerider\ Outlaw=1 Dunes\ of\ the\ Dead=1 Dungeon\ Geists=1 Dungeon\ Shade=1 +Duplicity=1 Durable\ Handicraft=1 Durkwood\ Baloth=1 Durkwood\ Tracker=1 @@ -2369,25 +2497,31 @@ Duskborne\ Skymarcher=1 Duskdale\ Wurm=1 Duskhunter\ Bat=1 Duskmantle,\ House\ of\ Shadow=1 -Duskmantle\ Guildmage=1 Duskmantle\ Prowler=1 -Duskrider\ Falcon=1 +Duskrider\ Peregrine=1 +Duskwalker=1 Duskworker=1 +Dust\ Corona=1 Dust\ Elemental=1 -Dust\ Stalker=1 -Dust\ of\ Moments=1 Dutiful\ Attendant=1 Dutiful\ Return=1 Dutiful\ Servants=1 +Dutiful\ Thrull=1 Duty-Bound\ Dead=1 -Dwarven\ Bloodboiler=1 +Dwarven\ Berserker=1 +Dwarven\ Blastminer=1 Dwarven\ Demolition\ Team=1 +Dwarven\ Driller=1 +Dwarven\ Landslide=1 Dwarven\ Nomad=1 Dwarven\ Patrol=1 -Dwarven\ Ruins=1 +Dwarven\ Priest=1 +Dwarven\ Recruiter=1 Dwarven\ Shrine=1 Dwarven\ Soldier=1 +Dwarven\ Strike\ Force=1 Dwarven\ Vigilantes=1 +Dwindle=1 Dwynen,\ Gilt-Leaf\ Daen=1 Dying\ Wail=1 Dying\ Wish=1 @@ -2395,19 +2529,22 @@ Dynacharge=1 Dynavolt\ Tower=1 Eager\ Cadet=1 Eager\ Construct=1 +Eagle\ of\ the\ Watch=1 Early\ Frost=1 -Earth\ Surge=1 +Earsplitting\ Rats=1 +Earth\ Elemental=1 Earthblighter=1 Earthbrawn=1 Earthen\ Arms=1 Earthshaker=1 Eastern\ Paladin=1 Eater\ of\ Hope=1 -Ebon\ Dragon=1 -Ebon\ Stronghold=1 +Ebon\ Drake=1 +Ebonblade\ Reaper=1 Ebony\ Horse=1 Ebony\ Rhino=1 Ebony\ Treefolk=1 +Echo\ Circlet=1 Echo\ Mage=1 Echo\ Tracer=1 Echoes\ of\ the\ Kin\ Tree=1 @@ -2416,28 +2553,33 @@ Echoing\ Courage=1 Echoing\ Ruin=1 Eddytrail\ Hawk=1 Edifice\ of\ Authority=1 +Edric,\ Spymaster\ of\ Trest=1 Eel\ Umbra=1 Eerie\ Procession=1 Efficient\ Construction=1 Efreet\ Weaponmaster=1 Ego\ Erasure=1 Eidolon\ of\ Countless\ Battles=1 +Eight-and-a-Half-Tails=1 Ekundu\ Cyclops=1 Ekundu\ Griffin=1 Elaborate\ Firecannon=1 Eland\ Umbra=1 Elder\ Cathar=1 -Elder\ Druid=1 +Elder\ Deep-Fiend=1 Elder\ Land\ Wurm=1 +Elder\ Mastery=1 Elder\ Pine\ of\ Jukai=1 Elder\ of\ Laurels=1 Eldrazi\ Aggressor=1 Eldrazi\ Devastator=1 +Eldrazi\ Mimic=1 Eldrazi\ Obligator=1 Eldrazi\ Skyspawner=1 Electrify=1 Electropotence=1 Electrostatic\ Bolt=1 +Electrostatic\ Pummeler=1 Electryte=1 Elegant\ Edgecrafters=1 Elemental\ Appeal=1 @@ -2445,13 +2587,11 @@ Elemental\ Bond=1 Elemental\ Mastery=1 Elemental\ Resonance=1 Elemental\ Uprising=1 -Elephant\ Graveyard=1 +Elephant\ Ambush=1 Elephant\ Guide=1 -Elf\ Replica=1 -Elfhame\ Sanctuary=1 +Elfhame\ Druid=1 Elgaud\ Inquisitor=1 Elgaud\ Shieldmate=1 -Eliminate\ the\ Competition=1 Elite\ Arcanist=1 Elite\ Archers=1 Elite\ Cat\ Warrior=1 @@ -2460,47 +2600,49 @@ Elite\ Javelineer=1 Elite\ Skirmisher=1 Elite\ Vanguard=1 Elixir\ of\ Immortality=1 +Elixir\ of\ Vitality=1 Elkin\ Bottle=1 +Elsewhere\ Flask=1 Elusive\ Krasis=1 -Elusive\ Spellfist=1 Elusive\ Tormentor=1 -Elven\ Cache=1 Elven\ Lyre=1 +Elven\ Riders=1 Elven\ Rite=1 -Elven\ Warhounds=1 Elves\ of\ Deep\ Shadow=1 Elvish\ Aberration=1 Elvish\ Berserker=1 Elvish\ Branchbender=1 Elvish\ Eulogist=1 Elvish\ Fury=1 -Elvish\ Harbinger=1 +Elvish\ Handservant=1 Elvish\ Herder=1 Elvish\ Hexhunter=1 -Elvish\ Hunter=1 Elvish\ Lookout=1 Elvish\ Lyrist=1 Elvish\ Pathcutter=1 -Elvish\ Promenade=1 +Elvish\ Piper=1 +Elvish\ Ranger=1 Elvish\ Scrapper=1 -Elvish\ Skysweeper=1 Elvish\ Soultiller=1 Elvish\ Warrior=1 -Emancipation\ Angel=1 Embalmed\ Brawler=1 Embalmer's\ Tools=1 Ember-Eye\ Wolf=1 -Ember-Fist\ Zubera=1 +Ember\ Beast=1 Ember\ Gale=1 -Ember\ Hauler=1 +Ember\ Shot=1 Ember\ Swallower=1 Emberhorn\ Minotaur=1 Embermaw\ Hellion=1 -Embersmith=1 +Emberstrike\ Duo=1 +Emberwilde\ Augur=1 +Emberwilde\ Caliph=1 +Emblazoned\ Golem=1 Emblem\ of\ the\ Warmind=1 Embodiment\ of\ Fury=1 Embodiment\ of\ Insight=1 Embodiment\ of\ Spring=1 +Embolden=1 Embraal\ Bruiser=1 Embraal\ Gear-Smasher=1 Emergent\ Growth=1 @@ -2515,11 +2657,11 @@ Emmessi\ Tome=1 Emperor's\ Vanguard=1 Emperor\ Crocodile=1 Empty-Shrine\ Kannushi=1 -Empty\ the\ Catacombs=1 Empyreal\ Voyager=1 Empyrial\ Armor=1 Empyrial\ Plate=1 Emrakul's\ Evangel=1 +Emrakul's\ Hatcher=1 Emrakul's\ Influence=1 Enatu\ Golem=1 Encampment\ Keeper=1 @@ -2528,11 +2670,11 @@ Enchantment\ Alteration=1 Encircling\ Fissure=1 Enclave\ Cryptologist=1 Enclave\ Elite=1 -Encroach=1 Encroaching\ Wastes=1 Encrust=1 End\ Hostilities=1 Endangered\ Armodon=1 +Endbringer's\ Revel=1 Endemic\ Plague=1 Endless\ Obedience=1 Endless\ Ranks\ of\ the\ Dead=1 @@ -2540,14 +2682,15 @@ Endless\ Sands=1 Endless\ Scream=1 Endless\ Swarm=1 Endless\ Whispers=1 -Endless\ Wurm=1 Endoskeleton=1 +Endrek\ Sahr,\ Master\ Breeder=1 Endure=1 +Energizer=1 Energy\ Arc=1 Enervate=1 Enfeeblement=1 Engineered\ Might=1 -Engulf\ the\ Shore=1 +Engulfing\ Flames=1 Engulfing\ Slagwurm=1 Enhanced\ Awareness=1 Enigma\ Drake=1 @@ -2563,23 +2706,29 @@ Enraging\ Licid=1 Enshrined\ Memories=1 Enshrouding\ Mist=1 Enslave=1 +Enslaved\ Dwarf=1 Ensouled\ Scimitar=1 Entangling\ Trap=1 Entangling\ Vines=1 Enter\ the\ Unknown=1 Enthralling\ Victor=1 Entomber\ Exarch=1 +Entrails\ Feaster=1 +Entrancing\ Melody=1 Entropic\ Eidolon=1 +Envelop=1 Eon\ Hub=1 Ephara's\ Enlightenment=1 Ephara's\ Radiance=1 Ephemeral\ Shields=1 Ephemeron=1 Epic\ Proportions=1 +Epicenter=1 Epiphany\ Storm=1 Epiphany\ at\ the\ Drownyard=1 Epitaph\ Golem=1 Epochrasite=1 +Equal\ Treatment=1 Equestrian\ Skill=1 Era\ of\ Innovation=1 Eradicate=1 @@ -2588,39 +2737,42 @@ Erdwal\ Illuminator=1 Erdwal\ Ripper=1 Erebos's\ Emissary=1 Erg\ Raiders=1 -Erhnam\ Djinn=1 Eron\ the\ Relentless=1 Errand\ of\ Duty=1 +Errant\ Doomsayers=1 Errant\ Ephemeron=1 Erratic\ Mutation=1 Ersatz\ Gnomes=1 -Escape\ Routes=1 -Esper\ Battlemage=1 -Esper\ Cormorants=1 +Ertai's\ Trickery=1 +Escaped\ Null=1 +Escaped\ Shapeshifter=1 Esper\ Sojourners=1 -Esper\ Stormblade=1 Esperzoa=1 Essence\ Backlash=1 -Essence\ Bottle=1 Essence\ Depleter=1 Essence\ Drain=1 Essence\ Feed=1 +Essence\ Filter=1 Essence\ Flare=1 Essence\ Flux=1 -Etali,\ Primal\ Storm=1 +Essence\ Fracture=1 +Essence\ Leak=1 Etched\ Monstrosity=1 Etched\ Oracle=1 -Eternal\ Dragon=1 +Eternal\ Dominion=1 +Eternal\ Scourge=1 Eternal\ Thirst=1 Eternal\ of\ Harsh\ Truths=1 Eternity\ Snare=1 Ether\ Well=1 Ethercaste\ Knight=1 -Ethereal\ Ambush=1 +Ethereal\ Champion=1 Ethereal\ Guidance=1 Ethereal\ Usher=1 +Etherium\ Astrolabe=1 Ethersworn\ Shieldmage=1 Etherwrought\ Page=1 +Evacuation=1 Evanescent\ Intellect=1 Evangel\ of\ Heliod=1 Evangelize=1 @@ -2629,48 +2781,57 @@ Ever\ After=1 Everbark\ Shaman=1 Everdawn\ Champion=1 Everflame\ Eidolon=1 -Everglove\ Courier=1 +Everflowing\ Chalice=1 +Everglades=1 Evernight\ Shade=1 Evershrike=1 Evil\ Eye\ of\ Orms-by-Gore=1 Evil\ Eye\ of\ Urborg=1 Evil\ Presence=1 Evil\ Twin=1 +Eviscerate=1 Eviscerator=1 Evolution\ Charm=1 Evolution\ Vat=1 -Evolutionary\ Escalation=1 Evolving\ Wilds=1 +Evra,\ Halcyon\ Witness=1 Exalted\ Dragon=1 Exava,\ Rakdos\ Blood\ Witch=1 +Excavation\ Elephant=1 Excavator=1 -Excise=1 Exclusion\ Ritual=1 Excommunicate=1 Excoriate=1 +Excruciator=1 Execute=1 +Executioner's\ Capsule=1 Executioner's\ Hood=1 Executioner's\ Swing=1 Exemplar\ of\ Strength=1 Exert\ Influence=1 +Exhumer\ Thrull=1 Exile=1 +Exile\ into\ Darkness=1 Exiled\ Boggart=1 Exiled\ Doomsayer=1 -Exorcist=1 +Exoskeletal\ Armor=1 +Exotic\ Curse=1 Exotic\ Disease=1 Expedite=1 Expedition\ Envoy=1 Expedition\ Raptor=1 Expel\ from\ Orazca=1 Expendable\ Troops=1 +Experiment\ Kraj=1 Experimental\ Aviator=1 Exploding\ Borders=1 Explorer's\ Scope=1 Explosive\ Apparatus=1 Explosive\ Growth=1 +Explosive\ Impact=1 Explosive\ Revelation=1 -Expose\ Evil=1 Expunge=1 +Exquisite\ Archangel=1 Extinguish\ All\ Hope=1 Extract\ from\ Darkness=1 Extractor\ Demon=1 @@ -2679,6 +2840,7 @@ Extruder=1 Exultant\ Cultist=1 Exultant\ Skymarcher=1 Eye\ Gouge=1 +Eye\ for\ an\ Eye=1 Eye\ of\ the\ Storm=1 Eyeblight's\ Ending=1 Eyeblight\ Assassin=1 @@ -2688,33 +2850,32 @@ Eyes\ in\ the\ Skies=1 Eyes\ of\ the\ Watcher=1 Eyes\ of\ the\ Wisent=1 Ezuri's\ Archers=1 -Ezuri's\ Brigade=1 Fa'adiyah\ Seer=1 +Fable\ of\ Wolf\ and\ Owl=1 Fabled\ Hero=1 Fabrication\ Module=1 -Faceless\ Butcher=1 -Faceless\ Devourer=1 +Face\ of\ Fear=1 Facevaulter=1 +Fact\ or\ Fiction=1 Fade\ from\ Memory=1 Fade\ into\ Antiquity=1 Faerie\ Harbinger=1 Faerie\ Impostor=1 Faerie\ Invaders=1 Faerie\ Mechanist=1 -Faerie\ Noble=1 +Faerie\ Squadron=1 Faerie\ Swarm=1 Faerie\ Tauntings=1 Faerie\ Trickery=1 Failed\ Inspection=1 Failure\ //\ Comply=1 Fairgrounds\ Trumpeter=1 +Fairgrounds\ Warden=1 Faith's\ Fetters=1 -Faith\ Healer=1 Faith\ Unbroken=1 Faith\ of\ the\ Devoted=1 Faithbearer\ Paladin=1 Faithful\ Squire=1 -Falkenrath\ Exterminator=1 Falkenrath\ Gorger=1 Falkenrath\ Marauders=1 Falkenrath\ Noble=1 @@ -2722,38 +2883,32 @@ Falkenrath\ Reaver=1 Falkenrath\ Torturer=1 Fall\ of\ the\ Gavel=1 Fall\ of\ the\ Hammer=1 +Fall\ of\ the\ Thran=1 Fall\ of\ the\ Titans=1 Fallen\ Angel=1 Fallen\ Cleric=1 Fallen\ Ferromancer=1 Fallen\ Ideal=1 Falling\ Timber=1 -Fallow\ Earth=1 -Fallow\ Wurm=1 Fallowsage=1 -False\ Cure=1 False\ Dawn=1 -False\ Defeat=1 -Falter=1 +False\ Memories=1 Familiar's\ Ruse=1 -Familiar\ Ground=1 Famine=1 +Famished\ Ghoul=1 Famished\ Paladin=1 Fan\ Bearer=1 Fanatic\ of\ Mogis=1 Fanatic\ of\ Xenagos=1 -Fanatical\ Firebrand=1 Fang\ Skulkin=1 Fangren\ Firstborn=1 Fangren\ Hunter=1 -Fangren\ Pathcutter=1 Fanning\ the\ Flames=1 Far\ //\ Away=1 +Farbog\ Boneflinger=1 Farbog\ Revenant=1 Farm\ //\ Market=1 -Farrel's\ Mantle=1 Farrel's\ Zealot=1 -Fatal\ Attraction=1 Fatal\ Blow=1 Fatal\ Frenzy=1 Fate\ Foretold=1 @@ -2769,23 +2924,23 @@ Fateful\ Showdown=1 Fatespinner=1 Fathom\ Feeder=1 Fathom\ Fleet\ Boarder=1 +Fathom\ Fleet\ Captain=1 Fathom\ Fleet\ Cutthroat=1 Fathom\ Fleet\ Firebrand=1 Fathom\ Mage=1 Fathom\ Seer=1 +Fathom\ Trawl=1 Fatigue=1 -Faultgrinder=1 +Fault\ Riders=1 Favor\ of\ the\ Mighty=1 Favor\ of\ the\ Woods=1 -Favorable\ Destiny=1 -Favorable\ Winds=1 Favored\ Hoplite=1 Fear=1 Fearsome\ Temper=1 -Feast\ of\ Blood=1 Feast\ of\ Dreams=1 Feast\ of\ Flesh=1 Feast\ on\ the\ Fallen=1 +Feast\ or\ Famine=1 Feat\ of\ Resistance=1 Feebleness=1 Feed\ the\ Pack=1 @@ -2794,90 +2949,88 @@ Feeling\ of\ Dread=1 Felhide\ Brawler=1 Felhide\ Minotaur=1 Felhide\ Petrifier=1 -Felhide\ Spiritbinder=1 Felidar\ Cub=1 Felidar\ Sovereign=1 Fell\ Flagship=1 -Femeref\ Archers=1 Femeref\ Healer=1 Femeref\ Knight=1 Femeref\ Scouts=1 Fen\ Hauler=1 -Fen\ Stalker=1 Fencer's\ Magemark=1 Fencing\ Ace=1 -Fend\ Off=1 Fendeep\ Summoner=1 +Feral\ Abomination=1 Feral\ Animist=1 Feral\ Contest=1 +Feral\ Hydra=1 Feral\ Incarnation=1 +Feral\ Instinct=1 Feral\ Invocation=1 Feral\ Krushok=1 Feral\ Lightning=1 Feral\ Prowler=1 Feral\ Shadow=1 Feral\ Thallid=1 -Feral\ Throwback=1 -Ferocious\ Charge=1 Ferocity=1 -Feroz's\ Ban=1 Ferropede=1 Ferrovore=1 Fertile\ Imagination=1 Fertile\ Thicket=1 -Fertilid=1 Fervent\ Cathar=1 Fervent\ Charge=1 Fervent\ Denial=1 Fervent\ Paincaster=1 +Fervent\ Strike=1 Fervor=1 Festercreep=1 Festergloom=1 Festerhide\ Boar=1 Festering\ Evil=1 Festering\ Goblin=1 -Festering\ March=1 Festering\ Mummy=1 Festering\ Newt=1 Festering\ Wound=1 +Festival\ of\ the\ Guildpact=1 Fetid\ Horror=1 Fetid\ Imp=1 Fettergeist=1 Feudkiller's\ Verdict=1 Fevered\ Strength=1 -Fiddlehead\ Kami=1 +Fevered\ Visions=1 Field\ Creeper=1 +Field\ Surgeon=1 Field\ of\ Souls=1 Fiend\ Binder=1 -Fiend\ of\ the\ Shadows=1 Fierce\ Invocation=1 -Fiery\ Bombardment=1 Fiery\ Cannonade=1 Fiery\ Conclusion=1 Fiery\ Fall=1 +Fiery\ Finish=1 Fiery\ Hellhound=1 Fiery\ Impulse=1 -Fiery\ Justice=1 -Fiery\ Mantle=1 +Fiery\ Intervention=1 Fiery\ Temper=1 +Fight\ or\ Flight=1 Fight\ to\ the\ Death=1 Fighting\ Chance=1 Fighting\ Drake=1 Filigree\ Angel=1 Filigree\ Crawler=1 Filigree\ Familiar=1 -Filigree\ Fracture=1 Filigree\ Sages=1 Fill\ with\ Fright=1 +Filth=1 +Filthy\ Cur=1 Final-Sting\ Faerie=1 -Final\ Judgment=1 +Final\ Parting=1 Final\ Punishment=1 Final\ Revels=1 Final\ Reward=1 Finest\ Hour=1 Fire-Belly\ Changeling=1 +Fire-Field\ Ogre=1 +Fire\ Ambush=1 Fire\ Ants=1 -Fire\ Dragon=1 Fire\ Drake=1 Fire\ Elemental=1 Fire\ Imp=1 @@ -2889,28 +3042,26 @@ Fire\ Tempest=1 Fire\ Whip=1 Fire\ at\ Will=1 Fireball=1 +Firebrand\ Archer=1 Firebreathing=1 Firecannon\ Blast=1 -Firecat\ Blitz=1 -Firedrinker\ Satyr=1 Firefiend\ Elemental=1 +Firefist\ Adept=1 Firefist\ Striker=1 Firefly=1 Fireforger's\ Puzzleknot=1 Firefright\ Mage=1 -Firehoof\ Cavalry=1 Firemane\ Angel=1 Firemane\ Avenger=1 Firemantle\ Mage=1 -Firemaw\ Kavu=1 Firemind's\ Foresight=1 Fires\ of\ Undeath=1 Fires\ of\ Yavimaya=1 +Firescreamer=1 Fireshrieker=1 -Fireslinger=1 +Firestorm\ Hellkite=1 Firestorm\ Phoenix=1 Firewake\ Sliver=1 -Firewing\ Phoenix=1 First\ Response=1 First\ Volley=1 Fishliver\ Oil=1 @@ -2919,50 +3070,54 @@ Fissure\ Vent=1 Fists\ of\ Ironwood=1 Fists\ of\ the\ Anvil=1 Fists\ of\ the\ Demigod=1 -Fit\ of\ Rage=1 Five-Alarm\ Fire=1 Flailing\ Drake=1 Flailing\ Manticore=1 Flame-Kin\ War\ Scout=1 Flame-Kin\ Zealot=1 +Flame-Wreathed\ Phoenix=1 +Flame\ Burst=1 +Flame\ Elemental=1 Flame\ Fusillade=1 -Flame\ Jab=1 Flame\ Javelin=1 +Flame\ Spirit=1 Flame\ Wave=1 -Flameblade\ Adept=1 Flameblade\ Angel=1 Flameblast\ Dragon=1 Flameborn\ Hellion=1 -Flameborn\ Viron=1 Flamebreak=1 Flamecast\ Wheel=1 Flamecore\ Elemental=1 Flamekin\ Bladewhirl=1 Flamekin\ Brawler=1 -Flamekin\ Spitfire=1 +Flames\ of\ the\ Blood\ Hand=1 Flames\ of\ the\ Firebrand=1 Flameshadow\ Conjuring=1 -Flamespeaker's\ Will=1 Flamespeaker\ Adept=1 Flametongue\ Kavu=1 Flamewave\ Invoker=1 +Flaming\ Sword=1 +Flare=1 Flaring\ Flame-Kin=1 Flash\ Conscription=1 -Flash\ Flood=1 +Flash\ Foliage=1 +Flash\ of\ Defiance=1 Flashfreeze=1 Flatten=1 +Flay=1 Flayed\ Nim=1 Flayer\ Drone=1 -Flayer\ of\ the\ Hatebound=1 Flaying\ Tendrils=1 -Fledgling\ Djinn=1 Fledgling\ Dragon=1 -Fledgling\ Griffin=1 +Fledgling\ Imp=1 +Fledgling\ Mawcor=1 +Fledgling\ Osprey=1 +Fleecemane\ Lion=1 Fleet\ Swallower=1 Fleetfeather\ Cockatrice=1 Fleetfeather\ Sandals=1 +Fleetfoot\ Panther=1 Fleeting\ Aven=1 -Fleeting\ Distraction=1 Fleeting\ Image=1 Fleeting\ Memories=1 Fleetwheel\ Cruiser=1 @@ -2973,41 +3128,43 @@ Flesh\ Allergy=1 Flesh\ Reaver=1 Flesh\ to\ Dust=1 Fleshbag\ Marauder=1 -Fleshformer=1 -Fleshgrafter=1 -Fleshpulper\ Giant=1 Fleshwrither=1 Flickerform=1 Flickering\ Spirit=1 Flight=1 Flight\ Spellbomb=1 +Flight\ of\ Fancy=1 Fling=1 +Flint\ Golem=1 Flinthoof\ Boar=1 Flitterstep\ Eidolon=1 Flood\ Plain=1 Flood\ of\ Recollection=1 Floodbringer=1 Floodchaser=1 +Floodgate=1 Floodtide\ Serpent=1 Floodwater\ Dam=1 Floodwaters=1 Flourishing\ Defenses=1 Flow\ of\ Ideas=1 +Flowstone\ Armor=1 Flowstone\ Blade=1 Flowstone\ Channeler=1 Flowstone\ Charger=1 Flowstone\ Crusher=1 +Flowstone\ Embrace=1 Flowstone\ Flood=1 -Flowstone\ Giant=1 -Flowstone\ Hellion=1 Flowstone\ Mauler=1 Flowstone\ Overseer=1 Flowstone\ Salamander=1 Flowstone\ Sculpture=1 Flowstone\ Shambler=1 Flowstone\ Slide=1 +Flowstone\ Strike=1 +Flowstone\ Surge=1 +Flowstone\ Thopter=1 Flowstone\ Wyvern=1 -Flurry\ of\ Horns=1 Flurry\ of\ Wings=1 Fluxcharger=1 Flying\ Carpet=1 @@ -3015,35 +3172,30 @@ Flying\ Crane\ Technique=1 Flying\ Men=1 Fodder\ Cannon=1 Fodder\ Launch=1 -Foe-Razer\ Regent=1 Fog=1 -Fog\ Bank=1 Fog\ Elemental=1 Fog\ Patch=1 Fog\ of\ Gnats=1 Fogwalker=1 Fold\ into\ Aether=1 Folk\ of\ the\ Pines=1 -Fomori\ Nomad=1 -Font\ of\ Fertility=1 +Followed\ Footsteps=1 Font\ of\ Fortunes=1 -Font\ of\ Ire=1 Font\ of\ Return=1 Font\ of\ Vigor=1 Fool's\ Demise=1 +Fool's\ Tome=1 Foot\ Soldiers=1 +Footbottom\ Feast=1 Foratog=1 Forbidden\ Lore=1 -Forbidding\ Watchtower=1 Force\ Away=1 -Force\ Bubble=1 Force\ of\ Nature=1 Force\ of\ Savagery=1 Forced\ Adaptation=1 -Forced\ Fruition=1 -Forced\ Retreat=1 Forced\ Worship=1 Forcemage\ Advocate=1 +Forebear's\ Blade=1 Forerunner\ of\ Slaughter=1 Forerunner\ of\ the\ Coalition=1 Forerunner\ of\ the\ Empire=1 @@ -3052,21 +3204,20 @@ Forerunner\ of\ the\ Legion=1 Foresee=1 Foreshadow=1 Forest=1 +Forfend=1 Forge\ Armor=1 Forge\ Devil=1 Forgeborn\ Oreads=1 -Forgestoker\ Dragon=1 Forgotten\ Creation=1 Forgotten\ Lore=1 Foriysian\ Interceptor=1 Foriysian\ Totem=1 Fork\ in\ the\ Road=1 Forked-Branch\ Garami=1 +Forked\ Lightning=1 Forlorn\ Pseudamma=1 Form\ of\ the\ Dinosaur=1 -Form\ of\ the\ Dragon=1 Formless\ Nurturing=1 -Forsake\ the\ Worldly=1 Forsaken\ Drifters=1 Forsaken\ Sanctuary=1 Fortified\ Rampart=1 @@ -3077,108 +3228,114 @@ Fortuitous\ Find=1 Fortune's\ Favor=1 Fortune\ Thief=1 Fossil\ Find=1 +Foul\ Emissary=1 +Foul\ Familiar=1 Foul\ Imp=1 Foul\ Orchard=1 +Foul\ Presence=1 Foul\ Renewal=1 -Foul\ Spirit=1 Foundry\ Assembler=1 Foundry\ Champion=1 Foundry\ Hornet=1 -Foundry\ Inspector=1 Foundry\ Screecher=1 Foundry\ of\ the\ Consuls=1 Fountain\ of\ Youth=1 Fourth\ Bridge\ Prowler=1 -Foxfire\ Oak=1 Fractured\ Loyalty=1 +Fragmentize=1 +Frantic\ Purification=1 Frantic\ Salvage=1 -Frazzle=1 Freejam\ Regent=1 +Freewind\ Equenaut=1 +Freewind\ Falcon=1 +Frenetic\ Ogre=1 Frenetic\ Raptor=1 Frenetic\ Sliver=1 -Frenzied\ Fugue=1 Frenzied\ Goblin=1 +Frenzied\ Rage=1 Frenzied\ Raptor=1 Frenzied\ Tilling=1 +Frenzy\ Sliver=1 Fresh\ Meat=1 Fresh\ Volunteers=1 Fretwork\ Colony=1 -Freyalise's\ Radiance=1 +Freyalise's\ Winds=1 +Frightcrawler=1 Frightful\ Delusion=1 +Frightshroud\ Courier=1 Frilled\ Deathspitter=1 Frilled\ Sandwalla=1 -Frogtosser\ Banneret=1 +Frilled\ Sea\ Serpent=1 From\ Beyond=1 From\ Under\ the\ Floorboards=1 Frontier\ Bivouac=1 Frontier\ Guide=1 -Frontier\ Mastodon=1 Frontline\ Devastator=1 Frontline\ Medic=1 Frontline\ Rebel=1 Frontline\ Sage=1 Frontline\ Strategist=1 Frost\ Lynx=1 -Frost\ Ogre=1 -Frost\ Walker=1 +Frost\ Marsh=1 +Frost\ Raptor=1 Frostburn\ Weird=1 Frostweb\ Spider=1 -Frostwielder=1 -Frostwind\ Invoker=1 Frozen\ Aether=1 Frozen\ Solid=1 Fuel\ for\ the\ Cause=1 -Fugitive\ Druid=1 Fugitive\ Wizard=1 Fugue=1 +Fulgent\ Distraction=1 Full\ Moon's\ Rise=1 Fumarole=1 -Funeral\ March=1 +Fumiko\ the\ Lowblood=1 +Funeral\ Pyre=1 Fungal\ Behemoth=1 +Fungal\ Infection=1 +Fungal\ Plots=1 Fungal\ Reaches=1 Fungal\ Shambler=1 -Fungal\ Sprouting=1 Fungus\ Sliver=1 +Furious\ Assault=1 Furious\ Reprisal=1 +Furious\ Resistance=1 Furnace\ Brood=1 Furnace\ Celebration=1 Furnace\ Dragon=1 Furnace\ Scamp=1 Furnace\ Spirit=1 Furnace\ Whelp=1 -Furnace\ of\ Rath=1 Furor\ of\ the\ Bitten=1 Furtive\ Homunculus=1 Fury\ Charm=1 -Fury\ Sliver=1 Furyblade\ Vampire=1 Furystoke\ Giant=1 Fusion\ Elemental=1 Future\ Sight=1 Fylamarid=1 -Fyndhorn\ Elder=1 -Fyndhorn\ Elves=1 Fyndhorn\ Pollen=1 -Gabriel\ Angelfire=1 Gaea's\ Anthem=1 -Gaea's\ Avenger=1 Gaea's\ Blessing=1 Gaea's\ Bounty=1 Gaea's\ Embrace=1 +Gaea's\ Herald=1 Gaea's\ Liege=1 +Gaea's\ Protector=1 Gaea's\ Revenge=1 Gainsay=1 Gale\ Force=1 Galepowder\ Mage=1 Galestrike=1 +Gallant\ Cavalry=1 +Gallantry=1 Gallows\ Warden=1 Gallows\ at\ Willow\ Hill=1 -Galvanic\ Alchemist=1 -Galvanic\ Arc=1 Galvanic\ Bombardment=1 Galvanic\ Juggernaut=1 +Galvanic\ Key=1 Galvanoth=1 Game-Trail\ Changeling=1 +Game\ Trail=1 Gamekeeper=1 Gang\ of\ Devils=1 Gang\ of\ Elk=1 @@ -3187,16 +3344,17 @@ Gangrenous\ Zombies=1 Gargantuan\ Gorilla=1 Gargoyle\ Castle=1 Gargoyle\ Sentinel=1 +Garna,\ the\ Bloodflame=1 Garruk's\ Companion=1 Garruk's\ Horde=1 Garruk's\ Packleader=1 Garrulous\ Sycophant=1 +Garza\ Zol,\ Plague\ Queen=1 Gaseous\ Form=1 Gate\ Hound=1 Gate\ Smasher=1 -Gate\ to\ the\ Aether=1 -Gate\ to\ the\ Afterlife=1 Gatecreeper\ Vine=1 +Gatekeeper\ of\ Malakir=1 Gateway\ Shade=1 Gathan\ Raiders=1 Gather\ Courage=1 @@ -3206,52 +3364,56 @@ Gatherer\ of\ Graces=1 Gatstaf\ Arsonists=1 Gatstaf\ Shepherd=1 Gauntlets\ of\ Chaos=1 +Gavony\ Ironwright=1 Gavony\ Unhallowed=1 Gaze\ of\ Adamaro=1 Gaze\ of\ Justice=1 Gearseeker\ Serpent=1 Gearshift\ Ace=1 +Gearsmith\ Guardian=1 +Gearsmith\ Prodigy=1 Geier\ Reach\ Bandit=1 Geist-Fueled\ Scarecrow=1 Geist-Honored\ Monk=1 Geist\ of\ the\ Archives=1 Geist\ of\ the\ Lonely\ Vigil=1 -Geist\ of\ the\ Moors=1 Geistblast=1 Geistflame=1 Gelatinous\ Genesis=1 Gelectrode=1 Gelid\ Shackles=1 -Gemhide\ Sliver=1 +Gem\ of\ Becoming=1 Gemini\ Engine=1 -Gempalm\ Strider=1 +Gempalm\ Avenger=1 Gemstone\ Array=1 General's\ Kabuto=1 +General\ Tazri=1 Genesis=1 -Genesis\ Hydra=1 Genju\ of\ the\ Cedars=1 Genju\ of\ the\ Falls=1 Genju\ of\ the\ Fens=1 +Genju\ of\ the\ Fields=1 Genju\ of\ the\ Realm=1 Genju\ of\ the\ Spires=1 Geosurge=1 Geralf's\ Mindcrusher=1 Gerrard's\ Battle\ Cry=1 +Gerrard's\ Command=1 Gerrard's\ Irregulars=1 -Geyser\ Glider=1 +Geth's\ Grimoire=1 Geyserfield\ Stalker=1 -Ghastly\ Discovery=1 +Ghastbark\ Twins=1 Ghastly\ Remains=1 -Ghazban\ Ogre=1 -Ghirapur\ Aether\ Grid=1 +Ghazbn\ Ogre=1 Ghirapur\ Gearcrafter=1 Ghirapur\ Guide=1 Ghirapur\ Orrery=1 Ghirapur\ Osprey=1 -Ghitu\ Encampment=1 +Ghitu\ Chronicler=1 Ghitu\ Fire-Eater=1 Ghitu\ Fire=1 Ghitu\ Firebreathing=1 +Ghitu\ Journeymage=1 Ghitu\ Slinger=1 Ghitu\ War\ Cry=1 Ghor-Clan\ Bloodscale=1 @@ -3269,7 +3431,6 @@ Ghostfire=1 Ghostfire\ Blade=1 Ghostflame\ Sliver=1 Ghostform=1 -Ghosthelm\ Courier=1 Ghostly\ Changeling=1 Ghostly\ Possession=1 Ghostly\ Sentinel=1 @@ -3278,19 +3439,16 @@ Ghostly\ Visit=1 Ghostly\ Wings=1 Ghosts\ of\ the\ Damned=1 Ghosts\ of\ the\ Innocent=1 +Ghoul's\ Feast=1 Ghoulcaller's\ Accomplice=1 Ghoulcaller's\ Bell=1 -Ghoulcaller's\ Chant=1 Ghoulflesh=1 -Ghoulraiser=1 Ghoulsteed=1 -Ghoultree=1 -Giant\ Ambush\ Beetle=1 +Giant's\ Ire=1 Giant\ Badger=1 Giant\ Caterpillar=1 Giant\ Cockroach=1 Giant\ Crab=1 -Giant\ Dustwasp=1 Giant\ Growth=1 Giant\ Harbinger=1 Giant\ Mantis=1 @@ -3302,28 +3460,30 @@ Giant\ Spectacle=1 Giant\ Spider=1 Giant\ Strength=1 Giant\ Tortoise=1 +Giant\ Trap\ Door\ Spider=1 Giantbaiting=1 Gibbering\ Descent=1 Gibbering\ Fiend=1 -Gibbering\ Kami=1 +Gibbering\ Hyenas=1 Gideon's\ Avenger=1 Gideon's\ Defeat=1 +Gideon's\ Intervention=1 Gideon's\ Lawkeeper=1 Gideon's\ Phalanx=1 Gideon's\ Reproach=1 +Gift\ of\ Granite=1 +Gift\ of\ Growth=1 Gift\ of\ Immortality=1 Gift\ of\ Orzhova=1 -Gift\ of\ Paradise=1 Gift\ of\ Strength=1 Gift\ of\ Tusks=1 Gift\ of\ the\ Deity=1 Gift\ of\ the\ Gargantuan=1 -Gigantiform=1 -Gigantomancer=1 Gigapede=1 Gild=1 Gilded\ Cerodon=1 Gilded\ Light=1 +Gilded\ Lotus=1 Gilded\ Sentinel=1 Gilt-Leaf\ Ambush=1 Gilt-Leaf\ Seer=1 @@ -3333,30 +3493,35 @@ Giltspire\ Avenger=1 Gisa's\ Bidding=1 Give\ //\ Take=1 Give\ No\ Ground=1 -Glacial\ Crasher=1 Glacial\ Crevasses=1 Glacial\ Plating=1 Glacial\ Ray=1 Glacial\ Stalker=1 Glacial\ Wall=1 +Glade\ Gnarr=1 Glade\ Watcher=1 Gladehart\ Cavalry=1 +Glamer\ Spinners=1 Glamerdye=1 Glare\ of\ Heresy=1 Glare\ of\ Subdual=1 Glarecaster=1 +Glaring\ Aegis=1 Glaring\ Spotlight=1 +Glass\ Asp=1 Glass\ Golem=1 Glassblower's\ Puzzleknot=1 Glassdust\ Hulk=1 -Glasses\ of\ Urza=1 +Glaze\ Fiend=1 +Gleam\ of\ Authority=1 Gleam\ of\ Battle=1 Gleam\ of\ Resistance=1 Gleaming\ Barrier=1 -Glen\ Elendra\ Pranksters=1 -Gliding\ Licid=1 +Gleancrawler=1 +Glen\ Elendra\ Liege=1 Glimmerdust\ Nap=1 Glimmerpoint\ Stag=1 +Glimmerpost=1 Glimpse\ the\ Future=1 Glimpse\ the\ Sun\ God=1 Glint-Eye\ Nephilim=1 @@ -3364,20 +3529,23 @@ Glint-Sleeve\ Artisan=1 Glint=1 Glint\ Hawk\ Idol=1 Glintwing\ Invoker=1 -Glissa's\ Courier=1 +Glissa's\ Scorn=1 Glissa\ Sunseeker=1 Glistening\ Oil=1 Glitterfang=1 +Glittering\ Lion=1 Gloom\ Surgeon=1 Gloomhunter=1 -Gloomlance=1 +Gloomwidow's\ Feast=1 Gloomwidow=1 Glorifier\ of\ Dusk=1 Glorious\ Anthem=1 +Glorious\ Charge=1 +Glory-Bound\ Initiate=1 Glory\ Seeker=1 Glory\ of\ Warfare=1 -Gloryscale\ Viashino=1 Glowering\ Rogon=1 +Glowing\ Anemone=1 Gluttonous\ Slime=1 Gluttonous\ Zombie=1 Glyph\ Keeper=1 @@ -3389,6 +3557,7 @@ Gnarlroot\ Trapper=1 Gnarlwood\ Dryad=1 Gnathosaur=1 Gnawing\ Zombie=1 +Goatnapper=1 Gobbling\ Ooze=1 Gobhobbler\ Rats=1 Goblin\ Archaeologist=1 @@ -3396,27 +3565,24 @@ Goblin\ Arsonist=1 Goblin\ Artillery=1 Goblin\ Assault=1 Goblin\ Bangchuckers=1 +Goblin\ Barrage=1 Goblin\ Battle\ Jester=1 -Goblin\ Berserker=1 Goblin\ Boom\ Keg=1 -Goblin\ Brawler=1 Goblin\ Brigand=1 Goblin\ Bully=1 Goblin\ Burrows=1 Goblin\ Cadets=1 Goblin\ Cannon=1 -Goblin\ Cavaliers=1 Goblin\ Chariot=1 -Goblin\ Clearcutter=1 Goblin\ Commando=1 Goblin\ Deathraiders=1 Goblin\ Digging\ Team=1 -Goblin\ Dirigible=1 -Goblin\ Dynamo=1 +Goblin\ Diplomats=1 Goblin\ Elite\ Infantry=1 -Goblin\ Festival=1 +Goblin\ Fire\ Fiend=1 Goblin\ Firebug=1 Goblin\ Fireslinger=1 +Goblin\ Firestarter=1 Goblin\ Flectomancer=1 Goblin\ Freerunner=1 Goblin\ Furrier=1 @@ -3428,20 +3594,19 @@ Goblin\ Glory\ Chaser=1 Goblin\ Goon=1 Goblin\ Grappler=1 Goblin\ Grenadiers=1 -Goblin\ Lackey=1 +Goblin\ Kaboomist=1 Goblin\ Legionnaire=1 Goblin\ Machinist=1 Goblin\ Medics=1 Goblin\ Mountaineer=1 -Goblin\ Mutant=1 Goblin\ Outlander=1 +Goblin\ Patrol=1 Goblin\ Piker=1 -Goblin\ Psychopath=1 Goblin\ Pyromancer=1 Goblin\ Raider=1 Goblin\ Rally=1 Goblin\ Razerunners=1 -Goblin\ Ringleader=1 +Goblin\ Rimerunner=1 Goblin\ Roughrider=1 Goblin\ Settler=1 Goblin\ Shortcutter=1 @@ -3451,32 +3616,36 @@ Goblin\ Sky\ Raider=1 Goblin\ Snowman=1 Goblin\ Spelunkers=1 Goblin\ Striker=1 +Goblin\ Swine-Rider=1 Goblin\ Taskmaster=1 Goblin\ Test\ Pilot=1 Goblin\ Trailblazer=1 Goblin\ Trenches=1 -Goblin\ Tunneler=1 Goblin\ Turncoat=1 +Goblin\ War\ Buggy=1 Goblin\ War\ Paint=1 Goblin\ War\ Wagon=1 Goblin\ Warchief=1 +Goblins\ of\ the\ Flarg=1 Goblinslide=1 God-Favored\ General=1 God-Pharaoh's\ Faithful=1 +Godhead\ of\ Awe=1 Godo's\ Irregulars=1 Gods'\ Eye,\ Gate\ to\ the\ Reikai=1 +Gods\ Willing=1 Godtoucher=1 -Godtracker\ of\ Jund=1 +Goham\ Djinn=1 Gold-Forged\ Sentinel=1 Gold\ Myr=1 -Golden\ Guardian=1 +Golden\ Demise=1 Golden\ Hind=1 Golden\ Urn=1 +Golden\ Wish=1 Goldenglow\ Moth=1 Goldenhide\ Ox=1 Goldmeadow\ Dodger=1 Goldmeadow\ Harrier=1 -Goldmeadow\ Lookout=1 Goldmeadow\ Stalwart=1 Goldnight\ Commander=1 Goldnight\ Redeemer=1 @@ -3484,34 +3653,33 @@ Golem's\ Heart=1 Golem-Skin\ Gauntlets=1 Golem\ Foundry=1 Golgari\ Cluestone=1 -Golgari\ Decoy=1 Golgari\ Germination=1 Golgari\ Guildgate=1 Golgari\ Guildmage=1 Golgari\ Keyrune=1 -Golgari\ Longlegs=1 Golgari\ Rotwurm=1 Golgari\ Signet=1 Goliath\ Beetle=1 Goliath\ Sphinx=1 -Goliath\ Spider=1 Gomazoa=1 Gone\ Missing=1 +Gonti's\ Aether\ Heart=1 Gonti's\ Machinations=1 Gore-House\ Chainwalker=1 +Gore\ Swine=1 Gorehorn\ Minotaurs=1 -Gorger\ Wurm=1 +Goretusk\ Firebeast=1 Gorgon's\ Head=1 Gorgon\ Flail=1 Gorgon\ Recluse=1 -Gorilla\ Chieftain=1 +Gorilla\ Titan=1 +Gorilla\ War\ Cry=1 Gorilla\ Warrior=1 Goring\ Ceratops=1 Gossamer\ Chains=1 Gossamer\ Phantasm=1 Govern\ the\ Guildless=1 Grab\ the\ Reins=1 -Graceblade\ Artisan=1 Graceful\ Adept=1 Graceful\ Antelope=1 Graceful\ Reprieve=1 @@ -3520,11 +3688,12 @@ Graf\ Mole=1 Graf\ Rats=1 Grafted\ Exoskeleton=1 Grand\ Melee=1 +Grand\ Warlord\ Radha=1 Grandmother\ Sengir=1 +Granite\ Gargoyle=1 Granite\ Grip=1 Granite\ Shard=1 Granitic\ Titan=1 -Granulate=1 Grapeshot\ Catapult=1 Grapple\ with\ the\ Past=1 Grappling\ Hook=1 @@ -3533,73 +3702,72 @@ Grasp\ of\ Phantoms=1 Grasp\ of\ the\ Hieromancer=1 Grasping\ Dunes=1 Grasping\ Scoundrel=1 -Grassland\ Crusader=1 Grasslands=1 Grave-Shell\ Scarab=1 Grave\ Betrayal=1 Grave\ Birthing=1 -Grave\ Bramble=1 -Grave\ Defiler=1 Grave\ Peril=1 -Grave\ Strength=1 +Grave\ Servitude=1 Gravebane\ Zombie=1 Gravebind=1 Graveblade\ Marauder=1 Gravedigger=1 Gravel\ Slinger=1 +Gravelgill\ Axeshark=1 Gravelgill\ Duo=1 Graven\ Abomination=1 Graven\ Dominator=1 Gravepurge=1 Graverobber\ Spider=1 -Gravespawn\ Sovereign=1 -Gravetiller\ Wurm=1 Gravity\ Negator=1 Gravity\ Well=1 +Graxiplon=1 Graypelt\ Hunter=1 Grazing\ Gladehart=1 Grazing\ Kelpie=1 Grazing\ Whiptail=1 +Great-Horn\ Krushok=1 +Great\ Hart=1 Great\ Teacher's\ Decree=1 Greatbow\ Doyen=1 +Greater\ Basilisk=1 Greater\ Forgeling=1 Greater\ Harvester=1 Greater\ Mossdog=1 Greater\ Sandwurm=1 -Greater\ Stone\ Spirit=1 Greatsword=1 +Greel's\ Caress=1 Greenhilt\ Trainee=1 Greenseeker=1 Greenside\ Watcher=1 Greenweaver\ Druid=1 +Greenwheel\ Liberator=1 Gremlin\ Infestation=1 -Gremlin\ Mine=1 Grenzo,\ Dungeon\ Warden=1 Grid\ Monitor=1 Gridlock=1 -Grief\ Tyrant=1 Griffin\ Dreamfinder=1 Griffin\ Guide=1 -Griffin\ Protector=1 Griffin\ Sentinel=1 +Grifter's\ Blade=1 Grim\ Affliction=1 -Grim\ Backwoods=1 Grim\ Captain's\ Call=1 Grim\ Contest=1 Grim\ Discovery=1 Grim\ Flowering=1 -Grim\ Guardian=1 Grim\ Haruspex=1 +Grim\ Poppet=1 Grim\ Reminder=1 Grim\ Return=1 Grim\ Roustabout=1 Grim\ Strider=1 -Grimclaw\ Bats=1 -Grimoire\ of\ the\ Dead=1 +Grimoire\ Thief=1 Grind\ //\ Dust=1 Grindclock=1 Grinning\ Demon=1 Grinning\ Ignus=1 +Grinning\ Totem=1 +Grip\ of\ Amnesia=1 Grip\ of\ Desolation=1 Grip\ of\ the\ Roil=1 Griptide=1 @@ -3626,17 +3794,18 @@ Grotesque\ Mutation=1 Ground\ Assault=1 Ground\ Rift=1 Groundling\ Pouncer=1 -Groundshaker\ Sliver=1 Groundskeeper=1 Grove\ Rumbler=1 Grove\ of\ the\ Guardian=1 Grovetender\ Druids=1 +Grow\ from\ the\ Ashes=1 Growing\ Ranks=1 Grozoth=1 Gruesome\ Deformity=1 Gruesome\ Encore=1 Gruesome\ Fate=1 Gruesome\ Slaughter=1 +Grunn,\ the\ Lonely\ King=1 Gruul\ Charm=1 Gruul\ Cluestone=1 Gruul\ Guildgate=1 @@ -3645,72 +3814,70 @@ Gruul\ Keyrune=1 Gruul\ Nodorog=1 Gruul\ Ragebeast=1 Gruul\ Scrapper=1 -Gruul\ Signet=1 -Gruul\ Turf=1 Gruul\ War\ Chant=1 Gruul\ War\ Plow=1 Gryff's\ Boon=1 Guan\ Yu's\ 1,000-Li\ March=1 Guan\ Yu,\ Sainted\ Warrior=1 +Guard\ Dogs=1 Guard\ Duty=1 Guard\ Gomazoa=1 Guardian\ Automaton=1 Guardian\ Seraph=1 Guardian\ Shield-Bearer=1 +Guardian\ Zendikon=1 Guardian\ of\ Pilgrims=1 Guardian\ of\ Solitude=1 Guardian\ of\ Tazeem=1 -Guardian\ of\ Vitu-Ghazi=1 Guardian\ of\ the\ Ages=1 Guardian\ of\ the\ Gateless=1 Guardians\ of\ Akrasa=1 +Guardians\ of\ Koilos=1 Guardians\ of\ Meletis=1 Guerrilla\ Tactics=1 Guild\ Feud=1 Guildscorn\ Ward=1 Guile=1 -Guise\ of\ Fire=1 +Guilty\ Conscience=1 Guma=1 Gurmag\ Drowner=1 Gurmag\ Swiftwing=1 -Gurzigost=1 Gust-Skimmer=1 Gust\ Walker=1 Gustcloak\ Cavalier=1 -Gustcloak\ Harrier=1 +Gustcloak\ Runner=1 +Gustcloak\ Savior=1 Gustcloak\ Sentinel=1 +Gustha's\ Scepter=1 Gustrider\ Exuberant=1 -Gutless\ Ghoul=1 Gutter\ Grime=1 Gutter\ Skulk=1 -Guttersnipe=1 +Gutwrencher\ Oni=1 +Guul\ Draz\ Assassin=1 Guul\ Draz\ Overseer=1 Guul\ Draz\ Specter=1 Gwafa\ Hazid,\ Profiteer=1 Gwyllion\ Hedge-Mage=1 -Gyre\ Sage=1 -Haazda\ Exonerator=1 Haazda\ Shield\ Mate=1 -Haazda\ Snare\ Squad=1 +Hada\ Spy\ Patrol=1 Hag\ Hedge-Mage=1 +Hagra\ Crocodile=1 Hagra\ Diabolist=1 Hagra\ Sharpshooter=1 -Hail\ Storm=1 Hail\ of\ Arrows=1 Hair-Strung\ Koto=1 +Halam\ Djinn=1 Halcyon\ Glaze=1 -Halfdane=1 Halimar\ Excavator=1 Halimar\ Tidecaller=1 Halimar\ Wavewatch=1 -Hall\ of\ Triumph=1 -Hallowed\ Ground=1 +Hallar,\ the\ Firefletcher=1 +Hallowed\ Moonlight=1 Halo\ Hunter=1 -Halt\ Order=1 Hamlet\ Captain=1 Hamletback\ Goliath=1 +Hammer\ of\ Bogardan=1 Hammer\ of\ Purphoros=1 -Hammer\ of\ Ruin=1 Hammerfist\ Giant=1 Hammerhand=1 Hammerhead\ Shark=1 @@ -3719,41 +3886,48 @@ Hammerheim\ Deadeye=1 Hana\ Kami=1 Hanabi\ Blast=1 Hand\ of\ Cruelty=1 -Hand\ of\ Honor=1 +Hand\ of\ Emrakul=1 Hand\ of\ Justice=1 Hand\ of\ Silumgar=1 Hand\ of\ the\ Praetors=1 +Hand\ to\ Hand=1 Hands\ of\ Binding=1 +Hanweir\ Battlements=1 Hanweir\ Lancer=1 +Hanweir\ Militia\ Captain=1 Hanweir\ Watchkeep=1 Hapatra's\ Mark=1 Hapatra,\ Vizier\ of\ Poisons=1 -Harbinger\ of\ Spring=1 +Haphazard\ Bombardment=1 Harbinger\ of\ the\ Hunt=1 +Harbor\ Bandit=1 +Harbor\ Guardian=1 Harbor\ Serpent=1 Hardened\ Berserker=1 Hardy\ Veteran=1 Harm's\ Way=1 -Harmless\ Assault=1 +Harmattan\ Efreet=1 Harmless\ Offering=1 Harmonic\ Convergence=1 -Harness\ by\ Force=1 Harness\ the\ Storm=1 Harpoon\ Sniper=1 Harrier\ Griffin=1 Harrier\ Naga=1 +Harrow=1 Harrowing\ Journey=1 -Harsh\ Justice=1 +Harsh\ Deceiver=1 +Harsh\ Scrutiny=1 Haru-Onna=1 Harvest\ Gwyllion=1 Harvest\ Hand=1 Harvest\ Mage=1 -Harvest\ Pyre=1 Harvest\ Season=1 Harvester\ Troll=1 Harvestguard\ Alseids=1 Hasran\ Ogress=1 +Hatchet\ Bully=1 Hate\ Weaver=1 +Hateflayer=1 Haunted\ Angel=1 Haunted\ Cadaver=1 Haunted\ Cloak=1 @@ -3765,27 +3939,33 @@ Haunting\ Apparition=1 Haunting\ Echoes=1 Haunting\ Hymn=1 Havengul\ Runebinder=1 +Havengul\ Skaab=1 Havengul\ Vampire=1 +Havenwood\ Battleground=1 Havenwood\ Wurm=1 Havoc\ Demon=1 +Havoc\ Devils=1 Havoc\ Festival=1 Havoc\ Sower=1 Hawkeater\ Moth=1 Hazardous\ Conditions=1 Haze\ Frog=1 Haze\ of\ Pollen=1 +Hazerider\ Drake=1 +Hazezon\ Tamar=1 Hazoret's\ Favor=1 Hazoret's\ Monument=1 Hazoret's\ Undying\ Fury=1 Hazy\ Homunculus=1 +He\ Who\ Hungers=1 Head\ Games=1 -Headhunter=1 Headless\ Skaab=1 Headstrong\ Brute=1 Headwater\ Sentries=1 -Heal\ the\ Scars=1 +Heal=1 Healer's\ Headdress=1 Healer\ of\ the\ Pride=1 +Healing\ Grace=1 Healing\ Hands=1 Healing\ Leaves=1 Healing\ Salve=1 @@ -3793,9 +3973,7 @@ Heap\ Doll=1 Heart-Piercer\ Bow=1 Heart-Piercer\ Manticore=1 Heart\ Warden=1 -Heart\ of\ Bogardan=1 Hearth\ Kami=1 -Hearthcage\ Giant=1 Hearthfire\ Hobgoblin=1 Heartlash\ Cinder=1 Heartless\ Pillage=1 @@ -3816,24 +3994,25 @@ Heavy\ Ballista=1 Heavy\ Fog=1 Heavy\ Infantry=1 Heavy\ Mattock=1 +Hecatomb=1 +Heckling\ Fiends=1 Hedonist's\ Trove=1 Hedron-Field\ Purists=1 Hedron\ Alignment=1 +Hedron\ Archive=1 Hedron\ Blade=1 Hedron\ Crawler=1 Hedron\ Matrix=1 +Hedron\ Rover=1 Hedron\ Scrabbler=1 Heed\ the\ Mists=1 -Heedless\ One=1 +Heidar,\ Rimewind\ Master=1 Heir\ of\ Falkenrath=1 Heir\ of\ the\ Wilds=1 Heirs\ of\ Stromkirk=1 Hekma\ Sentinels=1 Heliod's\ Emissary=1 -Heliophial=1 Helium\ Squirter=1 -Hell's\ Thunder=1 -Hell-Bent\ Raider=1 Hellcarver\ Demon=1 Helldozer=1 Hellhole\ Flailer=1 @@ -3843,51 +4022,56 @@ Hellion\ Eruption=1 Hellkite\ Charger=1 Hellkite\ Hatchling=1 Hellraiser\ Goblin=1 -Hellspark\ Elemental=1 Helm\ of\ the\ Ghastlord=1 Helm\ of\ the\ Gods=1 +Helm\ of\ the\ Host=1 Hematite\ Golem=1 Henchfiend\ of\ Ukor=1 Henge\ Guardian=1 Herald\ of\ Anafenza=1 -Herald\ of\ Dromoka=1 +Herald\ of\ Faith=1 Herald\ of\ Kozilek=1 -Herald\ of\ Serra=1 +Herald\ of\ Secret\ Streams=1 Herald\ of\ Torment=1 -Herald\ of\ War=1 Herald\ of\ the\ Fair=1 Herald\ of\ the\ Host=1 +Herald\ of\ the\ Pantheon=1 Herbal\ Poultice=1 Herdchaser\ Dragon=1 +Heretic's\ Punishment=1 Hermetic\ Study=1 Hermit\ Druid=1 Hermit\ of\ the\ Natterknolls=1 Hero's\ Demise=1 +Hero's\ Resolve=1 Hero\ of\ Goma\ Fada=1 Hero\ of\ Iroas=1 Hero\ of\ Leina\ Tower=1 +Heroes'\ Bane=1 Heroes'\ Podium=1 Heroes'\ Reunion=1 Heroes\ Remembered=1 Heroic\ Defiance=1 +Heroic\ Reinforcements=1 Heron's\ Grace\ Champion=1 Hesitation=1 Hewed\ Stone\ Retainers=1 Hex=1 -Hexplate\ Golem=1 Hibernation's\ End=1 -Hibernation=1 Hidden\ Ancients=1 -Hidden\ Dragonslayer=1 +Hidden\ Gibbons=1 +Hidden\ Guerrillas=1 Hidden\ Herbalists=1 Hidden\ Horror=1 -Hidden\ Retreat=1 -Hidden\ Stag=1 +Hidden\ Stockpile=1 Hideous\ End=1 Hideous\ Laughter=1 +Hideous\ Visage=1 Hidetsugu's\ Second\ Rite=1 Hieroglyphic\ Illumination=1 +Hieromancer's\ Cage=1 Hierophant's\ Chalice=1 +High\ Ground=1 High\ Priest\ of\ Penance=1 High\ Sentinels\ of\ Arashin=1 Highborn\ Ghoul=1 @@ -3904,15 +4088,17 @@ Higure,\ the\ Still\ Wind=1 Hijack=1 Hikari,\ Twilight\ Guardian=1 Hill\ Giant=1 -Hillcomber\ Giant=1 Hinder=1 +Hindering\ Light=1 Hindering\ Touch=1 Hindervines=1 Hint\ of\ Insanity=1 Hinterland\ Drake=1 Hinterland\ Hermit=1 Hinterland\ Logger=1 +Hired\ Blade=1 Hired\ Giant=1 +Hired\ Muscle=1 Hired\ Torturer=1 Hisoka's\ Guard=1 Hisoka,\ Minamo\ Sensei=1 @@ -3921,6 +4107,7 @@ Hissing\ Miasma=1 Hit\ //\ Run=1 Hitchclaw\ Recluse=1 Hivestone=1 +Hivis\ of\ the\ Scale=1 Hixus,\ Prison\ Warden=1 Hoard-Smelter\ Dragon=1 Hoarder's\ Greed=1 @@ -3930,38 +4117,38 @@ Hold\ at\ Bay=1 Hold\ the\ Gates=1 Hold\ the\ Line=1 Holdout\ Settlement=1 +Holistic\ Wisdom=1 Hollow\ Dogs=1 +Hollow\ Specter=1 Hollowborn\ Barghest=1 -Hollowhenge\ Scavenger=1 Hollowhenge\ Spirit=1 Hollowsage=1 -Holy\ Justiciar=1 Holy\ Mantle=1 Holy\ Strength=1 +Homarid\ Explorer=1 Homarid\ Spawning\ Bed=1 -Homicidal\ Seclusion=1 Homing\ Lightning=1 -Homing\ Sliver=1 -Homura,\ Human\ Ascendant=1 Honden\ of\ Cleansing\ Fire=1 Honden\ of\ Infinite\ Rage=1 Honden\ of\ Life's\ Web=1 Honden\ of\ Night's\ Reach=1 Honden\ of\ Seeing\ Winds=1 Honed\ Khopesh=1 -Honor's\ Reward=1 +Honor-Worn\ Shaku=1 Honor\ Guard=1 Honorable\ Passage=1 Honored\ Crop-Captain=1 Honored\ Hierarch=1 Honored\ Hydra=1 -Hooded\ Assassin=1 Hooded\ Brawler=1 Hooded\ Horror=1 +Hooded\ Kavu=1 +Hoof\ Skulkin=1 Hoofprints\ of\ the\ Stag=1 Hope\ Against\ Hope=1 Hope\ Charm=1 Hope\ Tender=1 +Hope\ and\ Glory=1 Hopeful\ Eidolon=1 Hopping\ Automaton=1 Horde\ of\ Boggarts=1 @@ -3972,55 +4159,51 @@ Horizon\ Drake=1 Horizon\ Scholar=1 Horizon\ Seed=1 Horizon\ Spellbomb=1 -Horn\ of\ Deafening=1 Horncaller's\ Chant=1 Horned\ Cheetah=1 Horned\ Helm=1 -Horned\ Troll=1 Horned\ Turtle=1 +Hornet\ Cannon=1 Hornet\ Harasser=1 Hornet\ Sting=1 Hornswoggle=1 Horobi's\ Whisper=1 +Horrible\ Hordes=1 Horribly\ Awry=1 Horrifying\ Revelation=1 Horror\ of\ Horrors=1 Horror\ of\ the\ Broken\ Lands=1 -Horror\ of\ the\ Dim=1 Horseshoe\ Crab=1 +Hostile\ Minotaur=1 Hostile\ Realm=1 Hostility=1 Hot\ Soup=1 -Hotheaded\ Giant=1 -Hound\ of\ Griselbrand=1 Hound\ of\ the\ Farbogs=1 Hour\ of\ Eternity=1 Hour\ of\ Need=1 +Hour\ of\ Revelation=1 Hover\ Barrier=1 +Hoverguard\ Observer=1 Hoverguard\ Sweepers=1 Hovermyr=1 Howl\ from\ Beyond=1 -Howl\ of\ the\ Horde=1 Howl\ of\ the\ Night\ Pack=1 Howlgeist=1 -Howling\ Banshee=1 -Howling\ Wolf=1 +Howling\ Gale=1 +Howling\ Golem=1 Howlpack\ Resurgence=1 Howlpack\ Wolf=1 Howltooth\ Hollow=1 Hubris=1 +Hulking\ Cyclops=1 Hulking\ Devil=1 -Hulking\ Goblin=1 -Hulking\ Ogre=1 Hum\ of\ the\ Radix=1 Human\ Frailty=1 Humble=1 Humble\ Budoka=1 Humble\ the\ Brute=1 Humbler\ of\ Mortals=1 -Hunding\ Gjornersen=1 Hundred-Handed\ One=1 -Hundred-Talon\ Kami=1 Hundred-Talon\ Strike=1 Hundroog=1 Hunger\ of\ the\ Nim=1 @@ -4028,7 +4211,6 @@ Hungering\ Yeti=1 Hungry\ Flames=1 Hungry\ Mist=1 Hungry\ Spriggan=1 -Hunt\ Down=1 Hunt\ the\ Hunter=1 Hunt\ the\ Weak=1 Hunted\ Dragon=1 @@ -4041,40 +4223,44 @@ Hunter's\ Ambush=1 Hunter's\ Insight=1 Hunter's\ Prowess=1 Hunter\ of\ Eyeblights=1 +Hunters'\ Feast=1 Hunting\ Cheetah=1 Hunting\ Drake=1 -Hunting\ Kavu=1 Hunting\ Moa=1 Hunting\ Pack=1 Hunting\ Triad=1 Hunting\ Wilds=1 Hurloon\ Minotaur=1 Hurloon\ Shaman=1 +Hurly-Burly=1 Hurricane=1 +Hush=1 Hussar\ Patrol=1 -Hyalopterous\ Lemure=1 Hydra\ Broodmaster=1 Hydroform=1 Hydrolash=1 +Hydromorph\ Guardian=1 +Hydromorph\ Gull=1 Hydrosurge=1 Hyena\ Pack=1 Hymn\ of\ Rebirth=1 Hypersonic\ Dragon=1 Hypervolt\ Grasp=1 +Hypnotic\ Cloud=1 Hypnotic\ Siren=1 Hypnotic\ Specter=1 +Hypochondria=1 +Hysterical\ Blindness=1 Hythonia\ the\ Cruel=1 Ib\ Halfheart,\ Goblin\ Tactician=1 Icatian\ Crier=1 Icatian\ Lieutenant=1 -Icatian\ Phalanx=1 Icatian\ Priest=1 -Icatian\ Scout=1 Icatian\ Town=1 Ice\ Cage=1 +Ice\ Cauldron=1 Ice\ Floe=1 Ice\ Over=1 -Ice\ Storm=1 Iceberg=1 Icefall=1 Icefeather\ Aven=1 @@ -4083,15 +4269,18 @@ Ichor\ Rats=1 Ichor\ Slick=1 Icy\ Blast=1 Icy\ Manipulator=1 +Icy\ Prison=1 Identity\ Crisis=1 Identity\ Thief=1 Idle\ Thoughts=1 +Ifh-Bff\ Efreet=1 Igneous\ Golem=1 Igneous\ Pouncer=1 Ignite\ Disorder=1 Ignite\ Memories=1 +Ignoble\ Soldier=1 Ignorant\ Bliss=1 -Ihsan's\ Shade=1 +Iizuka\ the\ Ruthless=1 Ikiral\ Outrider=1 Illness\ in\ the\ Ranks=1 Illuminate=1 @@ -4100,22 +4289,25 @@ Illuminated\ Wings=1 Illusion\ //\ Reality=1 Illusionary\ Forces=1 Illusionary\ Servant=1 -Illusionary\ Wall=1 -Illusionist's\ Stratagem=1 +Illusionist's\ Bracers=1 +Illusory\ Ambusher=1 Illusory\ Angel=1 Illusory\ Demon=1 Illusory\ Gains=1 Illusory\ Wrappings=1 Imagecrafter=1 +Imaginary\ Pet=1 Imaginary\ Threats=1 Imi\ Statue=1 -Immerwolf=1 +Immaculate\ Magistrate=1 Imminent\ Doom=1 Immobilizer\ Eldrazi=1 +Immobilizing\ Ink=1 Immolating\ Glare=1 -Immolating\ Souleater=1 Immolation=1 Immortal\ Coil=1 +Immortal\ Servitude=1 +Imp's\ Mischief=1 Impale=1 Impatience=1 Impeccable\ Timing=1 @@ -4125,84 +4317,80 @@ Imperial\ Ceratops=1 Imperial\ Hellkite=1 Imperial\ Lancer=1 Imperiosaur=1 -Imperious\ Perfect=1 +Impetuous\ Devils=1 Impetuous\ Sunchaser=1 Implement\ of\ Combustion=1 Implement\ of\ Examination=1 Implement\ of\ Ferocity=1 Implement\ of\ Improvement=1 Implement\ of\ Malice=1 -Implode=1 Imprisoned\ in\ the\ Moon=1 Impromptu\ Raid=1 Improvised\ Armor=1 -Imps'\ Taunt=1 -Impulsive\ Maneuvers=1 -In\ Garruk's\ Wake=1 +In\ Bolas's\ Clutches=1 In\ Oketra's\ Name=1 In\ the\ Web\ of\ War=1 Inaction\ Injunction=1 Iname,\ Death\ Aspect=1 Iname,\ Life\ Aspect=1 -Iname\ as\ One=1 Incandescent\ Soulstoke=1 -Incendiary=1 Incendiary\ Command=1 -Incendiary\ Flow=1 Incendiary\ Sabotage=1 Incite=1 Incite\ Hysteria=1 Incite\ War=1 Incorrigible\ Youths=1 -Increasing\ Savagery=1 Incremental\ Blight=1 Incremental\ Growth=1 Incubator\ Drone=1 Incurable\ Ogre=1 Incursion\ Specialist=1 Indebted\ Samurai=1 +Indentured\ Oaf=1 Indestructibility=1 Index=1 Indigo\ Faerie=1 Indomitable\ Ancients=1 Indomitable\ Archangel=1 Indrik\ Stomphowler=1 +Induce\ Despair=1 Induce\ Paranoia=1 Induced\ Amnesia=1 Indulgent\ Aristocrat=1 Indulgent\ Tormentor=1 Inertia\ Bubble=1 -Inescapable\ Brute=1 Inexorable\ Blob=1 Inexorable\ Tide=1 Infantry\ Veteran=1 Infected\ Vermin=1 -Infectious\ Bloodlust=1 Infectious\ Horror=1 Infectious\ Host=1 -Infernal\ Caretaker=1 +Infectious\ Rage=1 +Infernal\ Harvest=1 Infernal\ Kirin=1 Infernal\ Scarring=1 Inferno=1 +Inferno\ Elemental=1 Inferno\ Fist=1 Inferno\ Jet=1 Inferno\ Trap=1 Infest=1 +Infested\ Roothold=1 Infiltration\ Lens=1 Infiltrator's\ Magemark=1 Infiltrator\ il-Kor=1 Infinite\ Obliteration=1 Infinite\ Reflection=1 -Inflame=1 Infuse=1 Infuse\ with\ the\ Elements=1 Infused\ Arrows=1 Ingenious\ Skaab=1 Inheritance=1 Initiate's\ Companion=1 +Initiate\ of\ Blood=1 Ink-Treader\ Nephilim=1 Ink\ Dissolver=1 -Inkfathom\ Infiltrator=1 +Inkfathom\ Divers=1 Inkfathom\ Witch=1 Inner-Chamber\ Guard=1 Inner-Flame\ Acolyte=1 @@ -4211,12 +4399,11 @@ Inner\ Struggle=1 Innocence\ Kami=1 Inquisitor's\ Flail=1 Inquisitor's\ Ox=1 -Inquisitor\ Exarch=1 Insatiable\ Gorgers=1 Insatiable\ Harpy=1 -Insatiable\ Souleater=1 Insidious\ Will=1 Insight=1 +Insolence=1 Inspiration=1 Inspired\ Charge=1 Inspired\ Sprite=1 @@ -4226,48 +4413,54 @@ Inspirit=1 Instigator\ Gang=1 Instill\ Furor=1 Instill\ Infection=1 -Insubordination=1 Insult\ //\ Injury=1 -Intangible\ Virtue=1 -Interdict=1 -Interpret\ the\ Signs=1 Intervene=1 +Intet,\ the\ Dreamer=1 +Intimidation=1 Intimidation\ Bolt=1 Intimidator\ Initiate=1 +Into\ Thin\ Air=1 Into\ the\ Core=1 Into\ the\ Fray=1 Into\ the\ Maw\ of\ Hell=1 Into\ the\ Void=1 -Into\ the\ Wilds=1 Intrepid\ Hero=1 Intrepid\ Provisioner=1 +Inundate=1 Invader\ Parasite=1 -Invasion\ Plans=1 Invasive\ Species=1 Invasive\ Surgery=1 Inventor's\ Apprentice=1 Inventor's\ Goggles=1 Invert\ the\ Skies=1 +Inverter\ of\ Truth=1 +Invigorate=1 +Invigorated\ Rampage=1 +Invigorating\ Boon=1 +Invigorating\ Falls=1 Invincible\ Hymn=1 Invisibility=1 -Invocation\ of\ Saint\ Traft=1 +Invoke\ the\ Divine=1 +Invoke\ the\ Firemind=1 Invulnerability=1 Ion\ Storm=1 Iona's\ Blessing=1 -Iona's\ Judgment=1 Ior\ Ruin\ Expedition=1 Ire\ Shaman=1 Ire\ of\ Kaminari=1 Iridescent\ Drake=1 Iroas's\ Champion=1 +Iron-Barb\ Hellion=1 Iron-Heart\ Chimera=1 +Iron\ Lance=1 Iron\ League\ Steed=1 Iron\ Myr=1 +Iron\ Star=1 +Iron\ Tusk\ Elephant=1 Iron\ Will=1 Ironclad\ Revolutionary=1 Ironclad\ Slayer=1 Ironclaw\ Buzzardiers=1 -Ironclaw\ Orcs=1 Ironfist\ Crusher=1 Ironhoof\ Ox=1 Irontread\ Crusher=1 @@ -4275,6 +4468,7 @@ Ironwright's\ Cleansing=1 Irradiate=1 Irresistible\ Prey=1 Isao,\ Enlightened\ Bushi=1 +Ishi-Ishi,\ Akki\ Crackshot=1 Island=1 Isleback\ Spawn=1 Isolation\ Cell=1 @@ -4283,36 +4477,40 @@ Isperia's\ Skywatch=1 Isperia\ the\ Inscrutable=1 It\ of\ the\ Horrid\ Swarm=1 Ith,\ High\ Arcanist=1 -Ivory\ Charm=1 Ivory\ Crane\ Netsuke=1 Ivory\ Cup=1 Ivory\ Gargoyle=1 +Ivory\ Giant=1 Ivory\ Guardians=1 Ivory\ Tower=1 Ivorytusk\ Fortress=1 Ivy\ Dancer=1 +Ivy\ Elemental=1 Ivy\ Lane\ Denizen=1 +Ivy\ Seer=1 Iwamori\ of\ the\ Open\ Fist=1 Ixalli's\ Diviner=1 Ixalli's\ Keeper=1 +Ixidor's\ Will=1 Ixidron=1 +Izzet\ Chemister=1 Izzet\ Chronarch=1 Izzet\ Cluestone=1 Izzet\ Guildgate=1 Izzet\ Guildmage=1 Izzet\ Keyrune=1 +Jabari's\ Banner=1 Jace's\ Ingenuity=1 Jace's\ Mindseeker=1 Jace's\ Sanctum=1 Jace's\ Scrutiny=1 -Jackal\ Familiar=1 Jackal\ Pup=1 Jackalope\ Herd=1 -Jacques\ le\ Vert=1 +Jaddi\ Lifestrider=1 Jaddi\ Offshoot=1 Jade\ Bearer=1 Jade\ Guardian=1 -Jade\ Leech=1 +Jade\ Idol=1 Jade\ Mage=1 Jade\ Monolith=1 Jade\ Statue=1 @@ -4324,67 +4522,70 @@ Jagwasp\ Swarm=1 Jalira,\ Master\ Polymorphist=1 Jalum\ Tome=1 Jamuraan\ Lion=1 -Jangling\ Automaton=1 Janjeet\ Sentry=1 Jar\ of\ Eyeballs=1 Jarad's\ Orders=1 Jareth,\ Leonine\ Titan=1 -Jasmine\ Boreal=1 Jasmine\ Seer=1 Jawbone\ Skulkin=1 -Jaws\ of\ Stone=1 +Jaya's\ Immolating\ Inferno=1 Jaya\ Ballard,\ Task\ Mage=1 Jayemdae\ Tome=1 -Jedit's\ Dragoons=1 Jedit\ Ojanen=1 Jedit\ Ojanen\ of\ Efrava=1 Jeering\ Instigator=1 Jelenn\ Sphinx=1 Jerrard\ of\ the\ Closed\ Fist=1 +Jeskai\ Ascendancy=1 Jeskai\ Banner=1 Jeskai\ Charm=1 Jeskai\ Elder=1 Jeskai\ Infiltrator=1 -Jeskai\ Runemark=1 Jeskai\ Student=1 Jeskai\ Windscout=1 -Jetting\ Glasskite=1 +Jester's\ Scepter=1 +Jeweled\ Torque=1 +Jhessian\ Balmgiver=1 Jhessian\ Infiltrator=1 Jhessian\ Lookout=1 Jhessian\ Thief=1 Jhessian\ Zombies=1 +Jhoira's\ Familiar=1 Jhoira's\ Timebug=1 Jhoira's\ Toolbox=1 +Jilt=1 Jinxed\ Choker=1 Jinxed\ Idol=1 +Jinxed\ Ring=1 +Jiwari,\ the\ Earth\ Aflame=1 +Jodah's\ Avenger=1 +Jodah,\ Archmage\ Eternal=1 Johtull\ Wurm=1 Join\ the\ Ranks=1 Joiner\ Adept=1 Jokulmorder=1 -Jolrael's\ Centaur=1 Jolrael,\ Empress\ of\ Beasts=1 Jolt=1 -Jor\ Kadeen,\ the\ Prevailer=1 +Jolting\ Merfolk=1 Joraga\ Auxiliary=1 Joraga\ Bard=1 Joraga\ Invocation=1 Jori\ En,\ Ruin\ Diver=1 Jorubai\ Murk\ Lurker=1 -Jotun\ Grunt=1 -Jotun\ Owl\ Keeper=1 Journey\ of\ Discovery=1 +Jousting\ Lance=1 Joven's\ Ferrets=1 Joyous\ Respite=1 Judge\ Unworthy=1 Judge\ of\ Currents=1 +Jugan,\ the\ Rising\ Star=1 Juggernaut=1 Juju\ Bubble=1 -Jump=1 -Jund\ Hackblade=1 -Jund\ Panorama=1 +Jukai\ Messenger=1 +Jund\ Battlemage=1 +Jund\ Charm=1 Jund\ Sojourners=1 Jungle\ Barrier=1 -Jungle\ Basin=1 Jungle\ Creeper=1 Jungle\ Delver=1 Jungle\ Shrine=1 @@ -4395,20 +4596,24 @@ Juniper\ Order\ Advocate=1 Junk\ Golem=1 Junktroller=1 Junkyo\ Bell=1 -Junun\ Efreet=1 Jushi\ Apprentice=1 Just\ Fate=1 Just\ the\ Wind=1 Juvenile\ Gloomwidow=1 Juxtapose=1 Jwar\ Isle\ Avenger=1 +Jwari\ Scuttler=1 Jwari\ Shapeshifter=1 +Jtun\ Grunt=1 +Jtun\ Owl\ Keeper=1 Kabira\ Vindicator=1 +Kaboom!=1 Kabuto\ Moth=1 Kaervek's\ Hex=1 Kaervek's\ Torch=1 Kaervek\ the\ Merciless=1 Kagemaro's\ Clutch=1 +Kagemaro,\ First\ to\ Suffer=1 Kaho,\ Minamo\ Historian=1 Kaijin\ of\ the\ Vanishing\ Touch=1 Kalastria\ Healer=1 @@ -4416,51 +4621,55 @@ Kalastria\ Nightwatch=1 Kaleidostone=1 Kalonian\ Behemoth=1 Kalonian\ Twingrove=1 +Kamahl's\ Desire=1 +Kamahl's\ Druidic\ Vow=1 +Kamahl's\ Sledge=1 Kamahl,\ Pit\ Fighter=1 Kami\ of\ Ancient\ Law=1 -Kami\ of\ Empty\ Graves=1 Kami\ of\ Fire's\ Roar=1 Kami\ of\ Lunacy=1 -Kami\ of\ Tattered\ Shoji=1 +Kami\ of\ Twisted\ Reflection=1 Kami\ of\ the\ Honored\ Dead=1 -Kami\ of\ the\ Hunt=1 Kami\ of\ the\ Painted\ Road=1 -Kami\ of\ the\ Palace\ Fields=1 Kami\ of\ the\ Tended\ Garden=1 -Kami\ of\ the\ Waning\ Moon=1 -Kapsho\ Kitefins=1 Karametra's\ Acolyte=1 Karametra's\ Favor=1 -Karma=1 -Karn,\ Silver\ Golem=1 -Karoo=1 -Karoo\ Meerkat=1 +Karn's\ Temporal\ Sundering=1 Karplusan\ Giant=1 Karplusan\ Strider=1 +Karplusan\ Wolverine=1 +Karplusan\ Yeti=1 +Karstoderm=1 Kashi-Tribe\ Elite=1 Kashi-Tribe\ Reaver=1 Kashi-Tribe\ Warriors=1 +Katabatic\ Winds=1 Kathari\ Bomber=1 Kathari\ Remnant=1 +Kathari\ Screecher=1 Kavu\ Aggressor=1 +Kavu\ Chameleon=1 Kavu\ Climber=1 +Kavu\ Glider=1 +Kavu\ Howler=1 Kavu\ Mauler=1 Kavu\ Predator=1 Kavu\ Primarch=1 Kavu\ Recluse=1 -Kavu\ Scout=1 -Kavu\ Titan=1 +Kavu\ Runner=1 +Kazandu\ Refuge=1 Kazandu\ Tuskcaller=1 +Kazarov,\ Sengir\ Pureblood=1 Kazuul's\ Toll\ Collector=1 Kazuul,\ Tyrant\ of\ the\ Cliffs=1 Kazuul\ Warlord=1 Kederekt\ Creeper=1 Kederekt\ Leviathan=1 -Kederekt\ Parasite=1 Keeneye\ Aven=1 Keening\ Apparition=1 Keening\ Banshee=1 Keening\ Stone=1 +Keeper\ of\ Kookus=1 Keeper\ of\ Progenitus=1 Keeper\ of\ the\ Beasts=1 Keeper\ of\ the\ Dead=1 @@ -4468,34 +4677,33 @@ Keeper\ of\ the\ Flame=1 Keeper\ of\ the\ Lens=1 Keeper\ of\ the\ Light=1 Keeper\ of\ the\ Mind=1 -Keeper\ of\ the\ Nine\ Gales=1 Keepsake\ Gorgon=1 -Kefnet's\ Last\ Word=1 Kefnet's\ Monument=1 -Kei\ Takahashi=1 Keiga,\ the\ Tide\ Star=1 -Keldon\ Arsonist=1 Keldon\ Berserker=1 Keldon\ Champion=1 Keldon\ Halberdier=1 Keldon\ Mantle=1 -Keldon\ Marauders=1 Keldon\ Megaliths=1 Keldon\ Necropolis=1 -Keldon\ Vandals=1 +Keldon\ Overseer=1 +Keldon\ Raider=1 +Keldon\ Twilight=1 +Keldon\ Warcaller=1 Keldon\ Warlord=1 +Kelinore\ Bat=1 +Kemba's\ Legion=1 Kemba's\ Skyguard=1 -Kemba,\ Kha\ Regent=1 +Kemuri-Onna=1 +Kentaro,\ the\ Smiling\ Cat=1 Kessig\ Cagebreakers=1 Kessig\ Dire\ Swine=1 Kessig\ Forgemaster=1 Kessig\ Prowler=1 Kessig\ Recluse=1 -Kessig\ Wolf=1 Key\ to\ the\ City=1 Keymaster\ Rogue=1 Kezzerdrix=1 -Khabal\ Ghoul=1 Khalni\ Gem=1 Khenra\ Charioteer=1 Khenra\ Eternal=1 @@ -4504,6 +4712,7 @@ Kheru\ Bloodsucker=1 Kheru\ Dreadmaw=1 Kheru\ Lich\ Lord=1 Kheru\ Spellsnatcher=1 +Kiku's\ Shadow=1 Kiku,\ Night's\ Flower=1 Kill-Suit\ Cultist=1 Kill\ Shot=1 @@ -4522,87 +4731,95 @@ King\ Cheetah=1 King\ Crab=1 King\ Macar,\ the\ Gold-Cursed=1 Kingfisher=1 +Kingpin's\ Pet=1 Kinjalli's\ Caller=1 Kinsbaile\ Balloonist=1 -Kinsbaile\ Borderguard=1 Kinsbaile\ Skirmisher=1 +Kinscaer\ Harpoonist=1 Kiora's\ Dismissal=1 Kiora's\ Follower=1 Kird\ Chieftain=1 Kiri-Onna=1 +Kiss\ of\ the\ Amesha=1 Kite\ Shield=1 Kitesail=1 Kitesail\ Apprentice=1 Kitesail\ Corsair=1 Kitesail\ Scout=1 +Kithkin\ Armor=1 Kithkin\ Daggerdare=1 +Kithkin\ Greatheart=1 Kithkin\ Harbinger=1 Kithkin\ Healer=1 Kithkin\ Mourncaller=1 -Kithkin\ Rabble=1 Kithkin\ Spellduster=1 +Kithkin\ Zealot=1 Kithkin\ Zephyrnaut=1 -Kitsune\ Blademaster=1 Kitsune\ Bonesetter=1 Kitsune\ Dawnblade=1 Kitsune\ Diviner=1 -Kitsune\ Loreweaver=1 -Kitsune\ Mystic=1 +Kitsune\ Healer=1 Kitsune\ Palliator=1 Kitsune\ Riftwalker=1 Kiyomaro,\ First\ to\ Stand=1 -Kjeldoran\ Dead=1 Kjeldoran\ Elite\ Guard=1 Kjeldoran\ Frostbeast=1 Kjeldoran\ Gargoyle=1 +Kjeldoran\ Home\ Guard=1 Kjeldoran\ Javelineer=1 Kjeldoran\ Outpost=1 Kjeldoran\ Outrider=1 Kjeldoran\ Royal\ Guard=1 Kjeldoran\ Skycaptain=1 Kjeldoran\ War\ Cry=1 +Knacksaw\ Clique=1 +Knight's\ Pledge=1 Knight-Captain\ of\ Eos=1 Knight\ Errant=1 Knight\ Watch=1 Knight\ of\ Cliffhaven=1 -Knight\ of\ Dawn=1 Knight\ of\ Dusk=1 +Knight\ of\ Glory=1 Knight\ of\ Infamy=1 +Knight\ of\ New\ Benalia=1 Knight\ of\ Obligation=1 Knight\ of\ Stromgald=1 Knight\ of\ Sursi=1 +Knight\ of\ Valor=1 Knight\ of\ the\ Holy\ Nimbus=1 Knight\ of\ the\ Mists=1 Knight\ of\ the\ Pilgrim's\ Road=1 Knight\ of\ the\ Skyward\ Eye=1 Knight\ of\ the\ Stampede=1 +Knight\ of\ the\ Tusk=1 Knighthood=1 Knightly\ Valor=1 -Knights\ of\ Thorn=1 Knollspine\ Dragon=1 -Knollspine\ Invocation=1 Knotvine\ Mystic=1 Knotvine\ Paladin=1 +Knowledge\ Exploitation=1 Knowledge\ Pool=1 -Knowledge\ Vault=1 Knowledge\ and\ Power=1 Knucklebone\ Witch=1 Kobold\ Drill\ Sergeant=1 -Kobold\ Overlord=1 Kobold\ Taskmaster=1 Kodama's\ Might=1 Kodama\ of\ the\ Center\ Tree=1 Kodama\ of\ the\ North\ Tree=1 +Kodama\ of\ the\ South\ Tree=1 Kolaghan\ Aspirant=1 Kolaghan\ Forerunners=1 Kolaghan\ Monument=1 Kolaghan\ Stormsinger=1 +Konda's\ Banner=1 Konda's\ Hatamoto=1 +Konda,\ Lord\ of\ Eiganjo=1 Kongming,\ "Sleeping\ Dragon"=1 Kookus=1 Kor\ Bladewhirl=1 Kor\ Cartographer=1 Kor\ Castigator=1 +Kor\ Chant=1 Kor\ Duelist=1 Kor\ Entanglers=1 Kor\ Hookmaster=1 @@ -4612,7 +4829,6 @@ Kor\ Sky\ Climber=1 Korozda\ Gorgon=1 Korozda\ Guildmage=1 Korozda\ Monitor=1 -Koth's\ Courier=1 Kothophed,\ Soul\ Hoarder=1 Kozilek's\ Channeler=1 Kozilek's\ Pathfinder=1 @@ -4627,58 +4843,61 @@ Kraken\ Hatchling=1 Kraken\ of\ the\ Straits=1 Krakilin=1 Kranioceros=1 -Krark's\ Thumb=1 -Krark-Clan\ Engineers=1 -Krark-Clan\ Grunt=1 -Krark-Clan\ Ogre=1 Krasis\ Incubation=1 Kraul\ Warrior=1 Krenko's\ Enforcer=1 -Kris\ Mage=1 -Krosan\ Beast=1 +Krosan\ Avenger=1 Krosan\ Cloudscraper=1 +Krosan\ Colossus=1 Krosan\ Drover=1 +Krosan\ Druid=1 Krosan\ Groundshaker=1 +Krosan\ Reclamation=1 Krosan\ Tusker=1 Krosan\ Vorine=1 Krosan\ Warchief=1 +Krosan\ Wayfarer=1 Krovikan\ Fetish=1 +Krovikan\ Horror=1 Krovikan\ Rot=1 Krovikan\ Scoundrel=1 -Krovikan\ Sorcerer=1 Krovikan\ Vampire=1 -Krovikan\ Whispers=1 Kruin\ Outlaw=1 Kruin\ Striker=1 -Krumar\ Bond-Kin=1 Kudzu=1 Kujar\ Seedsculptor=1 Kukemssa\ Serpent=1 Kuldotha\ Flamefiend=1 Kuldotha\ Phoenix=1 -Kuldotha\ Ringleader=1 Kulrath\ Knight=1 +Kumano's\ Blessing=1 +Kumano's\ Pupils=1 Kumano,\ Master\ Yamabushi=1 Kumena's\ Awakening=1 +Kumena's\ Speaker=1 +Kuon,\ Ogre\ Ascendant=1 Kurgadon=1 Kurkesh,\ Onakke\ Ancient=1 Kuro's\ Taken=1 Kuro,\ Pitlord=1 -Kyren\ Glider=1 +Kusari-Gama=1 +Kwende,\ Pride\ of\ Femeref=1 +Kyoki,\ Sanity's\ Eclipse=1 +Kyren\ Legate=1 Kyren\ Sniper=1 Kytheon's\ Irregulars=1 Kytheon's\ Tactics=1 Lab\ Rats=1 Laboratory\ Brute=1 +Labyrinth\ Champion=1 Labyrinth\ Guardian=1 Labyrinth\ Minotaur=1 +Laccolith\ Grunt=1 Laccolith\ Rig=1 -Lady\ Caleria=1 -Lady\ Evangela=1 +Laccolith\ Warrior=1 Lady\ Orca=1 Lagac\ Lizard=1 Lagonna-Band\ Elder=1 -Lake\ of\ the\ Dead=1 Lambholt\ Elder=1 Lambholt\ Pacifist=1 Lammastide\ Weave=1 @@ -4688,16 +4907,22 @@ Landslide=1 Lantern-Lit\ Graveyard=1 Lantern\ Kami=1 Lantern\ Scout=1 +Lantern\ Spirit=1 Lapse\ of\ Certainty=1 Laquatus's\ Champion=1 +Laquatus's\ Disdain=1 +Larceny=1 +Larger\ Than\ Life=1 Lash\ Out=1 Lashknife=1 Lashknife\ Barrier=1 Lashweed\ Lurker=1 Last-Ditch\ Effort=1 Last\ Breath=1 +Last\ Caress=1 Last\ Gasp=1 Last\ Kiss=1 +Last\ Laugh=1 Last\ Stand=1 Last\ Thoughts=1 Last\ Word=1 @@ -4706,49 +4931,45 @@ Latch\ Seeker=1 Latchkey\ Faerie=1 Lathnu\ Hellion=1 Lathnu\ Sailback=1 -Latulla's\ Orders=1 Launch=1 -Launch\ Party=1 Lava\ Axe=1 Lava\ Burst=1 +Lava\ Dart=1 Lava\ Flow=1 Lava\ Hounds=1 -Lava\ Zombie=1 +Lava\ Runner=1 Lavaball\ Trap=1 Lavaborn\ Muse=1 -Lavacore\ Elemental=1 Lavafume\ Invoker=1 -Lavamancer's\ Skill=1 +Lavalanche=1 Lavastep\ Raider=1 Lavinia\ of\ the\ Tenth=1 -Lawbringer=1 Lawless\ Broker=1 Lay\ Bare\ the\ Heart=1 Lay\ Claim=1 Lay\ Waste=1 Lay\ of\ the\ Land=1 Lead-Belly\ Chimera=1 +Lead\ Astray=1 Lead\ Golem=1 Lead\ by\ Example=1 Leaden\ Fists=1 Leaden\ Myr=1 -Leaf\ Arrow=1 +Leaf\ Dancer=1 Leaf\ Gilder=1 Leafcrown\ Dryad=1 Leafdrake\ Roost=1 -Leap\ of\ Flame=1 Leaping\ Lizard=1 Leaping\ Master=1 Learn\ from\ the\ Past=1 Leashling=1 -Leatherback\ Baloth=1 Leave\ //\ Chance=1 -Leave\ No\ Trace=1 Leave\ in\ the\ Dust=1 Leech\ Bonder=1 +Leeches=1 Leeching\ Licid=1 -Leechridden\ Swamp=1 Leering\ Emblem=1 +Leering\ Gargoyle=1 Leery\ Fogbeast=1 Legacy's\ Allure=1 Legacy\ Weapon=1 @@ -4757,6 +4978,7 @@ Legion's\ Judgment=1 Legion\ Conquistador=1 Legion\ Lieutenant=1 Lens\ of\ Clarity=1 +Leonin\ Abunas=1 Leonin\ Armorguard=1 Leonin\ Battlemage=1 Leonin\ Bola=1 @@ -4769,146 +4991,162 @@ Leonin\ Snarecaster=1 Leonin\ Squire=1 Leonin\ Sun\ Standard=1 Leshrac's\ Rite=1 +Lesser\ Gargadon=1 Lesser\ Werewolf=1 Lethal\ Sting=1 +Lethargy\ Trap=1 Leveler=1 +Leviathan=1 Levitation=1 Ley\ Druid=1 +Ley\ Line=1 Leyline\ Phantom=1 Leyline\ of\ Lightning=1 Leyline\ of\ Vitality=1 +Lhurgoyf=1 Liar's\ Pendulum=1 +Liberate=1 +Liberated\ Dwarf=1 +Lich's\ Caress=1 +Lich's\ Mastery=1 Lich's\ Tomb=1 Liege\ of\ the\ Pit=1 -Life's\ Legacy=1 -Life\ //\ Death=1 -Life\ Chisel=1 +Life's\ Finale=1 +Life\ Goes\ On=1 Life\ and\ Limb=1 Lifecraft\ Awakening=1 Lifecraft\ Cavalry=1 Lifecrafter's\ Gift=1 -Lifesmith=1 +Lifegift=1 Lifespark\ Spellbomb=1 Lifespinner=1 Lifespring\ Druid=1 -Light\ of\ Day=1 Light\ of\ Sanction=1 Lightbringer=1 Lightkeeper\ of\ Emeria=1 -Lightmine\ Field=1 Lightning-Rig\ Crew=1 Lightning\ Blast=1 Lightning\ Blow=1 Lightning\ Cloud=1 -Lightning\ Coils=1 -Lightning\ Crafter=1 -Lightning\ Dragon=1 Lightning\ Elemental=1 Lightning\ Hounds=1 Lightning\ Javelin=1 -Lightning\ Prowess=1 Lightning\ Reaver=1 Lightning\ Reflexes=1 Lightning\ Rift=1 Lightning\ Runner=1 -Lightning\ Surge=1 Lightning\ Talons=1 Lightning\ Volley=1 Lightwielder\ Paladin=1 Liliana's\ Defeat=1 Liliana's\ Elite=1 Liliana's\ Indignation=1 -Liliana's\ Mastery=1 -Liliana's\ Reaver=1 Liliana's\ Shade=1 -Lim-Dul's\ Cohort=1 -Lim-Dul's\ High\ Guard=1 -Lim-Dul\ the\ Necromancer=1 +Liliana's\ Specter=1 +Lilting\ Refrain=1 +Lim-Dl's\ Cohort=1 +Lim-Dl's\ High\ Guard=1 +Lim-Dl\ the\ Necromancer=1 +Limestone\ Golem=1 Limits\ of\ Solidarity=1 Linessa,\ Zephyr\ Mage=1 -Lingering\ Death=1 +Lingering\ Mirage=1 +Lingering\ Phantom=1 Lingering\ Tormentor=1 +Linvala,\ the\ Preserver=1 +Lionheart\ Maverick=1 +Liquid\ Fire=1 Liquimetal\ Coating=1 +Lithatog=1 +Lithomancer's\ Focus=1 +Lithophage=1 Liturgy\ of\ Blood=1 Liu\ Bei,\ Lord\ of\ Shu=1 Live\ Fast=1 Livewire\ Lash=1 +Living\ Airship=1 +Living\ Death=1 Living\ Destiny=1 Living\ Hive=1 Living\ Inferno=1 -Living\ Lore=1 +Living\ Lands=1 +Living\ Terrain=1 Living\ Totem=1 Living\ Tsunami=1 -Living\ Wall=1 -Livonya\ Silone=1 +Llanowar\ Behemoth=1 +Llanowar\ Cavalry=1 +Llanowar\ Dead=1 Llanowar\ Empath=1 +Llanowar\ Envoy=1 Llanowar\ Mentor=1 +Llanowar\ Scout=1 Llanowar\ Sentinel=1 +Llanowar\ Vanguard=1 Loafing\ Giant=1 Loam\ Dryad=1 Loam\ Dweller=1 -Loam\ Larva=1 Loam\ Lion=1 Loamdragger\ Giant=1 +Loathsome\ Catoblepas=1 Lobber\ Crew=1 -Lobotomy=1 Locket\ of\ Yesterdays=1 Lockjaw\ Snapper=1 -Locust\ Miser=1 +Locust\ Swarm=1 Lodestone\ Myr=1 +Lone\ Missionary=1 Lone\ Revenant=1 Lone\ Rider=1 Lone\ Wolf=1 -Lonely\ Sandbar=1 Long-Finned\ Skywhale=1 Long-Forgotten\ Gohei=1 Long\ Road\ Home=1 Longbow\ Archer=1 Longshot\ Squad=1 +Longtusk\ Cub=1 +Lookout's\ Dispersal=1 Looming\ Altisaur=1 Looming\ Hoverguard=1 Looming\ Shade=1 Looming\ Spires=1 -Looter\ il-Kor=1 -Lord\ of\ the\ Accursed=1 +Lord\ of\ Shatterskull\ Pass=1 Lord\ of\ the\ Pit=1 Lore\ Broker=1 Lorescale\ Coatl=1 +Lorthos,\ the\ Tidemaker=1 Lose\ Calm=1 Lose\ Hope=1 Lost\ Auramancers=1 -Lost\ Hours=1 Lost\ Leonin=1 Lost\ Order\ of\ Jarkeld=1 +Lost\ in\ Thought=1 Lost\ in\ a\ Labyrinth=1 Lost\ in\ the\ Mist=1 -Lotleth\ Troll=1 -Lotus-Eye\ Mystics=1 +Lost\ in\ the\ Woods=1 Lotus\ Path\ Djinn=1 Lowland\ Basilisk=1 Lowland\ Giant=1 -Lowland\ Tracker=1 -Loxodon\ Convert=1 Loxodon\ Gatekeeper=1 Loxodon\ Hierarch=1 -Loxodon\ Mender=1 +Loxodon\ Line\ Breaker=1 Loxodon\ Mystic=1 +Loxodon\ Partisan=1 Loxodon\ Peacekeeper=1 Loxodon\ Punisher=1 Loyal\ Cathar=1 +Loyal\ Gyrfalcon=1 Loyal\ Pegasus=1 Lu\ Bu,\ Master-at-Arms=1 Lu\ Meng,\ Wu\ General=1 Lucent\ Liminid=1 Ludevic's\ Test\ Subject=1 -Lull=1 Lullmage\ Mentor=1 +Lumbering\ Satyr=1 Lumberknot=1 -Lumengrid\ Drake=1 +Lumengrid\ Augur=1 Lumengrid\ Gargoyle=1 +Lumengrid\ Sentinel=1 Lumengrid\ Warden=1 Luminate\ Primordial=1 -Luminesce=1 Luminous\ Angel=1 Luminous\ Bonds=1 Luminous\ Wake=1 @@ -4919,47 +5157,47 @@ Lunarch\ Mantle=1 Lunk\ Errant=1 Lupine\ Prototype=1 Lurching\ Rotbeast=1 +Lure=1 Lurebound\ Scarecrow=1 Lurking\ Arynx=1 Lurking\ Chupacabra=1 -Lurking\ Crocodile=1 -Lurking\ Evil=1 Lurking\ Informant=1 -Lurking\ Jackals=1 Lurking\ Skirge=1 Lush\ Growth=1 +Lust\ for\ War=1 Luxa\ River\ Shrine=1 Lyev\ Decree=1 Lyev\ Skyknight=1 Lymph\ Sliver=1 Lys\ Alana\ Bowmaster=1 Lys\ Alana\ Scarblade=1 -Lyzolda,\ the\ Blood\ Witch=1 Macabre\ Waltz=1 Macetail\ Hystrodon=1 +Machinate=1 Mad\ Auntie=1 Mad\ Prophet=1 Madblind\ Mountain=1 Madcap\ Skills=1 Madrush\ Cyclops=1 Maelstrom\ Djinn=1 +Maga,\ Traitor\ to\ Mortals=1 Mage-Ring\ Bully=1 Mage-Ring\ Network=1 Mage-Ring\ Responder=1 Mage\ Slayer=1 -Mage\ il-Vec=1 Magebane\ Armor=1 Magefire\ Wings=1 -Mageta's\ Boon=1 Magewright's\ Stone=1 Maggot\ Carrier=1 Maggot\ Therapy=1 +Magister\ Sphinx=1 Magister\ of\ Worth=1 +Magistrate's\ Veto=1 +Magma\ Burst=1 Magma\ Giant=1 Magma\ Mine=1 Magma\ Phoenix=1 -Magma\ Spray=1 -Magma\ Vein=1 +Magma\ Rift=1 Magmaquake=1 Magmaroth=1 Magmasaur=1 @@ -4967,58 +5205,64 @@ Magmatic\ Chasm=1 Magmatic\ Core=1 Magmatic\ Insight=1 Magmaw=1 -Magnetic\ Flux=1 -Magnetic\ Mine=1 Magnetic\ Theft=1 Magnifying\ Glass=1 Magnivore=1 Magosi,\ the\ Waterveil=1 Magus\ of\ the\ Abyss=1 -Magus\ of\ the\ Arena=1 Magus\ of\ the\ Candelabra=1 +Magus\ of\ the\ Coffers=1 Magus\ of\ the\ Disk=1 Magus\ of\ the\ Future=1 Magus\ of\ the\ Jar=1 Magus\ of\ the\ Library=1 Magus\ of\ the\ Mirror=1 Magus\ of\ the\ Scroll=1 +Magus\ of\ the\ Tabernacle=1 +Magus\ of\ the\ Vineyard=1 Mahamoti\ Djinn=1 Majestic\ Heliopterus=1 +Major\ Teroh=1 Make\ Mischief=1 Make\ Obsolete=1 Make\ a\ Stand=1 +Make\ a\ Wish=1 Makeshift\ Mannequin=1 Makeshift\ Mauler=1 Makeshift\ Munitions=1 Makindi\ Aeronaut=1 +Makindi\ Griffin=1 Makindi\ Patrol=1 Makindi\ Shieldmate=1 Makindi\ Sliderunner=1 +Malach\ of\ the\ Dawn=1 Malachite\ Golem=1 Malakir\ Bloodwitch=1 Malakir\ Cullblade=1 Malakir\ Familiar=1 Malakir\ Soothsayer=1 +Malevolent\ Awakening=1 Malevolent\ Whispers=1 Malfunction=1 +Malicious\ Advice=1 +Mammoth\ Spider=1 Mammoth\ Umbra=1 Man-o'-War=1 Mana\ Bloom=1 -Mana\ Breach=1 Mana\ Clash=1 Mana\ Cylix=1 -Mana\ Geyser=1 Mana\ Leech=1 -Mana\ Prism=1 Mana\ Seism=1 Mana\ Skimmer=1 Manabarbs=1 Manacles\ of\ Decay=1 Manaforce\ Mace=1 Manaforge\ Cinder=1 +Managorger\ Hydra=1 Manakin=1 Manalith=1 Manaplasm=1 +Mangara's\ Blessing=1 Mangara\ of\ Corondor=1 Manglehorn=1 Maniacal\ Rage=1 @@ -5027,19 +5271,21 @@ Manic\ Vandal=1 Mannichi,\ the\ Fevered\ Dream=1 Manor\ Gargoyle=1 Manor\ Skeleton=1 -Manriki-Gusari=1 Manta\ Ray=1 Manta\ Riders=1 Manticore\ Eternal=1 Manticore\ of\ the\ Gauntlet=1 +Mantis\ Engine=1 Mantle\ of\ Leadership=1 Mantle\ of\ Webs=1 Map\ the\ Wastes=1 Marang\ River\ Skeleton=1 +Marauder's\ Axe=1 Marauding\ Boneslasher=1 Marauding\ Looter=1 +Marauding\ Maulhorn=1 Marble\ Chalice=1 -March\ from\ the\ Tomb=1 +Marble\ Titan=1 March\ of\ the\ Drowned=1 March\ of\ the\ Machines=1 March\ of\ the\ Returned=1 @@ -5054,20 +5300,16 @@ Mardu\ Roughrider=1 Mardu\ Runemark=1 Mardu\ Skullhunter=1 Mardu\ Warshrieker=1 -Marhault\ Elsdragon=1 +Marionette\ Master=1 Marisi's\ Twinclaws=1 Maritime\ Guard=1 -Marjhan=1 Mark\ for\ Death=1 Mark\ of\ Eviction=1 -Mark\ of\ Fury=1 -Mark\ of\ Mutiny=1 Mark\ of\ Sakiko=1 Mark\ of\ the\ Oni=1 Mark\ of\ the\ Vampire=1 Marked\ by\ Honor=1 Marker\ Beetles=1 -Market\ Festival=1 Markov\ Blademaster=1 Markov\ Crusader=1 Markov\ Dreadknight=1 @@ -5075,11 +5317,12 @@ Markov\ Patrician=1 Markov\ Warlord=1 Maro=1 Marrow\ Bats=1 +Marrow\ Chomper=1 +Marrow\ Shards=1 Marsh\ Casualties=1 Marsh\ Flitter=1 Marsh\ Hulk=1 Marsh\ Lurker=1 -Marsh\ Threader=1 Marshal's\ Anthem=1 Marshaling\ Cry=1 Marshdrinker\ Giant=1 @@ -5088,38 +5331,37 @@ Martial\ Glory=1 Martial\ Law=1 Martyr's\ Cause=1 Martyr's\ Cry=1 +Martyr\ of\ Bones=1 Martyr\ of\ Dusk=1 Martyr\ of\ Frost=1 Martyred\ Rusalka=1 +Martyrs'\ Tomb=1 Martyrs\ of\ Korlis=1 +Marwyn,\ the\ Nurturer=1 Masako\ the\ Humorless=1 Mask\ of\ Avacyn=1 -Mask\ of\ Memory=1 +Mask\ of\ Intolerance=1 Mask\ of\ Riddles=1 Mask\ of\ the\ Mimic=1 Masked\ Admirers=1 -Masked\ Gorgon=1 Mass\ Appeal=1 Mass\ Calcify=1 Mass\ Polymorph=1 Mass\ of\ Ghouls=1 -Massive\ Raid=1 Master's\ Call=1 Master\ Decoy=1 -Master\ Healer=1 Master\ Splicer=1 Master\ Thief=1 Master\ Trinketeer=1 Master\ Warcraft=1 +Master\ of\ Arms=1 Master\ of\ Diversion=1 Master\ of\ Pearls=1 Master\ of\ Predicaments=1 Master\ the\ Way=1 -Mastery\ of\ the\ Unseen=1 Masticore=1 Masumaro,\ First\ to\ Live=1 Matca\ Rioters=1 -Matopi\ Golem=1 Matsu-Tribe\ Birdstalker=1 Matsu-Tribe\ Decoy=1 Matsu-Tribe\ Sniper=1 @@ -5131,54 +5373,64 @@ Mausoleum\ Guard=1 Mausoleum\ Harpy=1 Mausoleum\ Turnkey=1 Maverick\ Thopterist=1 +Mavren\ Fein,\ Dusk\ Apostle=1 Maw\ of\ Kozilek=1 Maw\ of\ the\ Mire=1 Maw\ of\ the\ Obzedat=1 Mawcor=1 +Mayor\ of\ Avabruck=1 Maze\ Abomination=1 Maze\ Behemoth=1 Maze\ Glider=1 Maze\ Rusher=1 +Maze\ Sentinel=1 Maze\ of\ Shadows=1 Meadowboon=1 Meandering\ River=1 Meandering\ Towershell=1 Measure\ of\ Wickedness=1 +Meddle=1 Medicine\ Runner=1 Meditation\ Puzzle=1 -Megantic\ Sliver=1 +Megatherium=1 +Megatog=1 Meglonoth=1 Megrim=1 Melancholy=1 +Melek,\ Izzet\ Paragon=1 +Melesse\ Spirit=1 Meletis\ Astronomer=1 Meletis\ Charlatan=1 Melira's\ Keepers=1 Meloku\ the\ Clouded\ Mirror=1 Melt\ Terrain=1 -Meltdown=1 +Memorial\ to\ Folly=1 +Memorial\ to\ Glory=1 +Memorial\ to\ Unity=1 Memory's\ Journey=1 Memory\ Erosion=1 Menacing\ Ogre=1 Mending\ Hands=1 Mending\ Touch=1 Meng\ Huo's\ Horde=1 +Mental\ Discipline=1 Mental\ Vapors=1 +Mephidross\ Vampire=1 Mephitic\ Ooze=1 Mer-Ek\ Nightblade=1 +Mercadian\ Bazaar=1 Merchant's\ Dockhand=1 Merciless\ Eternal=1 Merciless\ Javelineer=1 Merciless\ Resolve=1 Mercurial\ Chemister=1 -Mercurial\ Geists=1 Mercurial\ Kite=1 Mercurial\ Pretender=1 -Mercy\ Killing=1 Merfolk\ Assassin=1 Merfolk\ Looter=1 Merfolk\ Mesmerist=1 +Merfolk\ Mistbinder=1 Merfolk\ Observer=1 -Merfolk\ Raiders=1 Merfolk\ Seastalkers=1 Merfolk\ Seer=1 Merfolk\ Skyscout=1 @@ -5194,10 +5446,10 @@ Merrow\ Bonegnawer=1 Merrow\ Commerce=1 Merrow\ Grimeblotter=1 Merrow\ Harbinger=1 +Merrow\ Levitator=1 Merrow\ Witsniper=1 Mesa\ Enchantress=1 -Mesa\ Pegasus=1 -Mesmeric\ Fiend=1 +Mesa\ Unicorn=1 Mesmeric\ Sliver=1 Mesmeric\ Trance=1 Messenger's\ Speed=1 @@ -5207,23 +5459,25 @@ Metal\ Fatigue=1 Metallic\ Mastery=1 Metallurgeon=1 Metalspinner's\ Puzzleknot=1 -Metamorphose=1 +Metamorphic\ Wurm=1 Metathran\ Aerostat=1 -Metathran\ Elite=1 Metathran\ Soldier=1 +Metathran\ Transport=1 +Metathran\ Zombie=1 +Meteor\ Shower=1 Meteorite=1 +Metrognome=1 Metropolis\ Sprite=1 Miasmic\ Mummy=1 Midnight\ Banshee=1 Midnight\ Charm=1 -Midnight\ Duelist=1 +Midnight\ Covenant=1 Midnight\ Entourage=1 Midnight\ Guard=1 Midnight\ Haunting=1 Midnight\ Oil=1 -Midnight\ Recovery=1 +Midnight\ Ritual=1 Midnight\ Scavengers=1 -Midsummer\ Revel=1 Might\ Beyond\ Reason=1 Might\ Makes\ Right=1 Might\ Sliver=1 @@ -5236,21 +5490,22 @@ Mightstone=1 Mighty\ Emergence=1 Mighty\ Leap=1 Militant\ Inquisitor=1 -Military\ Intelligence=1 +Militant\ Monk=1 Militia's\ Pride=1 Millennial\ Gargoyle=1 Millikin=1 Millstone=1 Mimeofacture=1 +Mimic\ Vat=1 Miming\ Slime=1 Mina\ and\ Denn,\ Wildborn=1 Minamo\ Scrollkeeper=1 Minamo\ Sightbender=1 Mind\ Bend=1 +Mind\ Burst=1 Mind\ Control=1 Mind\ Extraction=1 Mind\ Grind=1 -Mind\ Maggots=1 Mind\ Peel=1 Mind\ Raker=1 Mind\ Rot=1 @@ -5258,79 +5513,79 @@ Mind\ Shatter=1 Mind\ Sludge=1 Mind\ Spring=1 Mindclaw\ Shaman=1 -Mindcrank=1 -Mindculling=1 Mindlash\ Sliver=1 Mindleech\ Mass=1 Mindless\ Automaton=1 Mindless\ Null=1 Mindlock\ Orb=1 Mindmelter=1 -Mindmoil=1 Mindreaver=1 -Mindscour\ Dragon=1 Mindshrieker=1 -Mindsparker=1 Mindstab=1 Mindstab\ Thrull=1 Mindstatic=1 Mindswipe=1 Mindwarper=1 +Mindwrack\ Liege=1 +Mine\ Bearer=1 Mine\ Excavation=1 -Miner's\ Bane=1 Minion\ Reflector=1 -Minion\ of\ Leshrac=1 -Minion\ of\ Tevesh\ Szat=1 Minion\ of\ the\ Wastes=1 Minions'\ Murmurs=1 Minister\ of\ Impediments=1 Minotaur\ Abomination=1 Minotaur\ Aggressor=1 +Minotaur\ Explorer=1 +Minotaur\ Illusionist=1 Minotaur\ Skullcleaver=1 Minotaur\ Sureshot=1 +Minotaur\ Tactician=1 Miraculous\ Recovery=1 +Mirage\ Mirror=1 Mirari=1 Mire's\ Malice=1 Mire's\ Toll=1 Mire\ Boa=1 -Mirko\ Vosk,\ Mind\ Drinker=1 +Mire\ Kavu=1 +Mire\ Shade=1 Mirozel=1 Mirran\ Mettle=1 Mirran\ Spy=1 Mirri,\ Cat\ Warrior=1 Mirri\ the\ Cursed=1 Mirror-Mad\ Phantasm=1 -Mirror\ Golem=1 -Mirror\ Mockery=1 Mirror\ Sheen=1 +Mirror\ Strike=1 +Mirror\ Wall=1 Mirror\ of\ Fate=1 Mirrorweave=1 +Mirrorwood\ Treefolk=1 Mirrorworks=1 Mischievous\ Poltergeist=1 Misery\ Charm=1 Misfortune's\ Gain=1 Misguided\ Rage=1 Mishra's\ Groundbreaker=1 +Mishra's\ Self-Replicator=1 Mishra,\ Artificer\ Prodigy=1 Misinformation=1 +Misstep=1 Mist-Cloaked\ Herald=1 Mist\ Intruder=1 Mist\ Leopard=1 Mist\ Raven=1 -Mistblade\ Shinobi=1 Mistcutter\ Hydra=1 -Mistfire\ Adept=1 Mistfire\ Weaver=1 Mistform\ Dreamer=1 Mistform\ Mask=1 Mistform\ Mutant=1 -Mistform\ Seaswift=1 Mistform\ Shrieker=1 Mistform\ Skyreaver=1 Mistform\ Sliver=1 Mistform\ Stalker=1 Mistform\ Ultimus=1 Mistform\ Wakecaster=1 +Mistform\ Wall=1 Mistform\ Warchief=1 Misthoof\ Kirin=1 Mistmeadow\ Skulk=1 @@ -5344,16 +5599,15 @@ Mizzium\ Mortars=1 Mizzium\ Skin=1 Mizzium\ Transreliquat=1 Mnemonic\ Nexus=1 -Mnemonic\ Wall=1 Moan\ of\ the\ Unhallowed=1 Moaning\ Wall=1 -Mob\ Mentality=1 Mobile\ Fort=1 Mobile\ Garrison=1 -Mobilization=1 +Mockery\ of\ Nature=1 Mogg\ Bombers=1 Mogg\ Flunkies=1 Mogg\ Hollows=1 +Mogg\ Salvage=1 Mogg\ Sentry=1 Mogg\ Squad=1 Mogis's\ Marauder=1 @@ -5366,52 +5620,60 @@ Moldervine\ Cloak=1 Moldgraf\ Monstrosity=1 Moldgraf\ Scavenger=1 Molimo,\ Maro-Sorcerer=1 -Molten\ Birth=1 Molten\ Disaster=1 Molten\ Firebird=1 -Molten\ Frame=1 +Molten\ Hydra=1 +Molten\ Influence=1 Molten\ Nursery=1 Molten\ Primordial=1 Molten\ Psyche=1 Molten\ Ravager=1 Molten\ Sentry=1 Molten\ Slagheap=1 +Molten\ Vortex=1 Moltensteel\ Dragon=1 +Molting\ Harpy=1 Molting\ Skin=1 Molting\ Snakeskin=1 +Moment\ of\ Craving=1 Moment\ of\ Heroism=1 Moment\ of\ Triumph=1 Momentary\ Blink=1 Momentous\ Fall=1 -Momentum=1 +Momir\ Vig,\ Simic\ Visionary=1 Monastery\ Flock=1 Monastery\ Loremaster=1 Mondronen\ Shaman=1 Monk\ Idealist=1 Monk\ Realist=1 Monomania=1 +Monstrify=1 +Monstrous\ Growth=1 +Monstrous\ Hound=1 Monstrous\ Onslaught=1 -Moon\ Heron=1 Moonbow\ Illusionist=1 Moonglove\ Changeling=1 -Moonglove\ Extract=1 Moonglove\ Winnower=1 Moonhold=1 Moonlace=1 -Moonlight\ Geist=1 +Moonlight\ Bargain=1 Moonlight\ Hunt=1 Moonlit\ Strider=1 Moonmist=1 Moonring\ Island=1 Moonring\ Mirror=1 Moonsilver\ Spear=1 +Moonwing\ Moth=1 Moorish\ Cavalry=1 Moorland\ Drifter=1 -Moorland\ Haunt=1 +Morality\ Shift=1 +Moratorium\ Stone=1 Morbid\ Bloom=1 Morbid\ Curiosity=1 Mordant\ Dragon=1 Morgue\ Burst=1 +Morgue\ Thrull=1 +Morgue\ Toad=1 Morinfen=1 Moriok\ Reaver=1 Moriok\ Replica=1 @@ -5419,53 +5681,60 @@ Moriok\ Rigger=1 Moriok\ Scavenger=1 Morkrut\ Banshee=1 Morkrut\ Necropod=1 +Morningtide=1 Moroii=1 +Morphling=1 Morsel\ Theft=1 Morselhoarder=1 Mortal's\ Ardor=1 Mortal's\ Resolve=1 Mortal\ Combat=1 Mortal\ Obstinacy=1 +Mortal\ Wound=1 Mortarpod=1 Mortician\ Beetle=1 Mortipede=1 -Mortis\ Dogs=1 +Mortiphobia=1 +Mortivore=1 Mortuary=1 Mortuary\ Mire=1 Mortus\ Strider=1 Mosquito\ Guard=1 +Moss\ Diamond=1 +Moss\ Kami=1 Moss\ Monster=1 Mossbridge\ Troll=1 -Mossdog=1 Mossfire\ Egg=1 Mothdust\ Changeling=1 +Mothrider\ Samurai=1 Mountain=1 Mountain\ Valley=1 Mountain\ Yeti=1 -Mounted\ Archers=1 -Mourning\ Thrull=1 +Mourner's\ Shield=1 +Mournful\ Zombie=1 +Mourning=1 Mournwhelk=1 Mournwillow=1 Mouth\ //\ Feed=1 -Mtenda\ Herder=1 +Mtenda\ Griffin=1 Muck\ Drubb=1 -Mudbrawler\ Raiders=1 Mudbutton\ Clanger=1 Mudbutton\ Torchrunner=1 -Mudhole=1 Mugging=1 Mul\ Daya\ Channelers=1 Mulch=1 Multani's\ Acolyte=1 +Multani's\ Harmony=1 Multani's\ Presence=1 -Multiform\ Wonder=1 Mummy\ Paramount=1 +Munda's\ Vanguard=1 Munda,\ Ambush\ Leader=1 Mundungu=1 Murasa\ Pyromancer=1 Murasa\ Ranger=1 Murder=1 Murder\ Investigation=1 +Murder\ of\ Crows=1 Murderer's\ Axe=1 Murderous\ Betrayal=1 Murderous\ Compulsion=1 @@ -5475,42 +5744,48 @@ Murderous\ Spoils=1 Murk\ Strider=1 Murmuring\ Phantasm=1 Murmurs\ from\ Beyond=1 +Muscle\ Burst=1 Muse\ Vessel=1 +Musician=1 Mutant's\ Prey=1 Mutiny=1 Muzzle=1 Mwonvuli\ Beast\ Tracker=1 +Mwonvuli\ Ooze=1 Mycoid\ Shepherd=1 Mycologist=1 Mycosynth\ Fiend=1 Mycosynth\ Wellspring=1 -Myojin\ of\ Cleansing\ Fire=1 +Myojin\ of\ Infinite\ Rage=1 Myr\ Adapter=1 Myr\ Galvanizer=1 Myr\ Incubator=1 -Myr\ Landshaper=1 -Myr\ Mindservant=1 Myr\ Moonvessel=1 Myr\ Propagator=1 Myr\ Prototype=1 +Myr\ Reservoir=1 Myr\ Sire=1 Myr\ Turbine=1 +Myr\ Welder=1 Myrsmith=1 -Mystic\ Crusader=1 +Mysteries\ of\ the\ Deep=1 Mystic\ Decree=1 -Mystic\ Enforcer=1 Mystic\ Genesis=1 Mystic\ Meditation=1 Mystic\ Melting=1 Mystic\ Monastery=1 Mystic\ Penitent=1 +Mystic\ Restraints=1 +Mystic\ Snake=1 Mystic\ Speculation=1 +Mystic\ Veil=1 Mystic\ Zealot=1 Mystic\ of\ the\ Hidden\ Way=1 Mystifying\ Maze=1 Mythic\ Proportions=1 Nacatl\ Hunt-Pride=1 Nacatl\ Outlander=1 +Nacatl\ Savage=1 Nacatl\ War-Pride=1 Naga\ Oracle=1 Naga\ Vitalist=1 @@ -5519,66 +5794,68 @@ Nagging\ Thoughts=1 Nahiri's\ Machinations=1 Nakaya\ Shade=1 Naked\ Singularity=1 -Nameless\ Inversion=1 +Nalathni\ Dragon=1 Nameless\ One=1 Nantuko\ Blightcutter=1 -Nantuko\ Cultivator=1 Nantuko\ Disciple=1 +Nantuko\ Elder=1 Nantuko\ Husk=1 +Nantuko\ Mentor=1 Nantuko\ Monastery=1 Nantuko\ Shade=1 Nantuko\ Shaman=1 +Nantuko\ Tracer=1 Nantuko\ Vigilante=1 +Narcissism=1 Narcolepsy=1 Narnam\ Cobra=1 +Narnam\ Renegade=1 +Narrow\ Escape=1 Narwhal=1 -Nath\ of\ the\ Gilt-Leaf=1 +Nath's\ Buffoon=1 +Nath's\ Elite=1 Natural\ Affinity=1 Natural\ Connection=1 -Natural\ End=1 +Natural\ Emergence=1 Natural\ Obsolescence=1 Natural\ Spring=1 Naturalize=1 Nature's\ Blessing=1 Nature's\ Kiss=1 -Nature's\ Lore=1 Nature's\ Panoply=1 -Nature's\ Ruin=1 +Nature's\ Resurgence=1 Nature's\ Spiral=1 Nature's\ Way=1 -Nature's\ Wrath=1 -Nav\ Squad\ Commandos=1 +Nature's\ Will=1 +Navigator's\ Compass=1 Navigator's\ Ruin=1 Naya\ Battlemage=1 -Naya\ Hushblade=1 -Naya\ Sojourners=1 +Naya\ Panorama=1 Near-Death\ Experience=1 Nearheath\ Chaplain=1 -Nearheath\ Pilgrim=1 Nearheath\ Stalker=1 Nebelgast\ Herald=1 Nebuchadnezzar=1 -Necratog=1 +Neck\ Snap=1 +Necra\ Disciple=1 +Necra\ Sanctuary=1 Necravolver=1 -Necrite=1 Necrobite=1 -Necrogen\ Mists=1 Necrogen\ Scudder=1 Necrogen\ Spellbomb=1 Necrogenesis=1 Necrologia=1 Necromancer's\ Assistant=1 Necromancer's\ Covenant=1 -Necromancer's\ Stockpile=1 Necromantic\ Summons=1 Necromantic\ Thirst=1 Necromaster\ Dragon=1 +Necroplasm=1 Necropolis\ Fiend=1 Necropouncer=1 -Necroskitter=1 -Necrotic\ Sliver=1 +Necrosavant=1 +Necrotic\ Plague=1 Nectar\ Faerie=1 -Needle\ Specter=1 Needle\ Storm=1 Needlebite\ Trap=1 Needlebug=1 @@ -5586,8 +5863,7 @@ Needlepeak\ Spider=1 Needleshot\ Gourna=1 Needletooth\ Raptor=1 Nef-Crop\ Entangler=1 -Nefarious\ Lich=1 -Nefashu=1 +Nefarox,\ Overlord\ of\ Grixis=1 Neglected\ Heirloom=1 Neheb,\ the\ Worthy=1 Neko-Te=1 @@ -5597,20 +5873,24 @@ Nemesis\ Mask=1 Nemesis\ Trap=1 Nemesis\ of\ Mortals=1 Nephalia\ Academy=1 -Nephalia\ Drownyard=1 Nephalia\ Moondrakes=1 +Nephalia\ Seakite=1 Nephalia\ Smuggler=1 Nessian\ Asp=1 Nessian\ Courser=1 Nessian\ Demolok=1 Nessian\ Game\ Warden=1 Nessian\ Wilds\ Ravager=1 +Nest\ Invader=1 Nest\ Robber=1 Nest\ of\ Scarabs=1 +Nested\ Ghoul=1 +Nesting\ Wurm=1 Netcaster\ Spider=1 +Nether\ Horror=1 Netherborn\ Phalanx=1 +Netter\ en-Dal=1 Nettle\ Drone=1 -Nettletooth\ Djinn=1 Nettlevine\ Blight=1 Nettling\ Curse=1 Neurok\ Commando=1 @@ -5618,11 +5898,9 @@ Neurok\ Familiar=1 Neurok\ Hoversail=1 Neurok\ Invisimancer=1 Neurok\ Prodigy=1 -Neurok\ Replica=1 Neurok\ Stealthsuit=1 Neurok\ Transmuter=1 Neutralizing\ Blast=1 -Neverending\ Torment=1 Nevermaker=1 New\ Benalia=1 New\ Horizons=1 @@ -5632,14 +5910,16 @@ Nezumi\ Bone-Reader=1 Nezumi\ Cutthroat=1 Nezumi\ Graverobber=1 Nezumi\ Ronin=1 +Nezumi\ Shadow-Watcher=1 Niblis\ of\ Dusk=1 Niblis\ of\ Frost=1 -Niblis\ of\ the\ Breath=1 Niblis\ of\ the\ Urn=1 -Night\ //\ Day=1 +Nicol\ Bolas=1 Night\ Dealings=1 Night\ Market\ Aeronaut=1 Night\ Market\ Guard=1 +Night\ Market\ Lookout=1 +Night\ Terrors=1 Nightbird's\ Clutches=1 Nightcreep=1 Nightfire\ Giant=1 @@ -5648,20 +5928,23 @@ Nighthaze=1 Nighthowler=1 Nightmare=1 Nightmare\ Incursion=1 +Nightmare\ Lash=1 Nightmare\ Void=1 Nightmarish\ End=1 +Nightscape\ Apprentice=1 Nightscape\ Battlemage=1 Nightscape\ Familiar=1 Nightshade\ Assassin=1 Nightshade\ Peddler=1 Nightshade\ Schemers=1 +Nightshade\ Seer=1 Nightshade\ Stinger=1 Nightsnare=1 -Nightsoil\ Kami=1 -Nightveil\ Specter=1 Nightwing\ Shade=1 Nihilistic\ Glee=1 +Nihilith=1 Nikko-Onna=1 +Nim\ Abomination=1 Nim\ Devourer=1 Nim\ Grotesque=1 Nim\ Lasher=1 @@ -5674,7 +5957,6 @@ Nimble\ Innovator=1 Nimbus\ Naiad=1 Nimbus\ Swimmer=1 Nimbus\ Wings=1 -Nimbus\ of\ the\ Isles=1 Ninth\ Bridge\ Patrol=1 Nirkana\ Assassin=1 Nirkana\ Cutthroat=1 @@ -5685,6 +5967,8 @@ Nissa's\ Judgment=1 Nissa's\ Pilgrimage=1 Nissa's\ Renewal=1 Nissa's\ Revelation=1 +Niv-Mizzet,\ Dracogenius=1 +Niv-Mizzet,\ the\ Firemind=1 Niveous\ Wisps=1 Nivix,\ Aerie\ of\ the\ Firemind=1 Nivix\ Barrier=1 @@ -5694,7 +5978,6 @@ No-Dachi=1 No\ Rest\ for\ the\ Wicked=1 Nobilis\ of\ War=1 Noble\ Elephant=1 -Noble\ Purpose=1 Noble\ Quarry=1 Noble\ Stand=1 Noble\ Templar=1 @@ -5703,36 +5986,37 @@ Nocturnal\ Raid=1 Noggin\ Whack=1 Noggle\ Bandit=1 Noggle\ Hedge-Mage=1 -Noggle\ Ransacker=1 +Nomad\ Decoy=1 Nomad\ Mythmaker=1 Nomad\ Outpost=1 +Nomad\ Stadium=1 Nomads'\ Assembly=1 -Nomads\ en-Kor=1 Noose\ Constrictor=1 Noosegraf\ Mob=1 +Norwood\ Priestess=1 Norwood\ Ranger=1 Nostalgic\ Dreams=1 -Nosy\ Goblin=1 Not\ Forgotten=1 -Nova\ Chaser=1 +Not\ of\ This\ World=1 +Nourish=1 Nova\ Pentacle=1 Novijen,\ Heart\ of\ Progress=1 Novijen\ Sages=1 -Noxious\ Dragon=1 +Noxious\ Hatchling=1 Noxious\ Vapors=1 -Noyan\ Dar,\ Roil\ Shaper=1 Nucklavee=1 Nuisance\ Engine=1 Null\ Caller=1 Null\ Champion=1 Null\ Profusion=1 Nullify=1 +Nullmage\ Advocate=1 Nullmage\ Shepherd=1 Nullstone\ Gargoyle=1 Nulltread\ Gargantuan=1 Numbing\ Dose=1 Numot,\ the\ Devastator=1 -Nurturer\ Initiate=1 +Nurturing\ Licid=1 Nylea's\ Disciple=1 Nylea's\ Emissary=1 Nylea's\ Presence=1 @@ -5748,13 +6032,14 @@ Oakenform=1 Oakgnarl\ Warrior=1 Oakheart\ Dryads=1 Oashra\ Cultivator=1 +Oasis=1 Oasis\ Ritualist=1 Oath\ of\ Ajani=1 Oath\ of\ Chandra=1 Oath\ of\ Gideon=1 Oath\ of\ Jace=1 Oath\ of\ Liliana=1 -Oath\ of\ Scholars=1 +Oath\ of\ Teferi=1 Oath\ of\ the\ Ancient\ Wood=1 Oathkeeper,\ Takeno's\ Daisho=1 Oathsworn\ Giant=1 @@ -5768,7 +6053,6 @@ Obelisk\ of\ Jund=1 Obelisk\ of\ Naya=1 Oblivion\ Crown=1 Oblivion\ Strike=1 -Oboro\ Breezecaller=1 Oboro\ Envoy=1 Obscuring\ Aether=1 Observant\ Alseid=1 @@ -5776,12 +6060,17 @@ Obsessive\ Search=1 Obsessive\ Skinner=1 Obsianus\ Golem=1 Obsidian\ Battle-Axe=1 +Obsidian\ Fireheart=1 +Obstinate\ Familiar=1 +Obzedat's\ Aid=1 +Ocular\ Halo=1 +Oculus=1 Odds\ //\ Ends=1 Odious\ Trow=1 Odric,\ Lunarch\ Marshal=1 Odric,\ Master\ Tactician=1 Odunos\ River\ Trawler=1 -Odylic\ Wraith=1 +Off\ Balance=1 Offalsnout=1 Offering\ to\ Asha=1 Ogre's\ Cleaver=1 @@ -5793,26 +6082,34 @@ Ogre\ Leadfoot=1 Ogre\ Marauder=1 Ogre\ Menial=1 Ogre\ Recluse=1 +Ogre\ Resister=1 Ogre\ Savant=1 +Ogre\ Sentry=1 Ogre\ Shaman=1 Ogre\ Slumlord=1 +Ogre\ Taskmaster=1 Ohran\ Yeti=1 Ojutai's\ Breath=1 Ojutai's\ Summons=1 Ojutai\ Interceptor=1 +Ojutai\ Monument=1 Oketra's\ Attendant=1 Oketra's\ Avenger=1 Oketra's\ Last\ Mercy=1 -Okina\ Nightwatch=1 +Okina,\ Temple\ to\ the\ Grandfathers=1 Okk=1 Old-Growth\ Dryads=1 +Old\ Ghastbark=1 Olivia's\ Bloodsworn=1 Olivia's\ Dragoon=1 Omen\ Machine=1 Omenspeaker=1 Ominous\ Sphinx=1 Omnibian=1 +On\ Serra's\ Wings=1 +Onakke\ Ogre=1 Ondu\ Champion=1 +Ondu\ Cleric=1 Ondu\ Giant=1 Ondu\ Greathorn=1 Ondu\ Rising=1 @@ -5821,19 +6118,26 @@ One-Eyed\ Scarecrow=1 One\ Dozen\ Eyes=1 One\ Thousand\ Lashes=1 One\ With\ the\ Wind=1 -One\ with\ Nature=1 One\ with\ Nothing=1 Ongoing\ Investigation=1 +Oni\ Possession=1 Oni\ of\ Wild\ Places=1 Onulet=1 Onward\ //\ Victory=1 +Onyx\ Goblet=1 +Oona's\ Blackguard=1 Oona's\ Gatewarden=1 Oona's\ Grace=1 +Oona's\ Prowler=1 +Oona,\ Queen\ of\ the\ Fae=1 Ooze\ Flux=1 Ooze\ Garden=1 -Opal-Eye,\ Konda's\ Yojimbo=1 +Opal\ Acrolith=1 +Opal\ Archangel=1 Opal\ Avenger=1 +Opal\ Caryatid=1 Opal\ Champion=1 +Opal\ Gargoyle=1 Opal\ Guardian=1 Opal\ Lake\ Gatekeepers=1 Opaline\ Sliver=1 @@ -5842,38 +6146,41 @@ Open\ Fire=1 Open\ into\ Wonder=1 Open\ the\ Armory=1 Ophidian=1 -Ophidian\ Eye=1 Opportunist=1 Opportunity=1 Oppressive\ Rays=1 Oppressive\ Will=1 -Opulent\ Palace=1 +Oracle's\ Attendants=1 Oracle's\ Insight=1 Oracle's\ Vault=1 +Oracle\ en-Vec=1 Oracle\ of\ Bones=1 Oracle\ of\ Dust=1 -Oracle\ of\ Nectars=1 Oran-Rief\ Hydra=1 Oran-Rief\ Invoker=1 +Oran-Rief\ Recluse=1 Orator\ of\ Ojutai=1 Oraxid=1 Orazca\ Frillback=1 Orazca\ Raptor=1 Orazca\ Relic=1 Orb\ of\ Dreams=1 +Orbs\ of\ Warding=1 Orbweaver\ Kumo=1 -Orc\ Sureshot=1 Orchard\ Spirit=1 Orchard\ Warden=1 Orcish\ Artillery=1 Orcish\ Bloodpainter=1 +Orcish\ Cannonade=1 Orcish\ Cannoneers=1 -Orcish\ Farmer=1 +Orcish\ Captain=1 Orcish\ Librarian=1 Orcish\ Lumberjack=1 Orcish\ Mechanics=1 Orcish\ Oriflamme=1 +Orcish\ Spy=1 Orcish\ Squatters=1 +Orcish\ Vandal=1 Orcish\ Veteran=1 Ordeal\ of\ Erebos=1 Ordeal\ of\ Heliod=1 @@ -5881,7 +6188,6 @@ Ordeal\ of\ Nylea=1 Ordeal\ of\ Purphoros=1 Ordeal\ of\ Thassa=1 Order\ //\ Chaos=1 -Order\ of\ Whiteclay=1 Order\ of\ Yawgmoth=1 Order\ of\ the\ Golden\ Cricket=1 Order\ of\ the\ Sacred\ Bell=1 @@ -5890,34 +6196,38 @@ Order\ of\ the\ White\ Shield=1 Ordered\ Migration=1 Ordruun\ Commando=1 Ordruun\ Veteran=1 +Ore\ Gorger=1 Oreskos\ Sun\ Guide=1 Oreskos\ Swiftclaw=1 +Organ\ Grinder=1 Orgg=1 Origin\ Spellbomb=1 -Orim's\ Prayer=1 Orim,\ Samite\ Healer=1 Ornamental\ Courage=1 -Ornate\ Kanzashi=1 Ornery\ Kudu=1 Ornitharch=1 Orochi\ Eggwatcher=1 +Orochi\ Hatchery=1 Orochi\ Leafcaller=1 Orochi\ Ranger=1 Orochi\ Sustainer=1 Oros,\ the\ Avenger=1 +Orzhov\ Charm=1 Orzhov\ Cluestone=1 Orzhov\ Euthanist=1 Orzhov\ Guildgate=1 Orzhov\ Guildmage=1 Orzhov\ Keyrune=1 -Orzhov\ Signet=1 Orzhova,\ the\ Church\ of\ Deals=1 Osai\ Vultures=1 +Ostiary\ Thrull=1 Ostracize=1 Otarian\ Juggernaut=1 +Otepec\ Huntmaster=1 Otherworldly\ Journey=1 Otherworldly\ Outburst=1 Ouphe\ Vandals=1 +Outbreak=1 Outland\ Boar=1 Outland\ Colossus=1 Outmaneuver=1 @@ -5925,43 +6235,43 @@ Outnumber=1 Outrage\ Shaman=1 Outrider\ en-Kor=1 Outrider\ of\ Jhess=1 -Outwit=1 Ovalchase\ Daredevil=1 Ovalchase\ Dragster=1 Overblaze=1 Overcome=1 -Overeager\ Apprentice=1 Overgrown\ Armasaur=1 -Overgrown\ Estate=1 Override=1 Overrule=1 Overrun=1 Overwhelm=1 Overwhelming\ Denial=1 -Overwhelming\ Intellect=1 Overwhelming\ Stampede=1 Ovinize=1 Ovinomancer=1 Oviya\ Pashiri,\ Sage\ Lifecrafter=1 Owl\ Familiar=1 +Oxidda\ Daredevil=1 Oxidda\ Golem=1 -Oxidize=1 +Oxidda\ Scrapmelter=1 +Oyobi,\ Who\ Split\ the\ Heavens=1 Pacification\ Array=1 Pacifism=1 Pack's\ Disdain=1 Pack\ Guardian=1 -Padeem,\ Consul\ of\ Innovation=1 Pain\ //\ Suffering=1 Pain\ Kami=1 Pain\ Magnification=1 Pain\ Seer=1 +Painbringer=1 Painful\ Lesson=1 +Painful\ Memories=1 Painful\ Quandary=1 +Painful\ Truths=1 Painsmith=1 Painted\ Bluffs=1 +Painwracker\ Oni=1 Palace\ Familiar=1 Palace\ Guard=1 -Paladin\ en-Vec=1 Paladin\ of\ Prahv=1 Paladin\ of\ the\ Bloodstained=1 Pale\ Recluse=1 @@ -5971,51 +6281,57 @@ Paleoloth=1 Palinchron=1 Palisade\ Giant=1 Palladia-Mors=1 -Palladium\ Myr=1 -Palliation\ Accord=1 Pallid\ Mycoderm=1 Pallimud=1 -Pandemonium=1 +Panacea=1 Panic=1 Panic\ Attack=1 Panic\ Spellbomb=1 +Panoptic\ Mirror=1 Panther\ Warriors=1 Paperfin\ Rascal=1 -Paradox\ Haze=1 Paragon\ of\ Eternal\ Wilds=1 Paragon\ of\ Fierce\ Defiance=1 Paragon\ of\ Gathering\ Mists=1 Paragon\ of\ New\ Dawns=1 Paragon\ of\ Open\ Graves=1 Paragon\ of\ the\ Amesha=1 +Parallax\ Wave=1 Parallectric\ Feedback=1 Paralyze=1 Paralyzing\ Grasp=1 Paranoid\ Delusions=1 Paranoid\ Parish-Blade=1 -Parapet=1 +Parapet\ Watchers=1 Paraselene=1 +Parasitic\ Bond=1 +Parasitic\ Implant=1 Parasitic\ Strix=1 +Parch=1 +Pardic\ Collaborator=1 Pardic\ Dragon=1 Pardic\ Firecat=1 +Pardic\ Lancer=1 Pardic\ Miner=1 +Pardic\ Wanderer=1 Pariah's\ Shield=1 Part\ the\ Veil=1 +Patagia\ Golem=1 Patagia\ Viper=1 Patchwork\ Gnomes=1 Path\ of\ Anger's\ Flame=1 Path\ of\ Bravery=1 -Path\ of\ Peace=1 Pathmaker\ Initiate=1 +Pathrazer\ of\ Ulamog=1 Pathway\ Arrows=1 -Patrol\ Signaler=1 +Patriarch's\ Desire=1 +Patron\ of\ the\ Akki=1 Patron\ of\ the\ Kitsune=1 Patron\ of\ the\ Moon=1 Patron\ of\ the\ Nezumi=1 -Patron\ of\ the\ Orochi=1 Patron\ of\ the\ Valiant=1 Patron\ of\ the\ Wild=1 -Pavel\ Maliki=1 +Pawn\ of\ Ulamog=1 Pay\ No\ Heed=1 Peace\ Strider=1 Peace\ and\ Quiet=1 @@ -6024,41 +6340,46 @@ Peacewalker\ Colossus=1 Peach\ Garden\ Oath=1 Peak\ Eruption=1 Pearl\ Shard=1 -Pedantic\ Learning=1 +Pearlspear\ Courier=1 Peel\ from\ Reality=1 Peema\ Aether-Seer=1 Peema\ Outrider=1 +Peer\ Pressure=1 Peer\ Through\ Depths=1 +Pegasus\ Charger=1 +Pegasus\ Courser=1 +Pegasus\ Refuge=1 Pegasus\ Stampede=1 Pelakka\ Wurm=1 Penance=1 Pendelhaven\ Elder=1 -Pendrell\ Flux=1 +Pendrell\ Drake=1 Pennon\ Blade=1 Pensive\ Minotaur=1 Pentagram\ of\ the\ Ages=1 Pentarch\ Paladin=1 Pentarch\ Ward=1 Pentavus=1 +Penumbra\ Bobcat=1 Penumbra\ Kavu=1 Penumbra\ Spider=1 Penumbra\ Wurm=1 Peppersmoke=1 Peregrination=1 -Peregrine\ Drake=1 Peregrine\ Griffin=1 Peregrine\ Mask=1 Perilous\ Forays=1 +Perilous\ Myr=1 Perilous\ Predicament=1 -Perilous\ Research=1 Perilous\ Shadow=1 Perilous\ Voyage=1 -Perimeter\ Captain=1 +Perish\ the\ Thought=1 Permafrost\ Trap=1 Permeating\ Mass=1 Perpetual\ Timepiece=1 Perplex=1 Perplexing\ Chimera=1 +Persecute=1 Personal\ Incarnation=1 Personal\ Sanctuary=1 Persuasion=1 @@ -6066,30 +6387,31 @@ Pestilence\ Demon=1 Pestilent\ Souleater=1 Petalmane\ Baku=1 Petals\ of\ Insight=1 -Petra\ Sphinx=1 Petradon=1 Petrahydrox=1 -Petrified\ Plating=1 +Petravark=1 Petrified\ Wood-Kin=1 Pewter\ Golem=1 -Phage\ the\ Untouchable=1 Phalanx\ Formation=1 Phalanx\ Leader=1 Phantasmagorian=1 +Phantasmal\ Abomination=1 Phantasmal\ Bear=1 Phantasmal\ Dragon=1 Phantasmal\ Fiend=1 -Phantasmal\ Forces=1 +Phantasmal\ Mount=1 Phantasmal\ Terrain=1 +Phantatog=1 +Phantom\ Beast=1 +Phantom\ Centaur=1 +Phantom\ Flock=1 Phantom\ General=1 Phantom\ Monster=1 -Phantom\ Nantuko=1 Phantom\ Nomad=1 +Phantom\ Tiger=1 Phantom\ Warrior=1 -Phantom\ Wings=1 Phantom\ Wurm=1 Pharagax\ Giant=1 -Pharika's\ Chosen=1 Pharika's\ Cure=1 Pharika's\ Disciple=1 Pharika's\ Mender=1 @@ -6104,66 +6426,72 @@ Phthisis=1 Phylactery\ Lich=1 Phyresis=1 Phyrexia's\ Core=1 +Phyrexian\ Battleflies=1 +Phyrexian\ Bloodstock=1 Phyrexian\ Colossus=1 Phyrexian\ Defiler=1 Phyrexian\ Denouncer=1 +Phyrexian\ Devourer=1 Phyrexian\ Digester=1 -Phyrexian\ Driver=1 -Phyrexian\ Furnace=1 +Phyrexian\ Etchings=1 Phyrexian\ Gargantua=1 -Phyrexian\ Ghoul=1 Phyrexian\ Grimoire=1 Phyrexian\ Hulk=1 Phyrexian\ Hydra=1 +Phyrexian\ Infiltrator=1 Phyrexian\ Ingester=1 +Phyrexian\ Ironfoot=1 Phyrexian\ Juggernaut=1 Phyrexian\ Monitor=1 -Phyrexian\ Plaguelord=1 -Phyrexian\ Portal=1 Phyrexian\ Prowler=1 +Phyrexian\ Reaper=1 Phyrexian\ Rebirth=1 -Phyrexian\ Snowcrusher=1 +Phyrexian\ Slayer=1 Phyrexian\ Splicer=1 -Phyrexian\ Swarmlord=1 Phyrexian\ Totem=1 Phyrexian\ Vatmother=1 -Phyrexian\ War\ Beast=1 +Phyrexian\ Vault=1 +Phytoburst=1 Phytohydra=1 Phytotitan=1 Pia's\ Revolution=1 Pianna,\ Nomad\ Captain=1 Pick\ the\ Brain=1 Pierce\ Strider=1 +Pierce\ the\ Sky=1 Piety\ Charm=1 Pilfered\ Plans=1 Pilgrim's\ Eye=1 +Pilgrim\ of\ Justice=1 +Pilgrim\ of\ Virtue=1 Pilgrim\ of\ the\ Fires=1 -Pillaging\ Horde=1 -Pillar\ of\ Light=1 +Pillage=1 +Pillar\ Tombs\ of\ Aku=1 Pillar\ of\ Origins=1 Pillar\ of\ War=1 +Pillar\ of\ the\ Paruns=1 +Pillarfield\ Ox=1 Pillory\ of\ the\ Sleepless=1 Pin\ to\ the\ Earth=1 +Pincer\ Spider=1 Pincher\ Beetles=1 +Pine\ Barrens=1 Pine\ Walker=1 Pinecrest\ Ridge=1 Pinion\ Feast=1 -Pinpoint\ Avalanche=1 Pious\ Evangel=1 Pious\ Interdiction=1 Pious\ Kitsune=1 -Pious\ Warrior=1 +Piper's\ Melody=1 Piranha\ Marsh=1 Pirate's\ Cutlass=1 Pirate's\ Pillage=1 Pirate's\ Prize=1 Pirate\ Ship=1 -Piston\ Sledge=1 Pit\ Fight=1 Pit\ Keeper=1 -Pit\ Spawn=1 +Pit\ Raptor=1 Pit\ Trap=1 -Pitchburn\ Devils=1 Pitfall\ Trap=1 Pith\ Driller=1 Pitiless\ Horde=1 @@ -6173,37 +6501,30 @@ Plagiarize=1 Plague\ Beetle=1 Plague\ Belcher=1 Plague\ Boiler=1 -Plague\ Dogs=1 -Plague\ Fiend=1 Plague\ Sliver=1 +Plague\ Spores=1 Plague\ Wind=1 -Plague\ Witch=1 Plague\ of\ Vermin=1 -Plagued\ Rusalka=1 Plaguemaw\ Beast=1 Plains=1 Planar\ Cleansing=1 -Planar\ Despair=1 -Planar\ Gate=1 Planar\ Guide=1 Planar\ Outburst=1 Planar\ Overlay=1 +Planar\ Void=1 Planeswalker's\ Fury=1 Planeswalker's\ Mirth=1 Planeswalker's\ Scorn=1 -Plasm\ Capture=1 +Plasma\ Elemental=1 Plated\ Crusher=1 Plated\ Geopede=1 Plated\ Pegasus=1 Plated\ Seastrider=1 -Plated\ Slagwurm=1 Plated\ Spider=1 Plaxcaster\ Frogling=1 Plaxmanta=1 Plea\ for\ Guidance=1 -Plea\ for\ Power=1 Pledge\ of\ Loyalty=1 -Plover\ Knights=1 Plow\ Through\ Reito=1 Plumes\ of\ Peace=1 Plumeveil=1 @@ -6211,57 +6532,52 @@ Plummet=1 Plunder=1 Poison\ the\ Well=1 Poisonbelly\ Ogre=1 -Polar\ Kraken=1 Polis\ Crusher=1 Pollen\ Lullaby=1 +Pollen\ Remedy=1 Pollenbright\ Wings=1 Polluted\ Bonds=1 Polluted\ Dead=1 +Polymorphist's\ Jest=1 Polymorphous\ Rush=1 Pontiff\ of\ Blight=1 Ponyback\ Brigade=1 Pooling\ Venom=1 -Porcelain\ Legionnaire=1 Pore\ Over\ the\ Pages=1 -Port\ Inspector=1 Portent\ of\ Betrayal=1 Possessed\ Aven=1 Possessed\ Barbarian=1 +Possessed\ Centaur=1 Possessed\ Nomad=1 Possessed\ Skaab=1 -Postmortem\ Lunge=1 Poultice\ Sliver=1 Pounce=1 Pouncing\ Cheetah=1 -Pouncing\ Wurm=1 -Power\ Conduit=1 -Power\ Sink=1 +Pouncing\ Kavu=1 +Power\ Armor=1 +Power\ Taint=1 Power\ of\ Fire=1 Powerstone\ Minefield=1 -Praetor's\ Grasp=1 +Powerstone\ Shard=1 Prahv,\ Spires\ of\ Order=1 Prakhata\ Club\ Security=1 Prakhata\ Pillar-Bug=1 Precinct\ Captain=1 Precise\ Strike=1 Precognition=1 +Precognition\ Field=1 Precursor\ Golem=1 -Predator's\ Gambit=1 Predator's\ Rapport=1 Predator,\ Flagship=1 Predator\ Dragon=1 Predatory\ Advantage=1 -Predatory\ Focus=1 -Predatory\ Hunger=1 Predatory\ Nightstalker=1 -Predatory\ Rampage=1 Predatory\ Urge=1 -Preeminent\ Captain=1 Premature\ Burial=1 Prepare\ //\ Fight=1 Prescient\ Chimera=1 +Presence\ of\ the\ Master=1 Presence\ of\ the\ Wise=1 -Press\ for\ Answers=1 Press\ into\ Service=1 Press\ the\ Advantage=1 Pressure\ Point=1 @@ -6271,15 +6587,14 @@ Prickleboar=1 Prickly\ Boggart=1 Pride\ Guardian=1 Pride\ of\ Conquerors=1 +Priest\ of\ Gix=1 Priest\ of\ Iroas=1 Priest\ of\ Urabrask=1 Priest\ of\ the\ Blood\ Rite=1 -Priest\ of\ the\ Wakening\ Sun=1 Priests\ of\ Norn=1 Primal\ Bellow=1 -Primal\ Boost=1 +Primal\ Beyond=1 Primal\ Clay=1 -Primal\ Cocoon=1 Primal\ Druid=1 Primal\ Forcemage=1 Primal\ Huntbeast=1 @@ -6289,23 +6604,29 @@ Primal\ Visitation=1 Primal\ Whisperer=1 Primeval\ Force=1 Primeval\ Light=1 +Primeval\ Shambler=1 +Primevals'\ Glorious\ Rebirth=1 Primitive\ Etchings=1 Primitive\ Justice=1 -Princess\ Lucrezia=1 +Primordial\ Sage=1 +Primordial\ Wurm=1 Prism\ Array=1 Prism\ Ring=1 +Prismatic\ Boon=1 +Prismatic\ Lens=1 Prismwake\ Merrow=1 Prison\ Barricade=1 Prison\ Term=1 Pristine\ Angel=1 Pristine\ Skywise=1 -Pristine\ Talisman=1 Private\ Research=1 +Prized\ Elephant=1 Prized\ Unicorn=1 Prizefighter\ Construct=1 Processor\ Assault=1 Prodigal\ Pyromancer=1 Prodigal\ Sorcerer=1 +Profane\ Command=1 Profane\ Prayers=1 Profaner\ of\ the\ Dead=1 Profit\ //\ Loss=1 @@ -6314,25 +6635,28 @@ Prognostic\ Sphinx=1 Promise\ of\ Power=1 Promised\ Kannushi=1 Propeller\ Pioneer=1 +Proper\ Burial=1 Prophet\ of\ Distortion=1 Prophet\ of\ Kruphix=1 Prophetic\ Bolt=1 Prophetic\ Ravings=1 Prosperous\ Pirates=1 +Protean\ Hydra=1 Protean\ Raider=1 -Protect\ //\ Serve=1 Protection\ of\ the\ Hekma=1 Protective\ Bubble=1 Proteus\ Machine=1 +Protomatter\ Powder=1 +Prototype\ Portal=1 Proven\ Combatant=1 Providence=1 -Provoke=1 Prowess\ of\ the\ Fair=1 Prowler's\ Helm=1 Prowling\ Nightstalker=1 Prowling\ Pangolin=1 Prying\ Blade=1 Prying\ Questions=1 +Psionic\ Gift=1 Psionic\ Sliver=1 Psychatog=1 Psychic\ Barrier=1 @@ -6340,83 +6664,91 @@ Psychic\ Drain=1 Psychic\ Intrusion=1 Psychic\ Membrane=1 Psychic\ Miasma=1 +Psychic\ Overload=1 Psychic\ Possession=1 Psychic\ Puppetry=1 Psychic\ Purge=1 Psychic\ Rebuttal=1 +Psychic\ Spear=1 Psychic\ Spiral=1 Psychic\ Surgery=1 +Psychic\ Symbiont=1 Psychic\ Trance=1 +Psychic\ Transfer=1 Psychogenic\ Probe=1 Psychotic\ Episode=1 Psychotic\ Fury=1 Psychotrope\ Thallid=1 Pterodon\ Knight=1 Pteron\ Ghost=1 +Public\ Execution=1 Puca's\ Mischief=1 +Puffer\ Extract=1 Pull\ Under=1 Pull\ from\ Eternity=1 Pull\ from\ the\ Deep=1 Pulling\ Teeth=1 -Pulmonic\ Sliver=1 Pulsating\ Illusion=1 Pulse\ of\ Llanowar=1 Pulse\ of\ the\ Dross=1 Pulse\ of\ the\ Fields=1 Pulse\ of\ the\ Forge=1 -Pulsemage\ Advocate=1 +Pulse\ of\ the\ Grid=1 +Pulse\ of\ the\ Tangle=1 Puncture\ Blast=1 +Puncture\ Bolt=1 Puncturing\ Blow=1 Puncturing\ Light=1 Punish\ Ignorance=1 -Punish\ the\ Enemy=1 Puppet\ Conjurer=1 +Puppet\ Strings=1 Puppeteer=1 Puppeteer\ Clique=1 Pure\ //\ Simple=1 +Pure\ Reflection=1 Puresight\ Merrow=1 Purge\ the\ Profane=1 Purging\ Scythe=1 -Purify=1 -Purify\ the\ Grave=1 Purity=1 Purphoros's\ Emissary=1 Pursue\ Glory=1 Pursuit\ of\ Flight=1 +Pus\ Kami=1 Put\ Away=1 +Putrefaction=1 Putrefax=1 Putrefy=1 Putrid\ Cyclops=1 -Putrid\ Imp=1 -Putrid\ Leech=1 Putrid\ Raptor=1 Putrid\ Warrior=1 +Pygmy\ Kavu=1 Pygmy\ Pyrosaur=1 +Pygmy\ Razorback=1 Pygmy\ Troll=1 Pyramid\ of\ the\ Pantheon=1 Pyre\ Charger=1 Pyre\ Hound=1 -Pyreheart\ Wolf=1 Pyrewild\ Shaman=1 Pyric\ Salamander=1 +Pyrite\ Spellbomb=1 +Pyroclasm=1 Pyroclast\ Consul=1 -Pyroconvergence=1 Pyrohemia=1 Pyromancer's\ Assault=1 Pyromancer's\ Gauntlet=1 Pyromancer's\ Swath=1 -Pyromatics=1 +Pyromancy=1 +Pyromania=1 Pyrotechnics=1 Pyrrhic\ Revival=1 Python=1 Pyxis\ of\ Pandemonium=1 Qal\ Sisma\ Behemoth=1 Qarsi\ Deceiver=1 -Qarsi\ High\ Priest=1 -Qarsi\ Sadist=1 Qasali\ Ambusher=1 +Quag\ Sickness=1 Quag\ Vampires=1 -Quagnoth=1 +Quagmire\ Druid=1 Quarry\ Beetle=1 Quarry\ Colossus=1 Quarry\ Hauler=1 @@ -6424,78 +6756,81 @@ Quash=1 Queen's\ Agent=1 Queen's\ Bay\ Soldier=1 Queen's\ Commission=1 +Quenchable\ Fire=1 Quest\ for\ Ancient\ Secrets=1 -Quest\ for\ Pure\ Flame=1 Quest\ for\ Renewal=1 Quest\ for\ Ula's\ Temple=1 Quest\ for\ the\ Gemblades=1 -Quest\ for\ the\ Goblin\ Lord=1 Quest\ for\ the\ Gravelord=1 -Quest\ for\ the\ Nihil\ Stone=1 -Quickchange=1 +Quicken=1 Quicksand=1 Quicksilver\ Behemoth=1 Quicksilver\ Dagger=1 Quicksilver\ Dragon=1 -Quicksilver\ Elemental=1 +Quicksilver\ Fountain=1 Quicksilver\ Geyser=1 +Quicksilver\ Wall=1 Quicksmith\ Genius=1 Quicksmith\ Rebel=1 Quicksmith\ Spy=1 Quiet\ Contemplation=1 Quiet\ Purity=1 Quiet\ Speculation=1 +Quietus\ Spike=1 Quill-Slinger\ Boggart=1 Quilled\ Slagwurm=1 Quilled\ Sliver=1 Quilled\ Wolf=1 Quillmane\ Baku=1 Quirion\ Dryad=1 -Quirion\ Trailblazer=1 +Quirion\ Explorer=1 +Quirion\ Sentinel=1 Qumulox=1 Rabble-Rouser=1 Rabid\ Bite=1 Rabid\ Bloodsucker=1 +Rabid\ Rats=1 Rabid\ Wolverines=1 Rabid\ Wombat=1 Rack\ and\ Ruin=1 -Radha,\ Heir\ to\ Keld=1 Radiant's\ Dragoons=1 Radiant's\ Judgment=1 Radiant,\ Archangel=1 -Radiant\ Essence=1 Radiant\ Flames=1 -Radiant\ Kavu=1 Radiant\ Purge=1 +Radiating\ Lightning=1 Radjan\ Spirit=1 -Rag\ Man=1 +Raff\ Capashen,\ Ship's\ Mage=1 Ragamuffyn=1 -Rage\ Extractor=1 Rage\ Forger=1 -Rage\ Nimbus=1 Rage\ Reflection=1 +Rage\ Thrower=1 Rage\ Weaver=1 Rage\ of\ Purphoros=1 -Rageform=1 +Rageblood\ Shaman=1 Ragemonger=1 Ragged\ Veins=1 Raging\ Goblin=1 +Raging\ Gorilla=1 +Raging\ Kavu=1 Raging\ Minotaur=1 Raging\ Regisaur=1 Raging\ Swordtooth=1 -Ragnar=1 Rags\ //\ Riches=1 Raid\ Bombardment=1 Raiders'\ Spoils=1 Raiders'\ Wake=1 -Rain\ of\ Blades=1 Rain\ of\ Daggers=1 Rain\ of\ Embers=1 Rain\ of\ Rust=1 Rain\ of\ Salt=1 Rain\ of\ Thorns=1 +Rainbow\ Crow=1 +Rainbow\ Efreet=1 Raise\ Dead=1 Raised\ by\ Wolves=1 +Raka\ Disciple=1 +Raka\ Sanctuary=1 Rakalite=1 Rakavolver=1 Rakdos\ Augermage=1 @@ -6511,29 +6846,32 @@ Rakdos\ Ragemutt=1 Rakdos\ Ringleader=1 Rakdos\ Riteknife=1 Rakdos\ Shred-Freak=1 +Rakdos\ Signet=1 +Rakeclaw\ Gargantuan=1 Raking\ Canopy=1 Rakish\ Heir=1 Rakka\ Mar=1 Raksha\ Golden\ Cub=1 -Rakshasa's\ Disdain=1 Rakshasa's\ Secret=1 Rakshasa\ Deathdealer=1 Rakshasa\ Gravecaller=1 Rakshasa\ Vizier=1 Rally\ the\ Forces=1 Rally\ the\ Horde=1 +Rally\ the\ Peasants=1 Rally\ the\ Righteous=1 Rallying\ Roar=1 Ramirez\ DePietro=1 +Ramosian\ Commander=1 Ramosian\ Revivalist=1 +Rampaging\ Cyclops=1 Rampaging\ Hippo=1 Rampant\ Growth=1 Ramroller=1 -Ramses\ Overdark=1 Ramunap\ Hydra=1 +Ramunap\ Ruins=1 Rancid\ Rats=1 Ranger's\ Guile=1 -Ranger's\ Path=1 Ranger\ en-Vec=1 Ranging\ Raptors=1 Rapacious\ One=1 @@ -6541,47 +6879,51 @@ Raptor\ Companion=1 Raptor\ Hatchling=1 Ratcatcher=1 Rathi\ Dragon=1 -Rathi\ Intimidator=1 +Rathi\ Fiend=1 Rathi\ Trapper=1 +Rats'\ Feast=1 Rats\ of\ Rath=1 Rattleblaze\ Scarecrow=1 Rattleclaw\ Mystic=1 +Ravaged\ Highlands=1 Ravaging\ Blaze=1 Ravaging\ Riftwurm=1 -Raven's\ Run\ Dragoon=1 Raven\ Familiar=1 Raven\ Guild\ Initiate=1 Ravenous\ Baloth=1 Ravenous\ Bloodseeker=1 Ravenous\ Daggertooth=1 Ravenous\ Demon=1 +Ravenous\ Harpy=1 Ravenous\ Intruder=1 -Ravenous\ Skirge=1 Raving\ Oni-Slave=1 Ray\ of\ Command=1 +Ray\ of\ Dissolution=1 +Ray\ of\ Distortion=1 Razaketh's\ Rite=1 Razia's\ Purification=1 Razia,\ Boros\ Archangel=1 Razing\ Snidd=1 Razor\ Barrier=1 +Razor\ Boomerang=1 Razor\ Golem=1 Razor\ Hippogriff=1 +Razor\ Pendulum=1 Razor\ Swine=1 -Razorfield\ Rhino=1 -Razorfield\ Thresher=1 Razorfin\ Abolisher=1 Razorfoot\ Griffin=1 -Razorjaw\ Oni=1 +Razorgrass\ Screen=1 Razormane\ Masticore=1 Razortip\ Whip=1 Razortooth\ Rats=1 Reach\ Through\ Mists=1 Reach\ of\ Branches=1 Reach\ of\ Shadows=1 -Read\ the\ Bones=1 -Ready\ //\ Willing=1 +Read\ the\ Runes=1 +Reality\ Acid=1 Reality\ Anchor=1 Reality\ Hemorrhage=1 +Reality\ Ripple=1 Reality\ Spasm=1 Reality\ Strobe=1 Realm\ Razer=1 @@ -6589,6 +6931,7 @@ Realm\ Seekers=1 Realms\ Uncharted=1 Realmwright=1 Reap=1 +Reap\ Intellect=1 Reap\ What\ Is\ Sown=1 Reap\ the\ Seagraf=1 Reaper\ of\ Flight\ Moonsilver=1 @@ -6611,8 +6954,10 @@ Recantation=1 Reciprocate=1 Reckless\ Charge=1 Reckless\ Cohort=1 +Reckless\ Embermage=1 Reckless\ Fireweaver=1 Reckless\ Imp=1 +Reckless\ Ogre=1 Reckless\ One=1 Reckless\ Racer=1 Reckless\ Rage=1 @@ -6620,15 +6965,17 @@ Reckless\ Reveler=1 Reckless\ Scholar=1 Reckless\ Spite=1 Reckless\ Waif=1 +Reckless\ Wurm=1 Reclaim=1 -Reclaiming\ Vines=1 Reclusive\ Artificer=1 Reclusive\ Wight=1 Recollect=1 +Reconstruction=1 +Recoup=1 Recover=1 Recumbent\ Bliss=1 Recuperate=1 -Recurring\ Insight=1 +Recurring\ Nightmare=1 Red\ Cliffs\ Armada=1 Red\ Sun's\ Zenith=1 Redeem=1 @@ -6639,33 +6986,40 @@ Reduce\ in\ Stature=1 Reduce\ to\ Ashes=1 Reduce\ to\ Dreams=1 Redwood\ Treefolk=1 -Reef\ Shaman=1 Reflex\ Sliver=1 Reflexes=1 Refraction\ Trap=1 +Refresh=1 +Refreshing\ Rain=1 Refuse\ //\ Cooperate=1 -Regathan\ Firecat=1 Regenerate=1 Regeneration=1 Regress=1 -Reincarnation=1 +Reign\ of\ the\ Pit=1 Reinforced\ Bulwark=1 Reinforcements=1 Reins\ of\ the\ Vinesteed=1 +Reiterate=1 Reito\ Lantern=1 Reiver\ Demon=1 Rejuvenate=1 +Rejuvenation\ Chamber=1 Rekindled\ Flame=1 Reknit=1 +Relearn=1 Release\ the\ Ants=1 Release\ the\ Gremlins=1 Release\ to\ the\ Wind=1 +Relentless\ Assault=1 Relentless\ Hunter=1 Relentless\ Raptor=1 +Relentless\ Rats=1 Relentless\ Skaabs=1 +Relic\ Bane=1 Relic\ Barrier=1 Relic\ Crush=1 Relic\ Putrescence=1 +Relic\ Runner=1 Relic\ Seeker=1 Relic\ Ward=1 Relief\ Captain=1 @@ -6673,26 +7027,24 @@ Reliquary\ Monk=1 Remember\ the\ Fallen=1 Reminisce=1 Remorseless\ Punishment=1 -Remove\ Soul=1 Rend\ Flesh=1 -Rend\ Spirit=1 +Render\ Silent=1 Rending\ Vines=1 Renegade's\ Getaway=1 -Renegade\ Demon=1 Renegade\ Doppelganger=1 Renegade\ Freighter=1 Renegade\ Krasis=1 -Renegade\ Map=1 +Renegade\ Rallier=1 Renegade\ Tactics=1 Renegade\ Warlord=1 Renegade\ Wheelsmith=1 Renewed\ Faith=1 +Renounce=1 Renounce\ the\ Guilds=1 Renowned\ Weaver=1 Repay\ in\ Kind=1 Repeal=1 Repeating\ Barrage=1 -Repel=1 Repel\ Intruders=1 Repel\ the\ Abominable=1 Repentance=1 @@ -6700,7 +7052,6 @@ Repentant\ Vampire=1 Repopulate=1 Reprisal=1 Reprocess=1 -Repulse=1 Requiem\ Angel=1 Reroute=1 Rescind=1 @@ -6710,29 +7061,35 @@ Research\ //\ Development=1 Research\ Assistant=1 Research\ the\ Deep=1 Reservoir\ Walker=1 +Resilient\ Wanderer=1 Resistance\ Fighter=1 Resize=1 Resolute\ Archangel=1 Resolute\ Blademaster=1 Resolute\ Survivors=1 -Resounding\ Roar=1 Resounding\ Scream=1 Resounding\ Silence=1 +Resounding\ Thunder=1 +Resounding\ Wave=1 Resourceful\ Return=1 Resplendent\ Griffin=1 +Resplendent\ Mentor=1 Rest\ for\ the\ Weary=1 Restless\ Apparition=1 Restless\ Bones=1 -Restless\ Dead=1 +Restless\ Dreams=1 Restock=1 Restoration\ Gearsmith=1 Restoration\ Specialist=1 Restore\ the\ Peace=1 +Restrain=1 Resupply=1 Resurrection=1 -Resuscitate=1 +Retaliate=1 Retaliation=1 Retaliator\ Griffin=1 +Retether=1 +Rethink=1 Retraction\ Helix=1 Retreat\ to\ Coralhelm=1 Retreat\ to\ Emeria=1 @@ -6747,34 +7104,34 @@ Returned\ Centaur=1 Returned\ Phalanx=1 Returned\ Reveler=1 Revealing\ Wind=1 -Reveka,\ Wizard\ Savant=1 +Reveille\ Squad=1 Revel\ in\ Riches=1 Revel\ of\ the\ Fallen\ God=1 Revelsong\ Horn=1 Revenant=1 Revenant\ Patriarch=1 -Revenge\ of\ the\ Hunted=1 Reverberate=1 Revered\ Dead=1 Revered\ Elder=1 +Revered\ Unicorn=1 Reverence=1 Reverent\ Hunter=1 Reversal\ of\ Fortune=1 -Reverse\ Damage=1 Reverse\ Engineer=1 Reverse\ the\ Sands=1 Revive=1 -Revive\ the\ Fallen=1 Reviving\ Dose=1 Reviving\ Melody=1 Reviving\ Vapors=1 Revoke\ Existence=1 Revoke\ Privileges=1 Revolutionary\ Rebuff=1 +Reward\ the\ Faithful=1 Rewards\ of\ Diversity=1 Reweave=1 Rewind=1 Rhet-Crop\ Spearmaster=1 +Rhonas's\ Last\ Stand=1 Rhonas's\ Monument=1 Rhonas's\ Stalwart=1 Rhox=1 @@ -6783,17 +7140,20 @@ Rhox\ Brute=1 Rhox\ Charger=1 Rhox\ Maulers=1 Rhox\ Meditant=1 +Rhox\ Oracle=1 Rhox\ Pikemaster=1 Rhox\ War\ Monk=1 -Rhys\ the\ Exiled=1 -Rhystic\ Deluge=1 -Ribbons\ of\ Night=1 +Rhystic\ Shield=1 +Rib\ Cage\ Spider=1 +Ribbon\ Snake=1 Ribbons\ of\ the\ Reikai=1 Riddle\ of\ Lightning=1 Riddleform=1 Riddlesmith=1 Ride\ Down=1 Ridge\ Rannet=1 +Ridged\ Kusite=1 +Ridgeline\ Rager=1 Ridgescale\ Tusker=1 Ridgetop\ Raptor=1 Riding\ the\ Dilu\ Horse=1 @@ -6801,24 +7161,22 @@ Rift\ Elemental=1 Riftmarked\ Knight=1 Riftsweeper=1 Riftwing\ Cloudskate=1 -Rigging\ Runner=1 -Righteous\ Aura=1 Righteous\ Authority=1 Righteous\ Avengers=1 Righteous\ Blow=1 Righteous\ Charge=1 +Righteous\ Fury=1 Righteousness=1 Rile=1 Rime\ Transfusion=1 Rimebound\ Dead=1 Rimefeather\ Owl=1 -Rimehorn\ Aurochs=1 +Rimescale\ Dragon=1 Rimewind\ Cryomancer=1 +Rimewind\ Taskmage=1 Ring\ of\ Evos\ Isle=1 Ring\ of\ Gix=1 Ring\ of\ Kalonia=1 -Ring\ of\ Ma'ruf=1 -Ring\ of\ Renewal=1 Ring\ of\ Thune=1 Ring\ of\ Valkas=1 Ring\ of\ Xathrid=1 @@ -6827,47 +7185,51 @@ Ringwarden\ Owl=1 Riot\ Control=1 Riot\ Gear=1 Riot\ Piker=1 -Riot\ Ringleader=1 -Rip-Clan\ Crasher=1 +Riot\ Spikes=1 Riparian\ Tiger=1 Ripscale\ Predator=1 Riptide\ Biologist=1 Riptide\ Chimera=1 Riptide\ Chronologist=1 -Riptide\ Crab=1 +Riptide\ Entrancer=1 Riptide\ Mangler=1 Riptide\ Pilferer=1 -Riptide\ Shapeshifter=1 +Riptide\ Replicator=1 Rise\ from\ the\ Grave=1 Rise\ from\ the\ Tides=1 Rise\ of\ Eagles=1 Rise\ to\ the\ Challenge=1 Risen\ Sanctuary=1 +Rishadan\ Airship=1 +Rishkar's\ Expertise=1 Rising\ Miasma=1 +Rite\ of\ Belzenlok=1 Rite\ of\ Ruin=1 Rite\ of\ Undoing=1 -Rite\ of\ the\ Serpent=1 Rites\ of\ Initiation=1 Rites\ of\ Reaping=1 Rites\ of\ Refusal=1 -Rith's\ Grove=1 +Rith's\ Attendant=1 Ritual\ of\ Rejuvenation=1 Ritual\ of\ Restoration=1 -Ritual\ of\ Steel=1 +Ritual\ of\ Subdual=1 Ritual\ of\ the\ Returned=1 Rivalry=1 -Riven\ Turnbull=1 +Rivals'\ Duel=1 River's\ Grasp=1 River\ Bear=1 River\ Darter=1 River\ Heralds'\ Boon=1 River\ Hoopoe=1 +River\ Kaijin=1 River\ Merfolk=1 River\ Serpent=1 +River\ Sneak=1 Riverfall\ Mimic=1 Riverwheel\ Aerialists=1 Riverwise\ Augur=1 Rix\ Maadi,\ Dungeon\ Palace=1 +Rix\ Maadi\ Guildmage=1 Roar\ of\ Challenge=1 Roar\ of\ Jukai=1 Roar\ of\ Reclamation=1 @@ -6875,13 +7237,15 @@ Roar\ of\ the\ Crowd=1 Roar\ of\ the\ Wurm=1 Roaring\ Primadox=1 Roaring\ Slagwurm=1 +Robber\ Fly=1 Robe\ of\ Mirrors=1 Roc\ Egg=1 +Roc\ Hatchling=1 Rock\ Badger=1 +Rock\ Basilisk=1 Rock\ Hydra=1 Rock\ Jockey=1 Rock\ Slide=1 -Rockcaster\ Platoon=1 Rockshard\ Elemental=1 Rockslide\ Ambush=1 Rockslide\ Elemental=1 @@ -6891,9 +7255,9 @@ Rofellos,\ Llanowar\ Emissary=1 Rogue's\ Gloves=1 Rogue's\ Passage=1 Rogue\ Kavu=1 +Rogue\ Refiner=1 Rogue\ Skycaptain=1 Roil's\ Retribution=1 -Roil\ Elemental=1 Roil\ Spout=1 Roiling\ Horror=1 Roiling\ Terrain=1 @@ -6901,9 +7265,9 @@ Roiling\ Waters=1 Roilmage's\ Trick=1 Rollick\ of\ Abandon=1 Rolling\ Spoil=1 -Rolling\ Stones=1 Rolling\ Temblor=1 Rolling\ Thunder=1 +Rona,\ Disciple\ of\ Gix=1 Ronin\ Cavekeeper=1 Ronin\ Cliffrider=1 Ronin\ Houndmaster=1 @@ -6914,17 +7278,16 @@ Ronom\ Unicorn=1 Roofstalker\ Wight=1 Rooftop\ Storm=1 Root-Kin\ Ally=1 -Root\ Elemental=1 -Root\ Greevil=1 Root\ Out=1 +Root\ Snare=1 Rootborn\ Defenses=1 Rootbreaker\ Wurm=1 Rootgrapple=1 +Rooting\ Kavu=1 Rootrunner=1 Roots=1 Rootwalla=1 Rootwater\ Alligator=1 -Rootwater\ Depths=1 Rootwater\ Diver=1 Rootwater\ Hunter=1 Rootwater\ Matriarch=1 @@ -6933,17 +7296,19 @@ Rorix\ Bladewing=1 Rosheen\ Meanderer=1 Rot\ Farm\ Skeleton=1 Rot\ Shambler=1 +Rot\ Wolf=1 Rotcrown\ Ghoul=1 Roterothopter=1 Rotfeaster\ Maggot=1 Rotted\ Hulk=1 -Rotted\ Hystrix=1 Rottenheart\ Ghoul=1 +Rotting\ Giant=1 Rotting\ Legion=1 Rotting\ Mastodon=1 -Rough\ //\ Tumble=1 +Roughshod\ Mentor=1 Rouse\ the\ Mob=1 Royal\ Assassin=1 +Royal\ Decree=1 Royal\ Trooper=1 Rubbleback\ Rhino=1 Rubblebelt\ Maaka=1 @@ -6951,7 +7316,7 @@ Rubblebelt\ Raiders=1 Rubblehulk=1 Rude\ Awakening=1 Rugged\ Highlands=1 -Ruin\ Ghost=1 +Ruham\ Djinn=1 Ruin\ Processor=1 Ruin\ Rat=1 Ruin\ in\ Their\ Wake=1 @@ -6961,17 +7326,18 @@ Ruinous\ Gremlin=1 Ruinous\ Minotaur=1 Ruinous\ Path=1 Ruins\ of\ Oran-Rief=1 +Ruins\ of\ Trokair=1 Rukh\ Egg=1 Rumbling\ Aftershocks=1 Rumbling\ Baloth=1 -Rumbling\ Crescendo=1 +Rumbling\ Slum=1 Rummaging\ Goblin=1 Rummaging\ Wizard=1 Run\ Aground=1 +Run\ Amok=1 Run\ Wild=1 -Runaway\ Carriage=1 -Rune-Cervin\ Rider=1 Rune\ of\ Protection:\ Artifacts=1 +Rune\ of\ Protection:\ Lands=1 Runeboggle=1 Runechanter's\ Pike=1 Runeclaw\ Bear=1 @@ -6979,25 +7345,26 @@ Runed\ Servitor=1 Runed\ Stalactite=1 Runeflare\ Trap=1 Runes\ of\ the\ Deus=1 -Runewing=1 Runic\ Repetition=1 Runner's\ Bane=1 Rush\ of\ Adrenaline=1 Rush\ of\ Battle=1 Rush\ of\ Blood=1 Rush\ of\ Ice=1 -Rush\ of\ Knowledge=1 Rush\ of\ Vitality=1 Rushing-Tide\ Zubera=1 -Rushing\ River=1 +Rushwood\ Dryad=1 Rushwood\ Herbalist=1 Rust\ Scarab=1 -Rust\ Tick=1 Rusted\ Relic=1 Rusted\ Sentinel=1 +Rusted\ Slasher=1 +Rustic\ Clachan=1 +Rusting\ Golem=1 Rustmouth\ Ogre=1 Rustrazor\ Butcher=1 Rustspore\ Ram=1 +Rustwing\ Falcon=1 Ruthless\ Cullblade=1 Ruthless\ Deathfang=1 Ruthless\ Disposal=1 @@ -7005,31 +7372,28 @@ Ruthless\ Instincts=1 Ruthless\ Knave=1 Ruthless\ Ripper=1 Ruthless\ Sniper=1 +Ryusei,\ the\ Falling\ Star=1 Saberclaw\ Golem=1 -Sabertooth\ Alley\ Cat=1 Sabertooth\ Outrider=1 Sabertooth\ Wyvern=1 Sabretooth\ Tiger=1 -Sacellum\ Archers=1 Sacellum\ Godspeaker=1 -Sachi,\ Daughter\ of\ Seshiro=1 Sacred\ Armory=1 -Sacred\ Boon=1 Sacred\ Excavation=1 +Sacred\ Ground=1 Sacred\ Mesa=1 Sacred\ Nectar=1 Sacred\ Prey=1 +Sacred\ Rites=1 Sacred\ Wolf=1 Saddleback\ Lagac=1 Sadistic\ Augermage=1 -Sadistic\ Glee=1 -Sadistic\ Sacrament=1 Sadistic\ Skymarcher=1 Safe\ Passage=1 Safeguard=1 -Safehold\ Duo=1 Safehold\ Sentry=1 Safewright\ Quest=1 +Saffi\ Eriksdotter=1 Sage's\ Dousing=1 Sage's\ Row\ Denizen=1 Sage-Eye\ Avengers=1 @@ -7037,19 +7401,20 @@ Sage-Eye\ Harrier=1 Sage\ Aven=1 Sage\ Owl=1 Sage\ of\ Ancient\ Lore=1 -Sage\ of\ Epityr=1 -Sage\ of\ Fables=1 +Sage\ of\ Lat-Nam=1 Sage\ of\ Shaila's\ Claim=1 Sage\ of\ the\ Inward\ Eye=1 Sages\ of\ the\ Anima=1 Sagu\ Archer=1 Sagu\ Mauler=1 Saheeli's\ Artistry=1 +Sailmonger=1 Sailor\ of\ Means=1 Sakiko,\ Mother\ of\ Summer=1 Sakura-Tribe\ Springcaller=1 Salivating\ Gremlins=1 Salt\ Flats=1 +Salt\ Marsh=1 Salt\ Road\ Ambushers=1 Salt\ Road\ Patrol=1 Salt\ Road\ Quartermasters=1 @@ -7058,25 +7423,29 @@ Saltcrusted\ Steppe=1 Saltfield\ Recluse=1 Saltskitter=1 Salvage\ Drone=1 +Salvage\ Scout=1 Salvage\ Scuttler=1 Salvage\ Slasher=1 Salvage\ Titan=1 +Salvager\ of\ Secrets=1 +Salvaging\ Station=1 Samite\ Archer=1 Samite\ Blessing=1 Samite\ Censer-Bearer=1 Samite\ Healer=1 +Samite\ Ministration=1 Samite\ Pilgrim=1 +Samite\ Sanctuary=1 Samurai\ of\ the\ Pale\ Curtain=1 Sanctified\ Charge=1 Sanctifier\ of\ Souls=1 -Sanctimony=1 Sanctuary\ Cat=1 Sanctum\ Gargoyle=1 Sanctum\ Guardian=1 Sanctum\ Plowbeast=1 +Sanctum\ Spirit=1 Sand\ Golem=1 Sand\ Strangler=1 -Sandbar\ Crocodile=1 Sandbar\ Merfolk=1 Sandbar\ Serpent=1 Sandblast=1 @@ -7085,16 +7454,16 @@ Sands\ of\ Delirium=1 Sandskin=1 Sandsower=1 Sandsteppe\ Citadel=1 -Sandsteppe\ Mastodon=1 +Sandsteppe\ Outcast=1 Sandsteppe\ Scavenger=1 Sandstone\ Bridge=1 +Sandstone\ Deadfall=1 Sandstone\ Warrior=1 +Sandstorm\ Eidolon=1 Sandwurm\ Convergence=1 -Sangrite\ Surge=1 -Sangrophage=1 +Sangromancer=1 Sanguimancy=1 Sanguinary\ Mage=1 -Sanguine\ Bond=1 Sanguine\ Glorifier=1 Sanguine\ Guard=1 Sanguine\ Praetor=1 @@ -7103,37 +7472,44 @@ Sanitarium\ Skeleton=1 Sanity\ Gnawers=1 Sanity\ Grinding=1 Sapphire\ Drake=1 +Sapphire\ Leech=1 +Saprazzan\ Legate=1 +Saprazzan\ Raider=1 Saproling\ Burst=1 +Saproling\ Migration=1 Sapseep\ Forest=1 +Sarcatog=1 Sarcomancy=1 Sarcomite\ Myr=1 Sarkhan's\ Rage=1 Sarpadian\ Empires,\ Vol.\ VII=1 Saruli\ Gatekeepers=1 +Sasaya,\ Orochi\ Ascendant=1 Satyr\ Firedancer=1 Satyr\ Grovedancer=1 Satyr\ Hedonist=1 Satyr\ Nyx-Smith=1 Satyr\ Piper=1 +Satyr\ Rambler=1 Savage\ Alliance=1 +Savage\ Beating=1 Savage\ Conception=1 -Savage\ Firecat=1 Savage\ Gorilla=1 -Savage\ Hunger=1 Savage\ Knuckleblade=1 -Savage\ Lands=1 Savage\ Punch=1 +Savage\ Silhouette=1 Savage\ Stomp=1 -Savage\ Summoning=1 Savage\ Surge=1 Savage\ Thallid=1 Savage\ Twister=1 -Savannah\ Lions=1 Saving\ Grace=1 Saving\ Grasp=1 Savra,\ Queen\ of\ the\ Golgari=1 +Sawback\ Manticore=1 +Sawtooth\ Loon=1 +Sawtooth\ Ogre=1 Sawtooth\ Thresher=1 -Scab-Clan\ Giant=1 +Scab-Clan\ Berserker=1 Scab-Clan\ Mauler=1 Scabland=1 Scald=1 @@ -7143,42 +7519,48 @@ Scale\ Blessing=1 Scale\ of\ Chiss-Goria=1 Scalebane's\ Elite=1 Scaled\ Behemoth=1 +Scaled\ Hulk=1 Scaleguard\ Sentinels=1 Scalpelexis=1 +Scandalmonger=1 Scapegoat=1 +Scar=1 Scarab\ Feast=1 Scarblade\ Elite=1 -Scare\ Tactics=1 Scarecrow=1 Scarred\ Puma=1 +Scarred\ Vinebreeder=1 Scars\ of\ the\ Veteran=1 +Scarscale\ Ritual=1 +Scarwood\ Bandits=1 +Scarwood\ Treefolk=1 Scathe\ Zombies=1 Scatter\ Arc=1 Scatter\ the\ Seeds=1 Scatter\ to\ the\ Winds=1 +Scattering\ Stroke=1 Scattershot=1 +Scavenged\ Weaponry=1 Scavenger\ Drake=1 Scavenger\ Folk=1 -Scavenging\ Ghoul=1 Scavenging\ Scarab=1 Scent\ of\ Brine=1 -Scent\ of\ Ivy=1 Scent\ of\ Jasmine=1 Scent\ of\ Nightshade=1 -Scepter\ of\ Dominance=1 Scepter\ of\ Empires=1 -Scepter\ of\ Fugue=1 Scepter\ of\ Insight=1 Schismotivate=1 Scholar\ of\ Athreos=1 +Scholar\ of\ Stars=1 +School\ of\ Piranha=1 Scion\ Summoner=1 Scion\ of\ Glaciers=1 Scion\ of\ Ugin=1 Scion\ of\ Vitu-Ghazi=1 -Scion\ of\ the\ Ur-Dragon=1 Scion\ of\ the\ Wild=1 Scorch\ the\ Fields=1 Scorched\ Rusalka=1 +Scorching\ Lava=1 Scorchwalker=1 Scoria\ Elemental=1 Scoria\ Wurm=1 @@ -7187,9 +7569,12 @@ Scornful\ Aether-Lich=1 Scornful\ Egotist=1 Scour=1 Scour\ from\ Existence=1 +Scour\ the\ Laboratory=1 +Scoured\ Barrens=1 Scourge\ Devil=1 +Scourge\ Servant=1 Scourge\ Wolf=1 -Scourge\ of\ Fleets=1 +Scourge\ of\ Geier\ Reach=1 Scourge\ of\ Kher\ Ridges=1 Scourge\ of\ Numai=1 Scourge\ of\ Skola\ Vale=1 @@ -7197,11 +7582,12 @@ Scourge\ of\ the\ Nobilis=1 Scourgemark=1 Scourglass=1 Scouring\ Sands=1 +Scout's\ Warning=1 Scout\ the\ Borders=1 Scragnoth=1 Scrambleverse=1 Scrapbasket=1 -Scrapdiver\ Serpent=1 +Scrapheap=1 Scrapper\ Champion=1 Scrapskin\ Drake=1 Scrapyard\ Mongrel=1 @@ -7209,6 +7595,8 @@ Scrapyard\ Salvo=1 Screaming\ Fury=1 Screaming\ Seahawk=1 Screamreach\ Brawler=1 +Screams\ from\ Within=1 +Screams\ of\ the\ Damned=1 Screeching\ Bat=1 Screeching\ Drake=1 Screeching\ Griffin=1 @@ -7219,7 +7607,6 @@ Screeching\ Sliver=1 Scrib\ Nibblers=1 Scribe\ of\ the\ Mindful=1 Scrivener=1 -Scroll\ Thief=1 Scroll\ of\ Avacyn=1 Scroll\ of\ Griselbrand=1 Scroll\ of\ Origins=1 @@ -7239,29 +7626,32 @@ Scythe\ Leopard=1 Scythe\ Tiger=1 Scythe\ of\ the\ Wretched=1 Sea\ Drake=1 -Sea\ Eagle=1 Sea\ Gate\ Loremaster=1 +Sea\ Gate\ Wreckage=1 Sea\ God's\ Revenge=1 Sea\ Legs=1 Sea\ Monster=1 +Sea\ Scryer=1 Sea\ Serpent=1 -Sea\ Spirit=1 +Sea\ Snidd=1 Sea\ Sprite=1 Seacoast\ Drake=1 -Seafloor\ Debris=1 Seagraf\ Skaab=1 Seal\ of\ Cleansing=1 Seal\ of\ Doom=1 -Seal\ of\ Fire=1 Seal\ of\ Primordium=1 +Seal\ of\ Strength=1 +Sealed\ Fate=1 Sealock\ Monster=1 -Seance=1 Search\ Warrant=1 Search\ the\ City=1 Searing\ Flesh=1 Searing\ Light=1 Searing\ Meditation=1 +Searing\ Rays=1 +Searing\ Spear=1 Searing\ Touch=1 +Searing\ Wind=1 Seascape\ Aerialist=1 Seashell\ Cameo=1 Seaside\ Citadel=1 @@ -7270,18 +7660,18 @@ Seasinger=1 Seasoned\ Marshal=1 Second\ Guess=1 Second\ Harvest=1 -Second\ Sight=1 -Second\ Thoughts=1 +Second\ Sunrise=1 +Second\ Wind=1 Secret\ Plans=1 Secret\ Salvage=1 Secretkeeper=1 -Secrets\ of\ the\ Dead=1 Secrets\ of\ the\ Golden\ City=1 -Security\ Blockade=1 +Security\ Detail=1 Sedge\ Scorpion=1 Sedge\ Troll=1 Sedraxis\ Alchemist=1 Sedraxis\ Specter=1 +See\ Beyond=1 See\ Red=1 Seed\ Guardian=1 Seed\ Spark=1 @@ -7292,23 +7682,22 @@ Seeds\ of\ Strength=1 Seek\ the\ Horizon=1 Seek\ the\ Wilds=1 Seeker\ of\ Insight=1 -Seeker\ of\ the\ Way=1 Seekers'\ Squire=1 Seer's\ Lantern=1 Seer's\ Sundial=1 Seer\ of\ the\ Last\ Tomorrow=1 -Seething\ Anger=1 Seething\ Pathblazer=1 Segmented\ Krotiq=1 Seismic\ Elemental=1 Seismic\ Rupture=1 +Seismic\ Shift=1 Seismic\ Spike=1 Seismic\ Stomp=1 Seismic\ Strike=1 Seizan,\ Perverter\ of\ Truth=1 Seize\ the\ Soul=1 Sejiri\ Merfolk=1 -Sekki,\ Seasons'\ Guide=1 +Sek'Kuar,\ Deathkeeper=1 Select\ for\ Inspection=1 Selective\ Memory=1 Selesnya\ Charm=1 @@ -7323,6 +7712,7 @@ Selesnya\ Signet=1 Self-Assembler=1 Self-Inflicted\ Wound=1 Selfless\ Cathar=1 +Selfless\ Exorcist=1 Selhoff\ Occultist=1 Selkie\ Hedge-Mage=1 Sell-Sword\ Brute=1 @@ -7332,32 +7722,30 @@ Send\ to\ Sleep=1 Sengir\ Autocrat=1 Sengir\ Nosferatu=1 Sengir\ Vampire=1 +Sensation\ Gorger=1 +Sensei\ Golden-Tail=1 Senseless\ Rage=1 Sensor\ Splicer=1 Sentinel\ Spider=1 -Sentinel\ Totem=1 Sentinel\ of\ the\ Eternal\ Watch=1 +Sentinel\ of\ the\ Pearl\ Trident=1 Sentinels\ of\ Glen\ Elendra=1 -Sentry\ Oak=1 Sentry\ of\ the\ Underworld=1 Separatist\ Voidmage=1 Septic\ Rats=1 Sepulchral\ Primordial=1 Sequestered\ Stash=1 -Seraph=1 -Seraph\ of\ Dawn=1 Seraph\ of\ the\ Masses=1 Seraph\ of\ the\ Suns=1 -Seraph\ of\ the\ Sword=1 Serendib\ Efreet=1 Serendib\ Sorcerer=1 Serene\ Offering=1 Serene\ Remembrance=1 Serene\ Steward=1 -Serpent\ Generator=1 +Serene\ Sunset=1 +Sergeant-at-Arms=1 Serpent\ Skin=1 Serpent\ Warrior=1 -Serpentine\ Basilisk=1 Serpentine\ Kavu=1 Serpentine\ Spike=1 Serra's\ Blessing=1 @@ -7369,6 +7757,10 @@ Serra\ Angel=1 Serra\ Avenger=1 Serra\ Aviary=1 Serra\ Bestiary=1 +Serra\ Disciple=1 +Serra\ Sphinx=1 +Serra\ Zealot=1 +Serrated\ Biskelion=1 Serum\ Raker=1 Serum\ Tank=1 Servant\ of\ Nefarox=1 @@ -7376,11 +7768,16 @@ Servant\ of\ Tymaret=1 Servant\ of\ Volrath=1 Servo\ Exhibition=1 Servo\ Schematic=1 +Seshiro\ the\ Anointed=1 Set\ Adrift=1 Setessan\ Battle\ Priest=1 +Setessan\ Griffin=1 Setessan\ Oathsworn=1 Setessan\ Starbreaker=1 Setessan\ Tactics=1 +Seton's\ Desire=1 +Seton's\ Scout=1 +Settle\ the\ Score=1 Sever\ Soul=1 Sever\ the\ Bloodline=1 Severed\ Legion=1 @@ -7390,11 +7787,11 @@ Sewerdreg=1 Sewn-Eye\ Drake=1 Shackles=1 Shade's\ Breath=1 +Shade's\ Form=1 Shade\ of\ Trokair=1 Shadow\ Alley\ Denizen=1 Shadow\ Glider=1 Shadow\ Guildmage=1 -Shadow\ Lance=1 Shadow\ Rider=1 Shadow\ Slice=1 Shadow\ Sliver=1 @@ -7403,44 +7800,48 @@ Shadowblood\ Egg=1 Shadowcloak\ Vampire=1 Shadowed\ Caravel=1 Shadowfeed=1 +Shadowmage\ Infiltrator=1 Shadows\ of\ the\ Past=1 +Shadowstorm=1 Shadowstorm\ Vizier=1 -Shah\ of\ Naar\ Isle=1 Shake\ the\ Foundations=1 +Shaleskin\ Bruiser=1 +Shaleskin\ Plower=1 Shaman's\ Trance=1 Shaman\ of\ Spring=1 -Shaman\ of\ the\ Pack=1 Shamble\ Back=1 Shambleshark=1 Shambling\ Attendants=1 Shambling\ Ghoul=1 -Shambling\ Goblin=1 Shambling\ Remains=1 Shambling\ Shell=1 Shambling\ Strider=1 +Shambling\ Swarm=1 +Shanna,\ Sisay's\ Legacy=1 Shanodin\ Dryads=1 Shape\ Anew=1 Shape\ Stealer=1 -Shape\ of\ the\ Wiitigo=1 Shape\ the\ Sands=1 Shaper\ Apprentice=1 Shaper\ Guildmage=1 -Shaper\ Parasite=1 Shapers\ of\ Nature=1 -Shapeshifter=1 +Shapeshifter's\ Marrow=1 Shard\ Convergence=1 Shard\ Phoenix=1 Shard\ of\ Broken\ Glass=1 Sharding\ Sphinx=1 +Shared\ Discovery=1 Shared\ Fate=1 Sharpened\ Pitchfork=1 Shatter=1 Shattered\ Angel=1 +Shattered\ Crypt=1 Shattered\ Dreams=1 Shattered\ Perception=1 Shattering\ Blow=1 Shatterskull\ Giant=1 Shatterskull\ Recruit=1 +Shauku's\ Minion=1 Shed\ Weakness=1 Sheer\ Drop=1 Shefet\ Monitor=1 @@ -7450,10 +7851,12 @@ Shelter=1 Sheltered\ Aerie=1 Sheltering\ Light=1 Shield\ Bearer=1 -Shield\ Mate=1 +Shield\ Dancer=1 Shield\ Wall=1 Shield\ of\ the\ Ages=1 +Shield\ of\ the\ Avatar=1 Shield\ of\ the\ Oversoul=1 +Shield\ of\ the\ Realm=1 Shield\ of\ the\ Righteous=1 Shielded\ Aether\ Thief=1 Shielded\ Passage=1 @@ -7462,26 +7865,26 @@ Shielding\ Plax=1 Shieldmage\ Elder=1 Shields\ of\ Velis\ Vel=1 Shifting\ Borders=1 -Shifting\ Loyalties=1 -Shifty\ Doppelganger=1 +Shifting\ Sky=1 Shimatsu\ the\ Bloodcloaked=1 Shimian\ Specter=1 -Shimmer\ Myr=1 Shimmering\ Barrier=1 +Shimmering\ Efreet=1 +Shimmering\ Glasskite=1 Shimmering\ Grotto=1 +Shimmering\ Mirage=1 Shimmering\ Wings=1 Shimmerscale\ Drake=1 -Shinen\ of\ Fear's\ Chill=1 -Shinen\ of\ Flight's\ Wings=1 -Shinen\ of\ Fury's\ Fire=1 Shinen\ of\ Life's\ Roar=1 Shinewend=1 Shining\ Aerosaur=1 +Shinka\ Gatekeeper=1 Shipbreaker\ Kraken=1 Shipwreck\ Looter=1 Shipwreck\ Moray=1 Shipwreck\ Singer=1 Shirei,\ Shizo's\ Caretaker=1 +Shisato,\ Whispering\ Hunter=1 Shiv's\ Embrace=1 Shivan\ Dragon=1 Shivan\ Emissary=1 @@ -7491,16 +7894,21 @@ Shivan\ Oasis=1 Shivan\ Phoenix=1 Shivan\ Raptor=1 Shivan\ Sand-Mage=1 +Shivan\ Wumpus=1 Shivan\ Wurm=1 Shizuko,\ Caller\ of\ Autumn=1 +Shoal\ Serpent=1 Shock=1 -Shock\ Troops=1 Shockmaw\ Dragon=1 Shore\ Keeper=1 Shore\ Snapper=1 Shorecrasher\ Mimic=1 +Shoreline\ Raider=1 Shoreline\ Ranger=1 +Short\ Sword=1 Shoulder\ to\ Shoulder=1 +Shoving\ Match=1 +Shower\ of\ Coals=1 Shower\ of\ Sparks=1 Showstopper=1 Shrapnel\ Blast=1 @@ -7509,34 +7917,30 @@ Shreds\ of\ Sanity=1 Shrewd\ Hatchling=1 Shrewd\ Negotiation=1 Shriek\ Raptor=1 +Shriek\ of\ Dread=1 Shriekgeist=1 Shriekhorn=1 Shrike\ Harpy=1 Shrill\ Howler=1 Shrine\ of\ Boundless\ Growth=1 +Shrine\ of\ Limitless\ Power=1 Shrine\ of\ Loyal\ Legions=1 Shrine\ of\ Piercing\ Vision=1 Shrine\ of\ the\ Forsaken\ Gods=1 Shrink=1 Shriveling\ Rot=1 Shrouded\ Lore=1 -Shrouded\ Serpent=1 +Shu\ Cavalry=1 Shu\ Elite\ Companions=1 -Shu\ General=1 Shu\ Soldier-Farmers=1 -Shuko=1 -Shunt=1 Shuriken=1 Shyft=1 Sibilant\ Spirit=1 -Sibsig\ Host=1 Sibsig\ Icebreakers=1 -Sibsig\ Muckdraggers=1 Sicken=1 Sickening\ Dreams=1 Sickle\ Ripper=1 Sickleslicer=1 -Sidar\ Jabari=1 Sideswipe=1 Sidewinder\ Naga=1 Sidisi's\ Pet=1 @@ -7545,31 +7949,32 @@ Siege\ Mastodon=1 Siege\ Modification=1 Siege\ Wurm=1 Siege\ of\ Towers=1 -Siegecraft=1 +Siegebreaker\ Giant=1 Sift=1 Sift\ Through\ Sands=1 -Sifter\ Wurm=1 Sifter\ of\ Skulls=1 +Sigarda's\ Aid=1 Sigardian\ Priest=1 Sight\ Beyond\ Sight=1 Sight\ of\ the\ Scalelords=1 Sighted-Caste\ Sorcerer=1 Sightless\ Brawler=1 +Sightless\ Ghoul=1 Sigil\ Blessing=1 Sigil\ Captain=1 +Sigil\ Tracer=1 Sigil\ of\ Distinction=1 Sigil\ of\ Valor=1 +Sigil\ of\ the\ Empty\ Throne=1 Sigil\ of\ the\ Nayan\ Gods=1 -Sigil\ of\ the\ New\ Dawn=1 Sigiled\ Behemoth=1 -Sigiled\ Paladin=1 Sigiled\ Skink=1 Sigiled\ Starfish=1 Signal\ the\ Clans=1 Silburlind\ Snapper=1 Silence\ the\ Believers=1 +Silent-Chant\ Zubera=1 Silent\ Artisan=1 -Silent\ Attendant=1 Silent\ Departure=1 Silent\ Observer=1 Silent\ Sentinel=1 @@ -7578,27 +7983,26 @@ Silhana\ Starfletcher=1 Silk\ Net=1 Silkbind\ Faerie=1 Silkenfist\ Fighter=1 +Silkenfist\ Order=1 Silklash\ Spider=1 Silkweaver\ Elite=1 -Silkwing\ Scout=1 +Silt\ Crawler=1 Silumgar\ Assassin=1 Silumgar\ Butcher=1 Silumgar\ Monument=1 Silumgar\ Sorcerer=1 Silumgar\ Spell-Eater=1 Silver-Inlaid\ Dagger=1 -Silver\ Drake=1 -Silver\ Knight=1 Silver\ Myr=1 Silver\ Seraph=1 Silver\ Wyvern=1 Silverback\ Ape=1 -Silverblade\ Paladin=1 Silverchase\ Fox=1 Silverclad\ Ferocidons=1 Silvercoat\ Lion=1 Silverfur\ Partisan=1 Silvergill\ Douser=1 +Silverskin\ Armor=1 Silverstorm\ Samurai=1 Silverstrike=1 Silvos,\ Rogue\ Elemental=1 @@ -7615,30 +8019,32 @@ Simic\ Manipulator=1 Simic\ Ragworm=1 Simic\ Sky\ Swallower=1 Simoon=1 -Sin\ Collector=1 +Sin\ Prodder=1 Sindbad=1 +Singe-Mind\ Ogre=1 +Singe=1 Singing\ Bell\ Strike=1 Singing\ Tree=1 Sinister\ Concoction=1 Sinister\ Possession=1 Sinister\ Strength=1 Sink\ into\ Takenuma=1 +Sinking\ Feeling=1 Sins\ of\ the\ Past=1 Sinuous\ Striker=1 Sir\ Shandlar\ of\ Eberyn=1 -Sire\ of\ the\ Storm=1 +Sire\ of\ Insanity=1 Siren's\ Ruse=1 Siren\ Lookout=1 Siren\ Reaver=1 Siren\ Song\ Lyre=1 Siren\ of\ the\ Fanged\ Coast=1 Siren\ of\ the\ Silent\ Song=1 -Sirocco=1 +Sisay's\ Ingenuity=1 Sisay's\ Ring=1 Sisters\ of\ Stone\ Death=1 Sivitri\ Scarzam=1 Sixth\ Sense=1 -Sizzle=1 Skaab\ Goliath=1 Skarrg,\ the\ Rage\ Pits=1 Skarrg\ Goliath=1 @@ -7650,6 +8056,7 @@ Skeletal\ Grimace=1 Skeletal\ Kathari=1 Skeletal\ Vampire=1 Skeletal\ Wurm=1 +Skeleton\ Archer=1 Skeleton\ Key=1 Skeleton\ Scavengers=1 Skeleton\ Shard=1 @@ -7661,34 +8068,36 @@ Skinbrand\ Goblin=1 Skinrender=1 Skinshifter=1 Skinthinner=1 +Skinwing=1 Skirge\ Familiar=1 Skirk\ Alarmist=1 Skirk\ Drill\ Sergeant=1 -Skirk\ Marauder=1 Skirk\ Outrider=1 Skirk\ Prospector=1 Skirk\ Ridge\ Exhumer=1 Skirk\ Shaman=1 Skirk\ Volcanist=1 -Skirsdag\ Cultist=1 Skirsdag\ Flayer=1 Skirsdag\ High\ Priest=1 Skirsdag\ Supplicant=1 Skitter\ of\ Lizards=1 Skittering\ Heartstopper=1 +Skittering\ Horror=1 Skittering\ Invasion=1 +Skittering\ Monstrosity=1 Skittering\ Skirge=1 +Skittering\ Surveyor=1 Skitterskin=1 +Skittish\ Kavu=1 Skittish\ Valesk=1 +Skizzik=1 Skulduggery=1 -Skulking\ Fugitive=1 Skulking\ Ghost=1 Skulking\ Knight=1 -Skull\ Catapult=1 -Skull\ Fracture=1 +Skull\ Collector=1 Skull\ Rend=1 +Skull\ of\ Orm=1 Skullcage=1 -Skullmane\ Baku=1 Skullmead\ Cauldron=1 Skullmulcher=1 Skullsnatcher=1 @@ -7696,12 +8105,13 @@ Skulltap=1 Sky\ Ruin\ Drake=1 Sky\ Scourer=1 Sky\ Skiff=1 +Sky\ Spirit=1 +Sky\ Swallower=1 Sky\ Terror=1 Skybind=1 Skyblade\ of\ the\ Legion=1 Skyblinder\ Staff=1 -Skyclaw\ Thrash=1 -Skyfire\ Kirin=1 +Skycloud\ Egg=1 Skygames=1 Skyhunter\ Cub=1 Skyhunter\ Prowler=1 @@ -7711,6 +8121,7 @@ Skylasher=1 Skyline\ Cascade=1 Skyline\ Predator=1 Skymarch\ Bloodletter=1 +Skymarcher\ Aspirant=1 Skymark\ Roc=1 Skyraker\ Giant=1 Skyreach\ Manta=1 @@ -7730,12 +8141,12 @@ Skyshroud\ Elite=1 Skyshroud\ Forest=1 Skyshroud\ Ranger=1 Skyshroud\ Sentinel=1 -Skyshroud\ Troll=1 -Skyshroud\ Troopers=1 +Skyshroud\ Vampire=1 Skyshroud\ War\ Beast=1 Skysnare\ Spider=1 Skyspear\ Cavalry=1 Skyswirl\ Harrier=1 +Skyward\ Eye\ Prophets=1 Skywatcher\ Adept=1 Skywhaler's\ Shot=1 Skywinder\ Drake=1 @@ -7748,8 +8159,8 @@ Slash\ Panther=1 Slash\ of\ Talons=1 Slashing\ Tiger=1 Slate\ Street\ Ruffian=1 -Slate\ of\ Ancestry=1 Slaughter=1 +Slaughter\ Cry=1 Slaughter\ Drone=1 Slaughterhorn=1 Slaughterhouse\ Bouncer=1 @@ -7764,41 +8175,55 @@ Sleep=1 Sleep\ Paralysis=1 Sleeper's\ Robe=1 Sleeper\ Agent=1 +Sleeping\ Potion=1 +Slice\ and\ Dice=1 Slice\ in\ Twain=1 Slime\ Molding=1 +Slimefoot,\ the\ Stowaway=1 +Slimy\ Kavu=1 Slingbow\ Trap=1 -Slinking\ Giant=1 +Slingshot\ Goblin=1 +Slinking\ Serpent=1 +Slinking\ Skirge=1 +Slinn\ Voda,\ the\ Rising\ Deep=1 Slip\ Through\ Space=1 Slippery\ Scoundrel=1 Slipstream\ Eel=1 Slipstream\ Serpent=1 +Sliptide\ Serpent=1 Slith\ Ascendant=1 +Slith\ Bloodletter=1 Slith\ Firewalker=1 Slith\ Predator=1 Slith\ Strider=1 Slither\ Blade=1 Slitherhead=1 +Slithering\ Shade=1 +Slithermuse=1 +Slithery\ Stalker=1 Sliver\ Construct=1 Sliversmith=1 Slobad,\ Goblin\ Tinkerer=1 +Slow\ Motion=1 Sludge\ Crawler=1 Sludge\ Strider=1 Sluggishness=1 Sluiceway\ Scorpion=1 Slum\ Reaper=1 +Slumbering\ Dragon=1 Slumbering\ Tora=1 Sly\ Requisitioner=1 Smash=1 +Smash\ to\ Smithereens=1 Smelt-Ward\ Gatekeepers=1 Smelt=1 Smite=1 Smite\ the\ Monstrous=1 +Smogsteed\ Rider=1 Smoke\ Teller=1 Smokebraider=1 Smokespew\ Invoker=1 -Smokestack=1 Smolder\ Initiate=1 -Smoldering\ Butcher=1 Smoldering\ Efreet=1 Smoldering\ Spires=1 Smoldering\ Tar=1 @@ -7806,35 +8231,31 @@ Smoldering\ Werewolf=1 Smother=1 Smothering\ Abomination=1 Snake\ Cult\ Initiation=1 +Snake\ Umbra=1 Snake\ of\ the\ Golden\ Grove=1 -Snakeform=1 Snapback=1 -Snapping\ Creeper=1 Snapping\ Drake=1 Snapping\ Gnarlid=1 Snapping\ Sailback=1 Snapping\ Thragg=1 -Snapsail\ Glider=1 Snare\ Thopter=1 -Snarling\ Undorak=1 Sneaky\ Homunculus=1 -Snow\ Fortress=1 +Snorting\ Gahr=1 Snowhorn\ Rider=1 Snubhorn\ Sentry=1 Soar=1 +Soaring\ Hope=1 Soaring\ Seacliff=1 +Soilshaper=1 Sokenzan\ Renegade=1 Sokenzan\ Spellblade=1 Sol'kanar\ the\ Swamp\ King=1 -Sol\ Grail=1 -Solar\ Blast=1 Solar\ Tide=1 Solarion=1 Soldevi\ Digger=1 Soldevi\ Golem=1 Soldevi\ Machinist=1 Soldevi\ Simulacrum=1 -Soldier\ Replica=1 Soldier\ of\ the\ Pantheon=1 Solemn\ Offering=1 Solemn\ Recruit=1 @@ -7845,7 +8266,6 @@ Solitary\ Hunter=1 Soliton=1 Soltari\ Champion=1 Soltari\ Crusader=1 -Soltari\ Emissary=1 Soltari\ Lancer=1 Soltari\ Monk=1 Soltari\ Priest=1 @@ -7854,97 +8274,106 @@ Somber\ Hoverguard=1 Somberwald\ Alpha=1 Somberwald\ Spider=1 Somberwald\ Stag=1 -Song\ of\ Blood=1 +Somnomancer=1 +Somnophore=1 +Song\ of\ Serenity=1 Songstitcher=1 +Sonic\ Seizure=1 Soot\ Imp=1 Sootfeather\ Flock=1 -Soothing\ Balm=1 Sootstoke\ Kindler=1 -Sootwalkers=1 Sophic\ Centaur=1 +Soramaro,\ First\ to\ Dream=1 +Soratami\ Cloud\ Chariot=1 Soratami\ Cloudskater=1 +Soratami\ Mindsweeper=1 Soratami\ Mirror-Guard=1 Soratami\ Mirror-Mage=1 +Soratami\ Rainshaper=1 Soratami\ Savant=1 Soratami\ Seer=1 Sorcerer's\ Strongbox=1 +Sorcerer's\ Wand=1 Sorin's\ Thirst=1 Sorin's\ Vengeance=1 Sorrow's\ Path=1 Sosuke's\ Summons=1 Sosuke,\ Son\ of\ Seshiro=1 -Soul's\ Majesty=1 +Soul's\ Fire=1 +Soul's\ Grace=1 +Soul's\ Might=1 +Soul\ Channeling=1 Soul\ Collector=1 Soul\ Conduit=1 Soul\ Exchange=1 Soul\ Feast=1 Soul\ Foundry=1 +Soul\ Kiss=1 Soul\ Link=1 Soul\ Manipulation=1 Soul\ Net=1 Soul\ Nova=1 Soul\ Ransom=1 -Soul\ Reap=1 +Soul\ Rend=1 +Soul\ Salvage=1 Soul\ Seizer=1 +Soul\ Separator=1 Soul\ Shepherd=1 Soul\ Shred=1 -Soul\ Snuffers=1 Soul\ Stair\ Expedition=1 -Soul\ Strings=1 -Soul\ Summons=1 Soul\ Swallower=1 Soul\ Tithe=1 Soul\ of\ Magma=1 Soul\ of\ the\ Rapids=1 Soulblade\ Djinn=1 Soulblast=1 -Soulbound\ Guardians=1 Soulbright\ Flamekin=1 Soulcage\ Fiend=1 Soulcatcher=1 Soulcatchers'\ Aerie=1 Souldrinker=1 +Soulgorger\ Orgg=1 Soulless\ Revival=1 Soulmender=1 Soulquake=1 Souls\ of\ the\ Faultless=1 -Soulscour=1 Soulstinger=1 Soulsworn\ Jury=1 Soulsworn\ Spirit=1 Soultether\ Golem=1 -Southern\ Elephant=1 Southern\ Paladin=1 Sowing\ Salt=1 Spare\ from\ Evil=1 Spark\ Jolt=1 +Spark\ Mage=1 Spark\ Spray=1 Spark\ Trooper=1 Spark\ of\ Creativity=1 Sparkmage's\ Gambit=1 -Sparkmage\ Apprentice=1 Sparkspitter=1 +Sparktongue\ Dragon=1 +Sparring\ Construct=1 +Sparring\ Golem=1 Sparring\ Mummy=1 -Spatial\ Contortion=1 +Spatial\ Binding=1 +Spawn\ of\ Thraxes=1 Spawnbinder\ Mage=1 Spawnbroker=1 Spawning\ Bed=1 Spawning\ Breath=1 Spawnsire\ of\ Ulamog=1 -Spawnwrithe=1 Spear\ of\ Heliod=1 Spearbreaker\ Behemoth=1 Spearpoint\ Oread=1 Species\ Gorger=1 Specter's\ Shroud=1 -Specter's\ Wail=1 Spectra\ Ward=1 Spectral\ Bears=1 Spectral\ Flight=1 -Spectral\ Gateguards=1 -Spectral\ Lynx=1 +Spectral\ Force=1 +Spectral\ Guardian=1 +Spectral\ Prison=1 Spectral\ Reserves=1 -Spectral\ Rider=1 Spectral\ Searchlight=1 Spectral\ Shepherd=1 Spectral\ Shield=1 @@ -7956,24 +8385,26 @@ Spell\ Burst=1 Spell\ Contortion=1 Spell\ Rupture=1 Spell\ Shrivel=1 -Spell\ Snip=1 +Spell\ Swindle=1 Spell\ Syphon=1 +Spellbane\ Centaur=1 +Spellbinder=1 Spellbook=1 Spellbound\ Dragon=1 Spellheart\ Chimera=1 Spellshift=1 -Spellshock=1 +Spelltithe\ Enforcer=1 Spelltwine=1 Spellweaver\ Eternal=1 -Spellwild\ Ouphe=1 -Sphere\ of\ Law=1 +Spellweaver\ Helix=1 +Sphere\ of\ Duty=1 +Sphere\ of\ Grace=1 Sphere\ of\ Purity=1 +Sphere\ of\ Reason=1 Sphere\ of\ Truth=1 Sphere\ of\ the\ Suns=1 -Sphinx's\ Decree=1 Sphinx's\ Disciple=1 Sphinx's\ Herald=1 -Sphinx's\ Tutelage=1 Sphinx-Bone\ Wand=1 Sphinx\ Summoner=1 Sphinx\ of\ Jwar\ Isle=1 @@ -7981,31 +8412,31 @@ Sphinx\ of\ Lost\ Truths=1 Sphinx\ of\ Magosi=1 Sphinx\ of\ Uthuun=1 Sphinx\ of\ the\ Chimes=1 +Spider\ Climb=1 Spider\ Spawning=1 -Spidersilk\ Net=1 -Spiderwig\ Boggart=1 Spidery\ Grasp=1 Spike-Tailed\ Ceratops=1 Spike\ Breeder=1 Spike\ Cannibal=1 Spike\ Colony=1 -Spike\ Feeder=1 +Spike\ Drone=1 Spike\ Hatcher=1 Spike\ Jester=1 Spike\ Rogue=1 Spike\ Soldier=1 Spike\ Tiller=1 +Spike\ Worker=1 Spikeshot\ Elder=1 Spikeshot\ Goblin=1 Spiketail\ Drakeling=1 Spiketail\ Hatchling=1 +Spin\ Engine=1 Spin\ into\ Myth=1 Spinal\ Graft=1 -Spinal\ Parasite=1 -Spinal\ Villain=1 Spincrusher=1 Spinebiter=1 Spined\ Basher=1 +Spined\ Fluke=1 Spined\ Sliver=1 Spined\ Thopter=1 Spined\ Wurm=1 @@ -8013,27 +8444,28 @@ Spineless\ Thug=1 Spiny\ Starfish=1 Spiraling\ Duelist=1 Spiraling\ Embers=1 -Spire\ Barrage=1 Spire\ Monitor=1 Spire\ Owl=1 Spire\ Patrol=1 -Spire\ Serpent=1 Spire\ Tracer=1 Spire\ Winder=1 Spireside\ Infiltrator=1 Spirespine=1 Spirit\ Away=1 +Spirit\ Bonds=1 Spirit\ Cairn=1 +Spirit\ Flare=1 Spirit\ Loop=1 Spirit\ Mirror=1 Spirit\ Shackle=1 Spirit\ Weaver=1 Spirit\ en-Dal=1 Spirit\ en-Kor=1 +Spirit\ of\ the\ Hearth=1 Spirit\ of\ the\ Hunt=1 Spiritmonger=1 Spiritual\ Visit=1 -Spite\ //\ Malice=1 +Spiritualize=1 Spite\ of\ Mogis=1 Spitebellows=1 Spiteflame\ Witch=1 @@ -8042,15 +8474,16 @@ Spiteful\ Bully=1 Spiteful\ Motives=1 Spiteful\ Returned=1 Spiteful\ Shadows=1 -Spitfire\ Handler=1 Spitting\ Drake=1 Spitting\ Earth=1 Spitting\ Gourna=1 Spitting\ Hydra=1 Spitting\ Sliver=1 +Spitting\ Slug=1 +Spitting\ Spider=1 Splatter\ Thug=1 Splendid\ Agony=1 -Splinter=1 +Splendid\ Reclamation=1 Splinterfright=1 Split-Tail\ Miko=1 Splitting\ Headache=1 @@ -8061,9 +8494,10 @@ Spontaneous\ Combustion=1 Spontaneous\ Mutation=1 Spore\ Burst=1 Spore\ Cloud=1 -Spore\ Flower=1 +Spore\ Swarm=1 Sporeback\ Troll=1 -Sporemound=1 +Sporecap\ Spider=1 +Sporecrown\ Thallid=1 Sporesower\ Thallid=1 Sporoloth\ Ancient=1 Spotted\ Griffin=1 @@ -8071,7 +8505,6 @@ Spread\ the\ Sickness=1 Spreading\ Algae=1 Spreading\ Flames=1 Spreading\ Rot=1 -Spring\ //\ Mind=1 Spring\ Cleaning=1 Springing\ Tiger=1 Springsage\ Ritual=1 @@ -8079,33 +8512,31 @@ Sprinting\ Warbrute=1 Sprite\ Noble=1 Sprout=1 Sprouting\ Thrinax=1 -Spur\ Grappler=1 Spurnmage\ Advocate=1 Spurred\ Wolverine=1 +Spy\ Network=1 +Squadron\ Hawk=1 Squall=1 Squall\ Drifter=1 Squall\ Line=1 -Squallmonger=1 Squeaking\ Pie\ Grubfellows=1 Squeaking\ Pie\ Sneak=1 Squealing\ Devil=1 -Squee's\ Embrace=1 +Squee's\ Toy=1 +Squee,\ the\ Immortal=1 Squelch=1 Squelching\ Leeches=1 Squire's\ Devotion=1 Squire=1 Squirming\ Mass=1 Stab\ Wound=1 -Stabbing\ Pain=1 Stabilizer=1 -Staff\ of\ Zegon=1 Staff\ of\ the\ Death\ Magus=1 Staff\ of\ the\ Flame\ Magus=1 Staff\ of\ the\ Mind\ Magus=1 Staff\ of\ the\ Sun\ Magus=1 Staff\ of\ the\ Wild\ Magus=1 Stag\ Beetle=1 -Staggershock=1 Stalker\ Hag=1 Stalking\ Assassin=1 Stalking\ Bloodsucker=1 @@ -8113,22 +8544,25 @@ Stalking\ Drone=1 Stalking\ Stones=1 Stalking\ Tiger=1 Stalking\ Yeti=1 -Stallion\ of\ Ashmouth=1 Stalwart\ Aven=1 Stalwart\ Shield-Bearers=1 +Stamina=1 +Stampede=1 Stampeding\ Elk\ Herd=1 Stampeding\ Horncrest=1 Stampeding\ Rhino=1 -Stampeding\ Serow=1 Stampeding\ Wildebeests=1 Stand\ //\ Deliver=1 +Stand\ Firm=1 Stand\ Together=1 +Standardize=1 Standing\ Troops=1 Stangg=1 +Star-Crowned\ Stag=1 +Star\ Compass=1 Starlight=1 Starlight\ Invoker=1 Starlit\ Sanctum=1 -Starstorm=1 Start\ //\ Finish=1 Start\ Your\ Engines=1 Starved\ Rusalka=1 @@ -8145,16 +8579,21 @@ Steadfast\ Guard=1 Steadfast\ Sentinel=1 Steady\ Progress=1 Steal\ Artifact=1 -Steal\ Enchantment=1 +Steal\ Strength=1 Stealer\ of\ Secrets=1 Steam\ Augury=1 Steam\ Blast=1 Steam\ Catapult=1 Steam\ Spitter=1 +Steam\ Vines=1 +Steamclaw=1 +Steamcore\ Weird=1 +Steamflogger\ Boss=1 Steel\ Golem=1 -Steel\ Wall=1 +Steel\ Leaf\ Paladin=1 +Steel\ Sabotage=1 Steelclad\ Serpent=1 -Steelform\ Sliver=1 +Steeling\ Stance=1 Steelshaper\ Apprentice=1 Steeple\ Roc=1 Stenchskipper=1 @@ -8163,12 +8602,13 @@ Stensia\ Bloodhall=1 Stensia\ Innkeeper=1 Stensia\ Masquerade=1 Steppe\ Glider=1 -Steppe\ Lynx=1 Stern\ Constable=1 +Stern\ Judge=1 Stern\ Mentor=1 Stern\ Proctor=1 Steward\ of\ Solidarity=1 Steward\ of\ Valeron=1 +Still\ Life=1 Stingerfling\ Spider=1 Stinging\ Licid=1 Stinging\ Shot=1 @@ -8182,7 +8622,6 @@ Stitch\ in\ Time=1 Stitched\ Drake=1 Stitched\ Mangler=1 Stitcher's\ Apprentice=1 -Stitcher's\ Graft=1 Stitchwing\ Skaab=1 Stoic\ Angel=1 Stoic\ Builder=1 @@ -8192,33 +8631,31 @@ Stoke\ the\ Flames=1 Stolen\ Goods=1 Stolen\ Grain=1 Stolen\ Identity=1 -Stomp\ and\ Howl=1 Stomper\ Cub=1 Stomping\ Slabs=1 +Stone-Seeder\ Hierophant=1 Stone-Tongue\ Basilisk=1 Stone\ Calendar=1 Stone\ Giant=1 -Stone\ Golem=1 Stone\ Haven\ Medic=1 Stone\ Haven\ Outfitter=1 Stone\ Idol\ Trap=1 Stone\ Quarry=1 +Stone\ Spirit=1 Stonebrow,\ Krosan\ Hero=1 Stonecloaker=1 Stoneforge\ Acolyte=1 -Stoneforge\ Masterwork=1 Stonefury=1 Stonehands=1 Stonehewer\ Giant=1 Stoneshaker\ Shaman=1 +Stoneshock\ Giant=1 Stonewise\ Fortifier=1 Stonewood\ Invocation=1 -Stonewood\ Invoker=1 Stonework\ Puma=1 Stonewright=1 Stonybrook\ Angler=1 Stonybrook\ Schoolmaster=1 -Storage\ Matrix=1 Storm\ Crow=1 Storm\ Elemental=1 Storm\ Entity=1 @@ -8234,25 +8671,28 @@ Storm\ Sculptor=1 Storm\ Seeker=1 Storm\ Shaman=1 Storm\ Spirit=1 +Storm\ the\ Vault=1 Stormblood\ Berserker=1 Stormchaser\ Chimera=1 -Stormcloud\ Djinn=1 -Stormcrag\ Elemental=1 Stormfront\ Pegasus=1 Stormfront\ Riders=1 Stormrider\ Rig=1 Stormrider\ Spirit=1 Stormscale\ Anarch=1 +Stormscape\ Apprentice=1 Stormscape\ Battlemage=1 Stormscape\ Familiar=1 Stormtide\ Leviathan=1 Stormwatch\ Eagle=1 Stormwing\ Dragon=1 -Strafe=1 +Strands\ of\ Night=1 Strandwalker=1 Strange\ Augmentation=1 Strangling\ Soot=1 +Strangling\ Spores=1 Strata\ Scythe=1 +Stratadon=1 +Stratozeppelid=1 Stratus\ Walk=1 Straw\ Golem=1 Stream\ Hopper=1 @@ -8262,50 +8702,62 @@ Stream\ of\ Unconsciousness=1 Streambed\ Aquitects=1 Street\ Savvy=1 Street\ Spasm=1 +Street\ Sweeper=1 Streetbreaker\ Wurm=1 Strength\ from\ the\ Fallen=1 Strength\ in\ Numbers=1 Strength\ of\ Arms=1 +Strength\ of\ Isolation=1 +Strength\ of\ Lunacy=1 Strength\ of\ Night=1 +Strength\ of\ Unity=1 Strength\ of\ the\ Pack=1 Strength\ of\ the\ Tajuru=1 Strider\ Harness=1 -Stroke\ of\ Genius=1 -Stromgald\ Cabal=1 -Stromkirk\ Condemned=1 +Strip\ Bare=1 +Striped\ Riverwinder=1 Stromkirk\ Mentor=1 +Stromkirk\ Noble=1 Stromkirk\ Occultist=1 -Stromkirk\ Patrol=1 Strongarm\ Monk=1 Strongarm\ Tactics=1 +Strongarm\ Thug=1 +Stronghold\ Assassin=1 +Stronghold\ Biologist=1 +Stronghold\ Confessor=1 Stronghold\ Discipline=1 +Stronghold\ Machinist=1 Stronghold\ Overseer=1 Stronghold\ Rats=1 +Stronghold\ Taskmaster=1 +Stronghold\ Zeppelin=1 Structural\ Collapse=1 Structural\ Distortion=1 -Struggle\ //\ Survive=1 Struggle\ for\ Sanity=1 +Student\ of\ Elements=1 Student\ of\ Ojutai=1 Stuffy\ Doll=1 Stun=1 Stun\ Sniper=1 +Stunted\ Growth=1 Stupefying\ Touch=1 Sturdy\ Hatchling=1 Sturmgeist=1 Stymied\ Hopes=1 -Su-Chi=1 -Subterranean\ Shambler=1 +Subjugator\ Angel=1 +Submerged\ Boneyard=1 +Subterranean\ Scout=1 Subtle\ Strike=1 Succumb\ to\ Temptation=1 Sudden\ Death=1 Sudden\ Disappearance=1 Sudden\ Impact=1 -Sudden\ Reclamation=1 Sudden\ Spoiling=1 Sudden\ Storm=1 Sudden\ Strength=1 Suffer\ the\ Past=1 Suicidal\ Charge=1 +Sulam\ Djinn=1 Sulfur\ Elemental=1 Sulfuric\ Vapors=1 Sulfurous\ Blast=1 @@ -8313,42 +8765,44 @@ Sultai\ Ascendancy=1 Sultai\ Banner=1 Sultai\ Charm=1 Sultai\ Flayer=1 -Sultai\ Runemark=1 -Sultai\ Skullkeeper=1 +Sultai\ Scavenger=1 Sultai\ Soothsayer=1 Summary\ Dismissal=1 Summit\ Apes=1 Summit\ Prowler=1 Summon\ the\ School=1 Summoner's\ Bane=1 +Summoner's\ Egg=1 Summoning\ Station=1 -Summoning\ Trap=1 Sun's\ Bounty=1 Sun-Collared\ Raptor=1 Sun-Crested\ Pterodon=1 Sun-Crowned\ Hunters=1 -Sun\ Clasp=1 Sun\ Sentinel=1 Sunastian\ Falconer=1 Sunbeam\ Spellbomb=1 +Sunbird's\ Invocation=1 Sunblade\ Elf=1 +Sunblast\ Angel=1 Sunbond=1 Sunbringer's\ Touch=1 Suncrusher=1 Sunder\ from\ Within=1 Sundering\ Growth=1 Sundering\ Vitae=1 +Sunfire\ Balm=1 Sunflare\ Shaman=1 Sunforger=1 Sungrace\ Pegasus=1 -Sunhome,\ Fortress\ of\ the\ Legion=1 +Sungrass\ Egg=1 Sunhome\ Enforcer=1 Sunhome\ Guildmage=1 Sunken\ City=1 Sunken\ Hope=1 +Sunlance=1 Sunrise\ Seeker=1 Sunrise\ Sovereign=1 -Sunscape\ Battlemage=1 +Sunscape\ Apprentice=1 Sunscorched\ Desert=1 Sunseed\ Nurturer=1 Sunset\ Pyramid=1 @@ -8360,11 +8814,14 @@ Sunstrike\ Legionnaire=1 Suntail\ Hawk=1 Suntouched\ Myr=1 Sunweb=1 +Superior\ Numbers=1 Supernatural\ Stamina=1 Supply\ //\ Demand=1 Supply\ Caravan=1 +Suppress=1 Suppression\ Bonds=1 Supreme\ Exemplar=1 +Supreme\ Inquisitor=1 Suq'Ata\ Assassin=1 Suq'Ata\ Lancer=1 Sure\ Strike=1 @@ -8373,13 +8830,14 @@ Surge\ Node=1 Surge\ of\ Righteousness=1 Surge\ of\ Thoughtweft=1 Surge\ of\ Zeal=1 -Surging\ Dementia=1 +Surgespanner=1 Surging\ Flame=1 Surging\ Might=1 Surging\ Sentinels=1 Surprise\ Deployment=1 -Surrakar\ Marauder=1 +Surrakar\ Banisher=1 Surrakar\ Spellblade=1 +Surreal\ Memoir=1 Surveilling\ Sprite=1 Survey\ the\ Wreckage=1 Survival\ Cache=1 @@ -8390,14 +8848,14 @@ Suspension\ Field=1 Suture\ Spirit=1 Sutured\ Ghoul=1 Svogthos,\ the\ Restless\ Tomb=1 -Swab\ Goblin=1 +Svyelunite\ Temple=1 Swaggering\ Corsair=1 +Swallowing\ Plague=1 Swamp=1 Swamp\ Mosquito=1 Swarm\ Intelligence=1 Swarm\ Surge=1 Swarm\ of\ Bloodflies=1 -Swarm\ of\ Rats=1 Swarmborn\ Giant=1 Swashbuckling=1 Swat=1 @@ -8407,6 +8865,7 @@ Sweatworks\ Brawler=1 Sweep\ Away=1 Swell\ of\ Courage=1 Swell\ of\ Growth=1 +Swelter=1 Swerve=1 Swift\ Justice=1 Swift\ Kick=1 @@ -8418,45 +8877,47 @@ Swift\ Warkite=1 Swirl\ the\ Mists=1 Swirling\ Spriggan=1 Switcheroo=1 -Swooping\ Talon=1 Sword-Point\ Diplomacy=1 Sword\ Dancer=1 -Sword\ of\ Kaldra=1 -Sword\ of\ the\ Ages=1 Swordwise\ Centaur=1 Sworn\ Guardian=1 Sygg,\ River\ Guide=1 +Sylvan\ Awakening=1 Sylvan\ Basilisk=1 Sylvan\ Bounty=1 Sylvan\ Echoes=1 -Sylvan\ Hierophant=1 Sylvan\ Messenger=1 Sylvan\ Might=1 Sylvan\ Primordial=1 Sylvan\ Ranger=1 +Sylvok\ Explorer=1 Sylvok\ Replica=1 Symbiosis=1 +Symbiotic\ Deployment=1 Symbiotic\ Wurm=1 -Symbol\ of\ Unsummoning=1 Synchronized\ Strike=1 Synchronous\ Sliver=1 Syncopate=1 Syndic\ of\ Tithes=1 Syndicate\ Enforcer=1 +Syndicate\ Trafficker=1 +Synod\ Artificer=1 Synod\ Centurion=1 Synod\ Sanctum=1 +Syphon\ Soul=1 Szadek,\ Lord\ of\ Secrets=1 +Sance=1 Tablet\ of\ Epityr=1 Tablet\ of\ the\ Guilds=1 Tah-Crop\ Elite=1 Tah-Crop\ Skirmisher=1 +Tahngarth's\ Glare=1 Tahngarth's\ Rage=1 Taigam's\ Scheming=1 Taigam's\ Strike=1 Tail\ Slash=1 Tainted\ Remedy=1 -Tainted\ Specter=1 -Tainted\ Strike=1 +Tainted\ Sigil=1 Taj-Nar\ Swordsmith=1 Tajic,\ Blade\ of\ the\ Legion=1 Tajuru\ Archer=1 @@ -8468,9 +8929,8 @@ Tajuru\ Warcaller=1 Take\ Down=1 Take\ Inventory=1 Take\ Possession=1 -Take\ Up\ Arms=1 +Take\ Vengeance=1 Take\ into\ Custody=1 -Takeno's\ Cavalry=1 Takeno,\ Samurai\ General=1 Takenuma\ Bleeder=1 Takklemaggot=1 @@ -8478,12 +8938,12 @@ Talas\ Researcher=1 Talent\ of\ the\ Telepath=1 Talisman\ of\ Impulse=1 Talisman\ of\ Unity=1 -Tallowisp=1 Talon\ Trooper=1 Talon\ of\ Pain=1 Talonrend=1 Talrand's\ Invocation=1 Talruum\ Champion=1 +Talruum\ Minotaur=1 Talruum\ Piper=1 Talus\ Paladin=1 Tamiyo's\ Journal=1 @@ -8493,138 +8953,130 @@ Tangle=1 Tangle\ Angler=1 Tangle\ Asp=1 Tangle\ Golem=1 -Tangle\ Hulk=1 Tangle\ Mantis=1 Tangle\ Spider=1 Tanglebloom=1 Tangleclaw\ Werewolf=1 Tangleroot=1 +Tanglesap=1 Tanglewalker=1 Tapestry\ of\ the\ Ages=1 Tar\ Fiend=1 Tar\ Pit\ Warrior=1 -Tar\ Pitcher=1 -Tar\ Snare=1 -Tarox\ Bladewing=1 -Tasigur's\ Cruelty=1 Tasseled\ Dromedary=1 Taste\ for\ Mayhem=1 -Taste\ of\ Blood=1 Tatsumasa,\ the\ Dragon's\ Fang=1 +Tattered\ Drake=1 Tattered\ Haunter=1 Tatterkite=1 Tattermunge\ Duo=1 Tattermunge\ Maniac=1 Tattermunge\ Witch=1 -Taunting\ Elf=1 -Tavern\ Swindler=1 +Tatyova,\ Benthic\ Druid=1 Tawnos's\ Coffin=1 Tawnos's\ Wand=1 Teardrop\ Kami=1 -Tears\ of\ Rage=1 Tears\ of\ Valakut=1 Tectonic\ Rift=1 -Teetering\ Peaks=1 -Teferi's\ Drake=1 +Teferi's\ Care=1 Teferi's\ Honor\ Guard=1 -Teferi's\ Moat=1 Tel-Jilad\ Archers=1 Tel-Jilad\ Chosen=1 Tel-Jilad\ Defiance=1 Tel-Jilad\ Fallen=1 -Tel-Jilad\ Justice=1 +Tel-Jilad\ Lifebreather=1 Tel-Jilad\ Outrider=1 +Tel-Jilad\ Stylus=1 +Tel-Jilad\ Wolf=1 +Telekinetic\ Bonds=1 Telekinetic\ Sliver=1 Telemin\ Performance=1 Telepathic\ Spies=1 Telepathy=1 Teleportal=1 -Telethopter=1 Telim'Tor's\ Darts=1 +Telim'Tor=1 Teller\ of\ Tales=1 Telling\ Time=1 Temmet,\ Vizier\ of\ Naktamun=1 +Temper=1 Tempest\ Caller=1 Tempest\ Drake=1 Tempest\ of\ Light=1 Temple\ Acolyte=1 Temple\ Altisaur=1 -Temple\ of\ Mystery=1 Temporal\ Adept=1 Temporal\ Cascade=1 Temporal\ Distortion=1 -Temporal\ Eddy=1 Temporal\ Fissure=1 Temporal\ Isolation=1 Tempting\ Licid=1 +Tempting\ Wurm=1 Temur\ Ascendancy=1 Temur\ Banner=1 Temur\ Charger=1 Temur\ Charm=1 -Temur\ Runemark=1 -Temur\ War\ Shaman=1 Tenacious\ Dead=1 Tenacious\ Hunter=1 Tenacity=1 -Tendrils\ of\ Agony=1 Teneb,\ the\ Harvester=1 +Tenement\ Crasher=1 Tenza,\ Godo's\ Maul=1 Tephraderm=1 Terashi's\ Cry=1 Terashi's\ Grasp=1 Terashi's\ Verdict=1 Teremko\ Griffin=1 -Terminal\ Moraine=1 -Teroh's\ Faithful=1 +Teroh's\ Vanguard=1 Terra\ Eternal=1 Terra\ Stomper=1 Terraformer=1 Terrarion=1 -Terrifying\ Presence=1 Territorial\ Baloth=1 +Territorial\ Gorger=1 Territorial\ Hammerskull=1 Terror=1 Terror\ of\ the\ Fairgrounds=1 Terrus\ Wurm=1 +Teshar,\ Ancestor's\ Apostle=1 Test\ of\ Faith=1 +Testament\ of\ Faith=1 Tethered\ Skirge=1 Tethmos\ High\ Priest=1 +Tetsuko\ Umezawa,\ Fugitive=1 +Teysa,\ Envoy\ of\ Ghosts=1 Tezzeret's\ Ambition=1 Tezzeret's\ Gambit=1 Tezzeret's\ Touch=1 -Thalakos\ Dreamsower=1 +Thada\ Adel,\ Acquisitor=1 Thalakos\ Drifters=1 +Thalakos\ Lowlands=1 Thalakos\ Mistfolk=1 -Thalakos\ Scout=1 Thalakos\ Seer=1 Thalia's\ Lancers=1 Thallid=1 -Thallid\ Devourer=1 Thallid\ Germinator=1 +Thallid\ Omnivore=1 Thallid\ Shell-Dweller=1 +Thallid\ Soothsayer=1 Thassa's\ Bounty=1 Thassa's\ Devourer=1 Thassa's\ Emissary=1 Thassa's\ Ire=1 Thassa's\ Rebuff=1 -That\ Which\ Was\ Taken=1 -Thaumatic\ Compass=1 -Thawing\ Glaciers=1 -The\ Fallen=1 +The\ First\ Eruption=1 The\ Hive=1 The\ Lady\ of\ the\ Mountain=1 +The\ Mending\ of\ Dominaria=1 The\ Unspeakable=1 The\ Wretched=1 Theft\ of\ Dreams=1 -Thelon\ of\ Havenwood=1 Thelonite\ Druid=1 -Thelonite\ Hermit=1 -Thermal\ Navigator=1 +Thermal\ Flux=1 Thermopod=1 Thick-Skinned\ Goblin=1 -Thicket\ Basilisk=1 Thief\ of\ Hope=1 -Thieves'\ Auction=1 +Thieves'\ Fortune=1 Thieving\ Magpie=1 Thieving\ Sprite=1 Thing\ from\ the\ Deep=1 @@ -8632,54 +9084,55 @@ Think\ Tank=1 Thirst=1 Thirsting\ Axe=1 Thistledown\ Duo=1 -Thopter\ Assembly=1 +Thopter\ Arrest=1 Thopter\ Engineer=1 Thopter\ Spy\ Network=1 Thopter\ Squadron=1 Thorn-Thrash\ Viashino=1 Thorn\ Elemental=1 -Thorn\ Thallid=1 Thornbite\ Staff=1 Thornbow\ Archer=1 -Thorncaster\ Sliver=1 Thorned\ Moloch=1 Thornhide\ Wolves=1 +Thornscape\ Apprentice=1 Thornscape\ Battlemage=1 Thornscape\ Master=1 Thorntooth\ Witch=1 Thornweald\ Archer=1 +Thornwind\ Faeries=1 +Thornwood\ Falls=1 Those\ Who\ Serve=1 Thought\ Courier=1 Thought\ Devourer=1 Thought\ Dissector=1 Thought\ Eater=1 +Thought\ Gorger=1 Thought\ Harvester=1 Thought\ Hemorrhage=1 Thought\ Prison=1 -Thoughtcutter\ Agent=1 +Thought\ Reflection=1 +Thoughtbind=1 +Thoughtbound\ Primoc=1 Thoughtflare=1 +Thoughtleech=1 Thoughtpicker\ Witch=1 Thoughtrender\ Lamia=1 Thoughts\ of\ Ruin=1 -Thoughtweft\ Gambit=1 -Thoughtweft\ Trio=1 Thousand-legged\ Kami=1 Thousand\ Winds=1 Thraben\ Foulbloods=1 Thraben\ Gargoyle=1 -Thraben\ Purebloods=1 Thraben\ Sentry=1 Thraben\ Standard\ Bearer=1 Thran\ Forge=1 +Thran\ Foundry=1 Thran\ Golem=1 -Thran\ Lens=1 -Thran\ Turbine=1 +Thran\ Temporal\ Gateway=1 Thran\ Weaponry=1 Thrash\ of\ Raptors=1 Thrashing\ Mossdog=1 Threaten=1 Three\ Dreams=1 -Three\ Tragedies=1 Thresher\ Lizard=1 Thrill-Kill\ Assassin=1 Thrill\ of\ the\ Hunt=1 @@ -8691,14 +9144,11 @@ Thriving\ Rats=1 Thriving\ Rhino=1 Thriving\ Turtle=1 Throat\ Slitter=1 -Throne\ Warden=1 Throne\ of\ Bone=1 Throne\ of\ Empires=1 -Throne\ of\ Geth=1 Throne\ of\ the\ God-Pharaoh=1 Throttle=1 Throwing\ Knife=1 -Thrull\ Champion=1 Thrull\ Parasite=1 Thrull\ Retainer=1 Thrull\ Surgeon=1 @@ -8707,64 +9157,61 @@ Thumbscrews=1 Thunder-Thrash\ Elder=1 Thunder\ Brute=1 Thunder\ Spirit=1 -Thunder\ Strike=1 Thunder\ Totem=1 -Thunder\ Wall=1 Thunder\ of\ Hooves=1 Thunderblade\ Charge=1 Thunderblust=1 Thunderbolt=1 -Thunderclap=1 Thunderclap\ Wyvern=1 +Thundercloud\ Elemental=1 Thundercloud\ Shaman=1 Thunderheads=1 +Thunderherd\ Migration=1 Thundering\ Giant=1 Thundering\ Spineback=1 Thundering\ Tanadon=1 Thundermare=1 Thunderous\ Might=1 -Thunderous\ Wrath=1 +Thunderscape\ Battlemage=1 Thundersong\ Trumpeter=1 Thunderstaff=1 +Tiana,\ Ship's\ Caretaker=1 Tibor\ and\ Lumia=1 -Ticking\ Gnomes=1 -Tidal\ Bore=1 -Tidal\ Courier=1 -Tidal\ Kraken=1 -Tidal\ Surge=1 +Tidal\ Visionary=1 Tidal\ Wave=1 Tide\ Drifter=1 Tide\ of\ War=1 Tideforce\ Elemental=1 +Tidehollow\ Strix=1 Tideshaper\ Mystic=1 Tidewalker=1 Tidewater\ Minion=1 Tidings=1 Tidy\ Conclusion=1 Tiger\ Claws=1 +Tigereye\ Cameo=1 Tightening\ Coils=1 Tilonalli's\ Crown=1 Tilonalli's\ Knight=1 Tilonalli's\ Skinshifter=1 Timber\ Gorge=1 +Timberland\ Ruins=1 Timbermare=1 +Timbermaw\ Larva=1 Timberpack\ Wolf=1 Time\ Bomb=1 Time\ Ebb=1 Time\ Stop=1 Time\ and\ Tide=1 Time\ of\ Heroes=1 -Time\ of\ Need=1 +Time\ of\ Ice=1 Time\ to\ Feed=1 Time\ to\ Reflect=1 Timebender=1 Timecrafting=1 Timely\ Hordemate=1 -Timesifter=1 Timid\ Drake=1 Tin-Wing\ Chimera=1 -Tin\ Street\ Hooligan=1 -Tin\ Street\ Market=1 Tine\ Shrike=1 Tireless\ Missionaries=1 Tishana's\ Wayfinder=1 @@ -8777,6 +9224,7 @@ Titania's\ Boon=1 Titania's\ Chosen=1 Titanic\ Bulvox=1 Titanic\ Growth=1 +Titanic\ Ultimatum=1 Titanium\ Golem=1 Tivadar's\ Crusade=1 Tivadar\ of\ Thorn=1 @@ -8787,28 +9235,29 @@ Toil\ //\ Trouble=1 Toil\ to\ Renown=1 Toils\ of\ Night\ and\ Day=1 Tolarian\ Drake=1 +Tolarian\ Emissary=1 +Tolarian\ Scholar=1 Tolarian\ Sentinel=1 Tolarian\ Serpent=1 Tolsimir\ Wolfblood=1 Tomb\ Robber=1 +Tomb\ of\ Urami=1 Tomb\ of\ the\ Spirit\ Dragon=1 -Tombfire=1 +Tome\ Scour=1 Tomorrow,\ Azami's\ Familiar=1 +Toolcraft\ Exemplar=1 Tooth\ Collector=1 Tooth\ and\ Claw=1 Tooth\ of\ Chiss-Goria=1 Topan\ Ascetic=1 Topan\ Freeblade=1 -Topple=1 Topplegeist=1 Tor\ Wauki=1 Torch\ Fiend=1 Torch\ Gauntlet=1 -Torch\ Slinger=1 Torch\ Song=1 Torchling=1 -Torii\ Watchward=1 -Torment=1 +Torgaar,\ Famine\ Incarnate=1 Torment\ of\ Scarabs=1 Torment\ of\ Venom=1 Tormented\ Angel=1 @@ -8818,18 +9267,25 @@ Tormented\ Soul=1 Tormented\ Thoughts=1 Tormenting\ Voice=1 Tormentor\ Exarch=1 +Tornado=1 Tornado\ Elemental=1 +Torpid\ Moloch=1 Torpor\ Dust=1 Torrent\ of\ Fire=1 Torrent\ of\ Souls=1 Torrent\ of\ Stone=1 Torsten\ Von\ Ursus=1 Tortoise\ Formation=1 -Torture\ Chamber=1 +Torture=1 +Toshiro\ Umezawa=1 +Totally\ Lost=1 Totem-Guide\ Hartebeest=1 +Totem\ Speaker=1 +Touch\ of\ Invisibility=1 Touch\ of\ Moonglove=1 Touch\ of\ the\ Eternal=1 Touch\ of\ the\ Void=1 +Touchstone=1 Tower\ Above=1 Tower\ Defense=1 Tower\ Drake=1 @@ -8843,11 +9299,7 @@ Tower\ of\ Murmurs=1 Towering\ Baloth=1 Towering\ Indrik=1 Town\ Gossipmonger=1 -Toxic\ Iguanar=1 Toxic\ Nim=1 -Trace\ of\ Abundance=1 -Tracker's\ Instincts=1 -Tracker=1 Trade\ Routes=1 Trade\ Secrets=1 Tradewind\ Rider=1 @@ -8857,20 +9309,18 @@ Tragic\ Poet=1 Trail\ of\ Evidence=1 Trail\ of\ Mystery=1 Trailblazer's\ Boots=1 -Train\ of\ Thought=1 Trained\ Armodon=1 Trained\ Caracal=1 Trained\ Orgg=1 -Training\ Drone=1 +Trained\ Pronghorn=1 Trait\ Doctoring=1 Traitor's\ Clutch=1 -Traitor's\ Roar=1 Traitorous\ Blood=1 Traitorous\ Instinct=1 Tranquil\ Cove=1 Tranquil\ Expanse=1 Tranquil\ Garden=1 -Tranquil\ Path=1 +Transcendence=1 Transgress\ the\ Mind=1 Transguild\ Courier=1 Transguild\ Promenade=1 @@ -8879,36 +9329,36 @@ Transmogrifying\ Licid=1 Trap\ Digger=1 Trap\ Essence=1 Trapjaw\ Kelpie=1 -Traproot\ Kami=1 +Trapmaker's\ Snare=1 Traumatize=1 Travel\ Preparations=1 Traveler's\ Amulet=1 Traveling\ Plague=1 -Treacherous\ Link=1 Treacherous\ Urge=1 +Treacherous\ Werewolf=1 Tread\ Upon=1 Treasure\ Cruise=1 +Treasure\ Hunter=1 Treasure\ Keeper=1 Treasure\ Trove=1 Treasured\ Find=1 Treasury\ Thrull=1 Tree\ Monkey=1 -Treefolk\ Harbinger=1 +Treefolk\ Healer=1 Treefolk\ Mystic=1 Treefolk\ Seedlings=1 Treespring\ Lorian=1 -Treetop\ Bracers=1 +Treetop\ Rangers=1 Treetop\ Sentinel=1 Tremor=1 Trench\ Wurm=1 +Trenching\ Steed=1 Trepanation\ Blade=1 Trespasser's\ Curse=1 Trespasser\ il-Vec=1 -Trespassing\ Souleater=1 -Tresserhorn\ Sinks=1 Tresserhorn\ Skyknight=1 Trestle\ Troll=1 -Treva's\ Ruins=1 +Treva's\ Attendant=1 Triad\ of\ Fates=1 Trial\ //\ Error=1 Trial\ of\ Ambition=1 @@ -8917,18 +9367,19 @@ Trial\ of\ Solidarity=1 Trial\ of\ Strength=1 Trial\ of\ Zeal=1 Triangle\ of\ War=1 +Triassic\ Egg=1 Tribal\ Flames=1 -Tribal\ Forcemage=1 +Tribal\ Golem=1 Tribal\ Unity=1 Tribute\ to\ Hunger=1 Tribute\ to\ the\ Wild=1 +Trickbind=1 Trickery\ Charm=1 Tricks\ of\ the\ Trade=1 +Trickster\ Mage=1 Triclopean\ Sight=1 +Trigon\ of\ Corruption=1 Trigon\ of\ Infestation=1 -Trigon\ of\ Mending=1 -Trigon\ of\ Rage=1 -Trigon\ of\ Thought=1 Trip\ Noose=1 Trip\ Wire=1 Triskaidekaphobia=1 @@ -8939,18 +9390,20 @@ Triton\ Fortune\ Hunter=1 Triton\ Shorethief=1 Triton\ Tactics=1 Triumph\ of\ Ferocity=1 +Triumph\ of\ Gerrard=1 Troll-Horn\ Cameo=1 -Troll\ Ascetic=1 -Trolls\ of\ Tel-Jilad=1 Tromokratis=1 Tromp\ the\ Domains=1 Trophy\ Hunter=1 Trophy\ Mage=1 +Tropical\ Storm=1 Trostani's\ Judgment=1 Trostani's\ Summoner=1 Troubled\ Healer=1 +Troublesome\ Spirit=1 Trove\ of\ Temptation=1 True-Faith\ Censer=1 +True\ Believer=1 True\ Conviction=1 Truefire\ Paladin=1 Trueheart\ Duelist=1 @@ -8961,14 +9414,15 @@ Trusted\ Advisor=1 Trusted\ Forcemage=1 Trusty\ Companion=1 Trusty\ Machete=1 +Trusty\ Packbeast=1 Truth\ or\ Tale=1 Trygon\ Predator=1 Tukatongue\ Thallid=1 -Tuknir\ Deathlock=1 Tuktuk\ Grunts=1 Tuktuk\ Scrapper=1 Tuktuk\ the\ Explorer=1 Tumble\ Magnet=1 +Tundra\ Kavu=1 Tunnel\ Vision=1 Tunneling\ Geopede=1 Turbulent\ Dreams=1 @@ -8977,9 +9431,10 @@ Turn\ Against=1 Turn\ Aside=1 Turn\ the\ Tables=1 Turn\ the\ Tide=1 +Turn\ to\ Dust=1 Turn\ to\ Frog=1 Turn\ to\ Mist=1 -Turnabout=1 +Turn\ to\ Slag=1 Turntimber\ Basilisk=1 Turntimber\ Grove=1 Turntimber\ Ranger=1 @@ -8987,11 +9442,11 @@ Turtleshell\ Changeling=1 Tusked\ Colossodon=1 Tuskguard\ Captain=1 Twiddle=1 +Twigwalker=1 +Twilight\ Drover=1 Twilight\ Shepherd=1 -Twin\ Bolt=1 Twinblade\ Slasher=1 Twincast=1 -Twinflame=1 Twinning\ Glass=1 Twins\ of\ Maurer\ Estate=1 Twinstrike=1 @@ -9000,13 +9455,15 @@ Twisted\ Abomination=1 Twisted\ Image=1 Twitch=1 Two-Headed\ Cerberus=1 +Two-Headed\ Dragon=1 +Two-Headed\ Giant=1 Two-Headed\ Giant\ of\ Foriys=1 Two-Headed\ Sliver=1 +Two-Headed\ Zombie=1 Tymaret,\ the\ Murder\ King=1 Typhoid\ Rats=1 Tyrannize=1 Tyrant's\ Choice=1 -Tyrant's\ Machine=1 Tyrant\ of\ Valakut=1 Tyrranax=1 Uba\ Mask=1 @@ -9017,11 +9474,11 @@ Uktabi\ Drake=1 Uktabi\ Efreet=1 Uktabi\ Faerie=1 Uktabi\ Orangutan=1 +Uktabi\ Wildcats=1 Ukud\ Cobra=1 Ulamog's\ Despoiler=1 Ulamog's\ Nullifier=1 Ulamog's\ Reclaimer=1 -Ulasht,\ the\ Hate\ Seed=1 Ulcerate=1 Ulrich's\ Kindred=1 Ultimate\ Price=1 @@ -9042,11 +9499,12 @@ Unbridled\ Growth=1 Unburden=1 Uncaged\ Fury=1 Unchecked\ Growth=1 -Uncle\ Istvan=1 +Uncomfortable\ Chill=1 Uncontrollable\ Anger=1 Unconventional\ Tactics=1 Uncovered\ Clues=1 Undead\ Alchemist=1 +Undead\ Gladiator=1 Undead\ Leotau=1 Undead\ Minotaur=1 Undead\ Servant=1 @@ -9057,11 +9515,13 @@ Undercity\ Shade=1 Undercity\ Troll=1 Undergrowth\ Scavenger=1 Underhanded\ Designs=1 +Undertaker=1 Underworld\ Coinsmith=1 -Underworld\ Dreams=1 Undo=1 -Undying\ Flames=1 Undying\ Rage=1 +Unerring\ Sling=1 +Unesh,\ Criosphinx\ Sovereign=1 +Unexpected\ Results=1 Unflinching\ Courage=1 Unforge=1 Unfriendly\ Fire=1 @@ -9074,62 +9534,68 @@ Uninvited\ Geist=1 Unity\ of\ Purpose=1 Universal\ Solvent=1 Unknown\ Shores=1 -Unlicensed\ Disintegration=1 Unliving\ Psychopath=1 Unmake\ the\ Graves=1 Unnatural\ Aggression=1 Unnatural\ Endurance=1 Unnatural\ Predation=1 -Unnatural\ Speed=1 -Unnerve=1 Unnerving\ Assault=1 Unquenchable\ Thirst=1 Unravel\ the\ Aether=1 Unraveling\ Mummy=1 Unruly\ Mob=1 -Unscythe,\ Killer\ of\ Kings=1 Unstable\ Footing=1 Unstable\ Frontier=1 Unstable\ Hulk=1 Unstoppable\ Ash=1 -Unsubstantiate=1 Unsummon=1 Untamed\ Hunger=1 +Untamed\ Kavu=1 Untamed\ Might=1 Untamed\ Wilds=1 Untethered\ Express=1 Unwavering\ Initiate=1 Unwilling\ Recruit=1 -Unworthy\ Dead=1 +Unwind=1 +Unyaro\ Bee\ Sting=1 Unyaro\ Bees=1 Unyielding\ Krumar=1 -Updraft\ Elemental=1 +Uphill\ Battle=1 Uproot=1 -Upwelling=1 Ur-Golem's\ Eye=1 Urban\ Burgeoning=1 Urban\ Evolution=1 Urbis\ Protector=1 +Urborg\ Elf=1 +Urborg\ Emissary=1 Urborg\ Mindsucker=1 +Urborg\ Phantom=1 +Urborg\ Shambler=1 +Urborg\ Skeleton=1 Urborg\ Stalker=1 +Urborg\ Syphon-Mage=1 Urborg\ Uprising=1 +Urborg\ Volcano=1 Urge\ to\ Feed=1 +Urgoros,\ the\ Empty\ One=1 Ursapine=1 -Ursine\ Fylgja=1 Urza's\ Armor=1 +Urza's\ Blueprints=1 Urza's\ Chalice=1 -Urza's\ Factory=1 Urza's\ Guilt=1 -Urza's\ Miter=1 -Utopia\ Mycon=1 +Urza's\ Tome=1 +Uthden\ Troll=1 Utopia\ Vow=1 +Utter\ End=1 Utvara\ Scalper=1 Uyo,\ Silent\ Prophet=1 +Vacuumelt=1 Vaevictis\ Asmadi=1 Vagrant\ Plowbeasts=1 Valakut\ Fireboar=1 Valakut\ Invoker=1 Valakut\ Predator=1 +Valduk,\ Keeper\ of\ the\ Flame=1 Valeron\ Outlander=1 Valeron\ Wardens=1 Valiant\ Guard=1 @@ -9142,12 +9608,9 @@ Valor\ in\ Akros=1 Vampire's\ Bite=1 Vampire's\ Zeal=1 Vampire\ Aristocrat=1 -Vampire\ Bats=1 -Vampire\ Champion=1 Vampire\ Cutthroat=1 Vampire\ Envoy=1 Vampire\ Interloper=1 -Vampire\ Lacerator=1 Vampire\ Nighthawk=1 Vampire\ Noble=1 Vampire\ Outcasts=1 @@ -9164,25 +9627,26 @@ Vandalize=1 Vanguard's\ Shield=1 Vanguard\ of\ Brimaz=1 Vanish\ into\ Memory=1 -Vanishing=1 Vanishment=1 Vanquish=1 -Vanquish\ the\ Foul=1 Vanquish\ the\ Weak=1 +Vaporkin=1 +Vaporous\ Djinn=1 Varchild's\ Crusader=1 +Varolz,\ the\ Scar-Striped=1 Vassal's\ Duty=1 +Vassal\ Soul=1 Vastwood\ Animist=1 Vastwood\ Gorger=1 -Vastwood\ Hydra=1 Vastwood\ Zendikon=1 Vault\ Skyward=1 Vaultbreaker=1 Vebulid=1 +Vec\ Townships=1 +Vectis\ Agents=1 Vectis\ Silencers=1 Vector\ Asp=1 -Vedalken\ Aethermage=1 Vedalken\ Anatomist=1 -Vedalken\ Archmage=1 Vedalken\ Blademaster=1 Vedalken\ Certarch=1 Vedalken\ Dismisser=1 @@ -9196,34 +9660,39 @@ Vedalken\ Outlander=1 Vedalken\ Plotter=1 Veil\ of\ Secrecy=1 Veilborn\ Ghoul=1 +Veiled\ Apparition=1 Veiled\ Crocodile=1 +Veiled\ Sentry=1 +Veiled\ Serpent=1 Veilstone\ Amulet=1 Vein\ Drinker=1 Venarian\ Glimmer=1 Vendetta=1 +Venerable\ Kumo=1 Venerable\ Lammasu=1 Venerable\ Monk=1 Venerated\ Teacher=1 Vengeance=1 -Vengeful\ Archon=1 Vengeful\ Firebrand=1 Vengeful\ Rebel=1 Vengeful\ Rebirth=1 Vengeful\ Vampire=1 Venomous\ Dragonfly=1 -Venomous\ Fangs=1 Venomspout\ Brackus=1 Venser's\ Diffusion=1 +Venser's\ Journal=1 Vent\ Sentinel=1 +Ventifact\ Bottle=1 Verdant\ Automaton=1 Verdant\ Eidolon=1 Verdant\ Embrace=1 +Verdant\ Field=1 Verdant\ Force=1 Verdant\ Haven=1 Verdant\ Rebirth=1 Verdant\ Sun's\ Avatar=1 Verdant\ Touch=1 -Verdeloth\ the\ Ancient=1 +Verdigris=1 Vermiculos=1 Vertigo\ Spawn=1 Vesper\ Ghoul=1 @@ -9234,39 +9703,37 @@ Vessel\ of\ Nascency=1 Vessel\ of\ Paramnesia=1 Vessel\ of\ Volatility=1 Vestige\ of\ Emrakul=1 +Vesuvan\ Shapeshifter=1 +Veteran's\ Armaments=1 Veteran's\ Reflexes=1 Veteran's\ Sidearm=1 Veteran\ Armorer=1 -Veteran\ Bodyguard=1 +Veteran\ Armorsmith=1 Veteran\ Cathar=1 -Veteran\ Cavalier=1 Veteran\ Motorist=1 Veteran\ Warleader=1 Veteran\ of\ the\ Depths=1 Vex=1 -Vexing\ Arcanix=1 -Vexing\ Beetle=1 Vexing\ Scuttler=1 -Vhati\ il-Dal=1 Vial\ of\ Dragonfire=1 +Vial\ of\ Poison=1 Viashino\ Bladescout=1 Viashino\ Cutthroat=1 -Viashino\ Fangtail=1 Viashino\ Firstblade=1 +Viashino\ Grappler=1 Viashino\ Outrider=1 Viashino\ Racketeer=1 Viashino\ Runner=1 Viashino\ Sandscout=1 Viashino\ Sandstalker=1 -Viashino\ Sandswimmer=1 +Viashino\ Skeleton=1 Viashino\ Slasher=1 Viashino\ Slaughtermaster=1 -Viashino\ Spearhunter=1 -Viashino\ Warrior=1 -Viashino\ Weaponsmith=1 -Viashivan\ Dragon=1 Vibrating\ Sphere=1 -Vicious\ Betrayal=1 +Vicious\ Conquistador=1 +Vicious\ Hunger=1 +Vicious\ Kavu=1 +Vicious\ Offering=1 Vicious\ Shadows=1 Victorious\ Destruction=1 Victory's\ Herald=1 @@ -9274,10 +9741,15 @@ Victual\ Sliver=1 View\ from\ Above=1 Vigean\ Graftmage=1 Vigean\ Hydropon=1 +Vigean\ Intuition=1 +Vigil\ for\ the\ Lost=1 +Vigilance=1 +Vigilant\ Baloth=1 Vigilant\ Drake=1 -Vigilant\ Martyr=1 +Vigilant\ Sentry=1 Vigilante\ Justice=1 Vigor\ Mortis=1 +Vigorous\ Charge=1 Vildin-Pack\ Outcast=1 Vile\ Aggregate=1 Vile\ Deacon=1 @@ -9302,7 +9774,7 @@ Vineshaper\ Mystic=1 Vineweft=1 Vintara\ Snapper=1 Violent\ Impact=1 -Violent\ Ultimatum=1 +Violet\ Pall=1 Viper's\ Kiss=1 Viral\ Drake=1 Viridescent\ Wisps=1 @@ -9310,52 +9782,54 @@ Viridian\ Acolyte=1 Viridian\ Betrayers=1 Viridian\ Claw=1 Viridian\ Emissary=1 -Viridian\ Harvest=1 Viridian\ Joiner=1 Viridian\ Lorebearers=1 Viridian\ Revel=1 Viridian\ Shaman=1 +Viridian\ Zealot=1 Virulent\ Swipe=1 Virulent\ Wound=1 Visara\ the\ Dreadful=1 Viscerid\ Armor=1 -Viscerid\ Deepwalker=1 +Viscerid\ Drone=1 Viscid\ Lemures=1 Vision\ Skeins=1 Visionary\ Augmenter=1 Visions\ of\ Brutality=1 Vital\ Splicer=1 Vital\ Surge=1 +Vitality\ Charm=1 +Vitalizing\ Cascade=1 Vitaspore\ Thallid=1 +Vithian\ Renegades=1 Vithian\ Stinger=1 Vitu-Ghazi,\ the\ City-Tree=1 Vitu-Ghazi\ Guildmage=1 -Vivid\ Marsh=1 +Vivify=1 Vivisection=1 Vizier\ of\ Deferment=1 +Vizier\ of\ Many\ Faces=1 Vizier\ of\ Remedies=1 Vizier\ of\ Tumbling\ Sands=1 Vizier\ of\ the\ Anointed=1 Vizier\ of\ the\ True=1 Vizkopa\ Confessor=1 Vizkopa\ Guildmage=1 +Vizzerdrix=1 +Vodalian\ Arcanist=1 +Vodalian\ Hypnotist=1 Vodalian\ Knights=1 +Vodalian\ Merchant=1 +Vodalian\ Serpent=1 Voice\ of\ All=1 Voice\ of\ Duty=1 Voice\ of\ Grace=1 Voice\ of\ Law=1 Voice\ of\ Reason=1 -Voice\ of\ Truth=1 -Voice\ of\ the\ Provinces=1 -Voice\ of\ the\ Woods=1 -Voiceless\ Spirit=1 -Voices\ from\ the\ Void=1 -Void=1 Void\ Attendant=1 Void\ Grafter=1 Void\ Maw=1 Void\ Shatter=1 -Void\ Snare=1 Void\ Squall=1 Void\ Stalker=1 Voidmage\ Apprentice=1 @@ -9367,34 +9841,38 @@ Volatile\ Rig=1 Volcanic\ Awakening=1 Volcanic\ Dragon=1 Volcanic\ Geyser=1 -Volcanic\ Hammer=1 Volcanic\ Rambler=1 Volcanic\ Rush=1 Volcanic\ Spray=1 Volcanic\ Strength=1 Volcanic\ Upheaval=1 +Volcanic\ Wind=1 Volcano\ Hellion=1 Volcano\ Imp=1 Voldaren\ Duelist=1 Voldaren\ Pariah=1 Volition\ Reins=1 -Volley\ of\ Boulders=1 +Volrath's\ Curse=1 Volrath's\ Dungeon=1 +Volrath's\ Gardens=1 Volrath's\ Laboratory=1 Volrath's\ Shapeshifter=1 Volt\ Charge=1 +Voltaic\ Brawler=1 Voltaic\ Construct=1 +Voltaic\ Servant=1 Volunteer\ Reserves=1 +Vona's\ Hunger=1 Voodoo\ Doll=1 Voracious\ Cobra=1 Voracious\ Dragon=1 Voracious\ Null=1 Voracious\ Vampire=1 Voracious\ Wurm=1 -Vorosh,\ the\ Hunter=1 Vorrac\ Battlehorns=1 -Vorstclaw=1 Vortex\ Elemental=1 +Votary\ of\ the\ Conclave=1 +Vow\ of\ Duty=1 Vow\ of\ Flight=1 Vow\ of\ Lightning=1 Vow\ of\ Malice=1 @@ -9403,10 +9881,14 @@ Voyage's\ End=1 Voyager\ Drake=1 Voyager\ Staff=1 Voyaging\ Satyr=1 +Vug\ Lizard=1 +Vulpine\ Goliath=1 Vulshok\ Battlemaster=1 +Vulshok\ Berserker=1 Vulshok\ Gauntlets=1 +Vulshok\ Heartstoker=1 Vulshok\ Morningstar=1 -Vulshok\ Refugee=1 +Vulshok\ Replica=1 Vulshok\ Sorcerer=1 Vulshok\ War\ Boar=1 Vulturous\ Zombie=1 @@ -9416,8 +9898,8 @@ Wake\ of\ Vultures=1 Wake\ the\ Reflections=1 Wakedancer=1 Waker\ of\ the\ Wilds=1 -Wakestone\ Gargoyle=1 Waking\ Nightmare=1 +Walk\ the\ Plank=1 Walker\ of\ Secret\ Ways=1 Walker\ of\ the\ Grove=1 Walker\ of\ the\ Wastes=1 @@ -9426,6 +9908,7 @@ Walking\ Atlas=1 Walking\ Corpse=1 Walking\ Desecration=1 Walking\ Dream=1 +Walking\ Sponge=1 Walking\ Wall=1 Wall\ of\ Air=1 Wall\ of\ Blood=1 @@ -9435,24 +9918,25 @@ Wall\ of\ Denial=1 Wall\ of\ Diffusion=1 Wall\ of\ Distortion=1 Wall\ of\ Essence=1 +Wall\ of\ Faith=1 Wall\ of\ Fire=1 Wall\ of\ Forgotten\ Pharaohs=1 Wall\ of\ Frost=1 -Wall\ of\ Junk=1 -Wall\ of\ Kelp=1 Wall\ of\ Light=1 Wall\ of\ Limbs=1 +Wall\ of\ Mist=1 Wall\ of\ Mulch=1 -Wall\ of\ Razors=1 Wall\ of\ Resurgence=1 Wall\ of\ Souls=1 Wall\ of\ Spears=1 Wall\ of\ Stone=1 Wall\ of\ Swords=1 Wall\ of\ Tanglecord=1 -Wall\ of\ Torches=1 Wall\ of\ Vines=1 -Wall\ of\ Wood=1 +Wall\ of\ Vipers=1 +Wall\ of\ Wonder=1 +Wallop=1 +Wand\ of\ Denial=1 Wand\ of\ the\ Elements=1 Wander\ in\ Death=1 Wanderbrine\ Rootcutters=1 @@ -9472,11 +9956,11 @@ Waning\ Wurm=1 Wanted\ Scoundrels=1 War-Name\ Aspirant=1 War-Spike\ Changeling=1 -War-Torch\ Goblin=1 War-Wing\ Siren=1 War\ Barge=1 War\ Behemoth=1 War\ Dance=1 +War\ Elemental=1 War\ Falcon=1 War\ Flare=1 War\ Horn=1 @@ -9487,27 +9971,24 @@ Warbreak\ Trumpeter=1 Warbringer=1 Warchanter\ of\ Mogis=1 Warchief\ Giant=1 -Warclamp\ Mastiff=1 +Warcry\ Phoenix=1 Ward\ of\ Piety=1 Warden\ of\ Evos\ Isle=1 Warden\ of\ Geometries=1 -Warden\ of\ the\ Beyond=1 Warden\ of\ the\ Eye=1 Wardscale\ Dragon=1 Warfire\ Javelineer=1 Warleader's\ Helix=1 -Warlord's\ Axe=1 +Warlord's\ Fury=1 Warmind\ Infantry=1 Warmonger's\ Chariot=1 Warmonger=1 -Warmth=1 Warning=1 Warp\ Artifact=1 Warp\ World=1 Warpath\ Ghoul=1 Warped\ Devotion=1 Warped\ Landscape=1 -Warped\ Physique=1 Warped\ Researcher=1 Warren-Scourge\ Elf=1 Warren\ Pilferers=1 @@ -9518,9 +9999,10 @@ Warrior\ en-Kor=1 Warriors'\ Lesson=1 Warthog=1 Wasp\ Lancer=1 +Waste\ Away=1 Wasteland\ Scorpion=1 +Wasteland\ Strangler=1 Wasteland\ Viper=1 -Wastes=1 Watchdog=1 Watcher\ Sliver=1 Watcher\ in\ the\ Web=1 @@ -9540,31 +10022,30 @@ Waterspout\ Elemental=1 Waterspout\ Weavers=1 Watertrap\ Weaver=1 Waterveil\ Cavern=1 -Waterwhirl=1 Wave-Wing\ Elemental=1 Wave\ of\ Indifference=1 Wavecrash\ Triton=1 -Waves\ of\ Aggression=1 +Waveskimmer\ Aven=1 +Wax\ //\ Wane=1 Waxing\ Moon=1 Waxmane\ Baku=1 Way\ of\ the\ Thief=1 -Wayfarer's\ Bauble=1 +Wayfaring\ Giant=1 Wayfaring\ Temple=1 Waylay=1 -Wayward\ Angel=1 Wayward\ Giant=1 Wayward\ Servant=1 Wayward\ Soul=1 Weakness=1 Weakstone=1 Weapon\ Surge=1 +Weaponcraft\ Enthusiast=1 Weapons\ Trainer=1 Wear\ Away=1 Weathered\ Bodyguards=1 Weatherseed\ Elf=1 Weatherseed\ Faeries=1 Weatherseed\ Totem=1 -Weatherseed\ Treefolk=1 Weave\ Fate=1 Weaver\ of\ Currents=1 Weaver\ of\ Lies=1 @@ -9576,12 +10057,12 @@ Weed\ Strangle=1 Wei\ Elite\ Companions=1 Wei\ Infantry=1 Wei\ Night\ Raiders=1 -Wei\ Strike\ Force=1 Weight\ of\ Conscience=1 +Weight\ of\ Memory=1 Weight\ of\ Spires=1 Weight\ of\ the\ Underworld=1 +Weird\ Harvest=1 Weirded\ Vampire=1 -Weirding\ Shaman=1 Weirding\ Wood=1 Welcome\ to\ the\ Fold=1 Welder\ Automaton=1 @@ -9591,7 +10072,7 @@ Weldfast\ Wingsmith=1 Welding\ Sparks=1 Welkin\ Guide=1 Welkin\ Tern=1 -Wellgabber\ Apothecary=1 +Well\ of\ Life=1 Western\ Paladin=1 Wetland\ Sambar=1 Wharf\ Infiltrator=1 @@ -9600,21 +10081,24 @@ Where\ Ancients\ Tread=1 Whetwheel=1 Whims\ of\ the\ Fates=1 Whimwader=1 -Whip-Spine\ Drake=1 Whip\ Sergeant=1 +Whip\ Silk=1 +Whip\ of\ Erebos=1 Whipcorder=1 -Whipgrass\ Entangler=1 +Whipkeeper=1 Whiplash\ Trap=1 -Whipstitched\ Zombie=1 Whiptail\ Moloch=1 Whiptail\ Wurm=1 +Whiptongue\ Frog=1 Whirler\ Rogue=1 Whirlermaker=1 Whirling\ Catapult=1 Whirling\ Dervish=1 -Whirlpool\ Whelm=1 +Whirlpool\ Drake=1 Whirlwind\ Adept=1 +Whisper,\ Blood\ Liturgist=1 Whispering\ Madness=1 +Whispering\ Shade=1 Whispering\ Specter=1 Whispers\ of\ Emrakul=1 Whispersilk\ Cloak=1 @@ -9622,16 +10106,16 @@ White\ Knight=1 White\ Shield\ Crusader=1 Whitemane\ Lion=1 Whiteout=1 -Whitewater\ Naiads=1 +Whitesun's\ Passage=1 Wicked\ Akuba=1 -Wicked\ Pact=1 +Wicked\ Reward=1 Wicker\ Warcrawler=1 Wicker\ Witch=1 -Wight\ of\ Precinct\ Six=1 Wiitigo=1 Wild-Field\ Scarecrow=1 Wild\ Aesthir=1 Wild\ Beastmaster=1 +Wild\ Colos=1 Wild\ Dogs=1 Wild\ Evocation=1 Wild\ Griffin=1 @@ -9639,8 +10123,9 @@ Wild\ Guess=1 Wild\ Hunger=1 Wild\ Instincts=1 Wild\ Leotau=1 -Wild\ Mongrel=1 -Wild\ Nacatl=1 +Wild\ Mammoth=1 +Wild\ Might=1 +Wild\ Onslaught=1 Wild\ Ox=1 Wild\ Pair=1 Wild\ Ricochet=1 @@ -9657,28 +10142,26 @@ Wildfire\ Eternal=1 Wildgrowth\ Walker=1 Wildheart\ Invoker=1 Wildsize=1 -Wildslayer\ Elves=1 -Wildwood\ Geist=1 Wildwood\ Rebirth=1 Will-Forged\ Golem=1 -Will\ of\ the\ Naga=1 Willbender=1 +Willbreaker=1 Willow\ Priestess=1 -Wilt-Leaf\ Cavaliers=1 Wily\ Bandar=1 Wily\ Goblin=1 Wind-Kin\ Raiders=1 +Wind-Scarred\ Crag=1 Wind\ Dancer=1 Wind\ Drake=1 Wind\ Shear=1 -Wind\ Spirit=1 Wind\ Strider=1 Windborne\ Charge=1 Windbrisk\ Raptor=1 +Windgrace\ Acolyte=1 Winding\ Wurm=1 +Windreaper\ Falcon=1 Windreaver=1 Windrider\ Patrol=1 -Winds\ of\ Qal\ Sisma=1 Winds\ of\ Rath=1 Winds\ of\ Rebuke=1 Windseeker\ Centaur=1 @@ -9686,17 +10169,19 @@ Windstorm=1 Windwright\ Mage=1 Wine\ of\ Blood\ and\ Iron=1 Wing\ Puncture=1 +Wing\ Shards=1 Wing\ Snare=1 Wing\ Splicer=1 -Wingbeat\ Warrior=1 +Wing\ Storm=1 Wingcrafter=1 Winged\ Coatl=1 Winged\ Shepherd=1 -Winged\ Sliver=1 +Wingmate\ Roc=1 Wingrattle\ Scarecrow=1 Wings\ of\ Aesthir=1 Wings\ of\ Velis\ Vel=1 Wingsteed\ Rider=1 +Winnow=1 Winnower\ Patrol=1 Winter\ Blast=1 Winterflame=1 @@ -9705,14 +10190,15 @@ Wirecat=1 Wirefly\ Hive=1 Wirewood\ Elf=1 Wirewood\ Guardian=1 -Wishmonger=1 +Wirewood\ Savage=1 Wispweaver\ Angel=1 Wistful\ Thinking=1 Wit's\ End=1 Witch's\ Familiar=1 +Witch's\ Mist=1 Witch-Maw\ Nephilim=1 -Witch\ Hunter=1 Witches'\ Eye=1 +Withered\ Wretch=1 Withering\ Gaze=1 Withering\ Hex=1 Withering\ Wisps=1 @@ -9729,28 +10215,27 @@ Woebearer=1 Woebringer\ Demon=1 Woeleecher=1 Wojek\ Apothecary=1 -Wojek\ Embermage=1 -Wojek\ Halberdiers=1 Wojek\ Siren=1 Wolf-Skull\ Shaman=1 Wolfbriar\ Elemental=1 +Wolfhunter's\ Quiver=1 Wolfir\ Avenger=1 -Wolfir\ Silverheart=1 Wolfkin\ Bond=1 Wonder=1 Wood\ Elemental=1 -Wood\ Sage=1 Woodborn\ Behemoth=1 Woodcloaker=1 Woodcutter's\ Grit=1 Wooden\ Sphere=1 Wooden\ Stake=1 Woodland\ Changeling=1 +Woodland\ Druid=1 Woodland\ Guidance=1 Woodland\ Patrol=1 Woodland\ Sleuth=1 Woodland\ Stream=1 Woodland\ Wanderer=1 +Woodlot\ Crawler=1 Woodlurker\ Mimic=1 Woodripper=1 Woodweaver's\ Puzzleknot=1 @@ -9758,28 +10243,34 @@ Woodwraith\ Corrupter=1 Woodwraith\ Strangler=1 Woolly\ Loxodon=1 Woolly\ Mammoths=1 -Woolly\ Razorback=1 Woolly\ Spider=1 Woolly\ Thoctar=1 Word\ of\ Seizing=1 Word\ of\ Undoing=1 Words\ of\ War=1 +Words\ of\ Waste=1 Words\ of\ Wilding=1 -Words\ of\ Wind=1 Workshop\ Assistant=1 World\ Queller=1 World\ Shaper=1 World\ at\ War=1 Worldgorger\ Dragon=1 +Worldheart\ Phoenix=1 +Worldly\ Counsel=1 Worldpurge=1 Worldslayer=1 Worm\ Harvest=1 +Wormfang\ Drake=1 Wormfang\ Manta=1 Wormwood\ Dryad=1 Wormwood\ Treefolk=1 Wort,\ Boggart\ Auntie=1 Wort,\ the\ Raidmother=1 +Worthy\ Cause=1 +Wound\ Reflection=1 Wrangle=1 +Wrap\ in\ Flames=1 +Wrath\ of\ Marit\ Lage=1 Wreak\ Havoc=1 Wreath\ of\ Geists=1 Wrecking\ Ball=1 @@ -9787,9 +10278,8 @@ Wrecking\ Ogre=1 Wren's\ Run\ Packmaster=1 Wren's\ Run\ Vanquisher=1 Wretched\ Camel=1 -Wring\ Flesh=1 +Wretched\ Gryff=1 Writ\ of\ Passage=1 -Write\ into\ Being=1 Wu\ Elite\ Cavalry=1 Wu\ Longbowman=1 Wu\ Warship=1 @@ -9802,24 +10292,26 @@ Wyluli\ Wolf=1 Xathrid\ Gorgon=1 Xathrid\ Slyblade=1 Xenic\ Poltergeist=1 -Xenograft=1 +Yamabushi's\ Flame=1 Yamabushi's\ Storm=1 -Yavimaya's\ Embrace=1 +Yare=1 +Yargle,\ Glutton\ of\ Urborg=1 Yavimaya\ Ancients=1 Yavimaya\ Ants=1 Yavimaya\ Dryad=1 Yavimaya\ Enchantress=1 -Yavimaya\ Granger=1 Yavimaya\ Kavu=1 +Yavimaya\ Sapherd=1 Yavimaya\ Scion=1 Yavimaya\ Wurm=1 Yawgmoth's\ Edict=1 Yawgmoth\ Demon=1 Yawning\ Fissure=1 -Ydwen\ Efreet=1 Yeva's\ Forcemage=1 +Yeva,\ Nature's\ Herald=1 Yew\ Spirit=1 Yixlid\ Jailer=1 +Yoke\ of\ the\ Damned=1 Yoked\ Ox=1 Yoked\ Plowbeast=1 Yomiji,\ Who\ Bars\ the\ Way=1 @@ -9831,26 +10323,29 @@ Youthful\ Knight=1 Youthful\ Scholar=1 Yuki-Onna=1 Yukora,\ the\ Prisoner=1 +Zada's\ Commando=1 Zada,\ Hedron\ Grinder=1 Zameck\ Guildmage=1 +Zanikev\ Locust=1 +Zap=1 Zarichi\ Tiger=1 Zealot\ il-Vec=1 -Zealots\ en-Dal=1 Zealous\ Guardian=1 Zealous\ Inquisitor=1 -Zealous\ Strike=1 +Zebra\ Unicorn=1 Zektar\ Shrine\ Expedition=1 Zendikar's\ Roil=1 +Zendikar\ Farguide=1 Zendikar\ Incarnate=1 Zendikar\ Resurgent=1 Zenith\ Seeker=1 Zephid's\ Embrace=1 Zephid=1 +Zephyr\ Charge=1 Zephyr\ Net=1 -Zephyr\ Scribe=1 Zephyr\ Spirit=1 +Zephyr\ Sprite=1 Zerapa\ Minotaur=1 -Zetalpa,\ Primal\ Dawn=1 Zhalfirin\ Commander=1 Zhalfirin\ Crusader=1 Zhalfirin\ Knight=1 @@ -9861,17 +10356,16 @@ Zhur-Taa\ Swine=1 Zodiac\ Monkey=1 Zoetic\ Cavern=1 Zof\ Shade=1 -Zombie\ Apocalypse=1 -Zombie\ Brute=1 +Zombie\ Boa=1 Zombie\ Cannibal=1 Zombie\ Cutthroat=1 Zombie\ Goliath=1 -Zombie\ Infestation=1 Zombie\ Musher=1 -Zombie\ Scavengers=1 +Zombie\ Trailblazer=1 Zombify=1 +Zoologist=1 Zulaport\ Chainmage=1 +Zulaport\ Cutthroat=1 Zulaport\ Enforcer=1 Zur's\ Weirding=1 -Zuran\ Orb=1 Zuran\ Spellcaster=1 diff --git a/Mage.Sets/pom.xml b/Mage.Sets/pom.xml index 8beaf1af446..f478419c232 100644 --- a/Mage.Sets/pom.xml +++ b/Mage.Sets/pom.xml @@ -7,7 +7,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 org.mage diff --git a/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java b/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java index a73a5b031f8..5d44aa8dd68 100644 --- a/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java +++ b/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java @@ -155,7 +155,7 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl { Card card = game.getCard(event.getTargetId()); if (card != null && watcher != null - && card.getOwnerId().equals(controller.getId())) { + && card.isOwnedBy(controller.getId())) { for (Ability ability : card.getAbilities()) { if (ability instanceof CyclingAbility) { cardHasCycling = true; @@ -199,7 +199,7 @@ class AbandonedSarcophagusWatcher extends Watcher { Player controller = game.getPlayer(event.getPlayerId()); if (card != null && controller != null - && card.getOwnerId().equals(controller.getId())) { + && card.isOwnedBy(controller.getId())) { Cards c = getCardsCycledThisTurn(event.getPlayerId()); c.add(card); cycledCardsThisTurn.put(event.getPlayerId(), c); diff --git a/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java b/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java index f7ae5aec0a8..c8a371940d5 100644 --- a/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java +++ b/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java @@ -108,7 +108,7 @@ class AbbotOfKeralKeepCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java b/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java new file mode 100644 index 00000000000..847823acadc --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java @@ -0,0 +1,43 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class AbnormalEndurance extends CardImpl { + + public AbnormalEndurance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); + + // Until end of turn, target creature gets +2/+0 and gains "When this creature dies, return it to the battlefield tapped under its owner's control." + getSpellAbility().addTarget(new TargetCreaturePermanent()); + getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("Until end of turn, target creature gets +2/+0") + ); + getSpellAbility().addEffect(new GainAbilityTargetEffect( + new DiesTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true, true), false), + Duration.EndOfTurn, + "and gains \"When this creature dies, return it to the battlefield tapped under its owner's control.\"" + )); + } + + public AbnormalEndurance(final AbnormalEndurance card) { + super(card); + } + + @Override + public AbnormalEndurance copy() { + return new AbnormalEndurance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AbruptDecay.java b/Mage.Sets/src/mage/cards/a/AbruptDecay.java index 434b41fdf26..ff509f11362 100644 --- a/Mage.Sets/src/mage/cards/a/AbruptDecay.java +++ b/Mage.Sets/src/mage/cards/a/AbruptDecay.java @@ -31,9 +31,9 @@ public final class AbruptDecay extends CardImpl { public AbruptDecay(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}{G}"); - // Abrupt Decay can't be countered by spells or abilities. + // Abrupt Decay can't be countered. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, effect); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java b/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java index 21d42c45d8c..e0503095188 100644 --- a/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java +++ b/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.ControlsCreatureGreatestToughnessCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +27,7 @@ public final class AbzanBeastmaster extends CardImpl { this.toughness = new MageInt(1); // At the beginning of your upkeep, draw a card if you control the creature with the greatest toughness or tied for the greatest toughness. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false), ControlsCreatureGreatestToughnessCondition.instance, "At the beginning of your upkeep, draw a card if you control the creature with the greatest toughness or tied for the greatest toughness." diff --git a/Mage.Sets/src/mage/cards/a/AcidicSoil.java b/Mage.Sets/src/mage/cards/a/AcidicSoil.java index a18d1636248..cbb5e62189c 100644 --- a/Mage.Sets/src/mage/cards/a/AcidicSoil.java +++ b/Mage.Sets/src/mage/cards/a/AcidicSoil.java @@ -57,7 +57,7 @@ class AcidicSoilEffect extends OneShotEffect { if (player != null) { int amount = 0; for (Permanent permanent : permanents) { - if (permanent.getControllerId().equals(playerId)) { + if (permanent.isControlledBy(playerId)) { amount++; } } diff --git a/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java b/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java index c1e338aceaa..1e1341a51e9 100644 --- a/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java +++ b/Mage.Sets/src/mage/cards/a/AdaptiveAutomaton.java @@ -3,10 +3,9 @@ package mage.cards.a; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; +import mage.abilities.effects.common.continuous.AddChosenSubtypeEffect; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.effects.common.continuous.BoostAllOfChosenSubtypeEffect; import mage.abilities.effects.common.enterAttribute.EnterAttributeAddChosenSubtypeEffect; @@ -15,8 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; /** * @author nantuko @@ -38,11 +35,11 @@ public final class AdaptiveAutomaton extends CardImpl { // As Adaptive Automaton enters the battlefield, choose a creature type. // Adaptive Automaton is the chosen type in addition to its other types. - AsEntersBattlefieldAbility ability = new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature), null, EnterEventType.SELF); + AsEntersBattlefieldAbility ability = new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature)); ability.addEffect(new EnterAttributeAddChosenSubtypeEffect()); this.addAbility(ability); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AdaptiveAutomatonAddSubtypeEffect())); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AddChosenSubtypeEffect())); // Other creatures you control of the chosen type get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllOfChosenSubtypeEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); } @@ -57,31 +54,3 @@ public final class AdaptiveAutomaton extends CardImpl { } } -class AdaptiveAutomatonAddSubtypeEffect extends ContinuousEffectImpl { - - public AdaptiveAutomatonAddSubtypeEffect() { - super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - staticText = "{this} is the chosen type in addition to its other types"; - } - - public AdaptiveAutomatonAddSubtypeEffect(final AdaptiveAutomatonAddSubtypeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(permanent.getId(), game); - if (subType != null && !permanent.hasSubtype(subType, game)) { - permanent.getSubtype(game).add(subType); - } - } - return true; - } - - @Override - public AdaptiveAutomatonAddSubtypeEffect copy() { - return new AdaptiveAutomatonAddSubtypeEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java b/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java index 9de6daa1946..fa866596582 100644 --- a/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java +++ b/Mage.Sets/src/mage/cards/a/AdelizTheCinderWind.java @@ -48,7 +48,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_INSTANT_OR_SORCERY_SPELL, false); + Ability ability = new SpellCastControllerTriggeredAbility(effect, StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AegisOfTheHeavens.java b/Mage.Sets/src/mage/cards/a/AegisOfTheHeavens.java new file mode 100644 index 00000000000..c66d70d625e --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AegisOfTheHeavens.java @@ -0,0 +1,33 @@ +package mage.cards.a; + +import java.util.UUID; +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.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class AegisOfTheHeavens extends CardImpl { + + public AegisOfTheHeavens(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Target creature gets +1/+7 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 7, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public AegisOfTheHeavens(final AegisOfTheHeavens card) { + super(card); + } + + @Override + public AegisOfTheHeavens copy() { + return new AegisOfTheHeavens(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AerialCaravan.java b/Mage.Sets/src/mage/cards/a/AerialCaravan.java index 8dadcf7bb7d..933595fcd9b 100644 --- a/Mage.Sets/src/mage/cards/a/AerialCaravan.java +++ b/Mage.Sets/src/mage/cards/a/AerialCaravan.java @@ -114,7 +114,7 @@ class AerialCaravanCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/a/AerialEngineer.java b/Mage.Sets/src/mage/cards/a/AerialEngineer.java new file mode 100644 index 00000000000..cfdaf87eb7d --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AerialEngineer.java @@ -0,0 +1,66 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +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.FlyingAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class AerialEngineer extends CardImpl { + + public AerialEngineer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // As long as you control an artifact, Aerial Engineer gets +2/+0 and has flying. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition( + StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT + ), + "As long as you control an artifact, {this} gets +2/+0" + ) + ); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + FlyingAbility.getInstance(), + Duration.WhileOnBattlefield + ), + new PermanentsOnTheBattlefieldCondition( + StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT + ), + "and has flying" + )); + this.addAbility(ability); + } + + public AerialEngineer(final AerialEngineer card) { + super(card); + } + + @Override + public AerialEngineer copy() { + return new AerialEngineer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AetherCharge.java b/Mage.Sets/src/mage/cards/a/AetherCharge.java index e2ce3a6dd38..6563c83d149 100644 --- a/Mage.Sets/src/mage/cards/a/AetherCharge.java +++ b/Mage.Sets/src/mage/cards/a/AetherCharge.java @@ -70,7 +70,7 @@ class AetherChargeTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent.isCreature() && permanent.hasSubtype(SubType.BEAST, game) - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { Effect effect = this.getEffects().get(0); effect.setValue("damageSource", event.getTargetId()); return true; diff --git a/Mage.Sets/src/mage/cards/a/AetherTunnel.java b/Mage.Sets/src/mage/cards/a/AetherTunnel.java new file mode 100644 index 00000000000..cef52b890c8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AetherTunnel.java @@ -0,0 +1,58 @@ +package mage.cards.a; + +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.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CantBeBlockedAttachedEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class AetherTunnel extends CardImpl { + + public AetherTunnel(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 gets +1/+0 and can't be blocked. + ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 0, Duration.WhileOnBattlefield) + ); + ability.addEffect( + new CantBeBlockedAttachedEffect(AttachmentType.AURA) + .setText("and can't be blocked") + ); + this.addAbility(ability); + } + + public AetherTunnel(final AetherTunnel card) { + super(card); + } + + @Override + public AetherTunnel copy() { + return new AetherTunnel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AetherWeb.java b/Mage.Sets/src/mage/cards/a/AetherWeb.java new file mode 100644 index 00000000000..339ba6c037c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AetherWeb.java @@ -0,0 +1,88 @@ +package mage.cards.a; + +import java.util.UUID; + +import mage.abilities.StaticAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.ReachAbility; +import mage.constants.*; +import mage.abilities.keyword.FlashAbility; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; + +/** + * + * @author noahg + */ +public final class AetherWeb extends CardImpl { + + public AetherWeb(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + 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/+1, has reach, and can block creatures with shadow as though they didn't have shadow. + StaticAbility staticAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1) + .setText("Enchanted creature gets +1/+1, has reach, and can block creatures with shadow as though they didn't have shadow.")); + staticAbility.addEffect(new GainAbilityAttachedEffect(ReachAbility.getInstance(), AttachmentType.AURA).setText("")); + staticAbility.addEffect(new AetherWebEffect()); + this.addAbility(staticAbility); + } + + public AetherWeb(final AetherWeb card) { + super(card); + } + + @Override + public AetherWeb copy() { + return new AetherWeb(this); + } +} + +class AetherWebEffect extends AsThoughEffectImpl { + + public AetherWebEffect() { + super(AsThoughEffectType.BLOCK_SHADOW, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = ""; + } + + public AetherWebEffect(final AetherWebEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public AetherWebEffect copy() { + return new AetherWebEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + return sourcePermanent != null && sourceId.equals(sourcePermanent.getAttachedTo()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AetherflameWall.java b/Mage.Sets/src/mage/cards/a/AetherflameWall.java new file mode 100644 index 00000000000..9579f21ccc2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AetherflameWall.java @@ -0,0 +1,50 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CanBlockAsThoughtItHadShadowEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +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 java.util.UUID; + +/** + * + * @author noahg + */ +public final class AetherflameWall extends CardImpl { + + public AetherflameWall(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.WALL); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // Aetherflame Wall can block creatures with shadow as though they didn’t have shadow. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAsThoughtItHadShadowEffect(Duration.WhileOnBattlefield))); + + // {R}: Aetherflame Wall gets +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + } + + public AetherflameWall(final AetherflameWall card) { + super(card); + } + + @Override + public AetherflameWall copy() { + return new AetherflameWall(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/Aetherplasm.java b/Mage.Sets/src/mage/cards/a/Aetherplasm.java new file mode 100644 index 00000000000..29862c661da --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/Aetherplasm.java @@ -0,0 +1,93 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BlocksTriggeredAbility; +import mage.abilities.costs.common.ReturnToHandFromBattlefieldSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +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.filter.StaticFilters; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInHand; + +/** + * + * @author noahg + */ +public final class Aetherplasm extends CardImpl { + + public Aetherplasm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + + this.subtype.add(SubType.ILLUSION); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Aetherplasm blocks a creature, you may return Aetherplasm to its owner's hand. If you do, you may put a creature card from your hand onto the battlefield blocking that creature. + this.addAbility(new BlocksTriggeredAbility(new DoIfCostPaid(new AetherplasmEffect(), new ReturnToHandFromBattlefieldSourceCost()), false, true)); + } + + public Aetherplasm(final Aetherplasm card) { + super(card); + } + + @Override + public Aetherplasm copy() { + return new Aetherplasm(this); + } +} + +class AetherplasmEffect extends OneShotEffect { + + public AetherplasmEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "you may put a creature card from your hand onto the battlefield blocking that creature"; + } + + public AetherplasmEffect(AetherplasmEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + if (player.chooseUse(Outcome.PutCardInPlay, "Put a creature card from your hand onto the battlefield?", source, game)) { + TargetCardInHand target = new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A); + if (player.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) { + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + Permanent blockedCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (player.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, false, null) + && game.getCombat() != null && blockedCreature != null) { + CombatGroup attacker = game.getCombat().findGroup(blockedCreature.getId()); + Permanent putIntoPlay = game.getPermanent(target.getFirstTarget()); + if (putIntoPlay != null && putIntoPlay.isCreature() && attacker != null) { + game.getCombat().findGroup(blockedCreature.getId()).addBlocker(putIntoPlay.getId(), source.getControllerId(), game); + + } + } + } + } + } + return true; + } + + @Override + public AetherplasmEffect copy() { + return new AetherplasmEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java b/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java new file mode 100644 index 00000000000..c2f5378979c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java @@ -0,0 +1,63 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class AethershieldArtificer extends CardImpl { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("artifact creature you control"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + + public AethershieldArtificer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.DWARF); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // At the beginning of combat on your turn, target artifact creature you control gets +2/+2 and gains indestructible until end of turn. + Ability ability = new BeginningOfCombatTriggeredAbility( + new BoostTargetEffect(2, 2, Duration.EndOfTurn) + .setText("target artifact creature you control gets +2/+2"), + TargetController.YOU, false + ); + ability.addEffect(new GainAbilityTargetEffect( + IndestructibleAbility.getInstance(), + Duration.EndOfTurn + ).setText("and gains indestructible until end of turn")); + ability.addTarget(new TargetControlledCreaturePermanent(filter)); + this.addAbility(ability); + } + + public AethershieldArtificer(final AethershieldArtificer card) { + super(card); + } + + @Override + public AethershieldArtificer copy() { + return new AethershieldArtificer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/Aetherspouts.java b/Mage.Sets/src/mage/cards/a/Aetherspouts.java index 9d6bf960fc3..4c565abaad6 100644 --- a/Mage.Sets/src/mage/cards/a/Aetherspouts.java +++ b/Mage.Sets/src/mage/cards/a/Aetherspouts.java @@ -49,7 +49,7 @@ public final class Aetherspouts extends CardImpl { of their library. The active player (the player whose turn it is) makes all of their choices first, followed by each other player in turn order. 7/18/2014 If an effect puts two or more cards on the top or bottom of a library at the same time, - the owner of those cards may arrange them in any order. That library’s owner doesn’t reveal + the owner of those cards may arrange them in any order. That library's owner doesn't reveal the order in which the cards go into their library. */ class AetherspoutsEffect extends OneShotEffect { @@ -81,7 +81,7 @@ class AetherspoutsEffect extends OneShotEffect { List permanentsToTop = new ArrayList<>(); List permanentsToBottom = new ArrayList<>(); for (Permanent permanent:game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source.getSourceId(), game)) { - if (permanent.getOwnerId().equals(player.getId())) { + if (permanent.isOwnedBy(player.getId())) { if (player.chooseUse(outcome, "Put " + permanent.getLogName() + " to the top? (else it goes to bottom)", source, game)) { permanentsToTop.add(permanent); game.informPlayers(permanent.getLogName() + " goes to the top of " + player.getLogName() + "'s library"); diff --git a/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java b/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java index 3b54846938b..3cbe3dbff4b 100644 --- a/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java +++ b/Mage.Sets/src/mage/cards/a/AfflictedDeserter.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class AfflictedDeserter extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Afflicted Deserter. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public AfflictedDeserter(final AfflictedDeserter card) { diff --git a/Mage.Sets/src/mage/cards/a/Afterburn.java b/Mage.Sets/src/mage/cards/a/Afterburn.java new file mode 100644 index 00000000000..87470510022 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/Afterburn.java @@ -0,0 +1,47 @@ +package mage.cards.a; + +import java.util.UUID; + +import mage.abilities.Mode; +import mage.abilities.effects.common.RemoveFromCombatTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Afterburn extends CardImpl { + + public Afterburn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); + + + // Choose One - + // Target creature gains haste and first strike until end of turn. + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("Target creature gains haste")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn).setText("and first strike until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Remove target creature from combat. + Mode mode = new Mode(); + mode.getEffects().add(new RemoveFromCombatTargetEffect()); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().addMode(mode); + } + + public Afterburn(final Afterburn card) { + super(card); + } + + @Override + public Afterburn copy() { + return new Afterburn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java b/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java new file mode 100644 index 00000000000..243294d59c9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java @@ -0,0 +1,43 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.effects.common.DamageWithPowerTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +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; + +/** + * + * @author TheElk801 + */ +public final class AggressiveInstinct extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + } + + public AggressiveInstinct(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); + + // Target creature you control deals damage equal to its power to target creature you don't control. + this.getSpellAbility().addEffect(new DamageWithPowerTargetEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public AggressiveInstinct(final AggressiveInstinct card) { + super(card); + } + + @Override + public AggressiveInstinct copy() { + return new AggressiveInstinct(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AggressiveMammoth.java b/Mage.Sets/src/mage/cards/a/AggressiveMammoth.java new file mode 100644 index 00000000000..5916a3abd25 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AggressiveMammoth.java @@ -0,0 +1,52 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class AggressiveMammoth extends CardImpl { + + public AggressiveMammoth(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}{G}"); + + this.subtype.add(SubType.ELEPHANT); + this.power = new MageInt(8); + this.toughness = new MageInt(8); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Other creatures you control have trample. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityControlledEffect( + TrampleAbility.getInstance(), + Duration.WhileOnBattlefield, + StaticFilters.FILTER_CONTROLLED_CREATURES, + true + ) + )); + } + + public AggressiveMammoth(final AggressiveMammoth card) { + super(card); + } + + @Override + public AggressiveMammoth copy() { + return new AggressiveMammoth(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java index f0509b855cc..8f35a937e29 100644 --- a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java +++ b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.*; import mage.constants.CardType; @@ -33,7 +33,7 @@ public final class AidFromTheCowl extends CardImpl { // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, // reveal the top card of your library. If it is a permanent card, you may put it onto the battlefield. Otherwise, put it on the bottom of your library. TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new AidFromTheCowlEffect(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, RevoltCondition.instance, ruleText), new RevoltWatcher()); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, RevoltCondition.instance, ruleText), new RevoltWatcher()); } public AidFromTheCowl(final AidFromTheCowl card) { diff --git a/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java b/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java index 9cd725b673d..9e79fe61da5 100644 --- a/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java +++ b/Mage.Sets/src/mage/cards/a/AirdropAeronauts.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class AirdropAeronauts extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Revolt — When Airdrop Aeronauts enters the battlefield, if a permanent you controlled left the battlefield this turn, you gain 5 life. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new GainLifeEffect(5), false), RevoltCondition.instance, "Revolt — When {this} enters the battlefield, if a permanent you controlled left" + " the battlefield this turn, you gain 5 life." diff --git a/Mage.Sets/src/mage/cards/a/AjaniAdversaryOfTyrants.java b/Mage.Sets/src/mage/cards/a/AjaniAdversaryOfTyrants.java new file mode 100644 index 00000000000..2197d263dc3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AjaniAdversaryOfTyrants.java @@ -0,0 +1,65 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.counters.CounterType; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.command.emblems.AjaniAdversaryOfTyrantsEmblem; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class AjaniAdversaryOfTyrants extends CardImpl { + + private static final FilterCreatureCard filter + = new FilterCreatureCard("creature card with converted mana cost 2 or less from your graveyard"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public AjaniAdversaryOfTyrants(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{W}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.AJANI); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Put a +1/+1 counter on each of up to two target creatures. + Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), 1); + ability.addTarget(new TargetCreaturePermanent(0, 2)); + this.addAbility(ability); + + // −2: Return target creature card with converted mana cost 2 or less from your graveyard to the battlefield. + ability = new LoyaltyAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), -2); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); + + // −7: You get an emblem with "At the beginning of your end step, create three 1/1 white Cat creature tokens with lifelink." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new AjaniAdversaryOfTyrantsEmblem()), -7)); + } + + public AjaniAdversaryOfTyrants(final AjaniAdversaryOfTyrants card) { + super(card); + } + + @Override + public AjaniAdversaryOfTyrants copy() { + return new AjaniAdversaryOfTyrants(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java b/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java new file mode 100644 index 00000000000..13636ab6ca1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AjaniWiseCounselor.java @@ -0,0 +1,60 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.dynamicvalue.common.ControllerLifeCount; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +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.counters.CounterType; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class AjaniWiseCounselor extends CardImpl { + + public AjaniWiseCounselor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{W}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.AJANI); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: You gain 1 life for each creature you control. + this.addAbility(new LoyaltyAbility(new GainLifeEffect( + new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_CREATURE) + ).setText("you gain 1 life for each creature you control"), 2)); + + // −3: Creatures you control get +2/+2 until end of turn. + this.addAbility(new LoyaltyAbility( + new BoostControlledEffect(2, 2, Duration.EndOfTurn), -3 + )); + + // −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() + ).setText("put X +1/+1 counters on target creature, where X is your life total"), -9); + this.addAbility(ability); + } + + public AjaniWiseCounselor(final AjaniWiseCounselor card) { + super(card); + } + + @Override + public AjaniWiseCounselor copy() { + return new AjaniWiseCounselor(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AjanisComrade.java b/Mage.Sets/src/mage/cards/a/AjanisComrade.java index df0f010c293..bb26d2ac246 100644 --- a/Mage.Sets/src/mage/cards/a/AjanisComrade.java +++ b/Mage.Sets/src/mage/cards/a/AjanisComrade.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -43,7 +43,7 @@ public final class AjanisComrade extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of combat on your turn, if you control an Ajani planeswalker, put a +1/+1 counter on Ajani's Comrade. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfCombatTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filter), "At the beginning of combat on your turn, if you control an Ajani planeswalker, put a +1/+1 counter on {this}.")); diff --git a/Mage.Sets/src/mage/cards/a/AjanisInfluence.java b/Mage.Sets/src/mage/cards/a/AjanisInfluence.java new file mode 100644 index 00000000000..f8dd582e052 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AjanisInfluence.java @@ -0,0 +1,54 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class AjanisInfluence extends CardImpl { + + private static final FilterCard filter = new FilterCard("a white card"); + + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + } + + public AjanisInfluence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}{W}"); + + // Put two +1/+1 counters on target creature. + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2))); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Look at the top five cards of your library. You may reveal a white card form among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect( + new StaticValue(5), false, new StaticValue(1), filter, + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false + ).setBackInRandomOrder(true).setText("Look at the top five cards of your library. " + + "You may reveal a white card from among them and put it into your hand. " + + "Put the rest on the bottom of your library in a random order.") + ); + } + + public AjanisInfluence(final AjanisInfluence card) { + super(card); + } + + @Override + public AjanisInfluence copy() { + return new AjanisInfluence(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AjanisLastStand.java b/Mage.Sets/src/mage/cards/a/AjanisLastStand.java new file mode 100644 index 00000000000..8be2b128f18 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AjanisLastStand.java @@ -0,0 +1,103 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DiscardedByOpponentTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +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.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.token.AvatarToken2; + +/** + * + * @author TheElk801 + */ +public final class AjanisLastStand extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(new SubtypePredicate(SubType.PLAINS)); + } + + public AjanisLastStand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + + // Whenever a creature or planeswalker you control dies, you may sacrifice Ajani's Last Stand. If you do, create a 4/4 white Avatar creature token with flying. + this.addAbility(new AjanisLastStandTriggeredAbility()); + + // When a spell or ability an opponent controls causes you to discard this card, if you control a Plains, create a 4/4 white Avatar creature token with flying. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new DiscardedByOpponentTriggeredAbility(new CreateTokenEffect(new AvatarToken2())), + new PermanentsOnTheBattlefieldCondition(filter), + "When a spell or ability an opponent controls causes you to discard this card, " + + "if you control a Plains, create a 4/4 white Avatar creature token with flying." + )); + } + + public AjanisLastStand(final AjanisLastStand card) { + super(card); + } + + @Override + public AjanisLastStand copy() { + return new AjanisLastStand(this); + } +} + +class AjanisLastStandTriggeredAbility extends TriggeredAbilityImpl { + + public AjanisLastStandTriggeredAbility() { + super(Zone.BATTLEFIELD, new DoIfCostPaid( + new CreateTokenEffect(new AvatarToken2()), + new SacrificeSourceCost() + ), false); + } + + public AjanisLastStandTriggeredAbility(final AjanisLastStandTriggeredAbility ability) { + super(ability); + } + + @Override + public AjanisLastStandTriggeredAbility copy() { + return new AjanisLastStandTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD + && zEvent.getToZone() == Zone.GRAVEYARD) { + if (zEvent.getTarget().isControlledBy(controllerId) + && (zEvent.getTarget().isCreature() + || zEvent.getTarget().isPlaneswalker())) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a creature or planeswalker you control dies, " + + "you may sacrifice {this}. " + + "If you do, create a 4/4 white Avatar creature token with flying."; + } +} diff --git a/Mage.Sets/src/mage/cards/a/AjanisWelcome.java b/Mage.Sets/src/mage/cards/a/AjanisWelcome.java new file mode 100644 index 00000000000..2fdd09018c2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AjanisWelcome.java @@ -0,0 +1,35 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class AjanisWelcome extends CardImpl { + + public AjanisWelcome(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); + + // Whenever a creature enters the battlefield under your control, you gain 1 life. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new GainLifeEffect(1), + StaticFilters.FILTER_PERMANENT_CREATURE + )); + } + + public AjanisWelcome(final AjanisWelcome card) { + super(card); + } + + @Override + public AjanisWelcome copy() { + return new AjanisWelcome(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AkoumFirebird.java b/Mage.Sets/src/mage/cards/a/AkoumFirebird.java index 53b699b5281..9a7d5c7f437 100644 --- a/Mage.Sets/src/mage/cards/a/AkoumFirebird.java +++ b/Mage.Sets/src/mage/cards/a/AkoumFirebird.java @@ -79,7 +79,7 @@ class AkoumFirebirdLandfallAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - return permanent != null && permanent.isLand() && permanent.getControllerId().equals(this.controllerId); + return permanent != null && permanent.isLand() && permanent.isControlledBy(this.controllerId); } @Override diff --git a/Mage.Sets/src/mage/cards/a/AkoumHellkite.java b/Mage.Sets/src/mage/cards/a/AkoumHellkite.java index 86698bc1f95..24a13cc1423 100644 --- a/Mage.Sets/src/mage/cards/a/AkoumHellkite.java +++ b/Mage.Sets/src/mage/cards/a/AkoumHellkite.java @@ -82,7 +82,7 @@ class AkoumHellkiteTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isLand() - && permanent.getControllerId().equals(getControllerId())) { + && permanent.isControlledBy(getControllerId())) { Permanent sourcePermanent = game.getPermanent(getSourceId()); if (sourcePermanent != null) { for (Effect effect : getEffects()) { diff --git a/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java b/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java index b405eb89848..fddd9d69a5a 100644 --- a/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java +++ b/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.MoreCardsInHandThanOpponentsCondition; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.keyword.HasteAbility; @@ -40,7 +40,7 @@ public final class AkutaBornOfAsh extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); // At the beginning of your upkeep, if you have more cards in hand than each opponent, you may sacrifice a Swamp. If you do, return Akuta, Born of Ash from your graveyard to the battlefield. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new SacrificeTargetCost(new TargetControlledPermanent(filterSwamp))), TargetController.YOU, false), diff --git a/Mage.Sets/src/mage/cards/a/AladdinsLamp.java b/Mage.Sets/src/mage/cards/a/AladdinsLamp.java index 040d1cf38bd..6db19c46d5e 100644 --- a/Mage.Sets/src/mage/cards/a/AladdinsLamp.java +++ b/Mage.Sets/src/mage/cards/a/AladdinsLamp.java @@ -87,6 +87,6 @@ class AladdinsLampEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java b/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java index 557b806e6ad..02b087e0ab3 100644 --- a/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java +++ b/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java @@ -111,7 +111,7 @@ class AlhammarretsArchiveReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getPlayerId().equals(source.getControllerId())) { - if (game.getActivePlayerId().equals(event.getPlayerId()) + if (game.isActivePlayer(event.getPlayerId()) && game.getPhase().getStep().getType() == PhaseStep.DRAW) { CardsDrawnDuringDrawStepWatcher watcher = (CardsDrawnDuringDrawStepWatcher) game.getState().getWatchers().get(CardsDrawnDuringDrawStepWatcher.class.getSimpleName()); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) { diff --git a/Mage.Sets/src/mage/cards/a/AlpineMoon.java b/Mage.Sets/src/mage/cards/a/AlpineMoon.java new file mode 100644 index 00000000000..a88fa999f84 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AlpineMoon.java @@ -0,0 +1,114 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ChooseACardNameEffect; +import mage.abilities.mana.AnyColorManaAbility; +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.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class AlpineMoon extends CardImpl { + + public AlpineMoon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}"); + + // As Alpine Moon enters the battlefield, choose a nonbasic land card name. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NONBASIC_LAND_NAME))); + + // Lands your opponents control with the chosen name lose all land types and abilities, and they gain "{T}: Add one mana of any color." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AlpineMoonEffect())); + } + + public AlpineMoon(final AlpineMoon card) { + super(card); + } + + @Override + public AlpineMoon copy() { + return new AlpineMoon(this); + } +} + +class AlpineMoonEffect extends ContinuousEffectImpl { + + private static final FilterPermanent filter = new FilterLandPermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + filter.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); + } + + public AlpineMoonEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + this.staticText = "lands your opponents control with the chosen name " + + "lose all land types and abilities, " + + "and they gain \"{T}: Add one mana of any color.\""; + } + + public AlpineMoonEffect(final AlpineMoonEffect effect) { + super(effect); + } + + @Override + public AlpineMoonEffect copy() { + return new AlpineMoonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + if (cardName == null) { + return false; + } + FilterPermanent filter2 = filter.copy(); + filter2.add(new NamePredicate(cardName)); + for (Permanent land : game.getBattlefield().getActivePermanents(filter2, source.getControllerId(), game)) { + switch (layer) { + 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)); + break; + case AbilityAddingRemovingEffects_6: + land.addAbility(new AnyColorManaAbility(), source.getSourceId(), game); + break; + } + } + return true; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage.Sets/src/mage/cards/a/Aluren.java b/Mage.Sets/src/mage/cards/a/Aluren.java index b032bdf8f3a..8397fa65c91 100644 --- a/Mage.Sets/src/mage/cards/a/Aluren.java +++ b/Mage.Sets/src/mage/cards/a/Aluren.java @@ -74,7 +74,7 @@ class AlurenRuleEffect extends ContinuousEffectImpl { public AlurenRuleEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Any player may play creature cards with converted mana cost 3 or less without paying their mana cost"; + staticText = "Any player may cast creature cards with converted mana cost 3 or less without paying their mana cost"; } public AlurenRuleEffect(final AlurenRuleEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java b/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java index fc57daa583c..2c8e04683a3 100644 --- a/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java +++ b/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java @@ -75,7 +75,7 @@ class AmbuscadeShamanTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { UUID targetId = event.getTargetId(); Permanent permanent = game.getPermanent(targetId); - if (permanent.getControllerId().equals(this.controllerId) + if (permanent.isControlledBy(this.controllerId) && permanent.isCreature()) { this.getEffects().setTargetPointer(new FixedTarget(permanent, game)); return true; diff --git a/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java b/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java new file mode 100644 index 00000000000..44168d26c0b --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java @@ -0,0 +1,191 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.CanBeYourCommanderAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +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.GainControlTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.Choice; +import mage.choices.ChoiceLeftOrRight; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.other.OwnerPredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.players.PlayerList; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInHand; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author Colin Redman + */ +public class AminatouTheFateShifter extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("permanent you own"); + + static { + filter.add(new OwnerPredicate(TargetController.YOU)); + filter.add(new AnotherPredicate()); + } + + public AminatouTheFateShifter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{W}{U}{B}"); + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.AMINATOU); + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); + + // +1: Draw a card, then put a card from your hand on top of your library. + Ability ability = new LoyaltyAbility(new AminatouPlusEffect(), +1); + this.addAbility(ability); + + // -1: Exile another target permanent you own, then return it to the battlefield under your control. + ability = new LoyaltyAbility(new ExileTargetForSourceEffect(), -1); + ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + + // -6: Choose left or right. Each player gains control of all nonland permanents other than Aminatou, the + // Fateshifter controlled by the next player in the chosen direction. + ability = new LoyaltyAbility(new AminatouUltimateEffect(), -6); + this.addAbility(ability); + + // Aminatou, the Fateshifter can be your commander. + this.addAbility(CanBeYourCommanderAbility.getInstance()); + } + public AminatouTheFateShifter(final AminatouTheFateShifter card) { + super(card); + } + + @Override + public AminatouTheFateShifter copy() { + return new AminatouTheFateShifter(this); + } +} + +class AminatouPlusEffect extends OneShotEffect { + public AminatouPlusEffect() { + super(Outcome.DrawCard); + staticText = "draw a card, then put a card from your hand on top of your library"; + } + + public AminatouPlusEffect(final AminatouPlusEffect effect) { + super(effect); + } + + @Override + public AminatouPlusEffect copy() { + return new AminatouPlusEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.drawCards(1, game); + putOnLibrary(player, source, game); + return true; + } + return false; + } + + private boolean putOnLibrary(Player player, Ability source, Game game) { + TargetCardInHand target = new TargetCardInHand(); + if (target.canChoose(source.getSourceId(), player.getId(), game)) { + player.chooseTarget(Outcome.ReturnToHand, target, source, game); + Card card = player.getHand().get(target.getFirstTarget(), game); + if (card != null) { + return player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.HAND, true, false); + } + } + return false; + } +} + +class AminatouUltimateEffect extends OneShotEffect { + public AminatouUltimateEffect (){ + super(Outcome.Benefit); + staticText = "Choose left or right. Each player gains control of all nonland permanents other than Aminatou," + + " the Fateshifter controlled by the next player in the chosen direction."; + } + + public AminatouUltimateEffect(final AminatouUltimateEffect effect) { + super(effect); + } + + @Override + public AminatouUltimateEffect copy(){return new AminatouUltimateEffect(this);} + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Choice choice = new ChoiceLeftOrRight(); + if (!controller.choose(Outcome.Neutral, choice, game)) { + return false; + } + boolean left = choice.getChoice().equals("Left"); + PlayerList playerList = game.getState().getPlayerList().copy(); + // set playerlist to controller + while (!playerList.get().equals(source.getControllerId())) { + playerList.getNext(); + } + UUID currentPlayer = playerList.get(); + UUID nextPlayer; + UUID firstNextPlayer = null; + while (!getNextPlayerInDirection(left, playerList, game).equals(firstNextPlayer)) { + nextPlayer = playerList.get(); + if (nextPlayer == null) { + return false; + } + // skip players out of range + if (!game.getState().getPlayersInRange(controller.getId(), game).contains(nextPlayer)){ + continue; + } + // save first next player to check for iteration stop + if (firstNextPlayer == null) { + firstNextPlayer = nextPlayer; + } + FilterNonlandPermanent nextPlayerNonlandPermanentsFilter = new FilterNonlandPermanent(); + nextPlayerNonlandPermanentsFilter.add(new ControllerIdPredicate(nextPlayer)); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(nextPlayerNonlandPermanentsFilter, game)) { + if (permanent.getId().equals(source.getSourceId())){ + continue; + } + ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame, currentPlayer); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + } + currentPlayer = nextPlayer; + } + return true; + } + return false; + } + + private UUID getNextPlayerInDirection(boolean left, PlayerList playerList, Game game) { + UUID nextPlayerId; + if (left) { + nextPlayerId = playerList.getNext(); + } else { + nextPlayerId = playerList.getPrevious(); + } + return nextPlayerId; + } +} + diff --git a/Mage.Sets/src/mage/cards/a/AminatousAugury.java b/Mage.Sets/src/mage/cards/a/AminatousAugury.java new file mode 100644 index 00000000000..303954e3aa5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AminatousAugury.java @@ -0,0 +1,253 @@ +package mage.cards.a; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.Costs; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.*; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Optional; +import java.util.UUID; + +/** + * + * @author credman0 + */ +public class AminatousAugury extends CardImpl { + + public AminatousAugury(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{U}{U}"); + + // Exile the top eight cards of your library. You may put a land card from among them onto the battlefield. + // Until end of turn, for each nonland card type, you may cast a card of that type from among the exiled cards + // without paying its mana cost. + this.getSpellAbility().addEffect(new AminatousAuguryEffect()); + } + + public AminatousAugury(final AminatousAugury card) { + super(card); + } + + @Override + public AminatousAugury copy() { + return new AminatousAugury(this); + } + +} + +class AminatousAuguryEffect extends OneShotEffect{ + + public AminatousAuguryEffect() { + super(Outcome.PlayForFree); + staticText = "Exile the top eight cards of your library. You may put a land card from among them onto the" + + " battlefield. Until end of turn, for each nonland card type, you may cast a card of that type from" + + " among the exiled cards without paying its mana cost."; + } + + public AminatousAuguryEffect(final AminatousAuguryEffect effect) { + super(effect); + } + + + @Override + public AminatousAuguryEffect copy() { + return new AminatousAuguryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + // move cards from library to exile + controller.moveCardsToExile(controller.getLibrary().getTopCards(game, 8), source, game, true, source.getSourceId(), CardUtil.createObjectRealtedWindowTitle(source, game, null)); + ExileZone auguryExileZone = game.getExile().getExileZone(source.getSourceId()); + if (auguryExileZone == null) { + return true; + } + Cards cardsToCast = new CardsImpl(); + cardsToCast.addAll(auguryExileZone.getCards(game)); + // put a land card from among them onto the battlefield + TargetCard target = new TargetCard( + Zone.EXILED, + StaticFilters.FILTER_CARD_LAND_A + ); + if (controller.chooseUse(Outcome.PutLandInPlay, "Put a land from among the exiled cards into play?", source, game)) { + if (controller.choose(Outcome.PutLandInPlay, cardsToCast, target, game)) { + Card card = cardsToCast.get(target.getFirstTarget(), game); + if (card != null) { + cardsToCast.remove(card); + controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null); + } + } + } + AminatousAuguryExileHandler exileHandler = new AminatousAuguryExileHandler(cardsToCast, source, game); + for (Card card:cardsToCast.getCards(StaticFilters.FILTER_CARD_NON_LAND,game)) { + AminatousAuguryCastFromExileEffect effect = new AminatousAuguryCastFromExileEffect(card.getCardType(), exileHandler); + effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + game.addEffect(effect, source); + } + } + return false; + } +} + +class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl { + private final AminatousAuguryExileHandler cardTypeHandler; + private final EnumSet cardType; + + public AminatousAuguryCastFromExileEffect(EnumSet cardType, AminatousAuguryExileHandler cardTypeTracker) { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.PlayForFree); + this.cardTypeHandler = cardTypeTracker; + this.cardType = cardType; + staticText = "Cast this card without paying its mana cost"; + } + + public AminatousAuguryCastFromExileEffect(final AminatousAuguryCastFromExileEffect effect) { + super(effect); + this.cardTypeHandler = effect.cardTypeHandler; + this.cardType = effect.cardType; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public AminatousAuguryCastFromExileEffect copy() { + return new AminatousAuguryCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (!cardTypeHandler.atLeastOneAvailable(cardType)){ + return false; + } + if (sourceId != null && sourceId.equals(getTargetPointer().getFirst(game, source)) + && affectedControllerId.equals(source.getControllerId())) { + Card card = game.getCard(sourceId); + if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) { + Player player = game.getPlayer(affectedControllerId); + Costs costs = card.getSpellAbility().getCosts().copy(); + costs.add(new ConsumeCardTypeCost(cardType, cardTypeHandler)); + player.setCastSourceIdWithAlternateMana(sourceId, null, costs); + return true; + } + } + return false; + } +} + + + +/** + * Tracks which card types have already been cast, and provides utility functions for confirming used types. + * (one ExileHandler is shared between all cards from a single cast of Animatou's Augury) + */ +class AminatousAuguryExileHandler { + private final EnumSet usedCardTypes; + + public AminatousAuguryExileHandler(Cards cards, Ability source, Game game){ + usedCardTypes = EnumSet.noneOf(CardType.class); + } + + public EnumSet availableTypes(EnumSet types){ + EnumSet available = EnumSet.copyOf(types); + available.removeAll(usedCardTypes); + return available; + } + + public boolean atLeastOneAvailable(EnumSet types){ + EnumSet available = availableTypes(types); + return !available.isEmpty(); + } + + public boolean useCardType(CardType type){ + if (usedCardTypes.contains(type)){ + return false; + } + usedCardTypes.add(type); + return true; + } + +} + +/** + * Allows the user to choose one of the given card types + */ +class CardTypeChoice extends ChoiceImpl{ + + public CardTypeChoice (EnumSet types){ + super(false); + for (CardType type:types){ + this.choices.add(type+""); + } + this.message = "Choose card type to cast as"; + } +} + +class ConsumeCardTypeCost extends CostImpl{ + + final private AminatousAuguryExileHandler exileHandler; + final private EnumSet types; + + public ConsumeCardTypeCost (EnumSet types, AminatousAuguryExileHandler exileHandler){ + this.exileHandler = exileHandler; + this.types = types; + this.text = "Cast as "+types; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + return exileHandler.atLeastOneAvailable(types); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + if (isPaid()){ + return true; + } + CardType choiceType; + EnumSet availableChoices = exileHandler.availableTypes(types); + if (availableChoices.size()==1){ + // if there is only one possibility, don't need to prompt for a choice + choiceType = availableChoices.iterator().next(); + }else { + Choice choice = new CardTypeChoice(availableChoices); + if (!game.getPlayer(controllerId).choose(Outcome.Neutral, choice, game)) { + return false; + } + Optional optionalChoice = Arrays.stream(CardType.values()).filter(type -> type.toString().equals(choice.getChoice())).findAny(); + if (optionalChoice.isPresent()){ + choiceType = optionalChoice.get(); + }else{ + return false; + } + } + paid = exileHandler.useCardType(choiceType); + return paid; + } + + @Override + public Cost copy() { + return new ConsumeCardTypeCost(types, exileHandler); + } +} + diff --git a/Mage.Sets/src/mage/cards/a/AmuletOfSafekeeping.java b/Mage.Sets/src/mage/cards/a/AmuletOfSafekeeping.java new file mode 100644 index 00000000000..fd9e1c7a399 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AmuletOfSafekeeping.java @@ -0,0 +1,100 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +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.TargetController; +import mage.constants.Zone; +import mage.filter.FilterStackObject; +import mage.filter.StaticFilters; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.StackObject; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class AmuletOfSafekeeping extends CardImpl { + + public AmuletOfSafekeeping(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + // Whenever you become the target of a spell or ability an opponent controls, counter that spell or ability unless its controller pays {1}. + this.addAbility(new AmuletOfSafekeepingTriggeredAbility()); + + // Creature tokens get -1/-0. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostAllEffect( + -1, 0, Duration.WhileOnBattlefield, + StaticFilters.FILTER_CREATURE_TOKENS, false + ) + )); + } + + public AmuletOfSafekeeping(final AmuletOfSafekeeping card) { + super(card); + } + + @Override + public AmuletOfSafekeeping copy() { + return new AmuletOfSafekeeping(this); + } +} + +class AmuletOfSafekeepingTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterStackObject filter = new FilterStackObject(); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public AmuletOfSafekeepingTriggeredAbility() { + super(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new GenericManaCost(1))); + } + + public AmuletOfSafekeepingTriggeredAbility(final AmuletOfSafekeepingTriggeredAbility ability) { + super(ability); + } + + @Override + public AmuletOfSafekeepingTriggeredAbility copy() { + return new AmuletOfSafekeepingTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TARGETED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); + if (event.getTargetId().equals(getControllerId()) + && filter.match(stackObject, getSourceId(), getControllerId(), game)) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(stackObject.getId(), game)); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever you become the target of a spell or ability an opponent controls, " + + "counter that spell or ability unless its controller pays {1}"; + } +} diff --git a/Mage.Sets/src/mage/cards/a/AmuletOfVigor.java b/Mage.Sets/src/mage/cards/a/AmuletOfVigor.java index 046b2b44c55..0915957d35b 100644 --- a/Mage.Sets/src/mage/cards/a/AmuletOfVigor.java +++ b/Mage.Sets/src/mage/cards/a/AmuletOfVigor.java @@ -58,7 +58,7 @@ class AmuletOfVigorTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent p = game.getPermanent(event.getTargetId()); - if (p != null && p.isTapped() && p.getControllerId().equals(this.controllerId)) { + if (p != null && p.isTapped() && p.isControlledBy(this.controllerId)) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); } diff --git a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java index efae604ac2e..f77efb80a82 100644 --- a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java +++ b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -51,12 +51,12 @@ public final class AnaBattlemage extends CardImpl { // When Ana Battlemage enters the battlefield, if it was kicked with its {2}{U} kicker, target player discards three cards. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(3)); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalTriggeredAbility(ability, new KickedCostCondition("{2}{U}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{2}{U}"), "When {this} enters the battlefield, if it was kicked with its {2}{U} kicker, target player discards three cards.")); // When Ana Battlemage enters the battlefield, if it was kicked with its {1}{B} kicker, tap target untapped creature and that creature deals damage equal to its power to its controller. ability = new EntersBattlefieldTriggeredAbility(new AnaBattlemageKickerEffect()); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility(ability, new KickedCostCondition("{1}{B}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{1}{B}"), "When {this} enters the battlefield, if it was kicked with its {1}{B} kicker, tap target untapped creature and that creature deals damage equal to its power to its controller.")); } diff --git a/Mage.Sets/src/mage/cards/a/AnaSanctuary.java b/Mage.Sets/src/mage/cards/a/AnaSanctuary.java index 3580234a44d..6d366638838 100644 --- a/Mage.Sets/src/mage/cards/a/AnaSanctuary.java +++ b/Mage.Sets/src/mage/cards/a/AnaSanctuary.java @@ -4,7 +4,7 @@ package mage.cards.a; import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryTriggeredAbility; +import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -27,7 +27,7 @@ public final class AnaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // At the beginning of your upkeep, if you control a blue or black permanent, target creature gets +1/+1 until end of turn. If you control a blue permanent and a black permanent, that creature gets +5/+5 until end of turn instead. - Ability ability = new SanctuaryTriggeredAbility( + Ability ability = new SanctuaryInterveningIfTriggeredAbility( new BoostEffect(1), new BoostEffect(5), ObjectColor.BLACK, ObjectColor.BLUE, "At the beginning of your upkeep, if you control a blue or black permanent, " + "target creature gets +1/+1 until end of turn. If you control a blue permanent and a black permanent, that creature gets +5/+5 until end of turn instead." diff --git a/Mage.Sets/src/mage/cards/a/AncestorDragon.java b/Mage.Sets/src/mage/cards/a/AncestorDragon.java new file mode 100644 index 00000000000..ffb6f54a8a6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AncestorDragon.java @@ -0,0 +1,76 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class AncestorDragon extends CardImpl { + + public AncestorDragon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); + + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(5); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever one or more creatures you control attack, you gain 1 life for each attacking creature. + this.addAbility(new AttacksWithCreaturesTriggeredAbility(new AncestorDragonEffect(), 1)); + } + + public AncestorDragon(final AncestorDragon card) { + super(card); + } + + @Override + public AncestorDragon copy() { + return new AncestorDragon(this); + } +} + +class AncestorDragonEffect extends OneShotEffect { + + private int attackers; + + public AncestorDragonEffect() { + super(Outcome.GainLife); + staticText = "you gain 1 life for each attacking creature"; + } + + public AncestorDragonEffect(final AncestorDragonEffect effect) { + super(effect); + } + + @Override + public AncestorDragonEffect copy() { + return new AncestorDragonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player you = game.getPlayer(source.getControllerId()); + attackers = game.getCombat().getAttackers().size(); + if (you != null) { + you.gainLife(attackers, game, source); + attackers = 0; + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java b/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java new file mode 100644 index 00000000000..c9935eb2c3c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java @@ -0,0 +1,99 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.constants.SubType; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.TrampleAbility; +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.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.game.Game; +import mage.game.permanent.token.StoneTrapIdolToken; +import mage.util.CardUtil; + +/** + * + * @author TheElk801 + */ +public final class AncientStoneIdol extends CardImpl { + + public AncientStoneIdol(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{10}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(12); + this.toughness = new MageInt(12); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // This spell costs {1} less to cast for each attacking creature. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new AncientStoneIdolCostReductionEffect())); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Ancient Stone Idol dies, create a 6/12 colorless Construct artifact creature token with trample. + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new StoneTrapIdolToken()))); + } + + public AncientStoneIdol(final AncientStoneIdol card) { + super(card); + } + + @Override + public AncientStoneIdol copy() { + return new AncientStoneIdol(this); + } +} + +class AncientStoneIdolCostReductionEffect extends CostModificationEffectImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new AttackingPredicate()); + } + + public AncientStoneIdolCostReductionEffect() { + super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "This spell costs {1} less to cast for each attacking creature"; + } + + protected AncientStoneIdolCostReductionEffect(AncientStoneIdolCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game); + CardUtil.reduceCost(abilityToModify, reductionAmount); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) { + return game.getCard(abilityToModify.getSourceId()) != null; + } + return false; + } + + @Override + public AncientStoneIdolCostReductionEffect copy() { + return new AncientStoneIdolCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AngelOfDeliverance.java b/Mage.Sets/src/mage/cards/a/AngelOfDeliverance.java index 9fd7226ac9c..166342229b6 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfDeliverance.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfDeliverance.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -46,7 +46,7 @@ public final class AngelOfDeliverance extends CardImpl { // Delirium — Whenever Angel of Deliverance deals damage, if there are four or more card types among cards in your graveyard, // exile target creature an opponent controls. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AngelOfDeliveranceDealsDamageTriggeredAbility(), DeliriumCondition.instance, "Delirium — Whenever {this} deals damage, if there are four or more card types among cards in your graveyard, exile target creature an opponent controls" diff --git a/Mage.Sets/src/mage/cards/a/AngelOfTheDawn.java b/Mage.Sets/src/mage/cards/a/AngelOfTheDawn.java new file mode 100644 index 00000000000..9cdbe5093ac --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngelOfTheDawn.java @@ -0,0 +1,55 @@ +package mage.cards.a; + +import java.util.UUID; +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.constants.SubType; +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.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class AngelOfTheDawn extends CardImpl { + + public AngelOfTheDawn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Angel of the Dawn enters the battlefield, creatures you control get +1/+1 and gain vigilance until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility( + new BoostControlledEffect(1, 1, Duration.EndOfTurn) + .setText("creatures you control get +1/+1"), false + ); + ability.addEffect(new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), + Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and gain vigilance until end of turn")); + this.addAbility(ability); + } + + public AngelOfTheDawn(final AngelOfTheDawn card) { + super(card); + } + + @Override + public AngelOfTheDawn copy() { + return new AngelOfTheDawn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java b/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java index b312075ab0b..2b3826169ca 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAllEffect; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlyingAbility; @@ -34,7 +34,7 @@ public final class AngelOfTheDireHour extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // When Angel of the Dire Hour enters the battlefield, if you cast it from your hand, exile all attacking creatures. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), false), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, exile all attacking creatures."), diff --git a/Mage.Sets/src/mage/cards/a/AngelicArbiter.java b/Mage.Sets/src/mage/cards/a/AngelicArbiter.java index 0415e145bf3..75693f80c0f 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicArbiter.java +++ b/Mage.Sets/src/mage/cards/a/AngelicArbiter.java @@ -65,7 +65,7 @@ class AngelicArbiterCantAttackTargetEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - if (game.getActivePlayerId().equals(permanent.getControllerId()) && game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) { + if (game.isActivePlayer(permanent.getControllerId()) && game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) { CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(permanent.getControllerId()) > 0) { return true; @@ -113,7 +113,7 @@ class AngelicArbiterEffect2 extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (game.getActivePlayerId().equals(event.getPlayerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.isActivePlayer(event.getPlayerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { PlayerAttackedWatcher watcher = (PlayerAttackedWatcher) game.getState().getWatchers().get(PlayerAttackedWatcher.class.getSimpleName()); if (watcher != null && watcher.getNumberOfAttackersCurrentTurn(event.getPlayerId()) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/a/AngelicBenediction.java b/Mage.Sets/src/mage/cards/a/AngelicBenediction.java index fdd6db3234a..82717661470 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicBenediction.java +++ b/Mage.Sets/src/mage/cards/a/AngelicBenediction.java @@ -62,7 +62,7 @@ class AngelicBenedictionTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.isActivePlayer(this.controllerId)) { if (game.getCombat().attacksAlone()) { return true; } diff --git a/Mage.Sets/src/mage/cards/a/AngelicChorus.java b/Mage.Sets/src/mage/cards/a/AngelicChorus.java index 077345b9f27..7bf37261066 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicChorus.java +++ b/Mage.Sets/src/mage/cards/a/AngelicChorus.java @@ -58,7 +58,7 @@ class AngelicChorusTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent.isCreature() - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { this.getEffects().get(0).setValue("lifeSource", event.getTargetId()); return true; } diff --git a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java index 9794a5d807c..a35ad846ac8 100644 --- a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java +++ b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java @@ -45,7 +45,7 @@ public final class AngrathMinotaurPirate extends CardImpl { Effects effects1 = new Effects(); effects1.add(new DamageTargetEffect(1)); effects1.add(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()) - .setText("and each creature that player or that planeswalker’s controller controls") + .setText("and each creature that player or that planeswalker's controller controls") ); LoyaltyAbility ability1 = new LoyaltyAbility(effects1, +2); ability1.addTarget(new TargetOpponentOrPlaneswalker()); diff --git a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java index 986e8d695d1..f7291fa1123 100644 --- a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java +++ b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java @@ -11,6 +11,7 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ProtectionAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -18,7 +19,6 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.stack.Spell; import mage.util.CardUtil; /** @@ -84,8 +84,8 @@ class AnimarCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { - Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + if (abilityToModify.isControlledBy(source.getControllerId())) { + Card spell = ((SpellAbility) abilityToModify).getCharacteristics(game); if (spell != null) { return spell.isCreature(); } diff --git a/Mage.Sets/src/mage/cards/a/AnimateDead.java b/Mage.Sets/src/mage/cards/a/AnimateDead.java index 90374b5bc91..c74a187ef30 100644 --- a/Mage.Sets/src/mage/cards/a/AnimateDead.java +++ b/Mage.Sets/src/mage/cards/a/AnimateDead.java @@ -8,7 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; @@ -47,7 +47,7 @@ public final class AnimateDead extends CardImpl { // When Animate Dead enters the battlefield, if it's on the battlefield, it loses "enchant creature card in a graveyard" // and gains "enchant creature put onto the battlefield with Animate Dead." Return enchanted creature card to the battlefield // under your control and attach Animate Dead to it. When Animate Dead leaves the battlefield, that creature's controller sacrifices it. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new AnimateDeadReAttachEffect(), false), SourceOnBattlefieldCondition.instance, "When {this} enters the battlefield, if it's on the battlefield, it loses \"enchant creature card in a graveyard\" and gains \"enchant creature put onto the battlefield with {this}.\" Return enchanted creature card to the battlefield under your control and attach {this} to it."); diff --git a/Mage.Sets/src/mage/cards/a/AnimationModule.java b/Mage.Sets/src/mage/cards/a/AnimationModule.java index 877681d2e02..2263af2ca3c 100644 --- a/Mage.Sets/src/mage/cards/a/AnimationModule.java +++ b/Mage.Sets/src/mage/cards/a/AnimationModule.java @@ -84,7 +84,7 @@ class AnimationModuleTriggeredAbility extends TriggeredAbilityImpl { if (permanent == null) { permanent = game.getPermanentEntering(event.getTargetId()); } - return permanent != null && permanent.getControllerId().equals(this.getControllerId()); + return permanent != null && permanent.isControlledBy(this.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AntiMagicAura.java b/Mage.Sets/src/mage/cards/a/AntiMagicAura.java index 930c78536e4..9b74e2983d5 100644 --- a/Mage.Sets/src/mage/cards/a/AntiMagicAura.java +++ b/Mage.Sets/src/mage/cards/a/AntiMagicAura.java @@ -53,7 +53,7 @@ public final class AntiMagicAura extends CardImpl { } } -// 9/25/2006 ruling: If Consecrate Land enters the battlefield attached to a land that’s enchanted by other Auras, those Auras are put into their owners’ graveyards. +// 9/25/2006 ruling: If Consecrate Land enters the battlefield attached to a land that's enchanted by other Auras, those Auras are put into their owners' graveyards. class AntiMagicAuraRuleEffect extends ContinuousRuleModifyingEffectImpl { public AntiMagicAuraRuleEffect() { diff --git a/Mage.Sets/src/mage/cards/a/ApexOfPower.java b/Mage.Sets/src/mage/cards/a/ApexOfPower.java new file mode 100644 index 00000000000..7cedb5425bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ApexOfPower.java @@ -0,0 +1,142 @@ +package mage.cards.a; + +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.mana.AddManaOfAnyColorEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class ApexOfPower extends CardImpl { + + public ApexOfPower(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{R}{R}{R}"); + + // Exile the top seven cards of your library. Until end of turn, you may cast nonland cards exiled this way. + this.getSpellAbility().addEffect(new ApexOfPowerSpellEffect()); + + // If this spell was cast from your hand, add ten mana of any one color. + this.getSpellAbility().addEffect(new ApexOfPowerManaEffect()); + } + + public ApexOfPower(final ApexOfPower card) { + super(card); + } + + @Override + public ApexOfPower copy() { + return new ApexOfPower(this); + } +} + +class ApexOfPowerSpellEffect extends OneShotEffect { + + public ApexOfPowerSpellEffect() { + super(Outcome.Benefit); + this.staticText = "exile the top seven cards of your library. Until end of turn, you may cast nonland cards exiled this way"; + } + + public ApexOfPowerSpellEffect(final ApexOfPowerSpellEffect effect) { + super(effect); + } + + @Override + public ApexOfPowerSpellEffect copy() { + return new ApexOfPowerSpellEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller == null || sourceObject == null) { + return false; + } + Set cards = controller.getLibrary().getTopCards(game, 7); + if (cards.isEmpty()) { + return false; + } + controller.moveCards(cards, Zone.EXILED, source, game); + for (Card card : cards) { + if (card.isLand()) { + continue; + } + ContinuousEffect effect = new ApexOfPowerCastFromExileEffect(); + effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + game.addEffect(effect, source); + } + return true; + } +} + +class ApexOfPowerCastFromExileEffect extends AsThoughEffectImpl { + + public ApexOfPowerCastFromExileEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + staticText = "You may play the card from exile"; + } + + public ApexOfPowerCastFromExileEffect(final ApexOfPowerCastFromExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public ApexOfPowerCastFromExileEffect copy() { + return new ApexOfPowerCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return source.isControlledBy(affectedControllerId) + && objectId.equals(getTargetPointer().getFirst(game, source)); + } +} + +class ApexOfPowerManaEffect extends OneShotEffect { + + public ApexOfPowerManaEffect() { + super(Outcome.Benefit); + this.staticText = "If this spell was cast from your hand, add ten mana of any one color."; + } + + public ApexOfPowerManaEffect(final ApexOfPowerManaEffect effect) { + super(effect); + } + + @Override + public ApexOfPowerManaEffect copy() { + return new ApexOfPowerManaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell == null || spell.getFromZone() != Zone.HAND) { + return false; + } + return new AddManaOfAnyColorEffect(10).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java b/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java index d11de09b959..db37a8a4433 100644 --- a/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java +++ b/Mage.Sets/src/mage/cards/a/ApocalypseDemon.java @@ -35,7 +35,7 @@ public final class ApocalypseDemon extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // Apocalypse Demon’s power and toughness are each equal to the number of cards in your graveyard. + // Apocalypse Demon's power and toughness are each equal to the number of cards in your graveyard. this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInControllerGraveyardCount(), Duration.EndOfGame))); // At the beginning of your upkeep, tap Apocalypse Demon unless you sacrifice another creature. diff --git a/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java b/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java index 623fa691225..97bf7f87a6b 100644 --- a/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java +++ b/Mage.Sets/src/mage/cards/a/ApothecaryGeist.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class ApothecaryGeist extends CardImpl { // When Apothecary Geist enters the battlefield, if you control another Spirit, you gain 3 life. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new PermanentsOnTheBattlefieldCondition(filter), "When {this} enters the battlefield, if you control another Spirit, you gain 3 life.")); diff --git a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java index 34e1ac83756..1877fee325f 100644 --- a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java +++ b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java @@ -43,7 +43,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect { public ApproachOfTheSecondSunEffect() { super(Outcome.Win); this.staticText - = "If {this} was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. " + = "If this spell was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. " + "Otherwise, put {this} into its owner's library seventh from the top and you gain 7 life."; } diff --git a/Mage.Sets/src/mage/cards/a/AquaticIncursion.java b/Mage.Sets/src/mage/cards/a/AquaticIncursion.java index 9c75b8cf410..15199eb5b8e 100644 --- a/Mage.Sets/src/mage/cards/a/AquaticIncursion.java +++ b/Mage.Sets/src/mage/cards/a/AquaticIncursion.java @@ -37,7 +37,7 @@ public final class AquaticIncursion extends CardImpl { // When Aquatic Incursion enters the battlefield, create two 1/1 blue Merfolk creature tokens with hexproof. this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MerfolkHexproofToken(), 2), false)); - // {3}{U}: Target Merfolk can’t be blocked this turn. + // {3}{U}: Target Merfolk can't be blocked this turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedTargetEffect(Duration.EndOfTurn), new ManaCostsImpl("{3}{U}")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java b/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java index 1d7ce04018a..9eb4e17736c 100644 --- a/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java +++ b/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java @@ -7,7 +7,7 @@ import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldOrCommandZoneCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DoIfCostPaid; @@ -56,7 +56,7 @@ public final class ArahboRoarOfTheWorld extends CardImpl { this.toughness = new MageInt(5); // Eminence — At the beginning of combat on your turn, if Arahbo, Roar of the World is in the command zone or on the battlefield, another target Cat you control gets +3/+3 until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfCombatTriggeredAbility(Zone.ALL, new BoostTargetEffect(3, 3, Duration.EndOfTurn), TargetController.YOU, false, false), SourceOnBattlefieldOrCommandZoneCondition.instance, "Eminence — At the beginning of combat on your turn, if Arahbo, Roar of the World is in the command zone or on the battlefield, another target Cat you control gets +3/+3 until end of turn."); diff --git a/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java b/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java new file mode 100644 index 00000000000..028bc5bfcab --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java @@ -0,0 +1,117 @@ +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.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.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; + +/** + * + * @author TheElk801 + */ +public final class ArcadesTheStrategist extends CardImpl { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("creature with defender"); + + static { + filter.add(new AbilityPredicate(DefenderAbility.class)); + } + + public ArcadesTheStrategist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever a creature with defender enters the battlefield under your control, draw a card. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter + )); + + // 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.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) { + super(card); + } + + @Override + public ArcadesTheStrategist copy() { + 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/ArcaneAdaptation.java b/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java index 12a962afb6f..0a0d05fd249 100644 --- a/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java +++ b/Mage.Sets/src/mage/cards/a/ArcaneAdaptation.java @@ -89,7 +89,7 @@ class ConspyEffect extends ContinuousEffectImpl { } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { - if (card.getOwnerId().equals(controller.getId()) && card.isCreature() && !card.hasSubtype(subType, game)) { + if (card.isOwnedBy(controller.getId()) && card.isCreature() && !card.hasSubtype(subType, game)) { game.getState().getCreateCardAttribute(card, game).getSubtype().add(subType); } } @@ -106,7 +106,7 @@ class ConspyEffect extends ContinuousEffectImpl { for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { StackObject stackObject = iterator.next(); if (stackObject instanceof Spell - && stackObject.getControllerId().equals(source.getControllerId()) + && stackObject.isControlledBy(source.getControllerId()) && stackObject.isCreature() && !stackObject.hasSubtype(subType, game)) { Card card = ((Spell) stackObject).getCard(); diff --git a/Mage.Sets/src/mage/cards/a/ArcaneEncyclopedia.java b/Mage.Sets/src/mage/cards/a/ArcaneEncyclopedia.java new file mode 100644 index 00000000000..8ec4b26eae8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArcaneEncyclopedia.java @@ -0,0 +1,41 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class ArcaneEncyclopedia extends CardImpl { + + public ArcaneEncyclopedia(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {3}, {T}: Draw a card. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(1), + new GenericManaCost(3) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public ArcaneEncyclopedia(final ArcaneEncyclopedia card) { + super(card); + } + + @Override + public ArcaneEncyclopedia copy() { + return new ArcaneEncyclopedia(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArchangelOfThune.java b/Mage.Sets/src/mage/cards/a/ArchangelOfThune.java index 7387ec98c32..c3f1bd3d29d 100644 --- a/Mage.Sets/src/mage/cards/a/ArchangelOfThune.java +++ b/Mage.Sets/src/mage/cards/a/ArchangelOfThune.java @@ -1,9 +1,8 @@ - package mage.cards.a; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.GainLifeControllerTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; @@ -11,12 +10,8 @@ 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.filter.common.FilterControlledCreaturePermanent; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; +import mage.filter.StaticFilters; /** * @@ -25,7 +20,7 @@ import mage.game.events.GameEvent.EventType; public final class ArchangelOfThune extends CardImpl { public ArchangelOfThune(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.ANGEL); this.power = new MageInt(3); @@ -33,11 +28,17 @@ public final class ArchangelOfThune extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Lifelink this.addAbility(LifelinkAbility.getInstance()); + // Whenever you gain life, put a +1/+1 counter on each creature you control. - this.addAbility(new ArchangelOfThuneAbility()); - + this.addAbility(new GainLifeControllerTriggeredAbility( + new AddCountersAllEffect( + CounterType.P1P1.createInstance(), + StaticFilters.FILTER_CONTROLLED_CREATURES + ), false + )); } public ArchangelOfThune(final ArchangelOfThune card) { @@ -49,35 +50,3 @@ public final class ArchangelOfThune extends CardImpl { return new ArchangelOfThune(this); } } - -class ArchangelOfThuneAbility extends TriggeredAbilityImpl { - - public ArchangelOfThuneAbility() { - super(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent()), false); - } - - public ArchangelOfThuneAbility(final ArchangelOfThuneAbility ability) { - super(ability); - } - - @Override - public ArchangelOfThuneAbility copy() { - return new ArchangelOfThuneAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.GAINED_LIFE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(controllerId); - } - - @Override - public String getRule() { - return "Whenever you gain life, put a +1/+1 counter on each creature you control."; - } - -} diff --git a/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java b/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java index dc0327fd01d..4d5bc436e43 100644 --- a/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java +++ b/Mage.Sets/src/mage/cards/a/ArchfiendOfDespair.java @@ -64,7 +64,7 @@ class ArchfiendOfDespairEffect extends OneShotEffect { public ArchfiendOfDespairEffect() { super(Outcome.LoseLife); - this.staticText = "each opponent loses life equal to the life he or she lost this turn"; + this.staticText = "each opponent loses life equal to the life that player lost this turn"; } public ArchfiendOfDespairEffect(final ArchfiendOfDespairEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java b/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java index 1386b5e8b2f..4107f3f9901 100644 --- a/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java +++ b/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java @@ -66,7 +66,7 @@ class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.getControllerId().equals(getControllerId()) + if (permanent.isControlledBy(getControllerId()) && permanent.isCreature() && (permanent.getId().equals(getSourceId()) || (permanent.getAbilities().contains(FlyingAbility.getInstance())))) { diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java b/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java index a205ddff478..ffc743472c6 100644 --- a/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java +++ b/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java @@ -34,7 +34,7 @@ import mage.util.CardUtil; public final class ArchonOfValorsReach extends CardImpl { public ArchonOfValorsReach(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{W}"); this.subtype.add(SubType.ARCHON); this.power = new MageInt(5); @@ -133,7 +133,7 @@ class ArchonOfValorsReachChoice extends ChoiceImpl { return CardType.INSTANT; case "Sorcery": return CardType.SORCERY; - case "Planewswalker": + case "Planeswalker": return CardType.PLANESWALKER; default: return null; diff --git a/Mage.Sets/src/mage/cards/a/ArgentSphinx.java b/Mage.Sets/src/mage/cards/a/ArgentSphinx.java index e3c98324de0..7f76777b23d 100644 --- a/Mage.Sets/src/mage/cards/a/ArgentSphinx.java +++ b/Mage.Sets/src/mage/cards/a/ArgentSphinx.java @@ -36,7 +36,7 @@ public final class ArgentSphinx extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // Metalcraft - {U}: Exile Argent Sphinx. Return it to the battlefield under your control at the beginning of the next end step. Activate this ability only if you control three or more artifacts. + // Metalcraft — {U}: Exile Argent Sphinx. Return it to the battlefield under your control at the beginning of the next end step. Activate this ability only if you control three or more artifacts. Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ArgentSphinxEffect(), new ManaCostsImpl("{U}"), MetalcraftCondition.instance); ability.setAbilityWord(AbilityWord.METALCRAFT); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java b/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java index c8ff49c1068..89be4d3219a 100644 --- a/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java +++ b/Mage.Sets/src/mage/cards/a/ArguelsBloodFast.java @@ -8,7 +8,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.FatefulHourCondition; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -40,7 +40,7 @@ public final class ArguelsBloodFast extends CardImpl { // At the beginning of your upkeep, if you have 5 or less life, you may transform Arguel's Blood Fast. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, true), FatefulHourCondition.instance, "At the beginning of your upkeep, if you have 5 or less life, you may transform {this}" diff --git a/Mage.Sets/src/mage/cards/a/ArisenGorgon.java b/Mage.Sets/src/mage/cards/a/ArisenGorgon.java new file mode 100644 index 00000000000..e56a9ff7dd4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArisenGorgon.java @@ -0,0 +1,60 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +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.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +/** + * + * @author TheElk801 + */ +public final class ArisenGorgon extends CardImpl { + + private static final FilterControlledPlaneswalkerPermanent filter + = new FilterControlledPlaneswalkerPermanent( + SubType.LILIANA, + "a Liliana planeswalker" + ); + + public ArisenGorgon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.subtype.add(SubType.GORGON); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Arisen Gorgon has deathtouch as long as you control a Liliana planeswalker. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + DeathtouchAbility.getInstance(), + Duration.WhileOnBattlefield + ), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} has deathtouch as long as you control a Liliana planeswalker" + ) + )); + } + + public ArisenGorgon(final ArisenGorgon card) { + super(card); + } + + @Override + public ArisenGorgon copy() { + return new ArisenGorgon(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java new file mode 100644 index 00000000000..3c6578b392a --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java @@ -0,0 +1,121 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +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 static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterSpell; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author spjspj + */ +public final class ArixmethesSlumberingIsle extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("a spell"); + + public ArixmethesSlumberingIsle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); + + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.KRAKEN); + this.power = new MageInt(12); + this.toughness = new MageInt(12); + + // Arixmethes, Slumbering Isle enters the battlefield tapped with five slumber counters on it. + this.addAbility(new EntersBattlefieldTappedAbility()); + Effect effect = new AddCountersSourceEffect(CounterType.SLUMBER.createInstance(5)); + this.addAbility(new EntersBattlefieldAbility(effect, "with five slumber counters")); + + // As long as Arixmethes, Slumbering Isle has a slumber counter on it, it's a land. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new ArixmethesIsLandEffect(), + new SourceHasCounterCondition(CounterType.SLUMBER, 1, Integer.MAX_VALUE), + "As long as {this} has a slumber counter on it, it's a land"))); + + // Whenever you cast a spell, you may remove a slumber counter from Arixmethes. + this.addAbility(new SpellCastControllerTriggeredAbility(new RemoveCounterSourceEffect(CounterType.SLUMBER.createInstance(1)), true)); + + // {T}: Add {G}{U}. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new Mana(0, 1, 1, 0, 0, 0, 0, 0), new TapSourceCost())); + } + + public ArixmethesSlumberingIsle(final ArixmethesSlumberingIsle card) { + super(card); + } + + @Override + public ArixmethesSlumberingIsle copy() { + return new ArixmethesSlumberingIsle(this); + } +} + +class ArixmethesIsLandEffect extends ContinuousEffectImpl { + + public ArixmethesIsLandEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + this.staticText = "As long as {this} has a slumber counter on it, it's a land"; + } + + public ArixmethesIsLandEffect(final ArixmethesIsLandEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public ArixmethesIsLandEffect copy() { + return new ArixmethesIsLandEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + permanent.getCardType().clear(); + permanent.addCardType(CardType.LAND); + permanent.getSubtype(game).clear(); + break; + } + return true; + } + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArmoredWhirlTurtle.java b/Mage.Sets/src/mage/cards/a/ArmoredWhirlTurtle.java new file mode 100644 index 00000000000..d42ca3b4379 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArmoredWhirlTurtle.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 ArmoredWhirlTurtle extends CardImpl { + + public ArmoredWhirlTurtle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.TURTLE); + this.power = new MageInt(0); + this.toughness = new MageInt(5); + } + + public ArmoredWhirlTurtle(final ArmoredWhirlTurtle card) { + super(card); + } + + @Override + public ArmoredWhirlTurtle copy() { + return new ArmoredWhirlTurtle(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArtifactPossession.java b/Mage.Sets/src/mage/cards/a/ArtifactPossession.java index 8725c3e1042..5cd51f52b09 100644 --- a/Mage.Sets/src/mage/cards/a/ArtifactPossession.java +++ b/Mage.Sets/src/mage/cards/a/ArtifactPossession.java @@ -74,7 +74,7 @@ class AbilityActivatedTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent aura = game.getPermanent(this.getSourceId()); - return aura != null && aura.getAttachedTo() != null && aura.getAttachedTo().equals(event.getSourceId()); + return aura != null && aura.isAttachedTo(event.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java b/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java index fb83369e994..ac415c84391 100644 --- a/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java +++ b/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java @@ -32,9 +32,9 @@ public final class ArtisanOfForms extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // Heroic — Whenever you cast a spell that targets Artisan of Forms, you may have Artisan of Forms become a copy of target creature and gain this ability. + // Heroic — Whenever you cast a spell that targets Artisan of Forms, you may have Artisan of Forms become a copy of target creature, except it has this ability. Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new ArtisanOfFormsApplyToPermanent(), true); - effect.setText("have {this} become a copy of target creature and gain this ability"); + effect.setText("have {this} become a copy of target creature, except it has this ability"); Ability ability = new HeroicAbility(effect, true); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); @@ -55,7 +55,7 @@ class ArtisanOfFormsApplyToPermanent extends ApplyToPermanent { @Override public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { Effect effect = new CopyPermanentEffect(new ArtisanOfFormsApplyToPermanent()); - effect.setText("have {this} become a copy of target creature and gain this ability"); + effect.setText("have {this} become a copy of target creature, except it has this ability"); mageObject.getAbilities().add(new HeroicAbility(effect, true)); return true; } @@ -63,7 +63,7 @@ class ArtisanOfFormsApplyToPermanent extends ApplyToPermanent { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { Effect effect = new CopyPermanentEffect(new ArtisanOfFormsApplyToPermanent()); - effect.setText("have {this} become a copy of target creature and gain this ability"); + effect.setText("have {this} become a copy of target creature, except it has this ability"); permanent.addAbility(new HeroicAbility(effect, true), game); return true; } diff --git a/Mage.Sets/src/mage/cards/a/AsLuckWouldHaveIt.java b/Mage.Sets/src/mage/cards/a/AsLuckWouldHaveIt.java index 83adf2f33fc..d24d1a4de07 100644 --- a/Mage.Sets/src/mage/cards/a/AsLuckWouldHaveIt.java +++ b/Mage.Sets/src/mage/cards/a/AsLuckWouldHaveIt.java @@ -68,7 +68,7 @@ class AsLuckWouldHaveItTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + if (this.isControlledBy(event.getPlayerId()) && event.getFlag()) { for (Effect effect : this.getEffects()) { effect.setValue("rolled", event.getAmount()); } diff --git a/Mage.Sets/src/mage/cards/a/AsajjVentress.java b/Mage.Sets/src/mage/cards/a/AsajjVentress.java index d93d1aacdfc..3e2aa60f81b 100644 --- a/Mage.Sets/src/mage/cards/a/AsajjVentress.java +++ b/Mage.Sets/src/mage/cards/a/AsajjVentress.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.BecomesBlockedTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.BlockedCreatureCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.BlocksIfAbleTargetEffect; @@ -45,7 +45,7 @@ public final class AsajjVentress extends CardImpl { this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); // Hate — Whenever Asajj Ventress attacks, if an opponent lost life from a source other than combat damage this turn, target creature blocks this turn if able. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new BlocksIfAbleTargetEffect(Duration.EndOfTurn), false), HateCondition.instance, "Hate — Whenever Asajj Ventress attacks, if an opponent lost life from a source other than combat damage this turn, target creature blocks this turn if able"); diff --git a/Mage.Sets/src/mage/cards/a/AshenGhoul.java b/Mage.Sets/src/mage/cards/a/AshenGhoul.java index 7b8b0d3f81e..b5ed0e24d78 100644 --- a/Mage.Sets/src/mage/cards/a/AshenGhoul.java +++ b/Mage.Sets/src/mage/cards/a/AshenGhoul.java @@ -61,8 +61,8 @@ enum AshenGhoulCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (!game.getStep().getType().equals(PhaseStep.UPKEEP) - || !game.getActivePlayerId().equals(source.getControllerId())) { + if (game.getStep().getType() != PhaseStep.UPKEEP + || !game.isActivePlayer(source.getControllerId())) { return false; } if (controller != null) { diff --git a/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java b/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java index 0cd79b5ec8c..70eb75951fa 100644 --- a/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java +++ b/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -27,7 +26,7 @@ import mage.target.common.TargetCreaturePermanent; public final class AshlingTheExtinguisher extends CardImpl { public AshlingTheExtinguisher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.SHAMAN); @@ -89,6 +88,6 @@ class AshlingTheExtinguisherTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, choose target creature that player controls. He or she sacrifices that creature."; + return "Whenever {this} deals combat damage to a player, choose target creature that player controls. The player sacrifices that creature."; } } diff --git a/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java b/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java index 8f8ac3242bf..60cb57bd4f0 100644 --- a/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java +++ b/Mage.Sets/src/mage/cards/a/AsmiraHolyAvenger.java @@ -78,7 +78,7 @@ class AsmiraHolyAvengerWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { MageObject card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (card != null && ((Card) card).getOwnerId().equals(this.controllerId) && card.isCreature()) { + if (card != null && ((Card) card).isOwnedBy(this.controllerId) && card.isCreature()) { creaturesCount++; } } diff --git a/Mage.Sets/src/mage/cards/a/AssassinsBlade.java b/Mage.Sets/src/mage/cards/a/AssassinsBlade.java index 407feee5bbf..fe2b98e641a 100644 --- a/Mage.Sets/src/mage/cards/a/AssassinsBlade.java +++ b/Mage.Sets/src/mage/cards/a/AssassinsBlade.java @@ -38,7 +38,7 @@ public final class AssassinsBlade extends CardImpl { // Cast Assassin's Blade only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AssaultSuit.java b/Mage.Sets/src/mage/cards/a/AssaultSuit.java index 34afdccb516..ac21d9ab6b4 100644 --- a/Mage.Sets/src/mage/cards/a/AssaultSuit.java +++ b/Mage.Sets/src/mage/cards/a/AssaultSuit.java @@ -95,8 +95,8 @@ public final class AssaultSuit extends CardImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT) { Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - return equipment.getAttachedTo().equals(event.getTargetId()); + if (equipment != null) { + return equipment.isAttachedTo(event.getTargetId()); } } return false; diff --git a/Mage.Sets/src/mage/cards/a/AssemblyHall.java b/Mage.Sets/src/mage/cards/a/AssemblyHall.java new file mode 100644 index 00000000000..a495718139e --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AssemblyHall.java @@ -0,0 +1,92 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author TheElk801 + */ +public final class AssemblyHall extends CardImpl { + + public AssemblyHall(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); + + // {4}, {tap}: Reveal a creature card in your hand. Search your library for a card with the same name as that card, reveal it, and put it into your hand. Then shuffle your library. + Ability ability = new SimpleActivatedAbility(new AssemblyHallEffect(), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public AssemblyHall(final AssemblyHall card) { + super(card); + } + + @Override + public AssemblyHall copy() { + return new AssemblyHall(this); + } +} + +class AssemblyHallEffect extends OneShotEffect { + + public AssemblyHallEffect() { + super(Outcome.Benefit); + this.staticText = "reveal a creature card from your hand. " + + "Search your library for a card with the same name as that card, " + + "reveal it, and put it into your hand. Then shuffle your library"; + } + + public AssemblyHallEffect(final AssemblyHallEffect effect) { + super(effect); + } + + @Override + public AssemblyHallEffect copy() { + return new AssemblyHallEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || controller.getHand().isEmpty() || sourceObject == null) { + return false; + } + Card cardToReveal = null; + Target target = new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE); + target.setNotTarget(true); + if (controller.chooseTarget(outcome, target, source, game)) { + cardToReveal = game.getCard(target.getFirstTarget()); + } + if (cardToReveal == null) { + return false; + } + controller.revealCards("from hand :" + sourceObject.getName(), new CardsImpl(cardToReveal), game); + String nameToSearch = cardToReveal.isSplitCard() ? ((SplitCard) cardToReveal).getLeftHalfCard().getName() : cardToReveal.getName(); + FilterCard filterCard = new FilterCard("card named " + nameToSearch); + filterCard.add(new NamePredicate(nameToSearch)); + return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true, true).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AstromechDroid.java b/Mage.Sets/src/mage/cards/a/AstromechDroid.java new file mode 100644 index 00000000000..492a15aa259 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AstromechDroid.java @@ -0,0 +1,63 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.RepairAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.constants.Duration; +import mage.constants.SubType; +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.mageobject.SubtypePredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class AstromechDroid extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("starship creature"); + + static { + filter.add(new SubtypePredicate(SubType.STARSHIP)); + } + + public AstromechDroid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.DROID); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // {T}: Target starship creature you control gets +1/+1 and gains vigilance until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new BoostTargetEffect(1, 1, Duration.EndOfTurn) + .setText("Target starship creature you control gets +1/+1"), + new TapSourceCost()); + ability.addEffect(new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn) + .setText("and gains vigilance until end of turn")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + + // Repair 4 + this.addAbility(new RepairAbility(4)); + } + + public AstromechDroid(final AstromechDroid card) { + super(card); + } + + @Override + public AstromechDroid copy() { + return new AstromechDroid(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AsylumVisitor.java b/Mage.Sets/src/mage/cards/a/AsylumVisitor.java index c7b7031a53f..bf7ea122ece 100644 --- a/Mage.Sets/src/mage/cards/a/AsylumVisitor.java +++ b/Mage.Sets/src/mage/cards/a/AsylumVisitor.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; @@ -33,7 +33,7 @@ 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 ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.ANY, false), + Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), 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); diff --git a/Mage.Sets/src/mage/cards/a/AuriokEdgewright.java b/Mage.Sets/src/mage/cards/a/AuriokEdgewright.java index f4d24b54469..a38161a38a5 100644 --- a/Mage.Sets/src/mage/cards/a/AuriokEdgewright.java +++ b/Mage.Sets/src/mage/cards/a/AuriokEdgewright.java @@ -22,7 +22,7 @@ import mage.constants.Zone; */ public final class AuriokEdgewright extends CardImpl { - protected static String effectText = "Metalcraft - Auriok Edgewright has double strike as long as you control three or more artifacts."; + protected static String effectText = "Metalcraft — Auriok Edgewright has double strike as long as you control three or more artifacts."; public AuriokEdgewright(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{W}"); diff --git a/Mage.Sets/src/mage/cards/a/AuriokSunchaser.java b/Mage.Sets/src/mage/cards/a/AuriokSunchaser.java index 6d071200ba8..249c912b492 100644 --- a/Mage.Sets/src/mage/cards/a/AuriokSunchaser.java +++ b/Mage.Sets/src/mage/cards/a/AuriokSunchaser.java @@ -23,8 +23,8 @@ import mage.constants.Zone; */ public final class AuriokSunchaser extends CardImpl { - protected static String effect1Text = "Metalcraft - As long as you control three or more artifacts, Auriok Sunchaser gets +2/+2"; - protected static String effect2Text = "Metalcraft - As long as you control three or more artifacts, Auriok Sunchaser has flying"; + protected static String effect1Text = "Metalcraft — As long as you control three or more artifacts, Auriok Sunchaser gets +2/+2"; + protected static String effect2Text = "Metalcraft — As long as you control three or more artifacts, Auriok Sunchaser has flying"; public AuriokSunchaser(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}"); diff --git a/Mage.Sets/src/mage/cards/a/AuroraChampion.java b/Mage.Sets/src/mage/cards/a/AuroraChampion.java index 6e851079e03..365bb5f82ec 100644 --- a/Mage.Sets/src/mage/cards/a/AuroraChampion.java +++ b/Mage.Sets/src/mage/cards/a/AuroraChampion.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class AuroraChampion extends CardImpl { this.toughness = new MageInt(2); // Whenever Aurora Champion attacks, if your team controls another Warrior, tap target creature. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new TapTargetEffect(), false), new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks, if your team controls another Warrior, tap target creature." diff --git a/Mage.Sets/src/mage/cards/a/AvariceAmulet.java b/Mage.Sets/src/mage/cards/a/AvariceAmulet.java index cf772fe3ff1..70aec2e44e9 100644 --- a/Mage.Sets/src/mage/cards/a/AvariceAmulet.java +++ b/Mage.Sets/src/mage/cards/a/AvariceAmulet.java @@ -45,7 +45,7 @@ public final class AvariceAmulet extends CardImpl { ability.addEffect(effect); this.addAbility(ability); - // When equipped creature dies, target opponent gains control of Avarice Amulet. + // Whenever equipped creature dies, target opponent gains control of Avarice Amulet. ability = new DiesAttachedTriggeredAbility(new AvariceAmuletChangeControlEffect(), "equipped creature", false); ability.addTarget(new TargetOpponent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AvenWindMage.java b/Mage.Sets/src/mage/cards/a/AvenWindMage.java new file mode 100644 index 00000000000..a5637dc93dc --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AvenWindMage.java @@ -0,0 +1,48 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class AvenWindMage extends CardImpl { + + public AvenWindMage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you cast an instant or sorcery spell, Aven Wind Mage gets +1/+1 until end of turn. + this.addAbility(new SpellCastControllerTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false + )); + } + + public AvenWindMage(final AvenWindMage card) { + super(card); + } + + @Override + public AvenWindMage copy() { + return new AvenWindMage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AviationPioneer.java b/Mage.Sets/src/mage/cards/a/AviationPioneer.java new file mode 100644 index 00000000000..7153d0c614e --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AviationPioneer.java @@ -0,0 +1,41 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.ThopterColorlessToken; + +/** + * + * @author TheElk801 + */ +public final class AviationPioneer extends CardImpl { + + public AviationPioneer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // When Aviation Pioneer enters the battlefield, create a 1/1 colorless Thopter creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new ThopterColorlessToken()) + )); + } + + public AviationPioneer(final AviationPioneer card) { + super(card); + } + + @Override + public AviationPioneer copy() { + return new AviationPioneer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java b/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java index 6703c451082..cf8165cc371 100644 --- a/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java +++ b/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterAbility; +import mage.filter.FilterStackObject; import mage.filter.predicate.ability.ArtifactSourcePredicate; import mage.target.common.TargetActivatedAbility; @@ -25,7 +26,7 @@ import mage.target.common.TargetActivatedAbility; */ public final class AyeshaTanaka extends CardImpl { - private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source"); + private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source"); static { filter.add(new ArtifactSourcePredicate()); diff --git a/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java b/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java index 0a7e1d40360..0933ac1fa1d 100644 --- a/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java +++ b/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java @@ -42,7 +42,7 @@ public final class AzorTheLawbringer extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // When Azor, the Lawbringer enters the battlefield, each opponent can’t cast instant or sorcery spells during that player’s next turn. + // When Azor, the Lawbringer enters the battlefield, each opponent can't cast instant or sorcery spells during that player's next turn. this.addAbility(new EntersBattlefieldTriggeredAbility(new AzorTheLawbringerEntersBattlefieldEffect(), false)); // Whenever Azor attacks, you may pay {X}{W}{U}{U}. If you do, you gain X life and draw X cards. @@ -123,7 +123,7 @@ class AzorTheLawbringerCantCastEffect extends ContinuousRuleModifyingEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { UUID opponentId = getTargetPointer().getFirst(game, source); - if (game.getActivePlayerId().equals(opponentId)) { + if (game.isActivePlayer(opponentId)) { if (playersNextTurn == 0) { playersNextTurn = game.getTurnNum(); } diff --git a/Mage.Sets/src/mage/cards/a/AzoriusPloy.java b/Mage.Sets/src/mage/cards/a/AzoriusPloy.java new file mode 100644 index 00000000000..c7e1c996d58 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AzoriusPloy.java @@ -0,0 +1,57 @@ +package mage.cards.a; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.AbilityImpl; +import mage.abilities.SpellAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventCombatDamageBySourceEffect; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +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.filter.common.FilterCreaturePermanent; +import mage.target.Target; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +/** + * + * @author noahg + */ +public final class AzoriusPloy extends CardImpl { + + public AzoriusPloy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}{W}{U}"); + + + // Prevent all combat damage 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."); + this.getSpellAbility().addEffect(effect); + Target target = new TargetCreaturePermanent(new FilterCreaturePermanent("first creature")); + this.getSpellAbility().addTarget(target); + + // Prevent all combat damage that would be dealt to target creature this turn. + Effect effect2 = new PreventDamageToTargetEffect(Duration.EndOfTurn, true); + effect2.setText("

Prevent all combat damage that would be dealt to target creature this turn."); + effect2.setTargetPointer(SecondTargetPointer.getInstance()); + this.getSpellAbility().addEffect(effect2); + target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)")); + this.getSpellAbility().addTarget(target); + + } + + public AzoriusPloy(final AzoriusPloy card) { + super(card); + } + + @Override + public AzoriusPloy copy() { + return new AzoriusPloy(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AzraOddsmaker.java b/Mage.Sets/src/mage/cards/a/AzraOddsmaker.java index b1695d18920..92a358a7ff4 100644 --- a/Mage.Sets/src/mage/cards/a/AzraOddsmaker.java +++ b/Mage.Sets/src/mage/cards/a/AzraOddsmaker.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -7,9 +6,9 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.BeginningOfCombatTriggeredAbility; -import mage.abilities.costs.Cost; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -18,9 +17,8 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.TargetController; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; @@ -41,7 +39,12 @@ public final class AzraOddsmaker extends CardImpl { this.toughness = new MageInt(3); // At the beginning of combat on your turn, you may discard a card. If you do, choose a creature. Whenever that creature deals combat damage to a player this turn, you draw two cards. - this.addAbility(new BeginningOfCombatTriggeredAbility(new AzraOddsmakerEffect(), TargetController.YOU, true)); + this.addAbility(new BeginningOfCombatTriggeredAbility( + new DoIfCostPaid( + new AzraOddsmakerEffect(), + new DiscardCardCost() + ), TargetController.YOU, false + )); } public AzraOddsmaker(final AzraOddsmaker card) { @@ -56,12 +59,12 @@ public final class AzraOddsmaker extends CardImpl { class AzraOddsmakerEffect extends OneShotEffect { - AzraOddsmakerEffect() { + public AzraOddsmakerEffect() { super(Outcome.Benefit); - this.staticText = "discard a card. If you do, choose a creature. Whenever that creature deals combat damage to a player this turn, you draw two cards"; + this.staticText = "choose a creature. Whenever that creature deals combat damage to a player this turn, you draw two cards"; } - AzraOddsmakerEffect(final AzraOddsmakerEffect effect) { + public AzraOddsmakerEffect(final AzraOddsmakerEffect effect) { super(effect); } @@ -76,40 +79,37 @@ class AzraOddsmakerEffect extends OneShotEffect { if (player == null) { return false; } - Cost cost = new DiscardCardCost(); Permanent permanent = null; - if (cost.canPay(source, source.getSourceId(), source.getControllerId(), game) - && cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) { - TargetCreaturePermanent target = new TargetCreaturePermanent(); - target.setNotTarget(true); - if (player.choose(Outcome.DrawCard, target, source.getSourceId(), game)) { - permanent = game.getPermanent(target.getFirstTarget()); - } + TargetCreaturePermanent target = new TargetCreaturePermanent(); + target.setNotTarget(true); + if (player.choose(Outcome.DrawCard, target, source.getSourceId(), game)) { + permanent = game.getPermanent(target.getFirstTarget()); } if (permanent == null) { return false; } - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new MageObjectReferencePredicate(new MageObjectReference(permanent, game))); - game.addDelayedTriggeredAbility(new AzraOddsmakerDelayedTriggeredAbility(filter, permanent.getName()), source); + game.addDelayedTriggeredAbility(new AzraOddsmakerDelayedTriggeredAbility( + new MageObjectReference(permanent, game), + permanent.getName() + ), source); return true; } } class AzraOddsmakerDelayedTriggeredAbility extends DelayedTriggeredAbility { - private final FilterCreaturePermanent filter; + private final MageObjectReference mor; private final String creatureName; - AzraOddsmakerDelayedTriggeredAbility(FilterCreaturePermanent filter, String creatureName) { - super(new DrawCardSourceControllerEffect(2), Duration.EndOfTurn, false); - this.filter = filter; + public AzraOddsmakerDelayedTriggeredAbility(MageObjectReference mor, String creatureName) { + super(new DrawCardSourceControllerEffect(2), Duration.EndOfTurn, false, false); + this.mor = mor; this.creatureName = creatureName; } - AzraOddsmakerDelayedTriggeredAbility(final AzraOddsmakerDelayedTriggeredAbility ability) { + public AzraOddsmakerDelayedTriggeredAbility(final AzraOddsmakerDelayedTriggeredAbility ability) { super(ability); - this.filter = ability.filter; + this.mor = ability.mor; this.creatureName = ability.creatureName; } @@ -125,17 +125,15 @@ class AzraOddsmakerDelayedTriggeredAbility extends DelayedTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getFlag()) { - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && filter.match(permanent, game)) { - return true; - } + if (((DamagedPlayerEvent) event).isCombatDamage()) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); + return mor.refersTo(permanent, game); } return false; } @Override public String getRule() { - return "Whenever " + creatureName + " deals damage to a player this turn, you draw two cards"; + return "Whenever " + creatureName + " deals combat damage to a player this turn, you draw two cards"; } } diff --git a/Mage.Sets/src/mage/cards/b/BalanWanderingKnight.java b/Mage.Sets/src/mage/cards/b/BalanWanderingKnight.java index 6b80f1088fd..98a1d0978ed 100644 --- a/Mage.Sets/src/mage/cards/b/BalanWanderingKnight.java +++ b/Mage.Sets/src/mage/cards/b/BalanWanderingKnight.java @@ -84,7 +84,7 @@ public final class BalanWanderingKnight extends CardImpl { filter.add(new SubtypePredicate(SubType.EQUIPMENT)); for (Permanent equipment : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(),game)) { if (equipment != null) { - //If an Equipment can’t equip, it isn’t attached, and it doesn’t become unattached (if it’s attached to a creature). + //If an Equipment can't equip, it isn't attached, and it doesn't become unattached (if it's attached to a creature). if (!balan.cantBeAttachedBy(equipment, game)) { balan.addAttachment(equipment.getId(), game); } diff --git a/Mage.Sets/src/mage/cards/b/Balance.java b/Mage.Sets/src/mage/cards/b/Balance.java index f89d8499531..279a020a109 100644 --- a/Mage.Sets/src/mage/cards/b/Balance.java +++ b/Mage.Sets/src/mage/cards/b/Balance.java @@ -1,4 +1,3 @@ - package mage.cards.b; import mage.abilities.Ability; @@ -26,7 +25,7 @@ import java.util.UUID; public final class Balance extends CardImpl { public Balance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}"); // Each player chooses a number of lands he or she controls equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players discard cards and sacrifice creatures the same way. this.getSpellAbility().addEffect(new BalanceEffect()); @@ -46,7 +45,10 @@ class BalanceEffect extends OneShotEffect { BalanceEffect() { super(Outcome.Sacrifice); - staticText = "Each player chooses a number of lands he or she controls equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players sacrifice creatures and discard cards the same way"; + staticText = "each player chooses a number of lands they control " + + "equal to the number of lands controlled by the player " + + "who controls the fewest, then sacrifices the rest. " + + "Players discard cards and sacrifice creatures the same way"; } BalanceEffect(final BalanceEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BalduvianFallen.java b/Mage.Sets/src/mage/cards/b/BalduvianFallen.java new file mode 100644 index 00000000000..6191b9cf44a --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BalduvianFallen.java @@ -0,0 +1,89 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ManaEvent; + +/** + * + * @author noahg + */ +public final class BalduvianFallen extends CardImpl { + + public BalduvianFallen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Cumulative upkeep {1} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); + + // Whenever Balduvian Fallen's cumulative upkeep is paid, it gets +1/+0 until end of turn for each {B} or {R} spent this way. + this.addAbility(new BalduvianFallenAbility()); + } + + public BalduvianFallen(final BalduvianFallen card) { + super(card); + } + + @Override + public BalduvianFallen copy() { + return new BalduvianFallen(this); + } +} + +class BalduvianFallenAbility extends TriggeredAbilityImpl { + + public BalduvianFallenAbility() { + super(Zone.BATTLEFIELD, null, false); + } + + public BalduvianFallenAbility(final BalduvianFallenAbility ability) { + super(ability); + } + + @Override + public BalduvianFallenAbility copy() { + return new BalduvianFallenAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PAID_CUMULATIVE_UPKEEP; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + this.getEffects().clear(); + if(event.getSourceId() != null && event.getSourceId().equals(this.getSourceId()) && event instanceof ManaEvent) { + ManaEvent manaEvent = (ManaEvent) event; + int total = manaEvent.getMana().getBlack() + manaEvent.getMana().getRed(); + if (total > 0) { + this.getEffects().add(new BoostSourceEffect(total, 0, Duration.EndOfTurn)); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this}'s cumulative upkeep is paid, it gets +1/+0 until end of turn for each {B} or {R} spent this way"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java index ad0aa4279ca..1adf661c5c1 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java @@ -134,7 +134,7 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect { if (chosenGroup != null) { // Relevant ruling for Balduvian Warlord: // 7/15/2006 If an attacking creature has an ability that triggers “When this creature becomes blocked,” - // it triggers when a creature blocks it due to the Warlord’s ability only if it was unblocked at that point. + // it triggers when a creature blocks it due to the Warlord's ability only if it was unblocked at that point. boolean notYetBlocked = chosenGroup.getBlockers().isEmpty(); chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game); game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h diff --git a/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java b/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java index 97ca6129480..a21b4c8deed 100644 --- a/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java +++ b/Mage.Sets/src/mage/cards/b/BaneOfHanweir.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.AttacksEachCombatStaticAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -38,7 +38,7 @@ public final class BaneOfHanweir extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Bane of Hanweir. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public BaneOfHanweir(final BaneOfHanweir card) { diff --git a/Mage.Sets/src/mage/cards/b/Banefire.java b/Mage.Sets/src/mage/cards/b/Banefire.java index cf741518d71..29d3a6a2fcc 100644 --- a/Mage.Sets/src/mage/cards/b/Banefire.java +++ b/Mage.Sets/src/mage/cards/b/Banefire.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.UUID; @@ -31,12 +30,12 @@ import mage.target.common.TargetAnyTarget; public final class Banefire extends CardImpl { public Banefire(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}"); // Banefire deals X damage to any target. this.getSpellAbility().addEffect(new BaneFireEffect()); this.getSpellAbility().addTarget(new TargetAnyTarget()); - // If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented. + // If X is 5 or more, Banefire can't be countered and the damage can't be prevented. this.addAbility(new SimpleStaticAbility(Zone.STACK, new BanefireCantCounterEffect())); } @@ -111,7 +110,7 @@ class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl { public BanefireCantCounterEffect() { super(Duration.WhileOnStack, Outcome.Benefit); - staticText = "If X is 5 or more, {this} can't be countered by spells or abilities and the damage can't be prevented"; + staticText = "If X is 5 or more, this spell can't be countered and the damage can't be prevented"; } public BanefireCantCounterEffect(final BanefireCantCounterEffect effect) { @@ -145,4 +144,4 @@ class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl { return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BarbarianBully.java b/Mage.Sets/src/mage/cards/b/BarbarianBully.java new file mode 100644 index 00000000000..d9c6ebfd503 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BarbarianBully.java @@ -0,0 +1,88 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class BarbarianBully extends CardImpl { + + public BarbarianBully(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.BARBARIAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Discard a card at random: Barbarian Bully gets +2/+2 until end of turn unless a player has Barbarian Bully deal 4 damage to him or her. Activate this ability only once each turn. + this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BarbarianBullyEffect(), new DiscardCardCost(true))); + } + + public BarbarianBully(final BarbarianBully card) { + super(card); + } + + @Override + public BarbarianBully copy() { + return new BarbarianBully(this); + } +} + +class BarbarianBullyEffect extends OneShotEffect { + + public BarbarianBullyEffect() { + super(Outcome.BoostCreature); + this.staticText = "{this} gets +2/+2 until end of turn " + + "unless a player has {this} deal 4 damage to them"; + } + + public BarbarianBullyEffect(final BarbarianBullyEffect effect) { + super(effect); + } + + @Override + public BarbarianBullyEffect copy() { + return new BarbarianBullyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (permanent == null) { + return false; + } + boolean costPaid = false; + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + if (player.chooseUse(Outcome.UnboostCreature, "Have " + permanent.getName() + " deal 4 damage to you?", source, game)) { + player.damage(4, permanent.getId(), game, false, true); + costPaid = true; + } + } + if (!costPaid) { + return new BoostSourceEffect(2, 2, Duration.EndOfTurn).apply(game, source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/b/Barishi.java b/Mage.Sets/src/mage/cards/b/Barishi.java new file mode 100644 index 00000000000..41500213b91 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Barishi.java @@ -0,0 +1,76 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileSourceEffect; +import mage.constants.SubType; +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.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class Barishi extends CardImpl { + + public Barishi(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // When Barishi dies, exile Barishi, then shuffle all creature cards from your graveyard into your library. + this.addAbility(new DiesTriggeredAbility(new BarishiEffect(), false)); + } + + public Barishi(final Barishi card) { + super(card); + } + + @Override + public Barishi copy() { + return new Barishi(this); + } +} + +class BarishiEffect extends OneShotEffect { + + public BarishiEffect() { + super(Outcome.Benefit); + this.staticText = "exile {this}, then shuffle all creature cards from your graveyard into your library"; + } + + public BarishiEffect(final BarishiEffect effect) { + super(effect); + } + + @Override + public BarishiEffect copy() { + return new BarishiEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + new ExileSourceEffect().apply(game, source); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards cards = new CardsImpl(); + cards.addAll(controller.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game)); + controller.putCardsOnTopOfLibrary(cards, game, source, false); + controller.shuffleLibrary(source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BarrenGlory.java b/Mage.Sets/src/mage/cards/b/BarrenGlory.java index 5ea7683cac6..78113c6343c 100644 --- a/Mage.Sets/src/mage/cards/b/BarrenGlory.java +++ b/Mage.Sets/src/mage/cards/b/BarrenGlory.java @@ -6,7 +6,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class BarrenGlory extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}{W}"); // At the beginning of your upkeep, if you control no permanents other than Barren Glory and have no cards in hand, you win the game. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false), new CompoundCondition( new CardsInHandCondition(ComparisonType.EQUAL_TO, 0), diff --git a/Mage.Sets/src/mage/cards/b/Batterskull.java b/Mage.Sets/src/mage/cards/b/Batterskull.java index 1d8049210b4..d165d8044b0 100644 --- a/Mage.Sets/src/mage/cards/b/Batterskull.java +++ b/Mage.Sets/src/mage/cards/b/Batterskull.java @@ -3,6 +3,7 @@ package mage.cards.b; import java.util.UUID; + import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; @@ -18,28 +19,30 @@ import mage.cards.CardSetInfo; import mage.constants.*; /** - * * @author Loki */ public final class Batterskull extends CardImpl { - public Batterskull (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + public Batterskull(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); this.subtype.add(SubType.EQUIPMENT); // Living weapon (When this Equipment enters the battlefield, create a 0/0 black Germ creature token, then attach this to it.) this.addAbility(new LivingWeaponAbility()); + // Equipped creature gets +4/+4 and has vigilance and lifelink. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(4, 4))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(LifelinkAbility.getInstance(), AttachmentType.EQUIPMENT))); + // {3}: Return Batterskull to its owner's hand. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new GenericManaCost(3))); + // Equip {5} this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(5))); } - public Batterskull (final Batterskull card) { + public Batterskull(final Batterskull card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/b/BattleOfWits.java b/Mage.Sets/src/mage/cards/b/BattleOfWits.java index 50fb2ac402a..9a0808abc28 100644 --- a/Mage.Sets/src/mage/cards/b/BattleOfWits.java +++ b/Mage.Sets/src/mage/cards/b/BattleOfWits.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +27,7 @@ public final class BattleOfWits extends CardImpl { // At the beginning of your upkeep, if you have 200 or more cards in your library, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new BattleOfWitsCondition(), "At the beginning of your upkeep, if you have 200 or more cards in your library, you win the game.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new BattleOfWitsCondition(), "At the beginning of your upkeep, if you have 200 or more cards in your library, you win the game.")); } public BattleOfWits(final BattleOfWits card) { diff --git a/Mage.Sets/src/mage/cards/b/BattlefieldThaumaturge.java b/Mage.Sets/src/mage/cards/b/BattlefieldThaumaturge.java index 7866b091db5..635027c5ad3 100644 --- a/Mage.Sets/src/mage/cards/b/BattlefieldThaumaturge.java +++ b/Mage.Sets/src/mage/cards/b/BattlefieldThaumaturge.java @@ -80,9 +80,9 @@ class BattlefieldThaumaturgeSpellsCostReductionEffect extends CostModificationEf @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if ((abilityToModify instanceof SpellAbility) - && abilityToModify.getControllerId().equals(source.getControllerId())) { + && abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); - return spell != null && StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL.match(spell, game); + return spell != null && StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY.match(spell, game); } return false; } diff --git a/Mage.Sets/src/mage/cards/b/BattlegraceAngel.java b/Mage.Sets/src/mage/cards/b/BattlegraceAngel.java index 10b675c1e76..62e5d7ea988 100644 --- a/Mage.Sets/src/mage/cards/b/BattlegraceAngel.java +++ b/Mage.Sets/src/mage/cards/b/BattlegraceAngel.java @@ -77,7 +77,7 @@ class BattlegraceAngelAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId) ) { + if (game.isActivePlayer(this.controllerId) ) { if (game.getCombat().attacksAlone()) { for (Effect effect: this.getEffects()) { effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); diff --git a/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java b/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java new file mode 100644 index 00000000000..f63d0ebc8ad --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BazaarOfWonders.java @@ -0,0 +1,98 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileGraveyardAllPlayersEffect; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class BazaarOfWonders extends CardImpl { + + public BazaarOfWonders(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}"); + + this.addSuperType(SuperType.WORLD); + + // When Bazaar of Wonders enters the battlefield, exile all cards from all graveyards. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ExileGraveyardAllPlayersEffect())); + + // Whenever a player casts a spell, counter it if a card with the same name is in a graveyard or a nontoken permanent with the same name is on the battlefield. + this.addAbility(new SpellCastAllTriggeredAbility(new BazaarOfWondersEffect(), StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL)); + } + + public BazaarOfWonders(final BazaarOfWonders card) { + super(card); + } + + @Override + public BazaarOfWonders copy() { + return new BazaarOfWonders(this); + } +} + +class BazaarOfWondersEffect extends OneShotEffect { + + public BazaarOfWondersEffect() { + super(Outcome.Benefit); + this.staticText = "counter it if a card with the same name is in a graveyard " + + "or a nontoken permanent with the same name is on the battlefield"; + } + + public BazaarOfWondersEffect(final BazaarOfWondersEffect effect) { + super(effect); + } + + @Override + public BazaarOfWondersEffect copy() { + return new BazaarOfWondersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getSpell(targetPointer.getFirst(game, source)); + if (spell == null) { + return false; + } + String spellName = spell.getName(); + FilterPermanent filter1 = new FilterPermanent(); + filter1.add(new NamePredicate(spellName)); + filter1.add(Predicates.not(new TokenPredicate())); + if (!game.getBattlefield().getActivePermanents(filter1, source.getControllerId(), game).isEmpty()) { + spell.counter(source.getControllerId(), game); + return true; + } + FilterCard filter2 = new FilterCard(); + filter2.add(new NamePredicate(spellName)); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + if (player.getGraveyard().count(filter2, game) > 0) { + spell.counter(source.getControllerId(), game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java b/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java index 1b30fac3aeb..d935f234c4a 100644 --- a/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java +++ b/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.UUID; @@ -13,7 +12,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; /** * @@ -22,14 +21,14 @@ import mage.filter.FilterPermanent; public final class BearerOfTheHeavens extends CardImpl { public BearerOfTheHeavens(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{7}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{7}{R}"); this.subtype.add(SubType.GIANT); this.power = new MageInt(10); this.toughness = new MageInt(10); // When Bearer of the Heavens dies, destroy all permanents at the beginning of the next end step. - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new DestroyAllEffect(new FilterPermanent("permanents"))); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT)); Effect effect = new CreateDelayedTriggeredAbilityEffect(delayedAbility); effect.setText("destroy all permanents at the beginning of the next end step"); this.addAbility(new DiesTriggeredAbility(effect, false)); diff --git a/Mage.Sets/src/mage/cards/b/BelbesPortal.java b/Mage.Sets/src/mage/cards/b/BelbesPortal.java index 99433187af5..3364c22b2b6 100644 --- a/Mage.Sets/src/mage/cards/b/BelbesPortal.java +++ b/Mage.Sets/src/mage/cards/b/BelbesPortal.java @@ -30,7 +30,7 @@ public final class BelbesPortal extends CardImpl { this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.PutCreatureInPlay))); // {3}, {tap}: You may put a creature card of the chosen type from your hand onto the battlefield. FilterCreatureCard filter = new FilterCreatureCard("a creature card of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutCardFromHandOntoBattlefieldEffect(filter), new ManaCostsImpl("{3}")); diff --git a/Mage.Sets/src/mage/cards/b/BellowingSaddlebrute.java b/Mage.Sets/src/mage/cards/b/BellowingSaddlebrute.java index 27742c3450c..10b298ca19a 100644 --- a/Mage.Sets/src/mage/cards/b/BellowingSaddlebrute.java +++ b/Mage.Sets/src/mage/cards/b/BellowingSaddlebrute.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class BellowingSaddlebrute extends CardImpl { this.toughness = new MageInt(5); // Raid - When Bellowing Saddlebrute enters the battlefield, you lose 4 life unless you attacked with a creature this turn - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new LoseLifeSourceControllerEffect(4)), new InvertCondition(RaidCondition.instance), "Raid — When {this} enters the battlefield, you lose 4 life unless you attacked with a creature this turn" diff --git a/Mage.Sets/src/mage/cards/b/BenalishEmissary.java b/Mage.Sets/src/mage/cards/b/BenalishEmissary.java index b70c84ccdd6..db324f7b896 100644 --- a/Mage.Sets/src/mage/cards/b/BenalishEmissary.java +++ b/Mage.Sets/src/mage/cards/b/BenalishEmissary.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class BenalishEmissary extends CardImpl { // When Benalish Emissary enters the battlefield, if it was kicked, destroy target land. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); ability.addTarget(new TargetLandPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target land.")); } diff --git a/Mage.Sets/src/mage/cards/b/Berserk.java b/Mage.Sets/src/mage/cards/b/Berserk.java index 0b54d1be549..f193dcae694 100644 --- a/Mage.Sets/src/mage/cards/b/Berserk.java +++ b/Mage.Sets/src/mage/cards/b/Berserk.java @@ -66,7 +66,7 @@ class BerserkReplacementEffect extends ContinuousRuleModifyingEffectImpl { BerserkReplacementEffect() { super(Duration.EndOfGame, Outcome.Detriment); - staticText = "Cast {this} only before the combat damage step"; + staticText = "Cast this spell only before the combat damage step"; } BerserkReplacementEffect(final BerserkReplacementEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BidentOfThassa.java b/Mage.Sets/src/mage/cards/b/BidentOfThassa.java index c6b52126a08..6161b610116 100644 --- a/Mage.Sets/src/mage/cards/b/BidentOfThassa.java +++ b/Mage.Sets/src/mage/cards/b/BidentOfThassa.java @@ -74,7 +74,7 @@ class BidentOfThassaTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/b/Bioshift.java b/Mage.Sets/src/mage/cards/b/Bioshift.java index cccdcd17130..2876e55ca5c 100644 --- a/Mage.Sets/src/mage/cards/b/Bioshift.java +++ b/Mage.Sets/src/mage/cards/b/Bioshift.java @@ -82,7 +82,7 @@ class MoveCounterFromTargetToTargetEffect extends OneShotEffect { if (source.getTargets().size() > 1) { toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); } - if (fromPermanent == null || toPermanent == null || !fromPermanent.getControllerId().equals(toPermanent.getControllerId())) { + if (fromPermanent == null || toPermanent == null || !fromPermanent.isControlledBy(toPermanent.getControllerId())) { return false; } int amountCounters = fromPermanent.getCounters(game).getCount(CounterType.P1P1); @@ -114,7 +114,7 @@ class SameControllerPredicate implements ObjectSourcePlayerPredicateMetalcraft — When Blade-Tribe Berserkers enters the battlefield, if you control three or more artifacts, Blade-Tribe Berserkers gets +3/+3 and gains haste until end of turn. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect(3, 3, Duration.EndOfTurn), false); ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); - this.addAbility(new ConditionalTriggeredAbility(ability, MetalcraftCondition.instance, effectText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MetalcraftCondition.instance, effectText)); } public BladeTribeBerserkers(final BladeTribeBerserkers card) { diff --git a/Mage.Sets/src/mage/cards/b/BlazeCommando.java b/Mage.Sets/src/mage/cards/b/BlazeCommando.java index 9b10f41a4a1..07376a338cc 100644 --- a/Mage.Sets/src/mage/cards/b/BlazeCommando.java +++ b/Mage.Sets/src/mage/cards/b/BlazeCommando.java @@ -89,7 +89,7 @@ class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getControllerId().equals(game.getControllerId(event.getSourceId()))) { + if (isControlledBy(game.getControllerId(event.getSourceId()))) { MageObject damageSource = game.getObject(event.getSourceId()); if (damageSource != null) { if (damageSource.isInstant()|| damageSource.isSorcery()) { diff --git a/Mage.Sets/src/mage/cards/b/BleakCovenVampires.java b/Mage.Sets/src/mage/cards/b/BleakCovenVampires.java index a72ec31ee52..61ec1d16679 100644 --- a/Mage.Sets/src/mage/cards/b/BleakCovenVampires.java +++ b/Mage.Sets/src/mage/cards/b/BleakCovenVampires.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MetalcraftCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; @@ -22,7 +22,7 @@ import mage.target.TargetPlayer; */ public final class BleakCovenVampires extends CardImpl { - private static final String effectText = "Metalcraft - When Bleak Coven Vampires enters the battlefield, if you control three or more artifacts, target player loses 4 life and you gain 4 life."; + private static final String effectText = "Metalcraft — When Bleak Coven Vampires enters the battlefield, if you control three or more artifacts, target player loses 4 life and you gain 4 life."; public BleakCovenVampires(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); @@ -31,12 +31,13 @@ public final class BleakCovenVampires extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(3); + //Metalcraft — When Bleak Coven Vampires enters the battlefield, if you control three or more artifacts, target player loses 4 life and you gain 4 life. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(4), false); ability.addEffect(new GainLifeEffect(4)); Target target = new TargetPlayer(); ability.addTarget(target); - this.addAbility(new ConditionalTriggeredAbility(ability, MetalcraftCondition.instance, effectText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MetalcraftCondition.instance, effectText)); } public BleakCovenVampires(final BleakCovenVampires card) { diff --git a/Mage.Sets/src/mage/cards/b/Blightning.java b/Mage.Sets/src/mage/cards/b/Blightning.java index 6345b97ab89..397629a8d54 100644 --- a/Mage.Sets/src/mage/cards/b/Blightning.java +++ b/Mage.Sets/src/mage/cards/b/Blightning.java @@ -45,7 +45,7 @@ class BlightningEffect extends OneShotEffect { BlightningEffect() { super(Outcome.Benefit); - this.staticText = "That player or that planeswalker’s controller discards two cards."; + this.staticText = "That player or that planeswalker's controller discards two cards."; } BlightningEffect(final BlightningEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BlindZealot.java b/Mage.Sets/src/mage/cards/b/BlindZealot.java index ebe2d5360ba..c1de1d9731b 100644 --- a/Mage.Sets/src/mage/cards/b/BlindZealot.java +++ b/Mage.Sets/src/mage/cards/b/BlindZealot.java @@ -1,19 +1,16 @@ - package mage.cards.b; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.keyword.IntimidateAbility; 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.filter.common.FilterCreaturePermanent; @@ -21,11 +18,8 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; /** * @@ -40,10 +34,11 @@ public final class BlindZealot extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); + // Intimidate this.addAbility(IntimidateAbility.getInstance()); + // Whenever Blind Zealot deals combat damage to a player, you may sacrifice it. If you do, destroy target creature that player controls. Ability ability = new BlindZealotTriggeredAbility(); - ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } @@ -60,7 +55,7 @@ public final class BlindZealot extends CardImpl { class BlindZealotTriggeredAbility extends TriggeredAbilityImpl { public BlindZealotTriggeredAbility() { - super(Zone.BATTLEFIELD, new BlindZealotEffect(), true); + super(Zone.BATTLEFIELD, new DoIfCostPaid(new DestroyTargetEffect(), new SacrificeSourceCost()), true); } public BlindZealotTriggeredAbility(final BlindZealotTriggeredAbility ability) { @@ -92,48 +87,7 @@ class BlindZealotTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, you may sacrifice it. If you do, destroy target creature that player controls"; - } -} - -class BlindZealotEffect extends OneShotEffect { - - public BlindZealotEffect() { - super(Outcome.DestroyPermanent); - staticText = "sacrifice {this}"; - } - - public BlindZealotEffect(final BlindZealotEffect effect) { - super(effect); - } - - @Override - public BlindZealotEffect copy() { - return new BlindZealotEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject == null) { - if (source.getSourceObject(game) instanceof Spell) { - sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null && sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { - return false; - } - } - } - if (sourceObject instanceof Permanent) { - Permanent permanent = (Permanent) sourceObject; - if (source.getControllerId().equals(permanent.getControllerId())) { - Effect effect = new DestroyTargetEffect(); - effect.setTargetPointer(new FixedTarget(targetPermanent.getId())); - effect.apply(game, source); - return permanent.sacrifice(source.getSourceId(), game); - } - return true; - } - return false; + return "Whenever {this} deals combat damage to a player, you may sacrifice it. " + + "If you do, destroy target creature that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/b/BlindingBeam.java b/Mage.Sets/src/mage/cards/b/BlindingBeam.java index 46e5286edac..3ce3042afd7 100644 --- a/Mage.Sets/src/mage/cards/b/BlindingBeam.java +++ b/Mage.Sets/src/mage/cards/b/BlindingBeam.java @@ -118,7 +118,7 @@ class BlindingBeamEffect2 extends ContinuousRuleModifyingEffectImpl { public boolean isInactive(Ability source, Game game) { // the PRE step part is directly after the UNTAP events for permanents if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) { - if (game.getActivePlayerId().equals(targetPlayerId) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (game.isActivePlayer(targetPlayerId) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { return true; } } @@ -135,7 +135,7 @@ class BlindingBeamEffect2 extends ContinuousRuleModifyingEffectImpl { // prevent untap event of creatures of target player if (game.getTurn().getStepType() == PhaseStep.UNTAP) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(targetPlayerId) && filter.match(permanent, game)) { + if (permanent != null && permanent.isControlledBy(targetPlayerId) && filter.match(permanent, game)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java b/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java index fac940cf33a..e454c0342dd 100644 --- a/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java +++ b/Mage.Sets/src/mage/cards/b/BlistercoilWeird.java @@ -29,7 +29,7 @@ public final class BlistercoilWeird extends CardImpl { 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_INSTANT_OR_SORCERY_SPELL, false); + Ability ability = new SpellCastControllerTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); ability.addEffect(new UntapSourceEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BloodDivination.java b/Mage.Sets/src/mage/cards/b/BloodDivination.java new file mode 100644 index 00000000000..c41255b8c24 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BloodDivination.java @@ -0,0 +1,38 @@ +package mage.cards.b; + +import java.util.UUID; +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 static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class BloodDivination extends CardImpl { + + public BloodDivination(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); + + // As an additional cost to cast this spell, sacrifice a creature. + this.getSpellAbility().addCost(new SacrificeTargetCost( + new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT) + )); + + // Draw three cards. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(3)); + } + + public BloodDivination(final BloodDivination card) { + super(card); + } + + @Override + public BloodDivination copy() { + return new BloodDivination(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BloodFeud.java b/Mage.Sets/src/mage/cards/b/BloodFeud.java index 9fa7427f6bd..e18b5f18656 100644 --- a/Mage.Sets/src/mage/cards/b/BloodFeud.java +++ b/Mage.Sets/src/mage/cards/b/BloodFeud.java @@ -25,7 +25,7 @@ public final class BloodFeud extends CardImpl { target.setTargetTag(1); this.getSpellAbility().addTarget(target); - FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); + FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(new AnotherTargetPredicate(2)); TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); target2.setTargetTag(2); diff --git a/Mage.Sets/src/mage/cards/b/BloodFrenzy.java b/Mage.Sets/src/mage/cards/b/BloodFrenzy.java index 9d83c8abdcb..a27725efde4 100644 --- a/Mage.Sets/src/mage/cards/b/BloodFrenzy.java +++ b/Mage.Sets/src/mage/cards/b/BloodFrenzy.java @@ -48,7 +48,7 @@ class BloodFrenzyCastRestriction extends ContinuousRuleModifyingEffectImpl { BloodFrenzyCastRestriction() { super(Duration.EndOfGame, Outcome.Detriment); - staticText = "Cast {this} only before the combat damage step"; + staticText = "Cast this spell only before the combat damage step"; } BloodFrenzyCastRestriction(final BloodFrenzyCastRestriction effect) { diff --git a/Mage.Sets/src/mage/cards/b/BloodOath.java b/Mage.Sets/src/mage/cards/b/BloodOath.java index d9c07dda95a..0edc503b6b6 100644 --- a/Mage.Sets/src/mage/cards/b/BloodOath.java +++ b/Mage.Sets/src/mage/cards/b/BloodOath.java @@ -80,7 +80,7 @@ class BloodOathEffect extends OneShotEffect { if (player != null && opponent != null && sourceObject != null) { Choice choiceImpl = new ChoiceImpl(); choiceImpl.setChoices(choice); - if (!player.choose(Outcome.Neutral, choiceImpl, game)) { + if (player.choose(Outcome.Neutral, choiceImpl, game)) { CardType type = null; String choosenType = choiceImpl.getChoice(); diff --git a/Mage.Sets/src/mage/cards/b/BloodSun.java b/Mage.Sets/src/mage/cards/b/BloodSun.java index 3782782b9bf..efa84ba2eb0 100644 --- a/Mage.Sets/src/mage/cards/b/BloodSun.java +++ b/Mage.Sets/src/mage/cards/b/BloodSun.java @@ -72,12 +72,7 @@ class BloodSunEffect extends ContinuousEffectImpl { for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS, player.getId(), source.getSourceId(), game)) { switch (layer) { case AbilityAddingRemovingEffects_6: - for (Iterator it = permanent.getAbilities().iterator(); it.hasNext();) { - Ability ability = it.next(); - if (!ability.getAbilityType().equals(AbilityType.MANA)) { - it.remove(); - } - } + permanent.getAbilities().removeIf(ability -> ability.getAbilityType() != AbilityType.MANA); break; } } diff --git a/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java b/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java index 9c49ebe1ded..03c7f503100 100644 --- a/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java +++ b/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java @@ -7,7 +7,7 @@ import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility; import mage.abilities.condition.common.OpponentLostLifeCondition; import mage.abilities.condition.common.SourceHasCounterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -38,7 +38,7 @@ public final class BloodchiefAscension extends CardImpl { true)); // Whenever a card is put into an opponent's graveyard from anywhere, if Bloodchief Ascension has three or more quest counters on it, you may have that player lose 2 life. If you do, you gain 2 life. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new PutCardIntoGraveFromAnywhereAllTriggeredAbility( new LoseLifeTargetEffect(2), true, new FilterCard("a card"), TargetController.OPPONENT, SetTargetPointer.PLAYER), new SourceHasCounterCondition(CounterType.QUEST, 3, Integer.MAX_VALUE), diff --git a/Mage.Sets/src/mage/cards/b/BloodhallPriest.java b/Mage.Sets/src/mage/cards/b/BloodhallPriest.java index 77995b35a95..86e9224fc87 100644 --- a/Mage.Sets/src/mage/cards/b/BloodhallPriest.java +++ b/Mage.Sets/src/mage/cards/b/BloodhallPriest.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.MadnessAbility; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class BloodhallPriest extends CardImpl { // Whenever Bloodhall Priest enters the battlefield or attacks, if you have no cards in hand, Bloodhall Priest deals 2 damage to any target. TriggeredAbility triggeredAbility = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageTargetEffect(2)); triggeredAbility.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, HellbentCondition.instance, "Whenever {this} enters the battlefield or attacks, if you have no cards in hand, {this} deals 2 damage to any target" diff --git a/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java b/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java index dbd1fb37eca..86cea40752e 100644 --- a/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java +++ b/Mage.Sets/src/mage/cards/b/BloodsporeThrinax.java @@ -66,7 +66,7 @@ class BloodsporeThrinaxEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - return creature != null && creature.getControllerId().equals(source.getControllerId()) + return creature != null && creature.isControlledBy(source.getControllerId()) && creature.isCreature() && !event.getTargetId().equals(source.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/b/BloodstoneGoblin.java b/Mage.Sets/src/mage/cards/b/BloodstoneGoblin.java index 62cf4e3da35..d446113a6cf 100644 --- a/Mage.Sets/src/mage/cards/b/BloodstoneGoblin.java +++ b/Mage.Sets/src/mage/cards/b/BloodstoneGoblin.java @@ -71,7 +71,7 @@ class BloodstoneGoblinTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getControllerId().equals(controllerId)) { + if (spell != null && spell.isControlledBy(controllerId)) { for (Ability ability : spell.getAbilities()) { if (ability instanceof KickerAbility && ((KickerAbility) ability).getKickedCounter(game, spell.getSpellAbility()) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/b/Bloodtracker.java b/Mage.Sets/src/mage/cards/b/Bloodtracker.java new file mode 100644 index 00000000000..bd4895f996e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Bloodtracker.java @@ -0,0 +1,57 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; + +/** + * + * @author TheElk801 + */ +public final class Bloodtracker extends CardImpl { + + public Bloodtracker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {B}, Pay 2 life: Put a +1/+1 counter on Bloodtracker. + Ability ability = new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{B}")); + ability.addCost(new PayLifeCost(2)); + this.addAbility(ability); + + // When Bloodtracker leaves the battlefield, draw a card for each +1/+1 counter on it. + this.addAbility(new LeavesBattlefieldTriggeredAbility( + new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.P1P1)) + .setText("draw a card for each +1/+1 counter on it"), false + )); + } + + public Bloodtracker(final Bloodtracker card) { + super(card); + } + + @Override + public Bloodtracker copy() { + return new Bloodtracker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BlowflyInfestation.java b/Mage.Sets/src/mage/cards/b/BlowflyInfestation.java index 1ed1d11e8e0..82ee8fe7708 100644 --- a/Mage.Sets/src/mage/cards/b/BlowflyInfestation.java +++ b/Mage.Sets/src/mage/cards/b/BlowflyInfestation.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -34,12 +34,12 @@ public final class BlowflyInfestation extends CardImpl { public BlowflyInfestation(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}"); - + //Whenever a creature dies, if it had a -1/-1 counter on it, put a -1/-1 counter on target creature. Effect effect = new BlowflyInfestationEffect(); TriggeredAbility triggeredAbility = new DiesCreatureTriggeredAbility(effect, false, false, true); triggeredAbility.addTarget(new TargetCreaturePermanent()); Condition condition = new BlowflyInfestationCondition(); - this.addAbility(new ConditionalTriggeredAbility(triggeredAbility, condition, rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggeredAbility, condition, rule)); } diff --git a/Mage.Sets/src/mage/cards/b/BludgeoningPain.java b/Mage.Sets/src/mage/cards/b/BludgeoningPain.java new file mode 100644 index 00000000000..8d23c725ef9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BludgeoningPain.java @@ -0,0 +1,36 @@ +package mage.cards.b; + +import java.util.UUID; +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.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class BludgeoningPain extends CardImpl { + + public BludgeoningPain(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); + + + // Target creature gets -2/-2 until end of turn. Tap that creature. + this.getSpellAbility().addEffect(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new TapTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public BludgeoningPain(final BludgeoningPain card) { + super(card); + } + + @Override + public BludgeoningPain copy() { + return new BludgeoningPain(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java b/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java index 2394574372e..7b232219997 100644 --- a/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java +++ b/Mage.Sets/src/mage/cards/b/BoardTheWeatherlight.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.UUID; @@ -30,10 +29,11 @@ public final class BoardTheWeatherlight extends CardImpl { this.getSpellAbility().addEffect( new LookLibraryAndPickControllerEffect( new StaticValue(5), false, new StaticValue(1), filter, - Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false - ).setText("Look at the top five cards of your library. You may reveal a historic card from among them" - + " and put it into your hand. Put the rest on the bottom of your library in a random order. " - + "(Artifacts, legendaries, and Sagas are historic.)") + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false) + .setBackInRandomOrder(true) + .setText("Look at the top five cards of your library. You may reveal a historic card from among them" + + " and put it into your hand. Put the rest on the bottom of your library in a random order. " + + "(Artifacts, legendaries, and Sagas are historic.)") ); } diff --git a/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java b/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java new file mode 100644 index 00000000000..e56829c19b6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java @@ -0,0 +1,93 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +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.counters.CounterType; +import mage.counters.Counters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class BogardanPhoenix extends CardImpl { + + public BogardanPhoenix(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}{R}"); + + this.subtype.add(SubType.PHOENIX); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Bogardan Phoenix dies, exile it if it had a death counter on it. Otherwise, return it to the battlefield under your control and put a death counter on it. + this.addAbility(new DiesTriggeredAbility(new BogardanPhoenixEffect(), false)); + } + + public BogardanPhoenix(final BogardanPhoenix card) { + super(card); + } + + @Override + public BogardanPhoenix copy() { + return new BogardanPhoenix(this); + } +} + +class BogardanPhoenixEffect extends OneShotEffect { + + public BogardanPhoenixEffect() { + super(Outcome.Benefit); + this.staticText = "exile it if it had a death counter on it. " + + "Otherwise, return it to the battlefield under your control " + + "and put a death counter on it."; + } + + public BogardanPhoenixEffect(final BogardanPhoenixEffect effect) { + super(effect); + } + + @Override + public BogardanPhoenixEffect copy() { + return new BogardanPhoenixEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + if (permanent == null + || controller == null + || permanent.getZoneChangeCounter(game) + 1 + != source.getSourceObjectZoneChangeCounter()) { + return false; + } + Card card = game.getCard(permanent.getId()); + if (card == null || card.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter()) { + return false; + } + if (permanent.getCounters(game).containsKey(CounterType.DEATH)) { + return controller.moveCards(card, Zone.EXILED, source, game); + } else { + Counters countersToAdd = new Counters(); + countersToAdd.addCounter(CounterType.DEATH.createInstance()); + game.setEnterWithCounters(source.getSourceId(), countersToAdd); + return controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + } +} diff --git a/Mage.Sets/src/mage/cards/b/Bogstomper.java b/Mage.Sets/src/mage/cards/b/Bogstomper.java new file mode 100644 index 00000000000..a0b247e554e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Bogstomper.java @@ -0,0 +1,32 @@ +package mage.cards.b; + +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 Bogstomper extends CardImpl { + + public Bogstomper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + } + + public Bogstomper(final Bogstomper card) { + super(card); + } + + @Override + public Bogstomper copy() { + return new Bogstomper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BoneDragon.java b/Mage.Sets/src/mage/cards/b/BoneDragon.java new file mode 100644 index 00000000000..591bbb9429e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoneDragon.java @@ -0,0 +1,61 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileFromGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AnotherCardPredicate; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author TheElk801 + */ +public final class BoneDragon extends CardImpl { + + private static final FilterCard filter = new FilterCard("other cards"); + + static { + filter.add(new AnotherCardPredicate()); + } + + public BoneDragon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + + this.subtype.add(SubType.DRAGON); + this.subtype.add(SubType.SKELETON); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {3}{B}{B}, Exile seven other cards from your graveyard: Return Bone Dragon from your graveyard to the battlefield tapped. + Ability ability = new SimpleActivatedAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToBattlefieldEffect(true), + new ManaCostsImpl("{3}{B}{B}") + ); + ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(7, filter))); + this.addAbility(ability); + } + + public BoneDragon(final BoneDragon card) { + super(card); + } + + @Override + public BoneDragon copy() { + return new BoneDragon(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/Bonehoard.java b/Mage.Sets/src/mage/cards/b/Bonehoard.java index 7085e45b1dd..5ff585c7e20 100644 --- a/Mage.Sets/src/mage/cards/b/Bonehoard.java +++ b/Mage.Sets/src/mage/cards/b/Bonehoard.java @@ -2,6 +2,7 @@ package mage.cards.b; import java.util.UUID; + import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; @@ -17,19 +18,22 @@ import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; /** - * * @author North */ public final class Bonehoard extends CardImpl { public Bonehoard(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); this.subtype.add(SubType.EQUIPMENT); - + // Living weapon (When this Equipment enters the battlefield, create a 0/0 black Germ creature token, then attach this to it.) this.addAbility(new LivingWeaponAbility()); + + // Equipped creature gets +X/+X, where X is the number of creature cards in all graveyards. CardsInAllGraveyardsCount value = new CardsInAllGraveyardsCount(new FilterCreatureCard()); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(value, value))); + + // Equip {2} this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); } diff --git a/Mage.Sets/src/mage/cards/b/BoneyardScourge.java b/Mage.Sets/src/mage/cards/b/BoneyardScourge.java index 7c409d64fc1..4b61d293488 100644 --- a/Mage.Sets/src/mage/cards/b/BoneyardScourge.java +++ b/Mage.Sets/src/mage/cards/b/BoneyardScourge.java @@ -92,7 +92,7 @@ class DiesWhileInGraveyardTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; for (Zone z : Zone.values()) { - if (game.getShortLivingLKI(sourceId, z) && !z.equals(Zone.GRAVEYARD)) { + if (game.getShortLivingLKI(sourceId, z) && z != Zone.GRAVEYARD) { return false; } } diff --git a/Mage.Sets/src/mage/cards/b/BonfireOfTheDamned.java b/Mage.Sets/src/mage/cards/b/BonfireOfTheDamned.java index 8409754955a..54a4f3ed72f 100644 --- a/Mage.Sets/src/mage/cards/b/BonfireOfTheDamned.java +++ b/Mage.Sets/src/mage/cards/b/BonfireOfTheDamned.java @@ -16,6 +16,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; +import mage.target.common.TargetPlayerOrPlaneswalker; /** * @@ -28,7 +29,7 @@ public final class BonfireOfTheDamned extends CardImpl { // Bonfire of the Damned deals X damage to target player and each creature he or she controls. this.getSpellAbility().addEffect(new BonfireOfTheDamnedEffect()); - this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); // Miracle {X}{R} this.addAbility(new MiracleAbility(this, new ManaCostsImpl("{X}{R}"))); @@ -50,7 +51,7 @@ class BonfireOfTheDamnedEffect extends OneShotEffect { public BonfireOfTheDamnedEffect() { super(Outcome.Damage); - staticText = "{this} deals X damage to target player or planeswalker and each creature that player or that planeswalker’s controller controls"; + staticText = "{this} deals X damage to target player or planeswalker and each creature that player or that planeswalker's controller controls"; } public BonfireOfTheDamnedEffect(final BonfireOfTheDamnedEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BoobyTrap.java b/Mage.Sets/src/mage/cards/b/BoobyTrap.java new file mode 100644 index 00000000000..ed7c8d844b3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoobyTrap.java @@ -0,0 +1,97 @@ +package mage.cards.b; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.common.ChooseACardNameEffect; +import mage.abilities.effects.common.ChooseOpponentEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.cards.Card; +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.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author noahg + */ +public final class BoobyTrap extends CardImpl { + + public BoobyTrap(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); + + // As Booby Trap enters the battlefield, name a card other than a basic land card and choose an opponent. + AsEntersBattlefieldAbility etbAbility = new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NOT_BASIC_LAND_NAME)); + etbAbility.addEffect(new ChooseOpponentEffect(Outcome.Damage)); + this.addAbility(etbAbility); + + // The chosen player reveals each card he or she draws. + // When the chosen player draws the named card, sacrifice Booby Trap. If you do, Booby Trap deals 10 damage to that player. + this.addAbility(new BoobyTrapTriggeredAbility()); + } + + public BoobyTrap(final BoobyTrap card) { + super(card); + } + + @Override + public BoobyTrap copy() { + return new BoobyTrap(this); + } +} + +class BoobyTrapTriggeredAbility extends TriggeredAbilityImpl { + + public BoobyTrapTriggeredAbility() { + super(Zone.BATTLEFIELD, new DoIfCostPaid(new DamageTargetEffect(10, true, "that player"), new SacrificeSourceCost(), "", false), false); + } + + public BoobyTrapTriggeredAbility(BoobyTrapTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DREW_CARD; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player controller = game.getPlayer(getControllerId()); + if (event.getPlayerId() == null || game.getState() == null || controller == null) { + return false; + } + if (event.getPlayerId().equals(game.getState().getValue(getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY))) { + Card drawn = game.getCard(event.getTargetId()); + if (drawn != null) { + controller.revealCards(this, new CardsImpl(drawn), game); + if (drawn.getName().equals(game.getState().getValue(getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { + //Set target + this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); + return true; + } + } + } + return false; + } + + @Override + public BoobyTrapTriggeredAbility copy() { + return new BoobyTrapTriggeredAbility(this); + } + + @Override + public String getRule() { + return "The chosen player reveals each card he or she draws.\n" + + "When the chosen player draws the named card, sacrifice {this}. If you do, {this} deals 10 damage to that player."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BorGullet.java b/Mage.Sets/src/mage/cards/b/BorGullet.java new file mode 100644 index 00000000000..a19260fa658 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BorGullet.java @@ -0,0 +1,42 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetOpponent; + +/** + * + * @author NinthWorld + */ +public final class BorGullet extends CardImpl { + + public BorGullet(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{B}"); + + this.subtype.add(SubType.HORROR); + this.subtype.add(SubType.CEPHALID); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // When Bor Gullet enters the battlefield, target opponent reveals his or her hand. You choose a card from it. That player discards that card. + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardCardYouChooseTargetEffect()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public BorGullet(final BorGullet card) { + super(card); + } + + @Override + public BorGullet copy() { + return new BorGullet(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BoreasCharger.java b/Mage.Sets/src/mage/cards/b/BoreasCharger.java new file mode 100644 index 00000000000..151cdfab2ff --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoreasCharger.java @@ -0,0 +1,168 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +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.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.FilterPlayer; +import mage.filter.StaticFilters; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author TheElk801 + */ +public final class BoreasCharger extends CardImpl { + + public BoreasCharger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.PEGASUS); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Boreas Charger leaves the battlefield, choose an opponent who controls more lands than you. Search your library for a number of Plains cards equal to the difference and reveal them. Put one of them onto the battlefield tapped and the rest into your hand. Then shuffle your library. + this.addAbility(new LeavesBattlefieldTriggeredAbility( + new BoreasChargerEffect(), false + )); + } + + public BoreasCharger(final BoreasCharger card) { + super(card); + } + + @Override + public BoreasCharger copy() { + return new BoreasCharger(this); + } +} + +class BoreasChargerEffect extends OneShotEffect { + + private static final FilterPlayer filter + = new FilterPlayer("opponent who controls more lands than you"); + private static final FilterCard filter2 + = new FilterCard("Plains cards"); + private static final FilterCard filter3 + = new FilterCard("a card to put onto the battlefield tapped"); + + static { + filter.add(new BoreasChargerPredicate()); + filter2.add(new SubtypePredicate(SubType.PLAINS)); + } + + public BoreasChargerEffect() { + super(Outcome.Benefit); + this.staticText = "choose an opponent who controls more lands than you. " + + "Search your library for a number of Plains cards " + + "equal to the difference and reveal them. " + + "Put one of them onto the battlefield tapped " + + "and the rest into your hand. Then shuffle your library"; + } + + public BoreasChargerEffect(final BoreasChargerEffect effect) { + super(effect); + } + + @Override + public BoreasChargerEffect copy() { + return new BoreasChargerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + TargetPlayer target = new TargetPlayer(1, 1, true, filter); + controller.choose(outcome, target, source.getSourceId(), game); + Player opponent = game.getPlayer(target.getFirstTarget()); + if (opponent == null) { + controller.shuffleLibrary(source, game); + return false; + } + int landDifference = game.getBattlefield().getAllActivePermanents( + StaticFilters.FILTER_LANDS, opponent.getId(), game + ).size(); + landDifference -= game.getBattlefield().getAllActivePermanents( + StaticFilters.FILTER_LANDS, controller.getId(), game + ).size(); + landDifference = Math.abs(landDifference); + TargetCardInLibrary target2 + = new TargetCardInLibrary(0, landDifference, filter2); + Cards cardsToHand = new CardsImpl(); + if (controller.searchLibrary(target2, game)) { + for (UUID cardId : target2.getTargets()) { + Card card = game.getCard(cardId); + if (card != null) { + cardsToHand.add(card); + } + } + } + if (cardsToHand.isEmpty()) { + controller.shuffleLibrary(source, game); + return true; + } + TargetCard target3 = new TargetCard(Zone.LIBRARY, filter3); + Card cardToBattlefield = null; + if (controller.choose(outcome, cardsToHand, target3, game)) { + cardToBattlefield = cardsToHand.get(target2.getFirstTarget(), game); + cardsToHand.remove(cardToBattlefield); + } + if (cardToBattlefield != null) { + controller.moveCards( + cardToBattlefield, Zone.BATTLEFIELD, source, game, + true, false, true, null + ); + } + controller.moveCards(cardsToHand, Zone.HAND, source, game); + controller.shuffleLibrary(source, game); + return true; + } +} + +class BoreasChargerPredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Player targetPlayer = input.getObject(); + UUID playerId = input.getPlayerId(); + if (targetPlayer == null || playerId == null) { + return false; + } + if (!targetPlayer.hasOpponent(playerId, game)) { + return false; + } + int countTargetPlayer = game.getBattlefield().countAll( + StaticFilters.FILTER_LANDS, targetPlayer.getId(), game + ); + int countController = game.getBattlefield().countAll( + StaticFilters.FILTER_LANDS, playerId, game + ); + + return countTargetPlayer > countController; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java b/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java index 8c87bc20ae4..9e19d3430a9 100644 --- a/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java +++ b/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java @@ -13,11 +13,10 @@ import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.mana.SimpleManaAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterCard; -import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; @@ -36,15 +35,15 @@ public final class BoseijuWhoSheltersAll extends CardImpl { // Boseiju, Who Shelters All enters the battlefield tapped. this.addAbility(new EntersBattlefieldTappedAbility()); - // {T}, Pay 2 life: Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered by spells or abilities. + // {T}, Pay 2 life: Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered. Mana mana = Mana.ColorlessMana(1); mana.setFlag(true); // used to indicate this mana ability SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, mana, new TapSourceCost()); ability.addCost(new PayLifeCost(2)); - ability.getEffects().get(0).setText("Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered by spells or abilities"); - this.addAbility(ability); + ability.getEffects().get(0).setText("Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered"); + this.addAbility(ability, new BoseijuWhoSheltersAllWatcher(ability.getOriginalId())); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoseijuWhoSheltersAllCantCounterEffect()), new BoseijuWhoSheltersAllWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new BoseijuWhoSheltersAllCantCounterEffect())); } public BoseijuWhoSheltersAll(final BoseijuWhoSheltersAll card) { @@ -59,14 +58,18 @@ public final class BoseijuWhoSheltersAll extends CardImpl { class BoseijuWhoSheltersAllWatcher extends Watcher { - public List spells = new ArrayList<>(); + private List spells = new ArrayList<>(); + private final String originalId; - public BoseijuWhoSheltersAllWatcher() { - super(BoseijuWhoSheltersAllWatcher.class.getSimpleName(), WatcherScope.GAME); + public BoseijuWhoSheltersAllWatcher(UUID originalId) { + super(BoseijuWhoSheltersAllWatcher.class.getSimpleName(), WatcherScope.CARD); + this.originalId = originalId.toString(); } public BoseijuWhoSheltersAllWatcher(final BoseijuWhoSheltersAllWatcher watcher) { super(watcher); + this.spells.addAll(watcher.spells); + this.originalId = watcher.originalId; } @Override @@ -77,14 +80,19 @@ class BoseijuWhoSheltersAllWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.MANA_PAID) { - MageObject object = game.getObject(event.getSourceId()); - // TODO: Replace identification by name by better method that also works if ability is copied from other land with other name - if (object != null && object.getName().equals("Boseiju, Who Shelters All") && event.getFlag()) { - spells.add(event.getTargetId()); + if (event.getData() != null && event.getData().equals(originalId)) { + Card spell = game.getSpell(event.getTargetId()); + if (spell != null && (spell.isInstant() || spell.isSorcery())) { + spells.add(event.getTargetId()); + } } } } + public boolean spellCantBeCountered(UUID spellId) { + return spells.contains(spellId); + } + @Override public void reset() { super.reset(); @@ -94,10 +102,8 @@ class BoseijuWhoSheltersAllWatcher extends Watcher { class BoseijuWhoSheltersAllCantCounterEffect extends ContinuousRuleModifyingEffectImpl { - private static final FilterCard filter = new FilterInstantOrSorceryCard(); - public BoseijuWhoSheltersAllCantCounterEffect() { - super(Duration.WhileOnBattlefield, Outcome.Benefit); + super(Duration.EndOfGame, Outcome.Benefit); staticText = null; } @@ -119,7 +125,7 @@ class BoseijuWhoSheltersAllCantCounterEffect extends ContinuousRuleModifyingEffe public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject sourceObject = game.getObject(source.getSourceId()); if (sourceObject != null) { - return "This spell can't be countered by spells or abilities (" + sourceObject.getName() + ")."; + return "This spell can't be countered because mana from " + sourceObject.getName() + " was spent to cast it."; } return null; } @@ -131,13 +137,8 @@ class BoseijuWhoSheltersAllCantCounterEffect extends ContinuousRuleModifyingEffe @Override public boolean applies(GameEvent event, Ability source, Game game) { - BoseijuWhoSheltersAllWatcher watcher = (BoseijuWhoSheltersAllWatcher) game.getState().getWatchers().get(BoseijuWhoSheltersAllWatcher.class.getSimpleName()); + BoseijuWhoSheltersAllWatcher watcher = (BoseijuWhoSheltersAllWatcher) game.getState().getWatchers().get(BoseijuWhoSheltersAllWatcher.class.getSimpleName(), source.getSourceId()); Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && watcher.spells.contains(spell.getId())) { - if (filter.match(spell.getCard(), game)) { - return true; - } - } - return false; + return spell != null && watcher != null && watcher.spellCantBeCountered(spell.getId()); } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/Bossk.java b/Mage.Sets/src/mage/cards/b/Bossk.java index 302bea02de9..f8742c1cac7 100644 --- a/Mage.Sets/src/mage/cards/b/Bossk.java +++ b/Mage.Sets/src/mage/cards/b/Bossk.java @@ -81,7 +81,7 @@ class BosskTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.isLand() && permanent.getControllerId().equals(this.getControllerId())) { + if (permanent != null && permanent.isLand() && permanent.isControlledBy(this.getControllerId())) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/b/BottledCloister.java b/Mage.Sets/src/mage/cards/b/BottledCloister.java index 40fe3da5154..8036cdc8f54 100644 --- a/Mage.Sets/src/mage/cards/b/BottledCloister.java +++ b/Mage.Sets/src/mage/cards/b/BottledCloister.java @@ -111,7 +111,7 @@ class BottledCloisterReturnEffect extends OneShotEffect { ExileZone exileZone = game.getExile().getExileZone(exileId); if (exileZone != null) { for (Card card: exileZone.getCards(game)) { - if (card.getOwnerId().equals(controller.getId())) { + if (card.isOwnedBy(controller.getId())) { numberOfCards++; card.moveToZone(Zone.HAND, source.getSourceId(), game, true); card.setFaceDown(false, game); diff --git a/Mage.Sets/src/mage/cards/b/BoundDetermined.java b/Mage.Sets/src/mage/cards/b/BoundDetermined.java index 169f9a275f8..cfb16ba5176 100644 --- a/Mage.Sets/src/mage/cards/b/BoundDetermined.java +++ b/Mage.Sets/src/mage/cards/b/BoundDetermined.java @@ -43,7 +43,7 @@ public final class BoundDetermined extends SplitCard { effect.setText("Exile this card"); getLeftHalfCard().getSpellAbility().addEffect(effect); // Determined - // Other spells you control can't be countered by spells or abilities this turn. + // Other spells you control can't be countered this turn. // Draw a card. getRightHalfCard().getSpellAbility().addEffect(new DeterminedEffect()); getRightHalfCard().getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); @@ -107,7 +107,7 @@ class DeterminedEffect extends ContinuousRuleModifyingEffectImpl { DeterminedEffect() { super(Duration.EndOfTurn, Outcome.Benefit); - staticText = "Other spells you control can't be countered by spells or abilities this turn"; + staticText = "Other spells you control can't be countered this turn"; } DeterminedEffect(final DeterminedEffect effect) { @@ -141,6 +141,6 @@ class DeterminedEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - return spell != null && !spell.getSourceId().equals(source.getSourceId()) && spell.getControllerId().equals(source.getControllerId()); + return spell != null && !spell.getSourceId().equals(source.getSourceId()) && spell.isControlledBy(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/b/BowerPassage.java b/Mage.Sets/src/mage/cards/b/BowerPassage.java index 9b4194823b8..2051063fd98 100644 --- a/Mage.Sets/src/mage/cards/b/BowerPassage.java +++ b/Mage.Sets/src/mage/cards/b/BowerPassage.java @@ -60,7 +60,7 @@ class BowerPassageEffect extends RestrictionEffect { @Override public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { - if (attacker != null && attacker.getControllerId().equals(source.getControllerId()) && blocker.getAbilities().contains(FlyingAbility.getInstance())) { + if (attacker != null && attacker.isControlledBy(source.getControllerId()) && blocker.getAbilities().contains(FlyingAbility.getInstance())) { return false; } return true; diff --git a/Mage.Sets/src/mage/cards/b/BrainPry.java b/Mage.Sets/src/mage/cards/b/BrainPry.java index bcb0a8920d1..2bebd65d8db 100644 --- a/Mage.Sets/src/mage/cards/b/BrainPry.java +++ b/Mage.Sets/src/mage/cards/b/BrainPry.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class BrainPry extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}"); //Name a nonland card. Target player reveals their hand. That player discards a card with that name. If he or she can't, you draw a card. - this.getSpellAbility().addEffect((new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new BrainPryEffect()); } @@ -56,7 +56,7 @@ class BrainPryEffect extends OneShotEffect { Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (targetPlayer != null && controller != null && sourceObject != null && cardName != null) { boolean hasDiscarded = false; for (Card card : targetPlayer.getHand().getCards(game)) { diff --git a/Mage.Sets/src/mage/cards/b/BramblewoodParagon.java b/Mage.Sets/src/mage/cards/b/BramblewoodParagon.java index b2445b48113..00a2692cc53 100644 --- a/Mage.Sets/src/mage/cards/b/BramblewoodParagon.java +++ b/Mage.Sets/src/mage/cards/b/BramblewoodParagon.java @@ -79,7 +79,7 @@ class BramblewoodParagonReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - return creature != null && creature.getControllerId().equals(source.getControllerId()) + return creature != null && creature.isControlledBy(source.getControllerId()) && creature.isCreature() && creature.hasSubtype(SubType.WARRIOR, game) && !event.getTargetId().equals(source.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/b/BrandedHowler.java b/Mage.Sets/src/mage/cards/b/BrandedHowler.java index f6774d1cc86..f51fc8c26a4 100644 --- a/Mage.Sets/src/mage/cards/b/BrandedHowler.java +++ b/Mage.Sets/src/mage/cards/b/BrandedHowler.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class BrandedHowler extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Branded Howler. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public BrandedHowler(final BrandedHowler card) { diff --git a/Mage.Sets/src/mage/cards/b/BrassHerald.java b/Mage.Sets/src/mage/cards/b/BrassHerald.java index 86d57ee69ba..870ccda042a 100644 --- a/Mage.Sets/src/mage/cards/b/BrassHerald.java +++ b/Mage.Sets/src/mage/cards/b/BrassHerald.java @@ -69,7 +69,7 @@ class BrassHeraldEntersEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { FilterCard filter = new FilterCard("creature cards of the chosen type"); - filter.add(new ChosenSubtypePredicate(source.getSourceId())); + filter.add(new ChosenSubtypePredicate()); return new RevealLibraryPutIntoHandEffect(4, filter, Zone.LIBRARY).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/b/BrawlBashOgre.java b/Mage.Sets/src/mage/cards/b/BrawlBashOgre.java new file mode 100644 index 00000000000..494919840b0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BrawlBashOgre.java @@ -0,0 +1,54 @@ +package mage.cards.b; + +import java.util.UUID; +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.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class BrawlBashOgre extends CardImpl { + + public BrawlBashOgre(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}"); + + this.subtype.add(SubType.OGRE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Menace + this.addAbility(new MenaceAbility()); + + // Whenever Brawl-Bash Ogre attacks, you may sacrifice another creature. If you do, Brawl-Bash Ogre gets +2/+2 until end of turn. + this.addAbility(new AttacksTriggeredAbility( + new DoIfCostPaid( + new BoostSourceEffect(2, 2, Duration.EndOfTurn), + new SacrificeTargetCost(new TargetControlledPermanent( + StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE + )) + ), true + )); + } + + public BrawlBashOgre(final BrawlBashOgre card) { + super(card); + } + + @Override + public BrawlBashOgre copy() { + return new BrawlBashOgre(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java b/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java index 02dfd315248..3171564a794 100644 --- a/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java +++ b/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java @@ -9,7 +9,7 @@ import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; @@ -40,7 +40,7 @@ public final class BreachingLeviathan extends CardImpl { this.toughness = new MageInt(9); // When Breaching Leviathan enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BreachingLeviathanEffect(), false), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps."), diff --git a/Mage.Sets/src/mage/cards/b/BreakneckRider.java b/Mage.Sets/src/mage/cards/b/BreakneckRider.java index 1622d77d4e3..015fdf0395e 100644 --- a/Mage.Sets/src/mage/cards/b/BreakneckRider.java +++ b/Mage.Sets/src/mage/cards/b/BreakneckRider.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class BreakneckRider extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Breakneck Rider. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public BreakneckRider(final BreakneckRider card) { diff --git a/Mage.Sets/src/mage/cards/b/BreathOfFire.java b/Mage.Sets/src/mage/cards/b/BreathOfFire.java new file mode 100644 index 00000000000..0939ad9f93d --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BreathOfFire.java @@ -0,0 +1,32 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class BreathOfFire extends CardImpl { + + public BreathOfFire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); + + // Breath of Fire deals 2 damage to target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(2)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public BreathOfFire(final BreathOfFire card) { + super(card); + } + + @Override + public BreathOfFire copy() { + return new BreathOfFire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BreathOfFury.java b/Mage.Sets/src/mage/cards/b/BreathOfFury.java index 2e8fb766f0e..f493139fadf 100644 --- a/Mage.Sets/src/mage/cards/b/BreathOfFury.java +++ b/Mage.Sets/src/mage/cards/b/BreathOfFury.java @@ -80,7 +80,7 @@ class BreathOfFuryAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(getSourceId()); if (damageEvent.isCombatDamage() && enchantment != null - && enchantment.getAttachedTo().equals(event.getSourceId())) { + && enchantment.isAttachedTo(event.getSourceId())) { Permanent creature = game.getPermanent(enchantment.getAttachedTo()); if (creature != null) { for (Effect effect : getEffects()) { diff --git a/Mage.Sets/src/mage/cards/b/BredForTheHunt.java b/Mage.Sets/src/mage/cards/b/BredForTheHunt.java index 13dca000ce4..2c5f15e810a 100644 --- a/Mage.Sets/src/mage/cards/b/BredForTheHunt.java +++ b/Mage.Sets/src/mage/cards/b/BredForTheHunt.java @@ -62,7 +62,7 @@ class BredForTheHuntTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(getControllerId()) && creature.getCounters(game).getCount(CounterType.P1P1) > 0) { + if (creature != null && creature.isControlledBy(getControllerId()) && creature.getCounters(game).getCount(CounterType.P1P1) > 0) { return true; } } diff --git a/Mage.Sets/src/mage/cards/b/Brightling.java b/Mage.Sets/src/mage/cards/b/Brightling.java index 31d6c7009ba..f99b0544ebd 100644 --- a/Mage.Sets/src/mage/cards/b/Brightling.java +++ b/Mage.Sets/src/mage/cards/b/Brightling.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.UUID; @@ -107,6 +106,7 @@ class BrightlingEffect extends OneShotEffect { return false; } int boost = (player.chooseUse(outcome, "Give +1/-1 or -1/+1?", null, "+1/-1", "-1/+1", source, game) ? 1 : -1); - return new BoostSourceEffect(boost, -1 * boost, Duration.EndOfTurn).apply(game, source); + game.addEffect(new BoostSourceEffect(boost, -1 * boost, Duration.EndOfTurn), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java b/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java index b0d2761eac0..dd37a947c6d 100644 --- a/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java +++ b/Mage.Sets/src/mage/cards/b/BrimstoneVolley.java @@ -24,7 +24,7 @@ public final class BrimstoneVolley extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); // Brimstone Volley deals 3 damage to any target. - // Morbid - Brimstone Volley deals 5 damage to that creature or player instead if a creature died this turn. + // Morbid — Brimstone Volley deals 5 damage to that creature or player instead if a creature died this turn. this.getSpellAbility().addEffect(new BrimstoneVolleyEffect()); this.getSpellAbility().addTarget(new TargetAnyTarget()); } @@ -43,7 +43,7 @@ class BrimstoneVolleyEffect extends OneShotEffect { public BrimstoneVolleyEffect() { super(Outcome.Damage); - staticText = "{this} deals 3 damage to any target.\n Morbid - {this} deals 5 damage to that permanent or player instead if a creature died this turn"; + staticText = "{this} deals 3 damage to any target.\n Morbid — {this} deals 5 damage to that permanent or player instead if a creature died this turn"; } public BrimstoneVolleyEffect(final BrimstoneVolleyEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BrineShaman.java b/Mage.Sets/src/mage/cards/b/BrineShaman.java index 3b43cbe04dc..2a2d0398ca0 100644 --- a/Mage.Sets/src/mage/cards/b/BrineShaman.java +++ b/Mage.Sets/src/mage/cards/b/BrineShaman.java @@ -18,6 +18,8 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterSpell; import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; + +import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.TargetSpell; @@ -30,7 +32,7 @@ import mage.target.common.TargetCreaturePermanent; */ public final class BrineShaman extends CardImpl { - private static final FilterSpell filter = new FilterSpell("noncreature spell"); + private static final FilterSpell filter = new FilterSpell("creature spell"); static { filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); @@ -54,7 +56,7 @@ public final class BrineShaman extends CardImpl { ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); ability.addCost(new ManaCostsImpl("{1}{U}{U}")); - ability.addTarget(new TargetSpell(filter)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java b/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java index 6e726cdf763..fe17742f0b6 100644 --- a/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java +++ b/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.Card; @@ -37,7 +37,7 @@ public final class BrinkOfMadness extends CardImpl { ability.addEffect(new BrinkOfMadnessEffect()); ability.addTarget(new TargetOpponent()); CardsInHandCondition contition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 0); - this.addAbility(new ConditionalTriggeredAbility(ability, contition, "At the beginning of your upkeep, if you have no cards in hand, sacrifice {this} and target opponent discards their hand.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, contition, "At the beginning of your upkeep, if you have no cards in hand, sacrifice {this} and target opponent discards their hand.")); } diff --git a/Mage.Sets/src/mage/cards/b/BristlingBoar.java b/Mage.Sets/src/mage/cards/b/BristlingBoar.java new file mode 100644 index 00000000000..03fb35048ff --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BristlingBoar.java @@ -0,0 +1,38 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByMoreThanOneSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class BristlingBoar extends CardImpl { + + public BristlingBoar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.BOAR); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Bristling Boar can't be blocked by more than one creature. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedByMoreThanOneSourceEffect())); + } + + public BristlingBoar(final BristlingBoar card) { + super(card); + } + + @Override + public BristlingBoar copy() { + return new BristlingBoar(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BroodingSaurian.java b/Mage.Sets/src/mage/cards/b/BroodingSaurian.java index ffc983361c1..135bbcff7c9 100644 --- a/Mage.Sets/src/mage/cards/b/BroodingSaurian.java +++ b/Mage.Sets/src/mage/cards/b/BroodingSaurian.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.Iterator; @@ -12,7 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.other.OwnerIdPredicate; import mage.filter.predicate.permanent.TokenPredicate; @@ -27,8 +25,8 @@ import mage.players.Player; public final class BroodingSaurian extends CardImpl { public BroodingSaurian(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); - this.subtype.add(SubType.LIZARD); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + this.subtype.add(SubType.LIZARD); this.power = new MageInt(4); this.toughness = new MageInt(4); @@ -49,7 +47,8 @@ public final class BroodingSaurian extends CardImpl { class BroodingSaurianControlEffect extends ContinuousEffectImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filter = new FilterPermanent(); + static { filter.add(Predicates.not(new TokenPredicate())); } @@ -77,7 +76,7 @@ class BroodingSaurianControlEffect extends ContinuousEffectImpl { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { FilterPermanent playerFilter = filter.copy(); playerFilter.add(new OwnerIdPredicate(playerId)); - for (Permanent permanent :game.getBattlefield().getActivePermanents(playerFilter, playerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(playerFilter, playerId, game)) { affectedObjectList.add(new MageObjectReference(permanent, game)); } } @@ -86,10 +85,10 @@ class BroodingSaurianControlEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { + for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { Permanent creature = it.next().getPermanent(game); if (creature != null) { - if (!creature.getControllerId().equals(creature.getOwnerId())) { + if (!creature.isControlledBy(creature.getOwnerId())) { creature.changeControllerId(creature.getOwnerId(), game); } } else { diff --git a/Mage.Sets/src/mage/cards/b/BrownOuphe.java b/Mage.Sets/src/mage/cards/b/BrownOuphe.java index 747c19d3206..b7ba3b157a6 100644 --- a/Mage.Sets/src/mage/cards/b/BrownOuphe.java +++ b/Mage.Sets/src/mage/cards/b/BrownOuphe.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterAbility; +import mage.filter.FilterStackObject; import mage.filter.predicate.ability.ArtifactSourcePredicate; import mage.target.common.TargetActivatedAbility; @@ -23,7 +24,7 @@ import mage.target.common.TargetActivatedAbility; */ public final class BrownOuphe extends CardImpl { - private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source"); + private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source"); static { filter.add(new ArtifactSourcePredicate()); diff --git a/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java b/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java new file mode 100644 index 00000000000..6da9effd66a --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BrudicladTelchorEngineer.java @@ -0,0 +1,113 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.HasteAbility; +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.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.BrudicladTelchorMyrToken; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; +import mage.util.functions.EmptyApplyToPermanent; + +/** + * + * @author spjspj + */ +public final class BrudicladTelchorEngineer extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature tokens you control"); + + static { + filter.add(new TokenPredicate()); + } + + public BrudicladTelchorEngineer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{U}{R}"); + + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Creature tokens you control have haste. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter, true))); + + // At the beginning of combat on your turn, create a 2/1 blue Myr artifact creature token. Then you may choose a token you control. If you do, each other token you control becomes a copy of that token. + this.addAbility(new BeginningOfCombatTriggeredAbility(new BrudicladTelchorCombatffect(), TargetController.YOU, false)); + } + + public BrudicladTelchorEngineer(final BrudicladTelchorEngineer card) { + super(card); + } + + @Override + public BrudicladTelchorEngineer copy() { + return new BrudicladTelchorEngineer(this); + } +} + +class BrudicladTelchorCombatffect extends OneShotEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(" token you control. If you do, each other token you control becomes a copy of that token"); + + static { + filter.add(new TokenPredicate()); + } + + public BrudicladTelchorCombatffect() { + super(Outcome.Sacrifice); + this.staticText = " you may choose a token you control. If you do, each other token you control becomes a copy of that token"; + } + + public BrudicladTelchorCombatffect(final BrudicladTelchorCombatffect effect) { + super(effect); + } + + @Override + public BrudicladTelchorCombatffect copy() { + return new BrudicladTelchorCombatffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + CreateTokenEffect effect = new CreateTokenEffect(new BrudicladTelchorMyrToken(), 1); + + if (effect.apply(game, source)) { + TargetControlledPermanent target = new TargetControlledPermanent(0, 1, filter, true); + target.setNotTarget(true); + if (controller.choose(Outcome.Neutral, target, source.getSourceId(), game)) { + Permanent toCopyFromPermanent = game.getPermanent(target.getFirstTarget()); + + if (toCopyFromPermanent != null) { + for (Permanent toCopyToPermanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { + if (!toCopyToPermanent.equals(toCopyFromPermanent)) { + game.copyPermanent(toCopyFromPermanent, toCopyToPermanent.getId(), source, new EmptyApplyToPermanent()); + } + } + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BrutalHordechief.java b/Mage.Sets/src/mage/cards/b/BrutalHordechief.java index eb3cc16faf9..e3b37d68008 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalHordechief.java +++ b/Mage.Sets/src/mage/cards/b/BrutalHordechief.java @@ -113,7 +113,7 @@ class BrutalHordechiefTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent source = game.getPermanent(event.getSourceId()); - if (source != null && source.getControllerId().equals(controllerId)) { + if (source != null && source.isControlledBy(controllerId)) { UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(event.getSourceId(), game); this.getEffects().get(0).setTargetPointer(new FixedTarget(defendingPlayerId)); return true; diff --git a/Mage.Sets/src/mage/cards/b/BudokaPupil.java b/Mage.Sets/src/mage/cards/b/BudokaPupil.java index c09d9a1225c..d665178aa52 100644 --- a/Mage.Sets/src/mage/cards/b/BudokaPupil.java +++ b/Mage.Sets/src/mage/cards/b/BudokaPupil.java @@ -8,7 +8,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FlipSourceEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -20,7 +20,6 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.events.GameEvent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +43,7 @@ public final class BudokaPupil extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.KI.createInstance()), StaticFilters.SPIRIT_OR_ARCANE_CARD, true)); // At the beginning of the end step, if there are two or more ki counters on Budoka Pupil, you may flip it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new IchigaWhoTopplesOaks()), true), new SourceHasCounterCondition(CounterType.KI, 2, Integer.MAX_VALUE), "At the beginning of the end step, if there are two or more ki counters on {this}, you may flip it.")); diff --git a/Mage.Sets/src/mage/cards/b/BuildersBane.java b/Mage.Sets/src/mage/cards/b/BuildersBane.java index 6b90776cfa4..094a17f47e8 100644 --- a/Mage.Sets/src/mage/cards/b/BuildersBane.java +++ b/Mage.Sets/src/mage/cards/b/BuildersBane.java @@ -77,7 +77,7 @@ class BuildersBaneEffect extends OneShotEffect { if (permanent.destroy(source.getSourceId(), game, false)) { game.applyEffects(); if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId()) - && !game.getState().getZone(permanent.getId()).equals(Zone.GRAVEYARD)) { + && game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) { // A replacement effect has moved the card to another zone as grvayard continue; } diff --git a/Mage.Sets/src/mage/cards/b/BullRushBruiser.java b/Mage.Sets/src/mage/cards/b/BullRushBruiser.java index 508f309439d..ac0cfeaab98 100644 --- a/Mage.Sets/src/mage/cards/b/BullRushBruiser.java +++ b/Mage.Sets/src/mage/cards/b/BullRushBruiser.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.constants.SubType; @@ -36,7 +36,7 @@ public final class BullRushBruiser extends CardImpl { this.toughness = new MageInt(3); // Whenever Bull-Rush Bruiser attacks, if your team controls another Warrior, Bull-Rush Bruiser gains first strike until end of turn. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance()), false), new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks, if your team controls another Warrior, " diff --git a/Mage.Sets/src/mage/cards/b/BurnAway.java b/Mage.Sets/src/mage/cards/b/BurnAway.java index 69db42a5ddf..54e6e9344d0 100644 --- a/Mage.Sets/src/mage/cards/b/BurnAway.java +++ b/Mage.Sets/src/mage/cards/b/BurnAway.java @@ -62,7 +62,7 @@ class BurnAwayDelayedTriggeredAbility extends DelayedTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.isDiesEvent() && zEvent.getTarget() != null && zEvent.getTargetId().equals(getTargets().getFirstTarget())) { - this.getTargets().clear(); // else spell fizzels because target creature died + this.getTargets().clear(); // else spell fizzles because target creature died Target target = new TargetPlayer(); target.add(zEvent.getTarget().getControllerId(), game); this.addTarget(target); diff --git a/Mage.Sets/src/mage/cards/b/BurntheImpure.java b/Mage.Sets/src/mage/cards/b/BurnTheImpure.java similarity index 69% rename from Mage.Sets/src/mage/cards/b/BurntheImpure.java rename to Mage.Sets/src/mage/cards/b/BurnTheImpure.java index 5d6e6bd3213..9c57bb8b0db 100644 --- a/Mage.Sets/src/mage/cards/b/BurntheImpure.java +++ b/Mage.Sets/src/mage/cards/b/BurnTheImpure.java @@ -18,40 +18,41 @@ import mage.target.common.TargetCreaturePermanent; * * @author ayratn */ -public final class BurntheImpure extends CardImpl { +public final class BurnTheImpure extends CardImpl { - public BurntheImpure(UUID ownerId, CardSetInfo setInfo) { + public BurnTheImpure(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); + // Burn the Impure deals 3 damage to target creature. If that creature has infect, Burn the Impure deals 3 damage to that creature’s controller. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new BurntheImpureEffect()); + this.getSpellAbility().addEffect(new BurnTheImpureEffect()); } - public BurntheImpure(final BurntheImpure card) { + public BurnTheImpure(final BurnTheImpure card) { super(card); } @Override - public BurntheImpure copy() { - return new BurntheImpure(this); + public BurnTheImpure copy() { + return new BurnTheImpure(this); } } -class BurntheImpureEffect extends OneShotEffect { +class BurnTheImpureEffect extends OneShotEffect { - public BurntheImpureEffect() { + public BurnTheImpureEffect() { super(Outcome.Damage); staticText = "{this} deals 3 damage to target creature. If that creature has infect, {this} deals 3 damage to that creature's controller."; } - public BurntheImpureEffect(final BurntheImpureEffect effect) { + public BurnTheImpureEffect(final BurnTheImpureEffect effect) { super(effect); } @Override - public BurntheImpureEffect copy() { - return new BurntheImpureEffect(this); + public BurnTheImpureEffect copy() { + return new BurnTheImpureEffect(this); } @Override diff --git a/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java b/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java index 1aa46781da6..e916504a73b 100644 --- a/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java +++ b/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class BurningEyeZubera extends CardImpl { this.toughness = new MageInt(3); // When Burning-Eye Zubera dies, if 4 or more damage was dealt to it this turn, Burning-Eye Zubera deals 3 damage to any target. - Ability ability = new ConditionalTriggeredAbility(new DiesTriggeredAbility(new DamageTargetEffect(3)),new SourceGotFourDamage(), + Ability ability = new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new DamageTargetEffect(3)),new SourceGotFourDamage(), "When {this} dies, if 4 or more damage was dealt to it this turn, Burning-Eye Zubera deals 3 damage to any target"); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CabalCoffers.java b/Mage.Sets/src/mage/cards/c/CabalCoffers.java index 72b167b5e4b..15afb42b599 100644 --- a/Mage.Sets/src/mage/cards/c/CabalCoffers.java +++ b/Mage.Sets/src/mage/cards/c/CabalCoffers.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -28,9 +27,9 @@ public final class CabalCoffers extends CardImpl { } public CabalCoffers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - // {2}, {tap}: Add {B} for each Swamp you control. + // {2}, {T}: Add {B} for each Swamp you control. Ability ability = new DynamicManaAbility(Mana.BlackMana(1), new PermanentsOnBattlefieldCount(filter), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CabalTherapy.java b/Mage.Sets/src/mage/cards/c/CabalTherapy.java index 75e691855c9..70d7f7863cb 100644 --- a/Mage.Sets/src/mage/cards/c/CabalTherapy.java +++ b/Mage.Sets/src/mage/cards/c/CabalTherapy.java @@ -1,11 +1,10 @@ - package mage.cards.c; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.*; import mage.constants.CardType; @@ -26,10 +25,10 @@ import java.util.UUID; public final class CabalTherapy extends CardImpl { public CabalTherapy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); // Name a nonland card. Target player reveals their hand and discards all cards with that name. - this.getSpellAbility().addEffect((new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new CabalTherapyEffect()); @@ -53,7 +52,7 @@ class CabalTherapyEffect extends OneShotEffect { public CabalTherapyEffect() { super(Outcome.Discard); - staticText = "Name a nonland card. Target player reveals their hand and discards all cards with that name"; + staticText = "Target player reveals their hand and discards all cards with that name"; } public CabalTherapyEffect(final CabalTherapyEffect effect) { @@ -66,16 +65,15 @@ class CabalTherapyEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (targetPlayer != null && controller != null && sourceObject != null) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); Cards hand = targetPlayer.getHand(); for (Card card : hand.getCards(game)) { - if(card.isSplitCard()){ + if (card.isSplitCard()) { SplitCard splitCard = (SplitCard) card; - if(splitCard.getLeftHalfCard().getName().equals(cardName)){ + if (splitCard.getLeftHalfCard().getName().equals(cardName)) { targetPlayer.discard(card, source, game); - } - else if(splitCard.getRightHalfCard().getName().equals(cardName)){ + } else if (splitCard.getRightHalfCard().getName().equals(cardName)) { targetPlayer.discard(card, source, game); } } diff --git a/Mage.Sets/src/mage/cards/c/CaligoSkinWitch.java b/Mage.Sets/src/mage/cards/c/CaligoSkinWitch.java index 511993aa510..1ecf21e9cc0 100644 --- a/Mage.Sets/src/mage/cards/c/CaligoSkinWitch.java +++ b/Mage.Sets/src/mage/cards/c/CaligoSkinWitch.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; import mage.abilities.keyword.KickerAbility; @@ -32,7 +32,7 @@ public final class CaligoSkinWitch extends CardImpl { this.addAbility(new KickerAbility("{3}{B}")); // When Caligo Skin-Witch enters the battlefield, if it was kicked, each opponent discards two cards. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect( new StaticValue(2), false, diff --git a/Mage.Sets/src/mage/cards/c/CallForUnity.java b/Mage.Sets/src/mage/cards/c/CallForUnity.java index 89acf06212f..cb5c59b1c31 100644 --- a/Mage.Sets/src/mage/cards/c/CallForUnity.java +++ b/Mage.Sets/src/mage/cards/c/CallForUnity.java @@ -6,7 +6,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostControlledEffect; @@ -34,7 +34,7 @@ public final class CallForUnity extends CardImpl { // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, put a unity counter on Call for Unity. TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.UNITY.createInstance(), true), false); - this.addAbility(new ConditionalTriggeredAbility(ability, RevoltCondition.instance, ruleText), new RevoltWatcher()); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, RevoltCondition.instance, ruleText), new RevoltWatcher()); // Creatures you control get +1/+1 for each unity counter on Call for Unity. Effect effect = new BoostControlledEffect(new CountersSourceCount(CounterType.UNITY), new CountersSourceCount(CounterType.UNITY), Duration.WhileOnBattlefield, diff --git a/Mage.Sets/src/mage/cards/c/CallOfTheFullMoon.java b/Mage.Sets/src/mage/cards/c/CallOfTheFullMoon.java index 15e9bc38b7a..c6346f70b1d 100644 --- a/Mage.Sets/src/mage/cards/c/CallOfTheFullMoon.java +++ b/Mage.Sets/src/mage/cards/c/CallOfTheFullMoon.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.SacrificeSourceEffect; @@ -47,7 +47,7 @@ public final class CallOfTheFullMoon extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, sacrifice Call of the Full Moon. TriggeredAbility ability2 = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect(), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability2, TwoOrMoreSpellsWereCastLastTurnCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, TwoOrMoreSpellsWereCastLastTurnCondition.instance, "At the beginning of each upkeep, if a player cast two or more spells last turn, sacrifice {this}.")); } diff --git a/Mage.Sets/src/mage/cards/c/CallToTheGrave.java b/Mage.Sets/src/mage/cards/c/CallToTheGrave.java index f639bab5c1f..5fa2e10f406 100644 --- a/Mage.Sets/src/mage/cards/c/CallToTheGrave.java +++ b/Mage.Sets/src/mage/cards/c/CallToTheGrave.java @@ -6,7 +6,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.CreatureCountCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class CallToTheGrave extends CardImpl { this.addAbility(ability); // At the beginning of the end step, if no creatures are on the battlefield, sacrifice Call to the Grave. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); } public CallToTheGrave(final CallToTheGrave card) { diff --git a/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java b/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java index b386732ee92..e5607074fe6 100644 --- a/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java +++ b/Mage.Sets/src/mage/cards/c/CallerOfTheClaw.java @@ -82,7 +82,7 @@ class CallerOfTheClawWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { Permanent card = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (card != null && card.getOwnerId().equals(this.controllerId) && card.isCreature() && !(card instanceof PermanentToken)) { + if (card != null && card.isOwnedBy(this.controllerId) && card.isCreature() && !(card instanceof PermanentToken)) { creaturesCount++; } } diff --git a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java index d27e9069319..f05249eeac4 100644 --- a/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java +++ b/Mage.Sets/src/mage/cards/c/CallerOfTheHunt.java @@ -49,7 +49,7 @@ public final class CallerOfTheHunt extends CardImpl { if (mageObject != null && effect.apply(game, ability)) { FilterPermanent filter = new FilterPermanent(); - filter.add(new ChosenSubtypePredicate(mageObject.getId())); + filter.add(new ChosenSubtypePredicate()); ContinuousEffect effectPower = new SetPowerSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.Custom); ContinuousEffect effectToughness = new SetToughnessSourceEffect(new PermanentsOnBattlefieldCount(filter), Duration.Custom); game.addEffect(effectPower, ability); diff --git a/Mage.Sets/src/mage/cards/c/CallowJushi.java b/Mage.Sets/src/mage/cards/c/CallowJushi.java index d0c38ae02e2..3c5915d34f2 100644 --- a/Mage.Sets/src/mage/cards/c/CallowJushi.java +++ b/Mage.Sets/src/mage/cards/c/CallowJushi.java @@ -10,7 +10,7 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CounterUnlessPaysEffect; import mage.abilities.effects.common.FlipSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -24,7 +24,6 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.events.GameEvent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import mage.target.TargetSpell; /** @@ -47,7 +46,7 @@ public final class CallowJushi extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.KI.createInstance()), StaticFilters.SPIRIT_OR_ARCANE_CARD, true)); // At the beginning of the end step, if there are two or more ki counters on Callow Jushi, you may flip it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new JarakuTheInterloper()), true), new SourceHasCounterCondition(CounterType.KI, 2, Integer.MAX_VALUE), "At the beginning of the end step, if there are two or more ki counters on {this}, you may flip it.")); diff --git a/Mage.Sets/src/mage/cards/c/Camouflage.java b/Mage.Sets/src/mage/cards/c/Camouflage.java index 5eb68019af9..ed8719b8c2f 100644 --- a/Mage.Sets/src/mage/cards/c/Camouflage.java +++ b/Mage.Sets/src/mage/cards/c/Camouflage.java @@ -39,7 +39,7 @@ public final class Camouflage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); // Cast Camouflage only during your declare attackers step. - this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_ATTACKERS, MyTurnCondition.instance, "Cast {this} only during your declare attackers step")); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_ATTACKERS, MyTurnCondition.instance, "Cast this spell only during your declare attackers step")); // This turn, instead of declaring blockers, each defending player chooses any number of creatures he or she controls and divides them into a number of piles equal to the number of attacking creatures for whom that player is the defending player. Creatures he or she controls that can block additional creatures may likewise be put into additional piles. Assign each pile to a different one of those attacking creatures at random. Each creature in a pile that can block the creature that pile is assigned to does so. (Piles can be empty.) this.getSpellAbility().addEffect(new CamouflageEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CampaignOfVengeance.java b/Mage.Sets/src/mage/cards/c/CampaignOfVengeance.java index 9db40745045..074e519a836 100644 --- a/Mage.Sets/src/mage/cards/c/CampaignOfVengeance.java +++ b/Mage.Sets/src/mage/cards/c/CampaignOfVengeance.java @@ -61,7 +61,7 @@ class CampaignOfVengeanceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent source = game.getPermanent(event.getSourceId()); - if (source != null && source.getControllerId().equals(controllerId)) { + if (source != null && source.isControlledBy(controllerId)) { UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(event.getSourceId(), game); this.getEffects().get(0).setTargetPointer(new FixedTarget(defendingPlayerId)); return true; diff --git a/Mage.Sets/src/mage/cards/c/CantoBightEnforcer.java b/Mage.Sets/src/mage/cards/c/CantoBightEnforcer.java new file mode 100644 index 00000000000..66559ce80f6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CantoBightEnforcer.java @@ -0,0 +1,48 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.BountyAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class CantoBightEnforcer extends CardImpl { + + public CantoBightEnforcer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.HUNTER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Canto Bight Enforcer enters the battlefield, you may put a bounty counter on target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), true); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // Bounty - Whenever a creature an opponent controls with a bounty counter on it dies, put a +1/+1 counter on Canto Bight Enforcer. + this.addAbility(new BountyAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()))); + } + + public CantoBightEnforcer(final CantoBightEnforcer card) { + super(card); + } + + @Override + public CantoBightEnforcer copy() { + return new CantoBightEnforcer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CantonicaCasino.java b/Mage.Sets/src/mage/cards/c/CantonicaCasino.java new file mode 100644 index 00000000000..4c528b303d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CantonicaCasino.java @@ -0,0 +1,79 @@ +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; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @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) { + super(card); + } + + @Override + public CantonicaCasino copy() { + return new CantonicaCasino(this); + } +} + +class CantonicaCasinoEffect extends OneShotEffect { + + public CantonicaCasinoEffect() { + super(Outcome.Neutral); + staticText = "Roll two six-sided dice. If you roll doubles, gain 10 life. Otherwise, lose 1 life"; + } + + public CantonicaCasinoEffect(final CantonicaCasinoEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player you = game.getPlayer(source.getControllerId()); + if(you != null) { + // Roll two six-sided dice + int dice1 = you.rollDice(game, 6); + int dice2 = you.rollDice(game, 6); + + if(dice1 == dice2) { + // If you roll doubles, gain 10 life + you.gainLife(10, game, source); + return false; + } + else { + // Otherwise, lose 1 life + you.loseLife(1, game, false); + return false; + } + } + return false; + } + + @Override + public CantonicaCasinoEffect copy() { + return new CantonicaCasinoEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CapitalPunishment.java b/Mage.Sets/src/mage/cards/c/CapitalPunishment.java index 9c3c9c8f832..12d184d2828 100644 --- a/Mage.Sets/src/mage/cards/c/CapitalPunishment.java +++ b/Mage.Sets/src/mage/cards/c/CapitalPunishment.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -13,7 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.TargetController; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; @@ -25,7 +24,6 @@ public final class CapitalPunishment extends CardImpl { public CapitalPunishment(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); - // Council's dilemma — Starting with you, each player votes for death or taxes. Each opponent sacrifices a creature for each death vote and discards a card for each taxes vote. this.getSpellAbility().addEffect(new CapitalPunishmentDilemmaEffect()); @@ -57,13 +55,15 @@ class CapitalPunishmentDilemmaEffect extends CouncilsDilemmaVoteEffect { Player controller = game.getPlayer(source.getControllerId()); //If no controller, exit out here and do not vote. - if (controller == null) return false; + if (controller == null) { + return false; + } this.vote("death", "taxes", controller, game, source); //Death Votes if (voteOneCount > 0) { - Effect sacrificeEffect = new SacrificeOpponentsEffect(voteOneCount, new FilterControlledCreaturePermanent()); + Effect sacrificeEffect = new SacrificeOpponentsEffect(voteOneCount, StaticFilters.FILTER_CONTROLLED_CREATURE); sacrificeEffect.apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/c/CaptainPhasma.java b/Mage.Sets/src/mage/cards/c/CaptainPhasma.java new file mode 100644 index 00000000000..829342d2b6c --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CaptainPhasma.java @@ -0,0 +1,67 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.TrooperToken; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author NinthWorld + */ +public final class CaptainPhasma extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Nontoken trooper creatures"); + private static final FilterCreatureCard filterCard = new FilterCreatureCard("Trooper card"); + + static { + filter.add(new SubtypePredicate(SubType.TROOPER)); + filter.add(Predicates.not(new TokenPredicate())); + filterCard.add(new SubtypePredicate(SubType.TROOPER)); + } + + public CaptainPhasma(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Nontoken Trooper creatures you control have "When this creature enters the battlefield, create 1/1/ white Trooper creature token." + Ability ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TrooperToken()) + .setText("When this creature enters the battlefield, create a 1/1 white Trooper creature token"), + false, true); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new GainAbilityControlledEffect(ability, Duration.WhileOnBattlefield, filter, false))); + + // {W}{U}{B}{R}{G}: Search your library for a Trooper creature card, reveal it, put it into your hand, then shuffle your library. + this.addAbility(new SimpleActivatedAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true, true), new ManaCostsImpl("{W}{U}{B}{R}{G}"))); + } + + public CaptainPhasma(final CaptainPhasma card) { + super(card); + } + + @Override + public CaptainPhasma copy() { + return new CaptainPhasma(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CarapaceForger.java b/Mage.Sets/src/mage/cards/c/CarapaceForger.java index 7e8b3f6367f..03ce8bd225e 100644 --- a/Mage.Sets/src/mage/cards/c/CarapaceForger.java +++ b/Mage.Sets/src/mage/cards/c/CarapaceForger.java @@ -21,7 +21,7 @@ import mage.constants.Zone; * @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"; + 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}"); diff --git a/Mage.Sets/src/mage/cards/c/CaravanVigil.java b/Mage.Sets/src/mage/cards/c/CaravanVigil.java index 543efe0bfce..963e149db37 100644 --- a/Mage.Sets/src/mage/cards/c/CaravanVigil.java +++ b/Mage.Sets/src/mage/cards/c/CaravanVigil.java @@ -26,7 +26,7 @@ public final class CaravanVigil extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}"); // Search your library for a basic land card, reveal it, put it into your hand, then shuffle your library. - // Morbid - You may put that card onto the battlefield instead of putting it into your hand if a creature died this turn. + // Morbid — You may put that card onto the battlefield instead of putting it into your hand if a creature died this turn. this.getSpellAbility().addEffect(new CaravanVigilEffect()); } diff --git a/Mage.Sets/src/mage/cards/c/CarnifexDemon.java b/Mage.Sets/src/mage/cards/c/CarnifexDemon.java index eab7da70aa9..9d2bb438dd5 100644 --- a/Mage.Sets/src/mage/cards/c/CarnifexDemon.java +++ b/Mage.Sets/src/mage/cards/c/CarnifexDemon.java @@ -1,5 +1,3 @@ - - package mage.cards.c; import java.util.UUID; @@ -9,18 +7,17 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; 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.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; /** * @@ -28,20 +25,38 @@ import mage.game.permanent.Permanent; */ public final class CarnifexDemon extends CardImpl { - public CarnifexDemon (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each other creature"); + + static { + filter.add(new AnotherPredicate()); + } + + public CarnifexDemon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); this.subtype.add(SubType.DEMON); this.power = new MageInt(6); this.toughness = new MageInt(6); + this.addAbility(FlyingAbility.getInstance()); - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(2)), "{this} enters the battlefield with two -1/-1 counters on it")); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CarnifexDemonEffect(), new ManaCostsImpl("{B}")); + + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.M1M1.createInstance(2)), + "{this} enters the battlefield with two -1/-1 counters on it" + )); + + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new AddCountersAllEffect( + CounterType.M1M1.createInstance(), + filter + ), new ManaCostsImpl("{B}") + ); ability.addCost(new RemoveCountersSourceCost(CounterType.M1M1.createInstance())); this.addAbility(ability); } - public CarnifexDemon (final CarnifexDemon card) { + public CarnifexDemon(final CarnifexDemon card) { super(card); } @@ -50,32 +65,3 @@ public final class CarnifexDemon extends CardImpl { return new CarnifexDemon(this); } } - -class CarnifexDemonEffect extends OneShotEffect { - public CarnifexDemonEffect() { - super(Outcome.UnboostCreature); - staticText = "Put a -1/-1 counter on each other creature"; - } - - public CarnifexDemonEffect(final CarnifexDemonEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - for (Permanent t : game.getBattlefield().getAllActivePermanents()) { - if (t.isCreature() && !t.getId().equals(source.getSourceId())) - t.addCounters(CounterType.M1M1.createInstance(), source, game); - } - } - return false; - } - - @Override - public CarnifexDemonEffect copy() { - return new CarnifexDemonEffect(this); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CastThroughTime.java b/Mage.Sets/src/mage/cards/c/CastThroughTime.java index 92a51e71af4..143688a4200 100644 --- a/Mage.Sets/src/mage/cards/c/CastThroughTime.java +++ b/Mage.Sets/src/mage/cards/c/CastThroughTime.java @@ -77,7 +77,7 @@ class GainReboundEffect extends ContinuousEffectImpl { } for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { StackObject stackObject = iterator.next(); - if (stackObject instanceof Spell && stackObject.getControllerId().equals(source.getControllerId())) { + if (stackObject instanceof Spell && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; Card card = spell.getCard(); if (card != null) { diff --git a/Mage.Sets/src/mage/cards/c/CatalystStone.java b/Mage.Sets/src/mage/cards/c/CatalystStone.java index bdcf7f251ef..0837d009974 100644 --- a/Mage.Sets/src/mage/cards/c/CatalystStone.java +++ b/Mage.Sets/src/mage/cards/c/CatalystStone.java @@ -89,7 +89,7 @@ class CatalystStoneCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { return SpellAbilityCastMode.FLASHBACK.equals(((SpellAbility) abilityToModify).getSpellAbilityCastMode()); } } diff --git a/Mage.Sets/src/mage/cards/c/CavalryDrillmaster.java b/Mage.Sets/src/mage/cards/c/CavalryDrillmaster.java new file mode 100644 index 00000000000..c2846c03559 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CavalryDrillmaster.java @@ -0,0 +1,52 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class CavalryDrillmaster extends CardImpl { + + public CavalryDrillmaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // When Cavalry Drillmaster enters the battlefield, target creature +2/+0 and gains first strike until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility( + new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("target creature gets +2/+0") + ); + ability.addEffect(new GainAbilityTargetEffect( + FirstStrikeAbility.getInstance(), + Duration.EndOfTurn + ).setText("and gains first strike until end of turn")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public CavalryDrillmaster(final CavalryDrillmaster card) { + super(card); + } + + @Override + public CavalryDrillmaster copy() { + return new CavalryDrillmaster(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CelestialColonnade.java b/Mage.Sets/src/mage/cards/c/CelestialColonnade.java index 1db83f2a875..fb98055c58a 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialColonnade.java +++ b/Mage.Sets/src/mage/cards/c/CelestialColonnade.java @@ -37,7 +37,7 @@ public final class CelestialColonnade extends CardImpl { this.addAbility(new BlueManaAbility()); this.addAbility(new WhiteManaAbility()); - // {3}{W}{U}: Until end of turn, Celestial Colonnade becomes a 4/4 white and blue Elemental creature with flying and vigilance. It’s still a land. + // {3}{W}{U}: Until end of turn, Celestial Colonnade becomes a 4/4 white and blue Elemental creature with flying and vigilance. It's still a land. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect( new CreatureToken(4, 4, "4/4 white and blue Elemental creature with flying and vigilance") .withColor("WU") diff --git a/Mage.Sets/src/mage/cards/c/CelestialConvergence.java b/Mage.Sets/src/mage/cards/c/CelestialConvergence.java index 424f2a8e923..5b8145a9c9a 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialConvergence.java +++ b/Mage.Sets/src/mage/cards/c/CelestialConvergence.java @@ -78,11 +78,11 @@ class CelestialConvergenceEffect extends OneShotEffect { /** * 801.14. If an effect states that a player wins the game, all of - * that player’s opponents within their range of influence lose the + * that player's opponents within their range of influence lose the * game instead. # * * 801.15. If the effect of a spell or ability states that the game - * is a draw, the game is a draw for that spell or ability’s + * is a draw, the game is a draw for that spell or ability's * controller and all players within their range of influence. They * leave the game. All remaining players continue to play the game. * diff --git a/Mage.Sets/src/mage/cards/c/CelestialDawn.java b/Mage.Sets/src/mage/cards/c/CelestialDawn.java index 26e74879d8a..787eaf39cc2 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialDawn.java +++ b/Mage.Sets/src/mage/cards/c/CelestialDawn.java @@ -122,13 +122,13 @@ class CelestialDawnToWhiteEffect extends ContinuousEffectImpl { } // Stack for (MageObject object : game.getStack()) { - if (object instanceof Spell && ((Spell) object).getControllerId().equals(controller.getId())) { + if (object instanceof Spell && ((Spell) object).isControlledBy(controller.getId())) { setColor(object.getColor(game), game); } } // Exile for (Card card : game.getExile().getAllCards(game)) { - if (card.getOwnerId().equals(controller.getId())) { + if (card.isOwnedBy(controller.getId())) { setColor(card.getColor(game), game); } } diff --git a/Mage.Sets/src/mage/cards/c/CemeteryPuca.java b/Mage.Sets/src/mage/cards/c/CemeteryPuca.java index 89b065aa716..37498a7238e 100644 --- a/Mage.Sets/src/mage/cards/c/CemeteryPuca.java +++ b/Mage.Sets/src/mage/cards/c/CemeteryPuca.java @@ -36,7 +36,7 @@ public final class CemeteryPuca extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - // Whenever a creature dies, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability. + // Whenever a creature dies, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature, except it has this ability. this.addAbility(new DiesCreatureTriggeredAbility(new DoIfCostPaid(new CemeteryPucaEffect(), new ManaCostsImpl("{1}")), false, new FilterCreaturePermanent("a creature"), true)); } @@ -55,7 +55,7 @@ class CemeteryPucaEffect extends OneShotEffect { public CemeteryPucaEffect() { super(Outcome.Copy); - staticText = " {this} becomes a copy of that creature and gains this ability"; + staticText = " {this} becomes a copy of that creature, except it has this ability"; } public CemeteryPucaEffect(final CemeteryPucaEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/CetaSanctuary.java b/Mage.Sets/src/mage/cards/c/CetaSanctuary.java index 920b60d38f3..8bd830649f9 100644 --- a/Mage.Sets/src/mage/cards/c/CetaSanctuary.java +++ b/Mage.Sets/src/mage/cards/c/CetaSanctuary.java @@ -4,7 +4,7 @@ package mage.cards.c; import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryTriggeredAbility; +import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ public final class CetaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // At the beginning of your upkeep, if you control a red or green permanent, draw a card, then discard a card. If you control a red permanent and a green permanent, instead draw two cards, then discard a card. - Ability ability = new SanctuaryTriggeredAbility( + Ability ability = new SanctuaryInterveningIfTriggeredAbility( new DrawDiscardControllerEffect(1, 1), new DrawDiscardControllerEffect(2, 1), ObjectColor.GREEN, ObjectColor.RED, "At the beginning of your upkeep, if you control a red or green permanent, draw a card, then discard a card. " + "If you control a red permanent and a green permanent, instead draw two cards, then discard a card." diff --git a/Mage.Sets/src/mage/cards/c/ChainLightning.java b/Mage.Sets/src/mage/cards/c/ChainLightning.java index 01ba69b796d..27492f792fb 100644 --- a/Mage.Sets/src/mage/cards/c/ChainLightning.java +++ b/Mage.Sets/src/mage/cards/c/ChainLightning.java @@ -44,7 +44,7 @@ class ChainLightningEffect extends OneShotEffect { ChainLightningEffect() { super(Outcome.Damage); - this.staticText = "Chain Lightning deals 3 damage to any target. Then that player or that creature's controller may pay {R}{R}. If the player does, he or she may copy this spell and may choose a new target for that copy."; + this.staticText = "{this} deals 3 damage to any target. Then that player or that permanent's controller may pay {R}{R}. If the player does, they may copy this spell and may choose a new target for that copy"; } ChainLightningEffect(final ChainLightningEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java index 664d9387ab5..04f12fe4cf8 100644 --- a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java +++ b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java @@ -85,7 +85,7 @@ class ChainsOfMephistophelesReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (game.getActivePlayerId().equals(event.getPlayerId()) && game.getPhase().getStep().getType() == PhaseStep.DRAW) { + if (game.isActivePlayer(event.getPlayerId()) && game.getPhase().getStep().getType() == PhaseStep.DRAW) { CardsDrawnDuringDrawStepWatcher watcher = (CardsDrawnDuringDrawStepWatcher) game.getState().getWatchers().get(CardsDrawnDuringDrawStepWatcher.class.getSimpleName()); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/c/ChakramRetriever.java b/Mage.Sets/src/mage/cards/c/ChakramRetriever.java index 70c5af3f67b..fd4704236da 100644 --- a/Mage.Sets/src/mage/cards/c/ChakramRetriever.java +++ b/Mage.Sets/src/mage/cards/c/ChakramRetriever.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -15,6 +14,8 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author TheElk801 diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java b/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java index 3422e28fc32..de10a0845e0 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java +++ b/Mage.Sets/src/mage/cards/c/ChampionOfLambholt.java @@ -79,7 +79,7 @@ class ChampionOfLambholtEffect extends RestrictionEffect { @Override public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null && attacker.getControllerId().equals(sourcePermanent.getControllerId())) { + if (sourcePermanent != null && attacker.isControlledBy(sourcePermanent.getControllerId())) { return blocker.getPower().getValue() >= sourcePermanent.getPower().getValue(); } return true; diff --git a/Mage.Sets/src/mage/cards/c/ChampionsVictory.java b/Mage.Sets/src/mage/cards/c/ChampionsVictory.java index 6624c1d9554..41ce200973f 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionsVictory.java +++ b/Mage.Sets/src/mage/cards/c/ChampionsVictory.java @@ -26,7 +26,7 @@ public final class ChampionsVictory extends CardImpl { // Cast Champion's Victory only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/ChanceEncounter.java b/Mage.Sets/src/mage/cards/c/ChanceEncounter.java index 9cae7a541b3..84d4fbbac84 100644 --- a/Mage.Sets/src/mage/cards/c/ChanceEncounter.java +++ b/Mage.Sets/src/mage/cards/c/ChanceEncounter.java @@ -6,7 +6,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -32,7 +32,7 @@ public final class ChanceEncounter extends CardImpl { // 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); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceHasCounterCondition(CounterType.LUCK, 10, Integer.MAX_VALUE), + 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")); } @@ -68,7 +68,7 @@ class ChanceEncounterTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return this.getControllerId().equals(event.getPlayerId()) && event.getFlag(); + return this.isControlledBy(event.getPlayerId()) && event.getFlag(); } @Override diff --git a/Mage.Sets/src/mage/cards/c/ChancellorOfTheTangle.java b/Mage.Sets/src/mage/cards/c/ChancellorOfTheTangle.java index d7a2f94c461..3b61a924634 100644 --- a/Mage.Sets/src/mage/cards/c/ChancellorOfTheTangle.java +++ b/Mage.Sets/src/mage/cards/c/ChancellorOfTheTangle.java @@ -67,7 +67,7 @@ class ChancellorOfTheTangleDelayedTriggeredAbility extends DelayedTriggeredAbili @Override public boolean checkTrigger(GameEvent event, Game game) { - return game.getActivePlayerId().equals(controllerId); + return game.isActivePlayer(controllerId); } @Override public ChancellorOfTheTangleDelayedTriggeredAbility copy() { diff --git a/Mage.Sets/src/mage/cards/c/ChandraNalaar.java b/Mage.Sets/src/mage/cards/c/ChandraNalaar.java index 2f193dd7147..34c5ef88410 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraNalaar.java +++ b/Mage.Sets/src/mage/cards/c/ChandraNalaar.java @@ -19,7 +19,6 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; @@ -36,9 +35,9 @@ public final class ChandraNalaar extends CardImpl { this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(6)); - // +1: Chandra Nalaar deals 1 damage to target player. + // +1: Chandra Nalaar deals 1 damage to target player or planeswalker. LoyaltyAbility ability1 = new LoyaltyAbility(new DamageTargetEffect(1), 1); - ability1.addTarget(new TargetPlayer()); + ability1.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability1); // -X: Chandra Nalaar deals X damage to target creature. @@ -46,11 +45,11 @@ public final class ChandraNalaar extends CardImpl { ability2.addTarget(new TargetCreaturePermanent()); this.addAbility(ability2); - // -8: Chandra Nalaar deals 10 damage to target player and each creature he or she controls. + // -8: Chandra Nalaar deals 10 damage to target player or planeswalker and each creature that player or that planeswalker’s controller controls. Effects effects1 = new Effects(); effects1.add(new DamageTargetEffect(10)); effects1.add(new DamageAllControlledTargetEffect(10, new FilterCreaturePermanent()) - .setText("and each creature that player or that planeswalker’s controller controls") + .setText("and each creature that player or that planeswalker's controller controls") ); LoyaltyAbility ability3 = new LoyaltyAbility(effects1, -8); ability3.addTarget(new TargetPlayerOrPlaneswalker()); diff --git a/Mage.Sets/src/mage/cards/c/ChandraPyrogenius.java b/Mage.Sets/src/mage/cards/c/ChandraPyrogenius.java index 5cce457cab8..900ad4bc2b2 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraPyrogenius.java +++ b/Mage.Sets/src/mage/cards/c/ChandraPyrogenius.java @@ -45,7 +45,7 @@ public final class ChandraPyrogenius extends CardImpl { Effects effects = new Effects(); effects.add(new DamageTargetEffect(6)); effects.add(new DamageAllControlledTargetEffect(6, new FilterCreaturePermanent()) - .setText("and each creature that player or that planeswalker’s controller controls") + .setText("and each creature that player or that planeswalker's controller controls") ); ability = new LoyaltyAbility(effects, -10); ability.addTarget(new TargetPlayerOrPlaneswalker()); diff --git a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java index cff315d1578..4e5b7fe082d 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java +++ b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java @@ -71,7 +71,7 @@ class ChandraPyromasterEffect1 extends OneShotEffect { public ChandraPyromasterEffect1() { super(Outcome.Damage); - staticText = "{this} deals 1 damage to target player or planeswalker and 1 damage to up to one target creature that player or that planeswalker’s controller controls. That creature can’t block this turn."; + staticText = "{this} deals 1 damage to target player or planeswalker and 1 damage to up to one target creature that player or that planeswalker's controller controls. That creature can't block this turn."; } public ChandraPyromasterEffect1(final ChandraPyromasterEffect1 effect) { @@ -115,7 +115,7 @@ class ChandraPyromasterTarget extends TargetPermanent { } UUID firstTarget = player.getId(); Permanent permanent = game.getPermanent(id); - if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + if (firstTarget != null && permanent != null && permanent.isControlledBy(firstTarget)) { return super.canTarget(id, source, game); } return false; @@ -142,7 +142,7 @@ class ChandraPyromasterTarget extends TargetPermanent { if (player != null) { for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.getControllerId().equals(player.getId())) { + if (permanent != null && permanent.isControlledBy(player.getId())) { possibleTargets.add(targetId); } } diff --git a/Mage.Sets/src/mage/cards/c/ChandraTorchOfDefiance.java b/Mage.Sets/src/mage/cards/c/ChandraTorchOfDefiance.java index 33fe592e33e..81a6e6c8613 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraTorchOfDefiance.java +++ b/Mage.Sets/src/mage/cards/c/ChandraTorchOfDefiance.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -22,7 +21,6 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.TargetController; -import mage.constants.Zone; import mage.game.Game; import mage.game.command.emblems.ChandraTorchOfDefianceEmblem; import mage.players.Library; @@ -92,10 +90,10 @@ class ChandraTorchOfDefianceEffect extends OneShotEffect { Card card = library.getFromTop(game); if (card != null) { boolean exiledCardWasCast = false; - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); - if (!card.getManaCost().isEmpty()) { - if (controller.chooseUse(Outcome.Benefit, "Cast the card? (You still pay the costs)", source, game) && !card.isLand()) { - exiledCardWasCast = controller.cast(card.getSpellAbility(), game, false, new MageObjectReference(source.getSourceObject(game), game)); + controller.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName()); + if (!card.getManaCost().isEmpty() && !card.isLand()) { + if (controller.chooseUse(Outcome.Benefit, "Cast " + card.getName() + "? (You still pay the costs)", source, game)) { + exiledCardWasCast = controller.cast(card.getSpellAbility(), game, false, new MageObjectReference(sourceObject, game)); } } if (!exiledCardWasCast) { diff --git a/Mage.Sets/src/mage/cards/c/ChandrasFury.java b/Mage.Sets/src/mage/cards/c/ChandrasFury.java index 44e6f4af180..89414b89dfa 100644 --- a/Mage.Sets/src/mage/cards/c/ChandrasFury.java +++ b/Mage.Sets/src/mage/cards/c/ChandrasFury.java @@ -22,7 +22,7 @@ public final class ChandrasFury extends CardImpl { // Chandra's Fury deals 4 damage to target player and 1 damage to each creature that player controls. this.getSpellAbility().addEffect(new DamageTargetEffect(4)); this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()) - .setText("and each creature that player or that planeswalker’s controller controls") + .setText("and each creature that player or that planeswalker's controller controls") ); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); } diff --git a/Mage.Sets/src/mage/cards/c/ChannelHarm.java b/Mage.Sets/src/mage/cards/c/ChannelHarm.java index 4d063d06442..ecd7da14f4f 100644 --- a/Mage.Sets/src/mage/cards/c/ChannelHarm.java +++ b/Mage.Sets/src/mage/cards/c/ChannelHarm.java @@ -82,14 +82,14 @@ class ChannelHarmEffect extends PreventionEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game)) { Permanent targetPermanent = game.getPermanent(event.getTargetId()); - if ((targetPermanent != null && targetPermanent.getControllerId().equals(source.getControllerId())) + if ((targetPermanent != null && targetPermanent.isControlledBy(source.getControllerId())) || event.getTargetId().equals(source.getControllerId())) { MageObject damageSource = game.getObject(event.getSourceId()); if (damageSource instanceof Controllable) { - return !((Controllable) damageSource).getControllerId().equals(source.getControllerId()); + return !((Controllable) damageSource).isControlledBy(source.getControllerId()); } else if (damageSource instanceof Card) { - return !((Card) damageSource).getOwnerId().equals(source.getControllerId()); + return !((Card) damageSource).isOwnedBy(source.getControllerId()); } } } diff --git a/Mage.Sets/src/mage/cards/c/ChaosWand.java b/Mage.Sets/src/mage/cards/c/ChaosWand.java new file mode 100644 index 00000000000..f5f790060aa --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChaosWand.java @@ -0,0 +1,98 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +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.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class ChaosWand extends CardImpl { + + public ChaosWand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {4}, {T}: Target opponent exiles cards from the top of their library until they exile an instant or sorcery card. You may cast that card without paying its mana cost. Then put the exiled cards that weren't cast this way on the bottom of that library in a random order. + Ability ability = new SimpleActivatedAbility( + new ChaosWandEffect(), + new GenericManaCost(4) + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public ChaosWand(final ChaosWand card) { + super(card); + } + + @Override + public ChaosWand copy() { + return new ChaosWand(this); + } +} + +class ChaosWandEffect extends OneShotEffect { + + public ChaosWandEffect() { + super(Outcome.Benefit); + this.staticText = "Target opponent exiles cards from the top of their library " + + "until they exile an instant or sorcery card. " + + "You may cast that card without paying its mana cost. " + + "Then put the exiled cards that weren't cast this way on the " + + "bottom of that library in a random order."; + } + + public ChaosWandEffect(final ChaosWandEffect effect) { + super(effect); + } + + @Override + public ChaosWandEffect copy() { + return new ChaosWandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(source.getFirstTarget()); + if (controller == null || opponent == null) { + return false; + } + Cards cardsToShuffle = new CardsImpl(); + while (opponent.getLibrary().hasCards()) { + Card card = opponent.getLibrary().getFromTop(game); + if (card == null) { + break; + } + opponent.moveCards(card, Zone.EXILED, source, game); + controller.revealCards(source, new CardsImpl(card), game); + if (card.isInstant() || card.isSorcery()) { + if (!controller.chooseUse(outcome, "Cast " + card.getName() + " without paying its mana cost?", source, game) + || !controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game))) { + cardsToShuffle.add(card); + } + break; + } else { + cardsToShuffle.add(card); + } + } + return opponent.putCardsOnBottomOfLibrary(cardsToShuffle, game, source, false); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java b/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java new file mode 100644 index 00000000000..4d6520a3fe8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChariotOfTheSun.java @@ -0,0 +1,82 @@ +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.costs.mana.GenericManaCost; +import mage.abilities.effects.ContinuousEffectImpl; +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.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class ChariotOfTheSun extends CardImpl { + + public ChariotOfTheSun(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {2}, {tap}: Until end of turn, target creature you control gains flying and its toughness becomes 1. + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect( + FlyingAbility.getInstance(), + Duration.EndOfTurn, + "until end of turn, target creature you control gains flying" + ), + new GenericManaCost(2) + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + ability.addEffect(new ChariotOfTheSunEffect()); + this.addAbility(ability); + } + + public ChariotOfTheSun(final ChariotOfTheSun card) { + super(card); + } + + @Override + public ChariotOfTheSun copy() { + return new ChariotOfTheSun(this); + } +} + +class ChariotOfTheSunEffect extends ContinuousEffectImpl { + + public ChariotOfTheSunEffect() { + super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.SetPT_7b, Outcome.UnboostCreature); + staticText = "and its toughness becomes 1"; + } + + public ChariotOfTheSunEffect(final ChariotOfTheSunEffect effect) { + super(effect); + } + + @Override + public ChariotOfTheSunEffect copy() { + return new ChariotOfTheSunEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); + if (permanent == null) { + this.discard(); + return false; + } + permanent.getToughness().setValue(1); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/c/CheeringFanatic.java b/Mage.Sets/src/mage/cards/c/CheeringFanatic.java index 277fa9c6578..e0288f1af83 100644 --- a/Mage.Sets/src/mage/cards/c/CheeringFanatic.java +++ b/Mage.Sets/src/mage/cards/c/CheeringFanatic.java @@ -7,8 +7,8 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; -import mage.abilities.effects.common.NameACardEffect.TypeOfName; +import mage.abilities.effects.common.ChooseACardNameEffect; +import mage.abilities.effects.common.ChooseACardNameEffect.TypeOfName; import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -65,8 +65,8 @@ class CheeringFanaticEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - new NameACardEffect(TypeOfName.ALL).apply(game, source); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + new ChooseACardNameEffect(TypeOfName.ALL).apply(game, source); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); FilterCard filter = new FilterCard(); filter.add(new NamePredicate(cardName)); ContinuousEffect effect = new SpellsCostReductionAllEffect(filter, 1); diff --git a/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java b/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java new file mode 100644 index 00000000000..d206feff7e5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java @@ -0,0 +1,60 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.keyword.PartnerWithAbility; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class ChewbaccaTheBeast extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target attacking creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(new AnotherPredicate()); + filter.add(new AttackingPredicate()); + } + + public ChewbaccaTheBeast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.WOOKIEE); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Partner with Han Solo, Scrumrat + this.addAbility(new PartnerWithAbility("Han Solo, Scrumrat")); + + // Whenever Chewbacca, the Beast attacks, another target attacking creature you control gains indestructible until end of turn. + Ability ability = new AttacksTriggeredAbility(new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), false); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public ChewbaccaTheBeast(final ChewbaccaTheBeast card) { + super(card); + } + + @Override + public ChewbaccaTheBeast copy() { + return new ChewbaccaTheBeast(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChickenALaKing.java b/Mage.Sets/src/mage/cards/c/ChickenALaKing.java index cfa4f6c851a..54fc631a3b3 100644 --- a/Mage.Sets/src/mage/cards/c/ChickenALaKing.java +++ b/Mage.Sets/src/mage/cards/c/ChickenALaKing.java @@ -89,7 +89,7 @@ class ChickenALaKingTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + if (this.isControlledBy(event.getPlayerId()) && event.getFlag()) { // event.getData holds the num of sides of the die to roll String data = event.getData(); if (data != null) { diff --git a/Mage.Sets/src/mage/cards/c/ChirrutImwe.java b/Mage.Sets/src/mage/cards/c/ChirrutImwe.java new file mode 100644 index 00000000000..99140f68271 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChirrutImwe.java @@ -0,0 +1,100 @@ +package mage.cards.c; + +import java.util.UUID; +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.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventCombatDamageToSourceEffect; +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.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author NinthWorld + */ +public final class ChirrutImwe extends CardImpl { + + public ChirrutImwe(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MONK); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Chirrut Imwe can block up to two additional creatures. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ChirrutImweEffect())); + + // {1}{W}: Prevent all combat damage that would be dealt to Chirrut Imwe until end of turn. + Effect effect = new PreventCombatDamageToSourceEffect(Duration.EndOfTurn); + effect.setText("Prevent all combat damage that would be dealt to {this} until end of turn"); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{W}"))); + } + + public ChirrutImwe(final ChirrutImwe card) { + super(card); + } + + @Override + public ChirrutImwe copy() { + return new ChirrutImwe(this); + } +} + +class ChirrutImweEffect extends ContinuousEffectImpl { + + public ChirrutImweEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "{this} can block up to two additional creatures"; + } + + public ChirrutImweEffect(final ChirrutImweEffect effect) { + super(effect); + } + + @Override + public ChirrutImweEffect copy() { + return new ChirrutImweEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent perm = game.getPermanent(source.getSourceId()); + if(perm != null) { + switch(layer) { + case RulesEffects: + // maxBlocks = 0 equals to "can block any number of creatures" + if(perm.getMaxBlocks() > 0) { + perm.setMaxBlocks(perm.getMaxBlocks() + 2); + } + break; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.RulesEffects; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ChitteringDoom.java b/Mage.Sets/src/mage/cards/c/ChitteringDoom.java index b6b626805db..5b50ecae6f7 100644 --- a/Mage.Sets/src/mage/cards/c/ChitteringDoom.java +++ b/Mage.Sets/src/mage/cards/c/ChitteringDoom.java @@ -57,7 +57,7 @@ class ChitteringDoomTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + if (this.isControlledBy(event.getPlayerId()) && event.getFlag()) { if (event.getAmount() >= 4) { return true; } diff --git a/Mage.Sets/src/mage/cards/c/ChoArrimLegate.java b/Mage.Sets/src/mage/cards/c/ChoArrimLegate.java index 95ba4e02045..22c24cc6b9c 100644 --- a/Mage.Sets/src/mage/cards/c/ChoArrimLegate.java +++ b/Mage.Sets/src/mage/cards/c/ChoArrimLegate.java @@ -41,7 +41,7 @@ public final class ChoArrimLegate extends CardImpl { // Protection from black this.addAbility(ProtectionAbility.from(ObjectColor.BLACK)); - // If an opponent controls a Swamp and you control a Plains, you may cast Cho-Arrim Legate without paying its mana cost. + // If an opponent controls a Swamp and you control a Plains, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Swamp and you control a Plains", new OpponentControlsPermanentCondition(filterSwamp), new PermanentsOnTheBattlefieldCondition(filterPlains)); diff --git a/Mage.Sets/src/mage/cards/c/ChromeMox.java b/Mage.Sets/src/mage/cards/c/ChromeMox.java index a0a02f20e36..b3b414ee191 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeMox.java +++ b/Mage.Sets/src/mage/cards/c/ChromeMox.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.ArrayList; @@ -127,8 +126,9 @@ class ChromeMoxManaEffect extends ManaEffect { 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); + Mana mana = getMana(game, source); + checkToFirePossibleEvents(mana, game, source); + controller.getManaPool().addMana(mana, game, source); return true; } diff --git a/Mage.Sets/src/mage/cards/c/ChromeSteed.java b/Mage.Sets/src/mage/cards/c/ChromeSteed.java index d9053812486..b0e34f7e10f 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeSteed.java +++ b/Mage.Sets/src/mage/cards/c/ChromeSteed.java @@ -21,7 +21,7 @@ import mage.constants.Zone; * @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"; + 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}"); diff --git a/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java b/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java new file mode 100644 index 00000000000..4ec39507c56 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java @@ -0,0 +1,92 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.CantBeCounteredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author TheElk801 + */ +public final class ChromiumTheMutable extends CardImpl { + + public ChromiumTheMutable(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // This spell can't be countered. + this.addAbility(new CantBeCounteredAbility()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Discard a card: Until end of turn, Chromium, the Mutable becomes a Human with base power and toughness 1/1, loses all abilities, and gains hexproof. It can't be blocked this turn. + Ability ability = new SimpleActivatedAbility( + new BecomesCreatureSourceEffect( + new ChromiumTheMutableToken(), null, Duration.EndOfTurn, + false, false, null, null, true + ).setText("Until end of turn, {this} becomes " + + "a Human with base power and toughness 1/1, " + + "loses all abilities, and gains hexproof."), + new DiscardCardCost() + ); + ability.addEffect( + new CantBeBlockedSourceEffect(Duration.EndOfTurn) + .setText("It can't be blocked this turn.") + ); + this.addAbility(ability); + } + + public ChromiumTheMutable(final ChromiumTheMutable card) { + super(card); + } + + @Override + public ChromiumTheMutable copy() { + return new ChromiumTheMutable(this); + } +} + +class ChromiumTheMutableToken extends TokenImpl { + + public ChromiumTheMutableToken() { + super("", "Human with base power and toughness 1/1, loses all abilities, and gains hexproof"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.HUMAN); + power = new MageInt(1); + toughness = new MageInt(1); + + addAbility(HexproofAbility.getInstance()); + } + + public ChromiumTheMutableToken(final ChromiumTheMutableToken token) { + super(token); + } + + public ChromiumTheMutableToken copy() { + return new ChromiumTheMutableToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChronicFlooding.java b/Mage.Sets/src/mage/cards/c/ChronicFlooding.java index e20d623828f..62f452388d3 100644 --- a/Mage.Sets/src/mage/cards/c/ChronicFlooding.java +++ b/Mage.Sets/src/mage/cards/c/ChronicFlooding.java @@ -72,10 +72,9 @@ class ChronicFloodingAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent source = game.getPermanent(this.sourceId); - if (source != null && source.getAttachedTo().equals(event.getTargetId())) { + if (source != null && source.isAttachedTo(event.getTargetId())) { Permanent attached = game.getPermanent(source.getAttachedTo()); if (attached != null) { - for (Effect e : getEffects()) { e.setTargetPointer(new FixedTarget(attached.getControllerId())); } diff --git a/Mage.Sets/src/mage/cards/c/Chronozoa.java b/Mage.Sets/src/mage/cards/c/Chronozoa.java index fb63297fc19..81a6153913c 100644 --- a/Mage.Sets/src/mage/cards/c/Chronozoa.java +++ b/Mage.Sets/src/mage/cards/c/Chronozoa.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.LastTimeCounterRemovedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -46,7 +46,7 @@ public final class Chronozoa extends CardImpl { // When Chronozoa is put into a graveyard from play, if it had no time counters on it, create two tokens that are copies of it. Effect effect = new CreateTokenCopySourceEffect(2); effect.setText("create two tokens that are copies of it"); - this.addAbility(new ConditionalTriggeredAbility(new DiesTriggeredAbility(effect, false), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(effect, false), LastTimeCounterRemovedCondition.instance, "When {this} dies, if it had no time counters on it, create two tokens that are copies of it.")); } diff --git a/Mage.Sets/src/mage/cards/c/CinderCloud.java b/Mage.Sets/src/mage/cards/c/CinderCloud.java index 077dc5a04ef..24d02c18e8a 100644 --- a/Mage.Sets/src/mage/cards/c/CinderCloud.java +++ b/Mage.Sets/src/mage/cards/c/CinderCloud.java @@ -61,7 +61,7 @@ class CinderCloudEffect extends OneShotEffect { if (permanent != null && permanent.destroy(source.getSourceId(), game, false) && permanent.getColor(game).equals(ObjectColor.WHITE)) { game.applyEffects(); if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId()) - && !game.getState().getZone(permanent.getId()).equals(Zone.GRAVEYARD)) { + && game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) { // A replacement effect has moved the card to another zone as grvayard return true; } diff --git a/Mage.Sets/src/mage/cards/c/CircleOfFlame.java b/Mage.Sets/src/mage/cards/c/CircleOfFlame.java index 028dd37cb2e..dc1c26cd8d2 100644 --- a/Mage.Sets/src/mage/cards/c/CircleOfFlame.java +++ b/Mage.Sets/src/mage/cards/c/CircleOfFlame.java @@ -77,7 +77,7 @@ class CircleOfFlameTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(event.getTargetId()); youOrYourPlaneswalker = permanent != null && permanent.isPlaneswalker() - && permanent.getControllerId().equals(this.getControllerId()); + && permanent.isControlledBy(this.getControllerId()); } if (youOrYourPlaneswalker) { for (Effect effect : this.getEffects()) { diff --git a/Mage.Sets/src/mage/cards/c/CitadelSiege.java b/Mage.Sets/src/mage/cards/c/CitadelSiege.java index 35620c0cedb..86093720e51 100644 --- a/Mage.Sets/src/mage/cards/c/CitadelSiege.java +++ b/Mage.Sets/src/mage/cards/c/CitadelSiege.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; @@ -21,6 +20,8 @@ import mage.game.Game; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/c/CitanulWoodreaders.java b/Mage.Sets/src/mage/cards/c/CitanulWoodreaders.java index a2bada5d746..0f8813d79d5 100644 --- a/Mage.Sets/src/mage/cards/c/CitanulWoodreaders.java +++ b/Mage.Sets/src/mage/cards/c/CitanulWoodreaders.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class CitanulWoodreaders extends CardImpl { this.addAbility(new KickerAbility("{2}{G}")); // When Citanul Woodreaders enters the battlefield, if it was kicked, draw two cards. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(2)), KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, draw two cards." diff --git a/Mage.Sets/src/mage/cards/c/CityInABottle.java b/Mage.Sets/src/mage/cards/c/CityInABottle.java index 675f0d796cb..00a469b7562 100644 --- a/Mage.Sets/src/mage/cards/c/CityInABottle.java +++ b/Mage.Sets/src/mage/cards/c/CityInABottle.java @@ -97,7 +97,7 @@ public final class CityInABottle extends CardImpl { namePredicatesArabianNights.add(new NamePredicate("Jandor's Saddlebags")); namePredicatesArabianNights.add(new NamePredicate("Jeweled Bird")); namePredicatesArabianNights.add(new NamePredicate("Jihad")); - namePredicatesArabianNights.add(new NamePredicate("Junún Efreet")); + namePredicatesArabianNights.add(new NamePredicate("Junun Efreet")); namePredicatesArabianNights.add(new NamePredicate("Juzam Djinn")); namePredicatesArabianNights.add(new NamePredicate("Khabal Ghoul")); namePredicatesArabianNights.add(new NamePredicate("King Suleiman")); diff --git a/Mage.Sets/src/mage/cards/c/CityOfSolitude.java b/Mage.Sets/src/mage/cards/c/CityOfSolitude.java index 40becef9f80..01291a62521 100644 --- a/Mage.Sets/src/mage/cards/c/CityOfSolitude.java +++ b/Mage.Sets/src/mage/cards/c/CityOfSolitude.java @@ -67,7 +67,7 @@ class CityOfSolitudeEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return !game.getActivePlayerId().equals(event.getPlayerId()); + return !game.isActivePlayer(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/c/CityOfTraitors.java b/Mage.Sets/src/mage/cards/c/CityOfTraitors.java index d5108787ed4..aa507b2a60d 100644 --- a/Mage.Sets/src/mage/cards/c/CityOfTraitors.java +++ b/Mage.Sets/src/mage/cards/c/CityOfTraitors.java @@ -62,7 +62,7 @@ class CityOfTraitorsTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent land = game.getPermanent(event.getTargetId()); return land.isLand() - && land.getControllerId().equals(this.controllerId) + && land.isControlledBy(this.controllerId) && !Objects.equals(event.getTargetId(), this.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/c/CleansingMeditation.java b/Mage.Sets/src/mage/cards/c/CleansingMeditation.java index d00337ab710..03bcd502104 100644 --- a/Mage.Sets/src/mage/cards/c/CleansingMeditation.java +++ b/Mage.Sets/src/mage/cards/c/CleansingMeditation.java @@ -74,7 +74,7 @@ class CleansingMeditationEffect extends OneShotEffect { for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_ENCHANTMENT_PERMANENT, source.getControllerId(), source.getSourceId(), game)) { if (permanent != null && permanent.destroy(source.getSourceId(), game, false)) { - if (threshold && controller != null && permanent.getOwnerId().equals(controller.getId())) { + if (threshold && controller != null && permanent.isOwnedBy(controller.getId())) { cardsToBattlefield.add(permanent); } } diff --git a/Mage.Sets/src/mage/cards/c/CleansingNova.java b/Mage.Sets/src/mage/cards/c/CleansingNova.java new file mode 100644 index 00000000000..c3b1237329c --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CleansingNova.java @@ -0,0 +1,42 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.filter.common.FilterArtifactOrEnchantmentPermanent; + +/** + * + * @author TheElk801 + */ +public final class CleansingNova extends CardImpl { + + private static final FilterArtifactOrEnchantmentPermanent filter + = new FilterArtifactOrEnchantmentPermanent("artifacts and enchantments"); + + public CleansingNova(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}"); + + // Choose one — + // • Destroy all creatures. + this.getSpellAbility().addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES)); + + // • Destroy all artifacts and enchantments. + Mode mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(filter)); + this.getSpellAbility().getModes().addMode(mode); + } + + public CleansingNova(final CleansingNova card) { + super(card); + } + + @Override + public CleansingNova copy() { + return new CleansingNova(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CleansingScreech.java b/Mage.Sets/src/mage/cards/c/CleansingScreech.java new file mode 100644 index 00000000000..e847419df3a --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CleansingScreech.java @@ -0,0 +1,32 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class CleansingScreech extends CardImpl { + + public CleansingScreech(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}"); + + // Cleansing Screech deals 4 damage to any target. + this.getSpellAbility().addEffect(new DamageTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetAnyTarget()); + } + + public CleansingScreech(final CleansingScreech card) { + super(card); + } + + @Override + public CleansingScreech copy() { + return new CleansingScreech(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java index cd2903327e0..7eabddb97fa 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java @@ -11,7 +11,7 @@ import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -51,7 +51,7 @@ public final class ClockworkAvian extends CardImpl { )); // At end of combat, if Clockwork Avian attacked or blocked this combat, remove a +1/+0 counter from it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), diff --git a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java index 9efa2a076df..e02f4434b43 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java @@ -11,7 +11,7 @@ import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -47,7 +47,7 @@ public final class ClockworkBeast extends CardImpl { )); // At end of combat, if Clockwork Beast attacked or blocked this combat, remove a +1/+0 counter from it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), diff --git a/Mage.Sets/src/mage/cards/c/ClockworkSteed.java b/Mage.Sets/src/mage/cards/c/ClockworkSteed.java index 06743d0ae22..fe4557ef8dd 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkSteed.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkSteed.java @@ -12,7 +12,7 @@ import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; @@ -58,7 +58,7 @@ public final class ClockworkSteed extends CardImpl { this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); // At end of combat, if Clockwork Steed attacked or blocked this combat, remove a +1/+0 counter from it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), diff --git a/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java b/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java index f56893ebccf..4480d844ced 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java @@ -12,7 +12,7 @@ import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; @@ -62,7 +62,7 @@ public final class ClockworkSwarm extends CardImpl { this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); // At end of combat, if Clockwork Swarm attacked or blocked this combat, remove a +1/+0 counter from it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), diff --git a/Mage.Sets/src/mage/cards/c/CloudCover.java b/Mage.Sets/src/mage/cards/c/CloudCover.java index 1793102559d..7367585c444 100644 --- a/Mage.Sets/src/mage/cards/c/CloudCover.java +++ b/Mage.Sets/src/mage/cards/c/CloudCover.java @@ -63,7 +63,7 @@ class CloudCoverAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(event.getTargetId()); Player controller = game.getPlayer(this.getControllerId()); if (permanent != null - && permanent.getControllerId().equals(getControllerId()) + && permanent.isControlledBy(getControllerId()) && !permanent.getId().equals(this.getSourceId()) && controller != null && controller.hasOpponent(event.getPlayerId(), game)) { diff --git a/Mage.Sets/src/mage/cards/c/CloudKey.java b/Mage.Sets/src/mage/cards/c/CloudKey.java index 7da1f97dfc8..5a9bd8158e1 100644 --- a/Mage.Sets/src/mage/cards/c/CloudKey.java +++ b/Mage.Sets/src/mage/cards/c/CloudKey.java @@ -119,7 +119,7 @@ class CloudKeyCostModificationEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility && abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify instanceof SpellAbility && abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = game.getStack().getSpell(abilityToModify.getSourceId()); if (spell != null && spell.getCardType().toString().contains((String) game.getState().getValue(source.getSourceId().toString() + "_CloudKey"))) { return true; diff --git a/Mage.Sets/src/mage/cards/c/CoalStoker.java b/Mage.Sets/src/mage/cards/c/CoalStoker.java index cfe982d61cc..17ead83cd53 100644 --- a/Mage.Sets/src/mage/cards/c/CoalStoker.java +++ b/Mage.Sets/src/mage/cards/c/CoalStoker.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.Mana; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.mana.BasicManaEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +27,7 @@ public final class CoalStoker extends CardImpl { this.toughness = new MageInt(3); // When Coal Stoker enters the battlefield, if you cast it from your hand, add {R}{R}{R}. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BasicManaEffect(Mana.RedMana(3)), false), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, add {R}{R}{R}."), diff --git a/Mage.Sets/src/mage/cards/c/CoastalPiracy.java b/Mage.Sets/src/mage/cards/c/CoastalPiracy.java index dab61d18513..f3a94fc0a6b 100644 --- a/Mage.Sets/src/mage/cards/c/CoastalPiracy.java +++ b/Mage.Sets/src/mage/cards/c/CoastalPiracy.java @@ -63,7 +63,7 @@ class CoastalPiracyTriggeredAbility extends TriggeredAbilityImpl { if (((DamagedPlayerEvent) event).isCombatDamage() && game.getOpponents(this.controllerId).contains(((DamagedPlayerEvent) event).getPlayerId())) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/c/CodeSlice.java b/Mage.Sets/src/mage/cards/c/CodeSlice.java new file mode 100644 index 00000000000..ca8ae2fa839 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CodeSlice.java @@ -0,0 +1,50 @@ +package mage.cards.c; + +import java.util.UUID; + +import mage.abilities.effects.common.combat.CantBlockAllEffect; +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.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class CodeSlice extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Artifact creatures with bounty counters on them"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + filter.add(new CounterPredicate(CounterType.BOUNTY)); + } + + public CodeSlice(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}"); + + + // Put a bounty counter on target creature. + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance())); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Artifact creatures with bounty counters on them can't block this turn. + this.getSpellAbility().addEffect(new CantBlockAllEffect(filter, Duration.EndOfTurn)); + } + + public CodeSlice(final CodeSlice card) { + super(card); + } + + @Override + public CodeSlice copy() { + return new CodeSlice(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java b/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java index aef7cf292a7..13e9dd83031 100644 --- a/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java +++ b/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java @@ -53,7 +53,7 @@ public final class CollectiveDefiance extends CardImpl { mode.getTargets().add(new TargetCreaturePermanent(filterCreature)); this.getSpellAbility().addMode(mode); - // Collective Defiance deals 3 damage to target opponent. + // Collective Defiance deals 3 damage to target opponent or planeswalker. mode = new Mode(); effect = new DamageTargetEffect(3); effect.setText("{this} deals 3 damage to target opponent or planeswalker"); diff --git a/Mage.Sets/src/mage/cards/c/ColorfulFeiyiSparrow.java b/Mage.Sets/src/mage/cards/c/ColorfulFeiyiSparrow.java new file mode 100644 index 00000000000..aa92ece6bfd --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ColorfulFeiyiSparrow.java @@ -0,0 +1,36 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class ColorfulFeiyiSparrow extends CardImpl { + + public ColorfulFeiyiSparrow(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.BIRD); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + } + + public ColorfulFeiyiSparrow(final ColorfulFeiyiSparrow card) { + super(card); + } + + @Override + public ColorfulFeiyiSparrow copy() { + return new ColorfulFeiyiSparrow(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ColossalMajesty.java b/Mage.Sets/src/mage/cards/c/ColossalMajesty.java new file mode 100644 index 00000000000..abd4bd9d6f8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ColossalMajesty.java @@ -0,0 +1,43 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.common.FerociousCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; + +/** + * + * @author TheElk801 + */ +public final class ColossalMajesty extends CardImpl { + + public ColossalMajesty(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + + // At the beginning of your upkeep, if you control a creature with power 4 or greater, draw a card. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility( + new DrawCardSourceControllerEffect(1), + TargetController.YOU, false + ), + FerociousCondition.instance, + "At the beginning of your upkeep, " + + "if you control a creature with power 4 or greater, " + + "draw a card." + )); + } + + public ColossalMajesty(final ColossalMajesty card) { + super(card); + } + + @Override + public ColossalMajesty copy() { + return new ColossalMajesty(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ComboAttack.java b/Mage.Sets/src/mage/cards/c/ComboAttack.java index 9a523b567d3..538197b83dc 100644 --- a/Mage.Sets/src/mage/cards/c/ComboAttack.java +++ b/Mage.Sets/src/mage/cards/c/ComboAttack.java @@ -55,7 +55,7 @@ class ComboAttackEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (source.getTargets().size() < 2) { + if (source.getTargets().size() < 2 || source.getTargets().get(0).getTargets().size() < 2) { return false; } Permanent permanent1 = game.getPermanent(source.getTargets().get(0).getTargets().get(0)); diff --git a/Mage.Sets/src/mage/cards/c/Combust.java b/Mage.Sets/src/mage/cards/c/Combust.java index 6db9710fd31..55d1d1d81d1 100644 --- a/Mage.Sets/src/mage/cards/c/Combust.java +++ b/Mage.Sets/src/mage/cards/c/Combust.java @@ -38,7 +38,7 @@ public final class Combust extends CardImpl { this.getSpellAbility().addEffect(new DamageTargetEffect(5, false)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); - // Combust can't be countered by spells or abilities. + // Combust can't be countered. Ability ability = new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect()); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/Comeuppance.java b/Mage.Sets/src/mage/cards/c/Comeuppance.java index 6abcda8ce10..8d03fa51c8b 100644 --- a/Mage.Sets/src/mage/cards/c/Comeuppance.java +++ b/Mage.Sets/src/mage/cards/c/Comeuppance.java @@ -71,7 +71,7 @@ class ComeuppanceEffect extends PreventionEffectImpl { MageObject damageDealingObject = game.getObject(event.getSourceId()); UUID objectControllerId = null; if (damageDealingObject instanceof Permanent) { - if (((Permanent) damageDealingObject).isCreature()) { + if (damageDealingObject.isCreature()) { ((Permanent) damageDealingObject).damage(preventionData.getPreventedDamage(), source.getSourceId(), game, false, true); } else { objectControllerId = ((Permanent) damageDealingObject).getControllerId(); @@ -102,7 +102,7 @@ class ComeuppanceEffect extends PreventionEffectImpl { } else { Permanent targetPermanent = game.getPermanent(event.getTargetId()); if (targetPermanent != null && - targetPermanent.getControllerId().equals(source.getControllerId()) && + targetPermanent.isControlledBy(source.getControllerId()) && targetPermanent.isPlaneswalker()) { catched = true; } @@ -110,11 +110,11 @@ class ComeuppanceEffect extends PreventionEffectImpl { if (catched) { MageObject damageSource = game.getObject(event.getSourceId()); if (damageSource instanceof StackObject) { - return !((StackObject) damageSource).getControllerId().equals(source.getControllerId()); + return !((StackObject) damageSource).isControlledBy(source.getControllerId()); } else if (damageSource instanceof Permanent) { - return !((Permanent) damageSource).getControllerId().equals(source.getControllerId()); + return !((Permanent) damageSource).isControlledBy(source.getControllerId()); } else if (damageSource instanceof Card) { - return !((Card) damageSource).getOwnerId().equals(source.getControllerId()); + return !((Card) damageSource).isOwnedBy(source.getControllerId()); } Logger.getLogger(Comeuppance.class).error("Comeuppance: could not define source objects controller - " + (damageSource != null ? damageSource.getName(): "null")); } diff --git a/Mage.Sets/src/mage/cards/c/CommandOfUnsummoning.java b/Mage.Sets/src/mage/cards/c/CommandOfUnsummoning.java index 8759f8be2d8..194ecbbe2dd 100644 --- a/Mage.Sets/src/mage/cards/c/CommandOfUnsummoning.java +++ b/Mage.Sets/src/mage/cards/c/CommandOfUnsummoning.java @@ -27,7 +27,7 @@ public final class CommandOfUnsummoning extends CardImpl { // Cast Command of Unsummoning only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CommandoRaid.java b/Mage.Sets/src/mage/cards/c/CommandoRaid.java new file mode 100644 index 00000000000..17bb3c5e85e --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CommandoRaid.java @@ -0,0 +1,123 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +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.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class CommandoRaid extends CardImpl { + + public CommandoRaid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); + + // Until end of turn, target creature you control gains "When this creature deals combat damage to a player, you may have it deal damage equal to its power to target creature that player controls." + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + new CommandoRaidTriggeredAbility(), Duration.EndOfTurn, + "Until end of turn, target creature you control gains " + + "\"When this creature deals combat damage to a player, " + + "you may have it deal damage equal to its power " + + "to target creature that player controls.\"" + )); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + public CommandoRaid(final CommandoRaid card) { + super(card); + } + + @Override + public CommandoRaid copy() { + return new CommandoRaid(this); + } +} + +class CommandoRaidTriggeredAbility extends TriggeredAbilityImpl { + + public CommandoRaidTriggeredAbility() { + super(Zone.BATTLEFIELD, new CommandoRaidEffect(), true); + } + + public CommandoRaidTriggeredAbility(final CommandoRaidTriggeredAbility ability) { + super(ability); + } + + @Override + public CommandoRaidTriggeredAbility copy() { + return new CommandoRaidTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; + Player opponent = game.getPlayer(event.getPlayerId()); + if (!damageEvent.isCombatDamage() + || !event.getSourceId().equals(this.getSourceId()) + || opponent == null) { + return false; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + opponent.getLogName() + " controls"); + filter.add(new ControllerIdPredicate(opponent.getId())); + this.getTargets().clear(); + this.addTarget(new TargetCreaturePermanent(filter)); + for (Effect effect : this.getAllEffects()) { + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + effect.setValue("damage", event.getAmount()); + } + return true; + } + + @Override + public String getRule() { + return "When this creature deals combat damage to a player, " + + "you may have it deal that much damage to target creature that player controls"; + } +} + +class CommandoRaidEffect extends OneShotEffect { + + public CommandoRaidEffect() { + super(Outcome.Damage); + staticText = "it deals that much damage to target creature that player controls"; + } + + public CommandoRaidEffect(final CommandoRaidEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return new DamageTargetEffect((Integer) getValue("damage")).apply(game, source); + } + + @Override + public CommandoRaidEffect copy() { + return new CommandoRaidEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CommuneWithLava.java b/Mage.Sets/src/mage/cards/c/CommuneWithLava.java index da68914daf3..e38056a591d 100644 --- a/Mage.Sets/src/mage/cards/c/CommuneWithLava.java +++ b/Mage.Sets/src/mage/cards/c/CommuneWithLava.java @@ -105,7 +105,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.getActivePlayerId().equals(source.getControllerId())) { + if (game.isActivePlayer(source.getControllerId())) { return true; } } @@ -119,7 +119,7 @@ class CommuneWithLavaMayPlayEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && getTargetPointer().getTargets(game, source).contains(sourceId); } diff --git a/Mage.Sets/src/mage/cards/c/ComplexAutomaton.java b/Mage.Sets/src/mage/cards/c/ComplexAutomaton.java index 2d1c8d2bab7..3697c4ab9f0 100644 --- a/Mage.Sets/src/mage/cards/c/ComplexAutomaton.java +++ b/Mage.Sets/src/mage/cards/c/ComplexAutomaton.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class ComplexAutomaton extends CardImpl { // At the beginning of your upkeep, if you control seven or more permanents, return Complex Automaton to its owner's hand. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(), ComparisonType.MORE_THAN, 6), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(), ComparisonType.MORE_THAN, 6), "At the beginning of your upkeep, if you control seven or more permanents, return Complex Automaton to its owner's hand.")); } diff --git a/Mage.Sets/src/mage/cards/c/ConcussiveBolt.java b/Mage.Sets/src/mage/cards/c/ConcussiveBolt.java index 729d9b2bc2f..50103876f9a 100644 --- a/Mage.Sets/src/mage/cards/c/ConcussiveBolt.java +++ b/Mage.Sets/src/mage/cards/c/ConcussiveBolt.java @@ -29,7 +29,7 @@ public final class ConcussiveBolt extends CardImpl { // Concussive Bolt deals 4 damage to target player. this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - // Metalcraft - If you control three or more artifacts, creatures that player controls can't block this turn. + // Metalcraft — If you control three or more artifacts, creatures that player controls can't block this turn. this.getSpellAbility().addEffect(new ConcussiveBoltEffect()); this.getSpellAbility().addEffect(new ConcussiveBoltRestrictionEffect()); } @@ -48,7 +48,7 @@ class ConcussiveBoltEffect extends OneShotEffect { public ConcussiveBoltEffect() { super(Outcome.Benefit); - this.staticText = "Metalcraft - If you control three or more artifacts, creatures controlled by that player or by that planeswalker’s controller can’t block this turn."; + this.staticText = "Metalcraft — If you control three or more artifacts, creatures controlled by that player or by that planeswalker's controller can't block this turn."; } public ConcussiveBoltEffect(final ConcussiveBoltEffect effect) { @@ -89,7 +89,7 @@ class ConcussiveBoltRestrictionEffect extends RestrictionEffect { if (player == null) { return false; } - if (metalcraft && permanent.getControllerId().equals(player.getId())) { + if (metalcraft && permanent.isControlledBy(player.getId())) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/c/ConfidenceFromStrength.java b/Mage.Sets/src/mage/cards/c/ConfidenceFromStrength.java new file mode 100644 index 00000000000..505bcf43fd3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConfidenceFromStrength.java @@ -0,0 +1,41 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class ConfidenceFromStrength extends CardImpl { + + public ConfidenceFromStrength(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); + + // Target creature gets +4/+4 until and gains trample until end of turn. + Effect effect = new BoostTargetEffect(4, 4, Duration.EndOfTurn); + effect.setText("Target creature gets +4/+4"); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains trample until end of turn"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public ConfidenceFromStrength(final ConfidenceFromStrength card) { + super(card); + } + + @Override + public ConfidenceFromStrength copy() { + return new ConfidenceFromStrength(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ConjurersBan.java b/Mage.Sets/src/mage/cards/c/ConjurersBan.java new file mode 100644 index 00000000000..f7624da9e81 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConjurersBan.java @@ -0,0 +1,85 @@ +package mage.cards.c; + +import java.util.UUID; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.ChooseACardNameEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +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.events.GameEvent; + +/** + * + * @author noahg + */ +public final class ConjurersBan extends CardImpl { + + public ConjurersBan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}{B}"); + + + // Choose a card name. Until your next turn, spells with the chosen name can’t be cast and lands with the chosen name can’t be played. + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); + this.getSpellAbility().addEffect(new ConjurersBanEffect()); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public ConjurersBan(final ConjurersBan card) { + super(card); + } + + @Override + public ConjurersBan copy() { + return new ConjurersBan(this); + } +} + +class ConjurersBanEffect extends ContinuousRuleModifyingEffectImpl { + + public ConjurersBanEffect() { + super(Duration.UntilYourNextTurn, Outcome.Detriment, true, false); + this.staticText = "spells with the chosen name can't be cast and lands with the chosen name can't be played"; + } + + public ConjurersBanEffect(final ConjurersBanEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public ConjurersBanEffect copy() { + return new ConjurersBanEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.CAST_SPELL || event.getType() == GameEvent.EventType.PLAY_LAND) { + MageObject object = game.getObject(event.getSourceId()); + return object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY)); + } + return false; + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + String namedCard = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + String playerName = game.getPlayer(source.getControllerId()).getName(); + if (namedCard == null || playerName == null || source.getSourceObject(game) == null){ + return super.getInfoMessage(source, event, game); + } + return "Until "+playerName+"'s next turn, spells named "+namedCard+" can't be cast and lands named "+namedCard+" can't be played ("+source.getSourceObject(game).getIdName()+")."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java b/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java index 3a350535550..477cd898b81 100644 --- a/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java +++ b/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java @@ -149,7 +149,7 @@ class ConquerorsFlailEffect extends ContinuousRuleModifyingEffectImpl { } } - if (isAttached && game.getActivePlayerId().equals(source.getControllerId()) + if (isAttached && game.isActivePlayer(source.getControllerId()) && game.getPlayer(source.getControllerId()).hasOpponent(event.getPlayerId(), game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/c/Conscription.java b/Mage.Sets/src/mage/cards/c/Conscription.java new file mode 100644 index 00000000000..103a2d695a2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/Conscription.java @@ -0,0 +1,49 @@ +package mage.cards.c; + +import java.util.UUID; + +import mage.abilities.effects.common.continuous.BecomesChosenCreatureTypeTargetEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureTypeTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +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 mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Conscription extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power 2 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public Conscription(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{U}"); + + + // Gain control of target creature with power 2 or less. It becomes a Trooper in addition to its other types. + this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfGame)); + this.getSpellAbility().addEffect(new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.TROOPER, false) + .setText("It becomes a Trooper in addition to its other types")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public Conscription(final Conscription card) { + super(card); + } + + @Override + public Conscription copy() { + return new Conscription(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ConsecrateLand.java b/Mage.Sets/src/mage/cards/c/ConsecrateLand.java index c900726ee83..8ba52ddf806 100644 --- a/Mage.Sets/src/mage/cards/c/ConsecrateLand.java +++ b/Mage.Sets/src/mage/cards/c/ConsecrateLand.java @@ -53,7 +53,7 @@ public final class ConsecrateLand extends CardImpl { } } -// 9/25/2006 ruling: If Consecrate Land enters the battlefield attached to a land that’s enchanted by other Auras, those Auras are put into their owners’ graveyards. +// 9/25/2006 ruling: If Consecrate Land enters the battlefield attached to a land that's enchanted by other Auras, those Auras are put into their owners' graveyards. class ConsecrateLandRuleEffect extends ContinuousRuleModifyingEffectImpl { public ConsecrateLandRuleEffect() { diff --git a/Mage.Sets/src/mage/cards/c/Conspiracy.java b/Mage.Sets/src/mage/cards/c/Conspiracy.java index c70361593e8..1b305eff23b 100644 --- a/Mage.Sets/src/mage/cards/c/Conspiracy.java +++ b/Mage.Sets/src/mage/cards/c/Conspiracy.java @@ -85,13 +85,13 @@ class ConspiracyEffect extends ContinuousEffectImpl { } // in Exile for (Card card : game.getState().getExile().getAllCards(game)) { - if (card.getOwnerId().equals(controller.getId()) && card.isCreature()) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { setCreatureSubtype(card, subType, game); } } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { - if (card.getOwnerId().equals(controller.getId()) && card.isCreature()) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { setCreatureSubtype(card, subType, game); } } @@ -108,7 +108,7 @@ class ConspiracyEffect extends ContinuousEffectImpl { for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { StackObject stackObject = iterator.next(); if (stackObject instanceof Spell - && stackObject.getControllerId().equals(source.getControllerId()) + && stackObject.isControlledBy(source.getControllerId()) && stackObject.isCreature()) { Card card = ((Spell) stackObject).getCard(); setCreatureSubtype(card, subType, game); diff --git a/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java b/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java index 57c34427a95..1653c18a411 100644 --- a/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java +++ b/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.RenownedSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.RenownAbility; @@ -34,7 +34,7 @@ public final class ConsulsLieutenant extends CardImpl { // Renown 1 this.addAbility(new RenownAbility(1)); // Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn. - this.addAbility(new ConditionalTriggeredAbility(new AttacksTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility( new BoostControlledEffect(1, 1, Duration.EndOfTurn, new FilterAttackingCreature("other attacking creatures you control"), true), false), RenownedSourceCondition.instance, "Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn.")); diff --git a/Mage.Sets/src/mage/cards/c/ContainmentPriest.java b/Mage.Sets/src/mage/cards/c/ContainmentPriest.java index 5eec1de7e6d..e3cffabc67c 100644 --- a/Mage.Sets/src/mage/cards/c/ContainmentPriest.java +++ b/Mage.Sets/src/mage/cards/c/ContainmentPriest.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -29,7 +28,7 @@ import mage.watchers.common.CreatureWasCastWatcher; public final class ContainmentPriest extends CardImpl { public ContainmentPriest(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); @@ -76,11 +75,10 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (controller != null) { Card card = game.getCard(event.getTargetId()); if (card != null) { - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, zEvent.getFromZone(), true); + controller.moveCardsToExile(card, source, game, true, null, null); } return true; diff --git a/Mage.Sets/src/mage/cards/c/ConvalescentCare.java b/Mage.Sets/src/mage/cards/c/ConvalescentCare.java index cd762d6a158..6153f6735d0 100644 --- a/Mage.Sets/src/mage/cards/c/ConvalescentCare.java +++ b/Mage.Sets/src/mage/cards/c/ConvalescentCare.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.XorLessLifeCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -27,7 +27,7 @@ public final class ConvalescentCare extends CardImpl { Effect effect = new DrawCardSourceControllerEffect(1); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(3), TargetController.YOU, false); ability.addEffect(effect); - this.addAbility(new ConditionalTriggeredAbility(ability, new XorLessLifeCondition(XorLessLifeCondition.CheckType.CONTROLLER, 5), "At the beginning of your upkeep, if you have 5 or less life, you gain 3 life and draw a card.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new XorLessLifeCondition(XorLessLifeCondition.CheckType.CONTROLLER, 5), "At the beginning of your upkeep, if you have 5 or less life, you gain 3 life and draw a card.")); } public ConvalescentCare(final ConvalescentCare card) { diff --git a/Mage.Sets/src/mage/cards/c/ConvictedKiller.java b/Mage.Sets/src/mage/cards/c/ConvictedKiller.java index 333cf8dd3e3..513878588fd 100644 --- a/Mage.Sets/src/mage/cards/c/ConvictedKiller.java +++ b/Mage.Sets/src/mage/cards/c/ConvictedKiller.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class ConvictedKiller extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Convicted Killer. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public ConvictedKiller(final ConvictedKiller card) { diff --git a/Mage.Sets/src/mage/cards/c/CopyEnchantment.java b/Mage.Sets/src/mage/cards/c/CopyEnchantment.java index fed00a94a06..f84ee371ddd 100644 --- a/Mage.Sets/src/mage/cards/c/CopyEnchantment.java +++ b/Mage.Sets/src/mage/cards/c/CopyEnchantment.java @@ -14,7 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; import mage.filter.FilterPermanent; -import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -31,7 +31,8 @@ public final class CopyEnchantment extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); // You may have Copy Enchantment enter the battlefield as a copy of any enchantment on the battlefield. - this.addAbility(new EntersBattlefieldAbility(new CopyEnchantmentEffect(new FilterEnchantmentPermanent("any enchantment")), true)); + //this.addAbility(new EntersBattlefieldAbility(new CopyEnchantmentEffect(new FilterEnchantmentPermanent("any enchantment")), true)); + this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), true)); } public CopyEnchantment(final CopyEnchantment card) { diff --git a/Mage.Sets/src/mage/cards/c/CorellianGunship.java b/Mage.Sets/src/mage/cards/c/CorellianGunship.java new file mode 100644 index 00000000000..68e89710026 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CorellianGunship.java @@ -0,0 +1,45 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetPlayerOrPlaneswalker; + +/** + * + * @author NinthWorld + */ +public final class CorellianGunship extends CardImpl { + + public CorellianGunship(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{R}"); + + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // When Corellian Gunship enters the battlefield, it deals 1 damage to target player or planeswalker. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(1)); + ability.addTarget(new TargetPlayerOrPlaneswalker()); + this.addAbility(ability); + } + + public CorellianGunship(final CorellianGunship card) { + super(card); + } + + @Override + public CorellianGunship copy() { + return new CorellianGunship(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java b/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java index bb3ea2454fe..cb0f555675a 100644 --- a/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java +++ b/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java @@ -83,7 +83,7 @@ class CorpsejackMenaceReplacementEffect extends ReplacementEffectImpl { if (permanent == null) { permanent = game.getPermanentEntering(event.getTargetId()); } - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) + if (permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.isCreature()) { return true; } diff --git a/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java b/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java index dda0916a501..ac19501f19b 100644 --- a/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java +++ b/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java @@ -175,8 +175,8 @@ class CorrosiveOozeCombatWatcher extends Watcher { } if (event.getType() == GameEvent.EventType.ZONE_CHANGE) { - if (((ZoneChangeEvent) event).getFromZone().equals(Zone.BATTLEFIELD)) { - if (game.getTurn() != null && TurnPhase.COMBAT.equals(game.getTurn().getPhaseType())) { + 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 (MageObjectReference mor : entry.getValue()) { diff --git a/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java b/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java index ae6c87c0950..b9b2f943eb3 100644 --- a/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java +++ b/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -9,7 +8,7 @@ import mage.abilities.SpellAbility; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.cards.Card; import mage.cards.CardImpl; @@ -35,7 +34,7 @@ public final class CouncilOfTheAbsolute extends CardImpl { this.toughness = new MageInt(4); // As Council of the Absolute enters the battlefield, name a card other than a creature or a land card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_AND_NON_CREATURE_NAME))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_AND_NON_CREATURE_NAME))); // Your opponents can't cast the chosen card. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CouncilOfTheAbsoluteReplacementEffect())); // Spells with the chosen name cost 2 less for you to cast. @@ -58,7 +57,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec public CouncilOfTheAbsoluteReplacementEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Your opponents can't cast the chosen card"; + staticText = "Your opponents can't cast spells with the chosen name"; } public CouncilOfTheAbsoluteReplacementEffect(final CouncilOfTheAbsoluteReplacementEffect effect) { @@ -79,7 +78,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); if (mageObject != null) { - return "You can't cast a card with that name (" + mageObject.getLogName() + " in play)."; + return "You can't cast a spell with that name (" + mageObject.getLogName() + " in play)."; } return null; } @@ -93,7 +92,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec public boolean applies(GameEvent event, Ability source, Game game) { if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } @@ -105,7 +104,7 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl public CouncilOfTheAbsoluteCostReductionEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); - this.staticText = "Spells with the chosen name cost 2 less for you to cast"; + this.staticText = "Spells with the chosen name you cast cost 2 less to cast"; } protected CouncilOfTheAbsoluteCostReductionEffect(CouncilOfTheAbsoluteCostReductionEffect effect) { @@ -121,9 +120,9 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if ((abilityToModify instanceof SpellAbility) - && abilityToModify.getControllerId().equals(source.getControllerId())) { + && abilityToModify.isControlledBy(source.getControllerId())) { Card card = game.getCard(abilityToModify.getSourceId()); - return card.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY)); + return card.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY)); } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CouncilsJudgment.java b/Mage.Sets/src/mage/cards/c/CouncilsJudgment.java index beda5d4bf05..340c01444bf 100644 --- a/Mage.Sets/src/mage/cards/c/CouncilsJudgment.java +++ b/Mage.Sets/src/mage/cards/c/CouncilsJudgment.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.HashMap; @@ -28,7 +27,7 @@ import mage.target.common.TargetNonlandPermanent; public final class CouncilsJudgment extends CardImpl { public CouncilsJudgment(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}{W}"); // Will of the council - Starting with you, each player votes for a nonland permanent you don't control. Exile each permanent with the most votes or tied for most votes. this.getSpellAbility().addEffect(new CouncilsJudgmentEffect()); @@ -89,7 +88,7 @@ class CouncilsJudgmentEffect extends OneShotEffect { } chosenCards.put(permanent, 1); } - game.informPlayers(player.getLogName() + " has chosen: " + permanent.getName()); + game.informPlayers(player.getLogName() + " has chosen: " + permanent.getLogName()); } } } diff --git a/Mage.Sets/src/mage/cards/c/Counterflux.java b/Mage.Sets/src/mage/cards/c/Counterflux.java index c56aa306fce..4f3703148bc 100644 --- a/Mage.Sets/src/mage/cards/c/Counterflux.java +++ b/Mage.Sets/src/mage/cards/c/Counterflux.java @@ -42,9 +42,9 @@ public final class Counterflux extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}{U}{R}"); - // Counterflux can't be countered by spells or abilities. + // Counterflux can't be countered. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK,effect); ability.setRuleAtTheTop(true); this.addAbility(ability); @@ -84,7 +84,7 @@ class CounterfluxEffect extends OneShotEffect { List spellsToCounter = new LinkedList<>(); for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell && !stackObject.getControllerId().equals(source.getControllerId())) { + if (stackObject instanceof Spell && !stackObject.isControlledBy(source.getControllerId())) { spellsToCounter.add((Spell) stackObject); } } diff --git a/Mage.Sets/src/mage/cards/c/CountlessGearsRenegade.java b/Mage.Sets/src/mage/cards/c/CountlessGearsRenegade.java index 1244c5d1281..72a01268b1f 100644 --- a/Mage.Sets/src/mage/cards/c/CountlessGearsRenegade.java +++ b/Mage.Sets/src/mage/cards/c/CountlessGearsRenegade.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class CountlessGearsRenegade extends CardImpl { // Revolt — When Countless Gears Renegade enters the battlefield, if a permanent you controlled // left the battlefield this turn, create a 1/1 colorless Servo artifact creature token. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new CreateTokenEffect(new ServoToken(), 1), false), RevoltCondition.instance, "Revolt — When {this} enters the battlefield, if a permanent you controlled left" + " the battlefield this turn, create a 1/1 colorless Servo artifact creature token."); diff --git a/Mage.Sets/src/mage/cards/c/CourtCleric.java b/Mage.Sets/src/mage/cards/c/CourtCleric.java new file mode 100644 index 00000000000..207987fa1f9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CourtCleric.java @@ -0,0 +1,60 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +/** + * + * @author TheElk801 + */ +public final class CourtCleric extends CardImpl { + + private static final FilterControlledPlaneswalkerPermanent filter + = new FilterControlledPlaneswalkerPermanent( + SubType.AJANI, + "an Ajani planeswalker" + ); + + public CourtCleric(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Court Cleric gets +1/+1 as long as you control an Ajani planeswalker. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} gets +1/+1 as long as you control an Ajani planeswalker" + ) + )); + } + + public CourtCleric(final CourtCleric card) { + super(card); + } + + @Override + public CourtCleric copy() { + return new CourtCleric(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CoverOfWinter.java b/Mage.Sets/src/mage/cards/c/CoverOfWinter.java new file mode 100644 index 00000000000..5497f041bb2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CoverOfWinter.java @@ -0,0 +1,102 @@ +package mage.cards.c; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectData; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.CumulativeUpkeepAbility; +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.game.permanent.Permanent; + +/** + * + * @author noahg + */ +public final class CoverOfWinter extends CardImpl { + + public CoverOfWinter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + + this.addSuperType(SuperType.SNOW); + + // Cumulative upkeep {S} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{S}"))); + + // If a creature would deal combat damage to you and/or one or more creatures you control, prevent X of that damage, where X is the number of age counters on Cover of Winter. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CoverOfWinterEffect())); + + // {S}: Put an age counter on Cover of Winter. + this.addAbility(new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.AGE.createInstance()), new ManaCostsImpl("{S}"))); + } + + public CoverOfWinter(final CoverOfWinter card) { + super(card); + } + + @Override + public CoverOfWinter copy() { + return new CoverOfWinter(this); + } +} + +class CoverOfWinterEffect extends PreventionEffectImpl { + + public CoverOfWinterEffect() { + super(Duration.WhileOnBattlefield, -1, true); + this.staticText = "If a creature would deal combat damage to you and/or one or more creatures you control, prevent X of that damage, where X is the number of age counters on {this}"; + } + + public CoverOfWinterEffect(CoverOfWinterEffect effect) { + super(effect); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER || event.getType() == GameEvent.EventType.DAMAGE_CREATURE; + } + + @Override + protected PreventionEffectData preventDamageAction(GameEvent event, Ability source, Game game) { + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (sourcePermanent != null) { + return game.preventDamage(event, source, game, sourcePermanent.getCounters(game).getCount(CounterType.AGE)); + } else { + this.discard(); + return game.preventDamage(event, source, game, 0); + } + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER + && event.getTargetId().equals(source.getControllerId())) { + return super.applies(event, source, game); + } + + if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + return super.applies(event, source, game); + } + } + return false; + } + + @Override + public CoverOfWinterEffect copy() { + return new CoverOfWinterEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CovetedJewel.java b/Mage.Sets/src/mage/cards/c/CovetedJewel.java new file mode 100644 index 00000000000..01cf2199b55 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CovetedJewel.java @@ -0,0 +1,138 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.DrawCardTargetEffect; +import mage.abilities.effects.common.UntapSourceEffect; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class CovetedJewel extends CardImpl { + + public CovetedJewel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); + + // When Coveted Jewel enters the battlefield, draw three cards. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DrawCardSourceControllerEffect(3) + )); + + // {T}: Add three mana of any one color. + this.addAbility(new SimpleManaAbility( + Zone.BATTLEFIELD, + new AddManaOfAnyColorEffect(3), + new TapSourceCost() + )); + + // Whenever one or more creatures an opponent controls attack you and aren't blocked, that player draws three cards and gains control of Coveted Jewel. Untap it. + this.addAbility(new CovetedJewelTriggeredAbility()); + } + + public CovetedJewel(final CovetedJewel card) { + super(card); + } + + @Override + public CovetedJewel copy() { + return new CovetedJewel(this); + } +} + +class CovetedJewelTriggeredAbility extends TriggeredAbilityImpl { + + public CovetedJewelTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardTargetEffect(3), false); + this.addEffect(new CovetedJewelControlEffect()); + this.addEffect(new UntapSourceEffect()); + } + + public CovetedJewelTriggeredAbility(final CovetedJewelTriggeredAbility ability) { + super(ability); + } + + @Override + public CovetedJewelTriggeredAbility copy() { + return new CovetedJewelTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARE_BLOCKERS_STEP; // this won't work correctly if multiple players can attack at the same time (what's currently not possible) + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player currentController = game.getPlayer(getControllerId()); + if (currentController == null) { + return false; + } + for (UUID attacker : game.getCombat().getAttackers()) { + Permanent attackingCreature = game.getPermanent(attacker); + if (attackingCreature != null + && currentController.hasOpponent(attackingCreature.getControllerId(), game) + && getControllerId().equals(game.getCombat().getDefenderId(attacker)) // does not trigger if planeswalker is attacked + && !attackingCreature.isBlocked(game)) { + this.getEffects().setTargetPointer(new FixedTarget(event.getPlayerId(), game)); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever one or more creatures an opponent controls attack you " + + "and aren't blocked, that player draws three cards " + + "and gains control of {this}. Untap it."; + } +} + +class CovetedJewelControlEffect extends ContinuousEffectImpl { + + public CovetedJewelControlEffect() { + super(Duration.Custom, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); + } + + public CovetedJewelControlEffect(final CovetedJewelControlEffect effect) { + super(effect); + } + + @Override + public CovetedJewelControlEffect copy() { + return new CovetedJewelControlEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + Player newControllingPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (permanent == null || newControllingPlayer == null || !newControllingPlayer.isInGame()) { + this.discard(); + return true; + } + permanent.changeControllerId(getTargetPointer().getFirst(game, source), game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/c/CowedByWisdom.java b/Mage.Sets/src/mage/cards/c/CowedByWisdom.java index 5561417e05e..7559402bc1b 100644 --- a/Mage.Sets/src/mage/cards/c/CowedByWisdom.java +++ b/Mage.Sets/src/mage/cards/c/CowedByWisdom.java @@ -80,7 +80,7 @@ class CowedByWisdomayCostToAttackBlockEffect extends PayCostToAttackBlockEffectI @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - return enchantment != null && enchantment.getAttachedTo().equals(event.getSourceId()); + return enchantment != null && enchantment.isAttachedTo(event.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/cards/c/CragganwickCremator.java b/Mage.Sets/src/mage/cards/c/CragganwickCremator.java index 2f3d745ec14..e59f756b108 100644 --- a/Mage.Sets/src/mage/cards/c/CragganwickCremator.java +++ b/Mage.Sets/src/mage/cards/c/CragganwickCremator.java @@ -15,7 +15,7 @@ import mage.constants.SubType; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; -import mage.target.TargetPlayer; +import mage.target.common.TargetPlayerOrPlaneswalker; /** * @@ -31,9 +31,9 @@ public final class CragganwickCremator extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(4); - // When Cragganwick Cremator enters the battlefield, discard a card at random. If you discard a creature card this way, Cragganwick Cremator deals damage equal to that card's power to target player. + // When Cragganwick Cremator enters the battlefield, discard a card at random. If you discard a creature card this way, Cragganwick Cremator deals damage equal to that card's power to target player or planeswalker. Ability ability = new EntersBattlefieldTriggeredAbility(new CragganwickCrematorEffect(), false); - ability.addTarget(new TargetPlayer()); + ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CrashOfRhinoBeetles.java b/Mage.Sets/src/mage/cards/c/CrashOfRhinoBeetles.java new file mode 100644 index 00000000000..720d7490e2e --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CrashOfRhinoBeetles.java @@ -0,0 +1,59 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class CrashOfRhinoBeetles extends CardImpl { + + public CrashOfRhinoBeetles(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.subtype.add(SubType.INSECT); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Crash of Rhino Beetles gets +10/+10 as long as you control ten or more lands. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect( + 10, 10, Duration.WhileOnBattlefield + ), + new PermanentsOnTheBattlefieldCondition( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, + ComparisonType.MORE_THAN, 9 + ), + "{this} gets +10/+10 as long as you control ten or more lands" + ) + )); + } + + public CrashOfRhinoBeetles(final CrashOfRhinoBeetles card) { + super(card); + } + + @Override + public CrashOfRhinoBeetles copy() { + return new CrashOfRhinoBeetles(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CrawlingSensation.java b/Mage.Sets/src/mage/cards/c/CrawlingSensation.java index 312d646ab53..f3c27887710 100644 --- a/Mage.Sets/src/mage/cards/c/CrawlingSensation.java +++ b/Mage.Sets/src/mage/cards/c/CrawlingSensation.java @@ -72,7 +72,7 @@ class CrawlingSensationTriggeredAbility extends TriggeredAbilityImpl { Set cardType = card.getCardType(); if (cardOwnerId != null - && card.getOwnerId().equals(getControllerId()) + && card.isOwnedBy(getControllerId()) && cardType != null && card.isLand()) { game.getState().setValue("usedOnTurn" + getControllerId() + getOriginalId(), game.getTurnNum()); diff --git a/Mage.Sets/src/mage/cards/c/CrestedSunmare.java b/Mage.Sets/src/mage/cards/c/CrestedSunmare.java index 9367d010c9c..bdfcd07bb72 100644 --- a/Mage.Sets/src/mage/cards/c/CrestedSunmare.java +++ b/Mage.Sets/src/mage/cards/c/CrestedSunmare.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.IndestructibleAbility; @@ -47,7 +47,7 @@ public final class CrestedSunmare extends CardImpl { // At the beginning of each end step, if you gained life this turn, create a 5/5 white Horse creature token. this.addAbility( - new ConditionalTriggeredAbility( + new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new CrestedSunmareToken()), TargetController.ANY, false), new YouGainedLifeCondition(ComparisonType.MORE_THAN, 0), "At the beginning of each end step, if you gained life this turn, create a 5/5 white Horse creature token."), diff --git a/Mage.Sets/src/mage/cards/c/CruelReality.java b/Mage.Sets/src/mage/cards/c/CruelReality.java index 40417f03cb6..ed9a9e29046 100644 --- a/Mage.Sets/src/mage/cards/c/CruelReality.java +++ b/Mage.Sets/src/mage/cards/c/CruelReality.java @@ -85,7 +85,7 @@ class CruelRealityTriggeredAbiilty extends TriggeredAbilityImpl { && enchantment.getAttachedTo() != null) { Player cursedPlayer = game.getPlayer(enchantment.getAttachedTo()); if (cursedPlayer != null - && game.getActivePlayerId().equals(cursedPlayer.getId())) { + && game.isActivePlayer(cursedPlayer.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(cursedPlayer.getId())); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CryptolithFragment.java b/Mage.Sets/src/mage/cards/c/CryptolithFragment.java index 394fed8a8da..2980d3aa903 100644 --- a/Mage.Sets/src/mage/cards/c/CryptolithFragment.java +++ b/Mage.Sets/src/mage/cards/c/CryptolithFragment.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.condition.common.XorLessLifeCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeAllPlayersEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -39,7 +39,7 @@ public final class CryptolithFragment extends CardImpl { // At the beginning of your upkeep, if each player has 10 or less life, transform Cryptolith Fragment. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), new XorLessLifeCondition(XorLessLifeCondition.CheckType.EACH_PLAYER, 10), "At the beginning of your upkeep, if each player has 10 or less life, transform Cryptolith Fragment.")); diff --git a/Mage.Sets/src/mage/cards/c/CunningBandit.java b/Mage.Sets/src/mage/cards/c/CunningBandit.java index 5afd4f65c2b..911eeccd417 100644 --- a/Mage.Sets/src/mage/cards/c/CunningBandit.java +++ b/Mage.Sets/src/mage/cards/c/CunningBandit.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FlipSourceEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -24,7 +24,6 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.events.GameEvent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +46,7 @@ public final class CunningBandit extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.KI.createInstance()), StaticFilters.SPIRIT_OR_ARCANE_CARD, true)); // At the beginning of the end step, if there are two or more ki counters on Cunning Bandit, you may flip it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new AzamukiTreacheryIncarnate()), true), new SourceHasCounterCondition(CounterType.KI, 2, Integer.MAX_VALUE), "At the beginning of the end step, if there are two or more ki counters on {this}, you may flip it.")); diff --git a/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java b/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java index 4904159e506..183beb3ef6c 100644 --- a/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java +++ b/Mage.Sets/src/mage/cards/c/CuriousHomunculus.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.abilities.mana.ConditionalColorlessManaAbility; @@ -42,7 +42,7 @@ public final class CuriousHomunculus extends CardImpl { // At the beginning of your upkeep, if there are three or more instant and/or sorcery cards in your graveyard, transform Curious Homunculus. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), new InstantOrSorceryCardsInControllerGraveCondition(3), "At the beginning of your upkeep, if there are three or more instant and/or sorcery cards in your graveyard, transform {this}")); diff --git a/Mage.Sets/src/mage/cards/c/CurseOfBloodletting.java b/Mage.Sets/src/mage/cards/c/CurseOfBloodletting.java index 8363d4848df..7fe65e93557 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfBloodletting.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfBloodletting.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; @@ -16,14 +15,15 @@ import mage.game.permanent.Permanent; import mage.target.TargetPlayer; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class CurseOfBloodletting extends CardImpl { public CurseOfBloodletting(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}"); this.subtype.add(SubType.AURA, SubType.CURSE); @@ -71,10 +71,9 @@ class CurseOfBloodlettingEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && - enchantment.getAttachedTo() != null && - event.getTargetId().equals(enchantment.getAttachedTo())) { - return true; + if (enchantment != null && + enchantment.isAttachedTo(event.getTargetId())) { + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfEchoes.java b/Mage.Sets/src/mage/cards/c/CurseOfEchoes.java index aa3e6b8d77e..fc85728ff25 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfEchoes.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfEchoes.java @@ -90,7 +90,7 @@ class CurseOfEchoesCopyTriggeredAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(sourceId); if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); - if (player != null && spell.getControllerId().equals(player.getId())) { + if (player != null && spell.isControlledBy(player.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(spell.getId())); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfOblivion.java b/Mage.Sets/src/mage/cards/c/CurseOfOblivion.java index e31da408eca..a12ec39a260 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfOblivion.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfOblivion.java @@ -79,7 +79,7 @@ class CurseOfOblivionAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(this.sourceId); if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId())) { + if (player != null && game.isActivePlayer(player.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfOpulence.java b/Mage.Sets/src/mage/cards/c/CurseOfOpulence.java index 6156af8739a..c6c93590741 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfOpulence.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfOpulence.java @@ -78,7 +78,7 @@ class CurseOfOpulenceEffect extends OneShotEffect { if (enchantment != null) { Player enchantedPlayer = game.getPlayer(enchantment.getAttachedTo()); if (enchantedPlayer != null) { - Set players = new HashSet(); + Set players = new HashSet<>(); for (UUID attacker : game.getCombat().getAttackers()) { UUID defender = game.getCombat().getDefenderId(attacker); if (defender.equals(enchantedPlayer.getId()) diff --git a/Mage.Sets/src/mage/cards/c/CurseOfPredation.java b/Mage.Sets/src/mage/cards/c/CurseOfPredation.java index be79d9fec45..a130d376858 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfPredation.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfPredation.java @@ -84,8 +84,7 @@ class CurseOfPredationTriggeredAbility extends TriggeredAbilityImpl { if (defender != null) { Permanent enchantment = game.getPermanent(this.getSourceId()); if (enchantment != null - && enchantment.getAttachedTo() != null - && enchantment.getAttachedTo().equals(defender.getId())) { + && enchantment.isAttachedTo(defender.getId())) { for (Effect effect: this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getSourceId())); } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java index dc12e4ebdc8..18040ebb79d 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java @@ -79,7 +79,7 @@ class CurseOfTheBloodyTomeAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(this.sourceId); if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId())) { + if (player != null && game.isActivePlayer(player.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java index d9fbded941e..8e2ab315d4e 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java @@ -7,7 +7,7 @@ import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -45,7 +45,7 @@ public final class CurseOfTheCabal extends CardImpl { // Suspend 2-{2}{B}{B} this.addAbility(new SuspendAbility(2, new ManaCostsImpl("{2}{B}{B}"), this)); // At the beginning of each player's upkeep, if Curse of the Cabal is suspended, that player may sacrifice a permanent. If he or she does, put two time counters on Curse of the Cabal. - this.addAbility(new CurseOfTheCabalTriggeredAbility()); + this.addAbility(new CurseOfTheCabalInterveningIfTriggeredAbility()); } public CurseOfTheCabal(final CurseOfTheCabal card) { @@ -99,9 +99,9 @@ class CurseOfTheCabalSacrificeEffect extends OneShotEffect { } } -class CurseOfTheCabalTriggeredAbility extends ConditionalTriggeredAbility { +class CurseOfTheCabalInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { - public CurseOfTheCabalTriggeredAbility() { + public CurseOfTheCabalInterveningIfTriggeredAbility() { super(new BeginningOfUpkeepTriggeredAbility( Zone.EXILED, new CurseOfTheCabalTriggeredAbilityConditionalDelay(), TargetController.ANY, false, true @@ -113,13 +113,13 @@ class CurseOfTheCabalTriggeredAbility extends ConditionalTriggeredAbility { // counters aren't placed } - public CurseOfTheCabalTriggeredAbility(final CurseOfTheCabalTriggeredAbility effect) { + public CurseOfTheCabalInterveningIfTriggeredAbility(final CurseOfTheCabalInterveningIfTriggeredAbility effect) { super(effect); } @Override - public CurseOfTheCabalTriggeredAbility copy() { - return new CurseOfTheCabalTriggeredAbility(this); + public CurseOfTheCabalInterveningIfTriggeredAbility copy() { + return new CurseOfTheCabalInterveningIfTriggeredAbility(this); } } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java b/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java index 2759845d264..f240a0e5d6f 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java @@ -83,8 +83,7 @@ class CurseOfTheForsakenTriggeredAbility extends TriggeredAbilityImpl { if (defender != null) { Permanent enchantment = game.getPermanent(this.getSourceId()); if (enchantment != null - && enchantment.getAttachedTo() != null - && enchantment.getAttachedTo().equals(defender.getId())) { + && enchantment.isAttachedTo(defender.getId())) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheNightlyHunt.java b/Mage.Sets/src/mage/cards/c/CurseOfTheNightlyHunt.java index 473f8d72df9..72aa6094a55 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheNightlyHunt.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheNightlyHunt.java @@ -67,7 +67,7 @@ class CurseOfTheNightlyHuntEffect extends RequirementEffect { public boolean applies(Permanent permanent, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null) { - if (permanent.getControllerId().equals(enchantment.getAttachedTo())) { + if (permanent.isControlledBy(enchantment.getAttachedTo())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfThePiercedHeart.java b/Mage.Sets/src/mage/cards/c/CurseOfThePiercedHeart.java index bfd840ef5a2..9f713dcde14 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfThePiercedHeart.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfThePiercedHeart.java @@ -81,7 +81,7 @@ class CurseOfThePiercedHeartAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(this.sourceId); if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId())) { + if (player != null && game.isActivePlayer(player.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java b/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java index 43dbcdb9670..cc40d560843 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java @@ -36,7 +36,7 @@ public final class CurseOfTheSwine extends CardImpl { @Override public void adjustTargets(Ability ability, Game game) { - if (ability instanceof SpellAbility && ability.getAbilityType().equals(AbilityType.SPELL)) { + if (ability instanceof SpellAbility && ability.getAbilityType() == AbilityType.SPELL) { ability.getTargets().clear(); ability.addTarget(new TargetCreaturePermanent(ability.getManaCostsToPay().getX())); } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfThirst.java b/Mage.Sets/src/mage/cards/c/CurseOfThirst.java index a0f2087a3e1..97c1c9c1eac 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfThirst.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfThirst.java @@ -81,7 +81,7 @@ class CurseOfThirstAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(this.sourceId); if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId())) { + if (player != null && game.isActivePlayer(player.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java b/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java index 0be3bf905dc..3fb01a3559e 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java @@ -84,8 +84,7 @@ class CurseOfVengeanceTriggeredAbility extends TriggeredAbilityImpl { Spell spell = game.getStack().getSpell(event.getSourceId()); if (enchantment != null && spell != null - && enchantment.getAttachedTo() != null - && enchantment.getAttachedTo().equals(spell.getControllerId())) { + && enchantment.isAttachedTo(spell.getControllerId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(getSourceId())); return true; } @@ -126,7 +125,7 @@ class CurseOfVengeancePlayerLosesTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent sourceObject = game.getPermanentOrLKIBattlefield(this.getSourceId()); - return sourceObject != null && sourceObject.getAttachedTo().equals(event.getPlayerId()); + return sourceObject != null && sourceObject.isAttachedTo(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/c/Cursecatcher.java b/Mage.Sets/src/mage/cards/c/Cursecatcher.java index fc035280704..6510807e1a3 100644 --- a/Mage.Sets/src/mage/cards/c/Cursecatcher.java +++ b/Mage.Sets/src/mage/cards/c/Cursecatcher.java @@ -33,7 +33,7 @@ public final class Cursecatcher extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new GenericManaCost(1)), new SacrificeSourceCost()); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CursedScroll.java b/Mage.Sets/src/mage/cards/c/CursedScroll.java index cf185e8b836..0278616567f 100644 --- a/Mage.Sets/src/mage/cards/c/CursedScroll.java +++ b/Mage.Sets/src/mage/cards/c/CursedScroll.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -8,7 +7,7 @@ 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.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; @@ -29,7 +28,7 @@ public final class CursedScroll extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {3}, {T}: Name a card. Reveal a card at random from your hand. If it's the named card, Cursed Scroll deals 2 damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NameACardEffect(NameACardEffect.TypeOfName.ALL), new ManaCostsImpl("{3}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new ManaCostsImpl("{3}")); ability.addEffect(new CursedScrollEffect()); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); @@ -50,7 +49,7 @@ class CursedScrollEffect extends OneShotEffect { public CursedScrollEffect() { super(Outcome.Neutral); - staticText = "Reveal a card at random from your hand. If it's the named card, {this} deals 2 damage to any target"; + staticText = ", then reveal a card at random from your hand. If that card has the chosen name, {this} deals 2 damage to any target"; } public CursedScrollEffect(final CursedScrollEffect effect) { @@ -61,7 +60,7 @@ class CursedScrollEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (sourceObject != null && controller != null && cardName != null && !cardName.isEmpty()) { if (!controller.getHand().isEmpty()) { Cards revealed = new CardsImpl(); diff --git a/Mage.Sets/src/mage/cards/c/CustodiLich.java b/Mage.Sets/src/mage/cards/c/CustodiLich.java index 1d8e2c41143..0fc1625b39c 100644 --- a/Mage.Sets/src/mage/cards/c/CustodiLich.java +++ b/Mage.Sets/src/mage/cards/c/CustodiLich.java @@ -70,7 +70,7 @@ class BecomesMonarchSourceControllerTriggeredAbility extends TriggeredAbilityImp @Override public boolean checkTrigger(GameEvent event, Game game) { - return getControllerId().equals(event.getPlayerId()); + return isControlledBy(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java b/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java new file mode 100644 index 00000000000..1c04cdb2a63 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java @@ -0,0 +1,44 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author noahg + */ +public final class CyclopeanGiant extends CardImpl { + + public CyclopeanGiant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.subtype.add(SubType.GIANT); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // When Cyclopean Giant dies, target land becomes a Swamp. Exile Cyclopean Giant. + DiesTriggeredAbility ability = new DiesTriggeredAbility(new BecomesBasicLandTargetEffect(Duration.EndOfGame, SubType.SWAMP)); + ability.addEffect(new ExileSourceEffect()); + ability.addTarget(new TargetLandPermanent()); + this.addAbility(ability); + } + + public CyclopeanGiant(final CyclopeanGiant card) { + super(card); + } + + @Override + public CyclopeanGiant copy() { + return new CyclopeanGiant(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DacksDuplicate.java b/Mage.Sets/src/mage/cards/d/DacksDuplicate.java index e58a15264ce..646597f79c2 100644 --- a/Mage.Sets/src/mage/cards/d/DacksDuplicate.java +++ b/Mage.Sets/src/mage/cards/d/DacksDuplicate.java @@ -32,9 +32,9 @@ public final class DacksDuplicate extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - // You may have Dack's Duplicate enter the battlefield as a copy of any creature on the battlefield except it gains haste and dethrone. + // You may have Dack's Duplicate enter the battlefield as a copy of any creature on the battlefield except it has haste and dethrone. Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new DacksDuplicateApplyToPermanent()); - effect.setText("as a copy of any creature on the battlefield except it gains haste and dethrone"); + effect.setText("as a copy of any creature on the battlefield except it has haste and dethrone"); this.addAbility(new EntersBattlefieldAbility(effect, true)); } @@ -53,7 +53,7 @@ class DacksDuplicateApplyToPermanent extends ApplyToPermanent { @Override public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { /** - * 29/05/2014 The ability of Dack’s Duplicate doesn’t target the + * 29/05/2014 The ability of Dack's Duplicate doesn't target the * creature. */ permanent.addAbility(new DethroneAbility(), game); diff --git a/Mage.Sets/src/mage/cards/d/DampingEngine.java b/Mage.Sets/src/mage/cards/d/DampingEngine.java new file mode 100644 index 00000000000..2884c643d09 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DampingEngine.java @@ -0,0 +1,215 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.d; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.SpecialAction; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +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.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author jeffwadsworth + */ +public class DampingEngine extends CardImpl { + + public DampingEngine(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + // A player who controls more permanents than each other player can't play lands or cast artifact, creature, or enchantment spells. That player may sacrifice a permanent for that player to ignore this effect until end of turn. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DampingEngineEffect())); + this.addAbility(new DampingEngineSpecialAction()); + + } + + public DampingEngine(final DampingEngine card) { + super(card); + } + + @Override + public DampingEngine copy() { + return new DampingEngine(this); + } +} + +class DampingEngineEffect extends ContinuousRuleModifyingEffectImpl { + + public DampingEngineEffect() { + super(Duration.WhileOnBattlefield, Outcome.AIDontUseIt); + staticText = "A player who controls more permanents than each other player can't play lands or cast artifact, creature, or enchantment spells" + + "That player may sacrifice a permanent for that player to ignore this effect until end of turn.

"; + } + + public DampingEngineEffect(final DampingEngineEffect effect) { + super(effect); + } + + @Override + public DampingEngineEffect copy() { + return new DampingEngineEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "You can't play the land or cast the spell (" + mageObject.getName() + " in play)."; + } + return null; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PLAY_LAND + || event.getType() == GameEvent.EventType.CAST_SPELL; + + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player player = game.getPlayer(event.getPlayerId()); + Permanent dampingEngine = game.getPermanent(source.getSourceId()); + final Card card = game.getCard(event.getSourceId()); + if (player != null + || card != null) { + // check type of spell + if (card.isCreature() + || card.isArtifact() + || card.isEnchantment() + || card.isLand()) { + // 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 false; + } +} + +class DampingEngineSpecialAction extends SpecialAction { + + public DampingEngineSpecialAction() { + super(Zone.BATTLEFIELD); + this.addCost(new SacrificeTargetCost(new TargetControlledPermanent(), true)); + this.addEffect(new DampingEngineIgnoreEffect()); + this.setMayActivate(TargetController.ANY); + } + + public DampingEngineSpecialAction(final DampingEngineSpecialAction ability) { + super(ability); + } + + @Override + public DampingEngineSpecialAction copy() { + return new DampingEngineSpecialAction(this); + } +} + +class DampingEngineIgnoreEffect extends OneShotEffect { + + public DampingEngineIgnoreEffect() { + super(Outcome.AIDontUseIt); + this.staticText = "That player may sacrifice a permanent for that player to ignore this effect until end of turn"; + } + + public DampingEngineIgnoreEffect(final DampingEngineIgnoreEffect effect) { + super(effect); + } + + @Override + public DampingEngineIgnoreEffect copy() { + return new DampingEngineIgnoreEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + String key = permanent.getId() + "ignoreEffect" + game.getState().getPriorityPlayerId() + game.getState().getTurnNum(); + if (key != null) { + game.getState().setValue("ignoreEffect", key); + } + return true; + } +} + +class ControlsMorePermanentsThanEachOtherPlayer implements Condition { + + Player player; + + public ControlsMorePermanentsThanEachOtherPlayer(Player player) { + this.player = player; + } + + @Override + public boolean apply(Game game, Ability source) { + int numPermanents = game.getBattlefield().countAll(new FilterPermanent(), player.getId(), game); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + if (numPermanents > game.getBattlefield().countAll(new FilterPermanent(), playerId, game)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "a player controls less permanents than you"; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java b/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java index 380ce8d79aa..40b8b5a6f38 100644 --- a/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java +++ b/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java @@ -11,7 +11,7 @@ import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -52,7 +52,7 @@ public final class DanceOfTheDead extends CardImpl { Ability enchantAbility = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(enchantAbility); // When Dance of the Dead enters the battlefield, if it's on the battlefield, it loses "enchant creature card in a graveyard" and gains "enchant creature put onto the battlefield with Dance of the Dead." Put enchanted creature card to the battlefield tapped under your control and attach Dance of the Dead to it. When Dance of the Dead leaves the battlefield, that creature's controller sacrifices it. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DanceOfTheDeadReAttachEffect(), false), SourceOnBattlefieldCondition.instance, "When {this} enters the battlefield, if it's on the battlefield, " diff --git a/Mage.Sets/src/mage/cards/d/DaredevilDragster.java b/Mage.Sets/src/mage/cards/d/DaredevilDragster.java index 66d9cad9306..112af1122ad 100644 --- a/Mage.Sets/src/mage/cards/d/DaredevilDragster.java +++ b/Mage.Sets/src/mage/cards/d/DaredevilDragster.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.CrewAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class DaredevilDragster extends CardImpl { this.toughness = new MageInt(4); // At end of combat, if Daredevil Dragster attacked or blocked this combat, put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EndOfCombatTriggeredAbility(new DaredevilDragsterEffect(), false), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, if {this} attacked or blocked this combat, put a velocity counter on it. Then if it has two or more velocity counters on it, sacrifice it and draw two cards."), diff --git a/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java b/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java index 3d23098e3d7..e4623e5e5a2 100644 --- a/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java +++ b/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; @@ -59,7 +59,7 @@ public final class DarigaazReincarnated extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DarigaazReincarnatedDiesEffect())); // At the beginning of your upkeep, if Darigaaz is exiled with an egg counter on it, remove an egg counter from it. Then if Darigaaz has no egg counters on it, return it to the battlefield. - this.addAbility(new DarigaazReincarnatedTriggeredAbility()); + this.addAbility(new DarigaazReincarnatedInterveningIfTriggeredAbility()); } public DarigaazReincarnated(final DarigaazReincarnated card) { @@ -119,22 +119,22 @@ class DarigaazReincarnatedDiesEffect extends ReplacementEffectImpl { } -class DarigaazReincarnatedTriggeredAbility extends ConditionalTriggeredAbility { +class DarigaazReincarnatedInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { - public DarigaazReincarnatedTriggeredAbility() { + public DarigaazReincarnatedInterveningIfTriggeredAbility() { super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new DarigaazReincarnatedReturnEffect(), TargetController.YOU, false), DarigaazReincarnatedCondition.instance, "At the beginning of your upkeep, if {this} is exiled with an egg counter on it, " + "remove an egg counter from it. Then if {this} has no egg counters on it, return it to the battlefield"); } - public DarigaazReincarnatedTriggeredAbility(final DarigaazReincarnatedTriggeredAbility effect) { + public DarigaazReincarnatedInterveningIfTriggeredAbility(final DarigaazReincarnatedInterveningIfTriggeredAbility effect) { super(effect); } @Override - public DarigaazReincarnatedTriggeredAbility copy() { - return new DarigaazReincarnatedTriggeredAbility(this); + public DarigaazReincarnatedInterveningIfTriggeredAbility copy() { + return new DarigaazReincarnatedInterveningIfTriggeredAbility(this); } } @@ -161,7 +161,7 @@ class DarigaazReincarnatedReturnEffect extends OneShotEffect { return false; } MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject != null && sourceObject instanceof Card) { + if (sourceObject instanceof Card) { Card card = (Card) sourceObject; new RemoveCounterSourceEffect(CounterType.EGG.createInstance()).apply(game, source); if (card.getCounters(game).getCount(CounterType.EGG) == 0) { diff --git a/Mage.Sets/src/mage/cards/d/DarkApprenticeship.java b/Mage.Sets/src/mage/cards/d/DarkApprenticeship.java index 43224cdd757..f4db672b491 100644 --- a/Mage.Sets/src/mage/cards/d/DarkApprenticeship.java +++ b/Mage.Sets/src/mage/cards/d/DarkApprenticeship.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -24,7 +24,7 @@ public final class DarkApprenticeship extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); // Hate — At the beggining of your end step, if an opponent lost life from source other than combat damage this turn, Dark Apprenticeship deals 2 damage to target player. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new DamageTargetEffect(2), TargetController.YOU, false), HateCondition.instance, "Hate — At the beggining of your end step, if an opponent lost life from source other than combat damage this turn, Dark Apprenticeship deals 2 damage to target player."); diff --git a/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java b/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java new file mode 100644 index 00000000000..bef6334009f --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java @@ -0,0 +1,127 @@ +package mage.cards.d; + +import java.util.UUID; +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.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Library; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class DarkDwellerOracle extends CardImpl { + + public DarkDwellerOracle(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(2); + + // {1}, Sacrifice a creature: Exile the top card of your library. You may play that card this turn. + Ability ability = new SimpleActivatedAbility( + new DarkDwellerOracleExileEffect(), + new GenericManaCost(1) + ); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); + this.addAbility(ability); + } + + public DarkDwellerOracle(final DarkDwellerOracle card) { + super(card); + } + + @Override + public DarkDwellerOracle copy() { + return new DarkDwellerOracle(this); + } +} + +class DarkDwellerOracleExileEffect extends OneShotEffect { + + public DarkDwellerOracleExileEffect() { + super(Outcome.Detriment); + this.staticText = "exile the top card of your library. " + + "You may play that card this turn. " + + "(You still pay its costs. " + + "You can play a land this way only if " + + "you have an available land play remaining.)"; + } + + public DarkDwellerOracleExileEffect(final DarkDwellerOracleExileEffect effect) { + super(effect); + } + + @Override + public DarkDwellerOracleExileEffect copy() { + return new DarkDwellerOracleExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourcePermanent != null && controller != null && controller.getLibrary().hasCards()) { + Library library = controller.getLibrary(); + Card card = library.getFromTop(game); + if (card != null) { + String exileName = sourcePermanent.getIdName() + " "; + controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); + ContinuousEffect effect = new DarkDwellerOracleCastFromExileEffect(); + effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + game.addEffect(effect, source); + } + return true; + } + return false; + } +} + +class DarkDwellerOracleCastFromExileEffect extends AsThoughEffectImpl { + + public DarkDwellerOracleCastFromExileEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + staticText = "You may play the card from exile"; + } + + public DarkDwellerOracleCastFromExileEffect(final DarkDwellerOracleCastFromExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public DarkDwellerOracleCastFromExileEffect copy() { + return new DarkDwellerOracleCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return source.isControlledBy(affectedControllerId) + && objectId.equals(getTargetPointer().getFirst(game, source)); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DarksteelGarrison.java b/Mage.Sets/src/mage/cards/d/DarksteelGarrison.java index dfdba117cd8..78c63b2bfc2 100644 --- a/Mage.Sets/src/mage/cards/d/DarksteelGarrison.java +++ b/Mage.Sets/src/mage/cards/d/DarksteelGarrison.java @@ -12,6 +12,7 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.FortifyAbility; import mage.abilities.keyword.IndestructibleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -53,7 +54,7 @@ public final class DarksteelGarrison extends CardImpl { this.addAbility(ability); // Fortify {3} - this.addAbility(new FortifyAbility(Outcome.AddAbility, new GenericManaCost(3))); + this.addAbility(new FortifyAbility(3)); } @@ -66,49 +67,3 @@ public final class DarksteelGarrison extends CardImpl { return new DarksteelGarrison(this); } } - -class FortifyAbility extends ActivatedAbilityImpl { - - private static final FilterControlledPermanent filter = new FilterControlledPermanent("land you control"); - - static { - filter.add(new CardTypePredicate(CardType.LAND)); - } - - public FortifyAbility(Outcome outcome, Cost cost) { - this(outcome, cost, new TargetControlledPermanent(filter)); - } - - public FortifyAbility(Outcome outcome, Cost cost, Target target) { - super(Zone.BATTLEFIELD, new AttachEffect(outcome, "Fortify"), cost); - this.addTarget(target); - this.timing = TimingRule.SORCERY; - } - - @Override - public ActivationStatus canActivate(UUID playerId, Game game) { - ActivationStatus activationStatus = super.canActivate(playerId, game); - if (activationStatus.canActivate()) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.hasSubtype(SubType.FORTIFICATION, game)) { - return activationStatus; - } - } - return ActivationStatus.getFalse(); - } - - public FortifyAbility(final FortifyAbility ability) { - super(ability); - } - - @Override - public FortifyAbility copy() { - return new FortifyAbility(this); - } - - @Override - public String getRule() { - return "Fortify " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": Attach to target land you control. Fortify only as a sorcery.)"; - } - -} diff --git a/Mage.Sets/src/mage/cards/d/DarksteelJuggernaut.java b/Mage.Sets/src/mage/cards/d/DarksteelJuggernaut.java index 404963e427e..a237698395f 100644 --- a/Mage.Sets/src/mage/cards/d/DarksteelJuggernaut.java +++ b/Mage.Sets/src/mage/cards/d/DarksteelJuggernaut.java @@ -31,7 +31,7 @@ public final class DarksteelJuggernaut extends CardImpl { // Indestructible this.addAbility(IndestructibleAbility.getInstance()); - // Darksteel Juggernaut’s power and toughness are each equal to the number of artifacts you control. + // Darksteel Juggernaut's power and toughness are each equal to the number of artifacts you control. this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent("artifacts you control")), Duration.EndOfGame))); diff --git a/Mage.Sets/src/mage/cards/d/DarthMaul.java b/Mage.Sets/src/mage/cards/d/DarthMaul.java index a34a33fcc5e..9805ceecc73 100644 --- a/Mage.Sets/src/mage/cards/d/DarthMaul.java +++ b/Mage.Sets/src/mage/cards/d/DarthMaul.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.CantBeBlockedByTargetSourceEffect; import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.HasteAbility; @@ -40,7 +40,7 @@ public final class DarthMaul extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Hate — Whenever Darth Maul attacks, if an opponent loses life from a source other than combat damage this turn, target creature can't block this turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new CantBeBlockedByTargetSourceEffect(Duration.EndOfTurn), false), HateCondition.instance, "Hate — Whenever Darth Maul attacks, if an opponent loses life from a source other than combat damage this turn, target creature can't block this turn."); diff --git a/Mage.Sets/src/mage/cards/d/DarthTyranus.java b/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java similarity index 93% rename from Mage.Sets/src/mage/cards/d/DarthTyranus.java rename to Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java index fea86e5c631..124c90a7b0b 100644 --- a/Mage.Sets/src/mage/cards/d/DarthTyranus.java +++ b/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java @@ -31,9 +31,9 @@ import mage.target.common.TargetCreaturePermanent; * * @author Styxo */ -public final class DarthTyranus extends CardImpl { +public final class DarthTyranusCountOfSerenno extends CardImpl { - public DarthTyranus(UUID ownerId, CardSetInfo setInfo) { + public DarthTyranusCountOfSerenno(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{1}{W}{U}{B}"); this.subtype.add(SubType.DOOKU); @@ -55,13 +55,13 @@ public final class DarthTyranus extends CardImpl { this.addAbility(ability); } - public DarthTyranus(final DarthTyranus card) { + public DarthTyranusCountOfSerenno(final DarthTyranusCountOfSerenno card) { super(card); } @Override - public DarthTyranus copy() { - return new DarthTyranus(this); + public DarthTyranusCountOfSerenno copy() { + return new DarthTyranusCountOfSerenno(this); } } diff --git a/Mage.Sets/src/mage/cards/d/DauntingDefender.java b/Mage.Sets/src/mage/cards/d/DauntingDefender.java index 69e9b5d0f46..bc1b8020875 100644 --- a/Mage.Sets/src/mage/cards/d/DauntingDefender.java +++ b/Mage.Sets/src/mage/cards/d/DauntingDefender.java @@ -65,7 +65,7 @@ class DauntingDefenderEffect extends PreventionEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.hasSubtype(SubType.CLERIC, game)) { + if (permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.hasSubtype(SubType.CLERIC, game)) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/cards/d/DawnbreakReclaimer.java b/Mage.Sets/src/mage/cards/d/DawnbreakReclaimer.java index 89094a3b695..b3f06e02e77 100644 --- a/Mage.Sets/src/mage/cards/d/DawnbreakReclaimer.java +++ b/Mage.Sets/src/mage/cards/d/DawnbreakReclaimer.java @@ -75,13 +75,13 @@ class DawnbreakReclaimerEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { /** * 04.11.2015 If any opponent has a creature card in their - * graveyard as Dawnbreak Reclaimer’s ability resolves, then you must - * choose one of those cards. You can’t choose a different opponent with + * graveyard as Dawnbreak Reclaimer's ability resolves, then you must + * choose one of those cards. You can't choose a different opponent with * no creature cards in their graveyard to avoid returning one of * those cards. * - * 04.11.2015 If there are no creature cards in any opponent’s graveyard - * as Dawnbreak Reclaimer’s ability resolves, you’ll still have the + * 04.11.2015 If there are no creature cards in any opponent's graveyard + * as Dawnbreak Reclaimer's ability resolves, you'll still have the * option to return a creature card from your graveyard to the * battlefield. You choose which opponent will choose a creature card in * your graveyard. diff --git a/Mage.Sets/src/mage/cards/d/DawnsReflection.java b/Mage.Sets/src/mage/cards/d/DawnsReflection.java index 95c1d28040a..85b962c8727 100644 --- a/Mage.Sets/src/mage/cards/d/DawnsReflection.java +++ b/Mage.Sets/src/mage/cards/d/DawnsReflection.java @@ -76,7 +76,7 @@ class DawnsReflectionTriggeredAbility extends TriggeredManaAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent enchantment = game.getPermanent(this.getSourceId()); - return enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo()); + return enchantment != null && enchantment.isAttachedTo(event.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java b/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java index fa8c284a894..0f13053b5a6 100644 --- a/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java +++ b/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java @@ -144,7 +144,7 @@ class DaxosOfMeletisCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(cardId) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(cardId) && source.isControlledBy(affectedControllerId)) { ExileZone exileZone = game.getState().getExile().getExileZone(exileId); return exileZone != null && exileZone.contains(cardId); } @@ -175,7 +175,7 @@ class DaxosOfMeletisSpendAnyManaEffect extends AsThoughEffectImpl implements AsT @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && Objects.equals(objectId, ((FixedTarget) getTargetPointer()).getTarget()) && ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId) && (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId)) diff --git a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java index d26396ac697..19f86a0c96e 100644 --- a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java +++ b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java @@ -9,7 +9,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -56,7 +56,7 @@ public final class DaybreakRanger extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Daybreak Ranger. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public DaybreakRanger(final DaybreakRanger card) { diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeBrawler.java b/Mage.Sets/src/mage/cards/d/DeadeyeBrawler.java index e3f3b085b89..88ace23bc5e 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeBrawler.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeBrawler.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.constants.SubType; import mage.abilities.keyword.DeathtouchAbility; @@ -35,7 +35,7 @@ public final class DeadeyeBrawler extends CardImpl { this.addAbility(new AscendAbility()); // Whenever Deadeye Brawler deals combat damage to a player, if you have the city's blessing, draw a card. - this.addAbility(new ConditionalTriggeredAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DealsCombatDamageToAPlayerTriggeredAbility( new DrawCardSourceControllerEffect(1), false, false), CitysBlessingCondition.instance, "Whenever {this} deals combat damage to a player, if you have the city's blessing, draw a card.")); diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java b/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java index cf49c078049..eeb855dd357 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeHarpooner.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +39,7 @@ public final class DeadeyeHarpooner extends CardImpl { this.toughness = new MageInt(2); // Revolt — When Deadeye Harpooner enters the battlefield, if a permanent you controlled left the battlefield this turn, destroy target tapped creature an opponent controls. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new DestroyTargetEffect(), false), RevoltCondition.instance, "Revolt — When {this} enters the battlefield, if a permanent you controlled left" + " the battlefield this turn, destroy target tapped creature an opponent controls." diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeRigHauler.java b/Mage.Sets/src/mage/cards/d/DeadeyeRigHauler.java index 2330ad10d25..96cba582c90 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeRigHauler.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeRigHauler.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class DeadeyeRigHauler extends CardImpl { this.toughness = new MageInt(2); // Raid— When Deadeye Rig-Hauler enters the battlefield, if you attacked with a creature this turn, you may return target creature to its owner's hand. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true), RaidCondition.instance, + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, you may return target creature to its owner's hand."); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability, new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeTormentor.java b/Mage.Sets/src/mage/cards/d/DeadeyeTormentor.java index fabc2fb55f8..2a7df4690c6 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeTormentor.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeTormentor.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class DeadeyeTormentor extends CardImpl { this.toughness = new MageInt(2); // Raid — When Deadeye Tormentor enters the battlefield, if you attacked with a creature this turn, target opponent discards a card. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)), RaidCondition.instance, + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, target opponent discards a card."); ability.addTarget(new TargetOpponent()); this.addAbility(ability, new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/d/DeadlyGrub.java b/Mage.Sets/src/mage/cards/d/DeadlyGrub.java index 3bfc96c3664..ddf8afee2da 100644 --- a/Mage.Sets/src/mage/cards/d/DeadlyGrub.java +++ b/Mage.Sets/src/mage/cards/d/DeadlyGrub.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.LastTimeCounterRemovedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.VanishingSacrificeAbility; @@ -38,7 +38,7 @@ public final class DeadlyGrub extends CardImpl { this.addAbility(new VanishingUpkeepAbility(3)); this.addAbility(new VanishingSacrificeAbility()); // When Deadly Grub dies, if it had no time counters on it, create a 6/1 green Insect creature token with shroud. - this.addAbility(new ConditionalTriggeredAbility(new DiesTriggeredAbility(new CreateTokenEffect(new DeadlyGrubToken(), 1)), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new CreateTokenEffect(new DeadlyGrubToken(), 1)), LastTimeCounterRemovedCondition.instance, "When {this} dies, if it had no time counters on it, create a 6/1 green Insect creature token with shroud.")); } diff --git a/Mage.Sets/src/mage/cards/d/DearlyDeparted.java b/Mage.Sets/src/mage/cards/d/DearlyDeparted.java index af910d5c795..6083900b5c3 100644 --- a/Mage.Sets/src/mage/cards/d/DearlyDeparted.java +++ b/Mage.Sets/src/mage/cards/d/DearlyDeparted.java @@ -64,7 +64,7 @@ class DearlyDepartedEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.hasSubtype(SubType.HUMAN, game)) { + if (permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.hasSubtype(SubType.HUMAN, game)) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/d/DeathOfAThousandStings.java b/Mage.Sets/src/mage/cards/d/DeathOfAThousandStings.java index 29217e9fc85..90113472edf 100644 --- a/Mage.Sets/src/mage/cards/d/DeathOfAThousandStings.java +++ b/Mage.Sets/src/mage/cards/d/DeathOfAThousandStings.java @@ -4,7 +4,7 @@ package mage.cards.d; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.MoreCardsInHandThanOpponentsCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; @@ -37,7 +37,7 @@ public final class DeathOfAThousandStings extends CardImpl { this.getSpellAbility().addEffect(effect); // At the beginning of your upkeep, if you have more cards in hand than each opponent, you may return Death of a Thousand Stings from your graveyard to your hand. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), TargetController.YOU, true), diff --git a/Mage.Sets/src/mage/cards/d/DeathSpark.java b/Mage.Sets/src/mage/cards/d/DeathSpark.java index ed911402690..fea3d9c3bf5 100644 --- a/Mage.Sets/src/mage/cards/d/DeathSpark.java +++ b/Mage.Sets/src/mage/cards/d/DeathSpark.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; @@ -35,7 +35,7 @@ public final class DeathSpark extends CardImpl { this.getSpellAbility().addTarget(new TargetAnyTarget()); // At the beginning of your upkeep, if Death Spark is in your graveyard with a creature card directly above it, you may pay {1}. If you do, return Death Spark to your hand. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility( Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new GenericManaCost(1)), diff --git a/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java b/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java index dcfd3b4b74c..4aa59062ae6 100644 --- a/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java +++ b/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class DeathbringerRegent extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Deathbringer Regent enters the battlefield, if you cast it from your hand and there are five or more other creatures on the battlefield, destroy all other creatures. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter), false), new DeathbringerRegentCondition(), "When {this} enters the battlefield, if you cast it from your hand and there are five or more other creatures on the battlefield, destroy all other creatures."), diff --git a/Mage.Sets/src/mage/cards/d/DeathreapRitual.java b/Mage.Sets/src/mage/cards/d/DeathreapRitual.java index 5761d43d37b..afe72c7fbdd 100644 --- a/Mage.Sets/src/mage/cards/d/DeathreapRitual.java +++ b/Mage.Sets/src/mage/cards/d/DeathreapRitual.java @@ -20,7 +20,7 @@ public final class DeathreapRitual extends CardImpl { public DeathreapRitual(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{G}"); - // Morbid - At the beginning of each end step, if a creature died this turn, you may draw a card. + // Morbid — At the beginning of each end step, if a creature died this turn, you may draw a card. this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), TargetController.ANY, MorbidCondition.instance, true)); } diff --git a/Mage.Sets/src/mage/cards/d/DeathsPresence.java b/Mage.Sets/src/mage/cards/d/DeathsPresence.java index 00aac1bb567..0d69324a1cf 100644 --- a/Mage.Sets/src/mage/cards/d/DeathsPresence.java +++ b/Mage.Sets/src/mage/cards/d/DeathsPresence.java @@ -66,7 +66,7 @@ class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent != null && permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { + if (permanent != null && permanent.isControlledBy(this.getControllerId()) && permanent.isCreature()) { this.getTargets().clear(); this.addTarget(new TargetControlledCreaturePermanent()); this.getEffects().clear(); diff --git a/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java b/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java index 31a5f63eaa1..7fef07ec16a 100644 --- a/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java +++ b/Mage.Sets/src/mage/cards/d/DeclarationOfNaught.java @@ -6,7 +6,7 @@ import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CounterTargetEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -27,7 +27,7 @@ public final class DeclarationOfNaught extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}"); // As Declaration of Naught enters the battlefield, name a card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL))); // {U}: Counter target spell with the chosen name. SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}")); diff --git a/Mage.Sets/src/mage/cards/d/DeclareDominance.java b/Mage.Sets/src/mage/cards/d/DeclareDominance.java new file mode 100644 index 00000000000..6d0dbf5447f --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeclareDominance.java @@ -0,0 +1,37 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.effects.common.combat.MustBeBlockedByAllTargetEffect; +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.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class DeclareDominance extends CardImpl { + + public DeclareDominance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); + + // Target creature gets +3/+3 until end of turn. All creatures able to block it this turn do so. + this.getSpellAbility().addEffect(new BoostTargetEffect(3, 3, Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new MustBeBlockedByAllTargetEffect(Duration.EndOfTurn) + .setText("All creatures able to block it this turn do so.") + ); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public DeclareDominance(final DeclareDominance card) { + super(card); + } + + @Override + public DeclareDominance copy() { + return new DeclareDominance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeepSeaKraken.java b/Mage.Sets/src/mage/cards/d/DeepSeaKraken.java index 5af9ee3b8d7..0d02f4049b5 100644 --- a/Mage.Sets/src/mage/cards/d/DeepSeaKraken.java +++ b/Mage.Sets/src/mage/cards/d/DeepSeaKraken.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.SpellCastAllTriggeredAbility; import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.CantBeBlockedSourceAbility; import mage.abilities.keyword.SuspendAbility; @@ -45,7 +45,7 @@ public final class DeepSeaKraken extends CardImpl { // Suspend 9-{2}{U} this.addAbility(new SuspendAbility(9, new ManaCostsImpl("{2}{U}"), this)); // Whenever an opponent casts a spell, if Deep-Sea Kraken is suspended, remove a time counter from it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new SpellCastAllTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), filter, false, SetTargetPointer.NONE), SuspendedCondition.instance, "Whenever an opponent casts a spell, if Deep-Sea Kraken is suspended, remove a time counter from it.")); } diff --git a/Mage.Sets/src/mage/cards/d/DeepWood.java b/Mage.Sets/src/mage/cards/d/DeepWood.java index bc7d91e4c2a..e3aa5d2a452 100644 --- a/Mage.Sets/src/mage/cards/d/DeepWood.java +++ b/Mage.Sets/src/mage/cards/d/DeepWood.java @@ -31,7 +31,7 @@ public final class DeepWood extends CardImpl { // Cast Deep Wood only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DeepfathomSkulker.java b/Mage.Sets/src/mage/cards/d/DeepfathomSkulker.java index 490a04b2b8a..d251e952760 100644 --- a/Mage.Sets/src/mage/cards/d/DeepfathomSkulker.java +++ b/Mage.Sets/src/mage/cards/d/DeepfathomSkulker.java @@ -80,7 +80,7 @@ class DeepfathomSkulkerTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DeepwoodLegate.java b/Mage.Sets/src/mage/cards/d/DeepwoodLegate.java index fc2be841219..d0dcb0ca4b7 100644 --- a/Mage.Sets/src/mage/cards/d/DeepwoodLegate.java +++ b/Mage.Sets/src/mage/cards/d/DeepwoodLegate.java @@ -40,7 +40,7 @@ public final class DeepwoodLegate extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // If an opponent controls a Forest and you control a Swamp, you may cast Deepwood Legate without paying its mana cost. + // If an opponent controls a Forest and you control a Swamp, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Forest and you control a Swamp", new OpponentControlsPermanentCondition(filterForest), new PermanentsOnTheBattlefieldCondition(filterSwamp)); diff --git a/Mage.Sets/src/mage/cards/d/DefenseGrid.java b/Mage.Sets/src/mage/cards/d/DefenseGrid.java index 9699d07b17a..e4aaa65939f 100644 --- a/Mage.Sets/src/mage/cards/d/DefenseGrid.java +++ b/Mage.Sets/src/mage/cards/d/DefenseGrid.java @@ -57,7 +57,7 @@ class DefenseGridCostModificationEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (!abilityToModify.getControllerId().equals(game.getActivePlayerId())) { + if (!abilityToModify.isControlledBy(game.getActivePlayerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java b/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java index a668098a145..f703fa21696 100644 --- a/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java +++ b/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class DefenseOfTheHeart extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU, false); ability.addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 2, new FilterCreatureCard()), false, Outcome.PutLandInPlay)); DefenseOfTheHeartCondition contition = new DefenseOfTheHeartCondition(); - this.addAbility(new ConditionalTriggeredAbility(ability, contition, "At the beginning of your upkeep, if an opponent controls three or more creatures, sacrifice {this}, search your library for up to two creature cards, and put those cards onto the battlefield. Then shuffle your library")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, contition, "At the beginning of your upkeep, if an opponent controls three or more creatures, sacrifice {this}, search your library for up to two creature cards, and put those cards onto the battlefield. Then shuffle your library")); } diff --git a/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java b/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java index 300c5788e3f..b71d27ff4f1 100644 --- a/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java +++ b/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java @@ -80,7 +80,7 @@ class DefiantGreatmawTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - boolean weAreDoingIt = getControllerId().equals(game.getControllerId(event.getSourceId())); + boolean weAreDoingIt = isControlledBy(game.getControllerId(event.getSourceId())); boolean isM1M1Counters = event.getData().equals(CounterType.M1M1.getName()); if (weAreDoingIt && isM1M1Counters && event.getTargetId().equals(this.getSourceId())) { return true; diff --git a/Mage.Sets/src/mage/cards/d/DefiantStand.java b/Mage.Sets/src/mage/cards/d/DefiantStand.java index aafb271c078..1ba93cf23a5 100644 --- a/Mage.Sets/src/mage/cards/d/DefiantStand.java +++ b/Mage.Sets/src/mage/cards/d/DefiantStand.java @@ -28,7 +28,7 @@ public final class DefiantStand extends CardImpl { // Cast Defiant Stand only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DegaSanctuary.java b/Mage.Sets/src/mage/cards/d/DegaSanctuary.java index 87bcf90913c..7c9e60a17a9 100644 --- a/Mage.Sets/src/mage/cards/d/DegaSanctuary.java +++ b/Mage.Sets/src/mage/cards/d/DegaSanctuary.java @@ -4,7 +4,7 @@ package mage.cards.d; import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryTriggeredAbility; +import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ public final class DegaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // At the beginning of your upkeep, if you control a black or red permanent, you gain 2 life. If you control a black permanent and a red permanent, you gain 4 life instead. - Ability ability = new SanctuaryTriggeredAbility( + Ability ability = new SanctuaryInterveningIfTriggeredAbility( new GainLifeEffect(2), new GainLifeEffect(4), ObjectColor.BLACK, ObjectColor.RED, "At the beginning of your upkeep, if you control a black or red permanent, you gain 2 life. " + "If you control a black permanent and a red permanent, you gain 4 life instead." diff --git a/Mage.Sets/src/mage/cards/d/Deicide.java b/Mage.Sets/src/mage/cards/d/Deicide.java index 19f3886ff0f..3e72df10a88 100644 --- a/Mage.Sets/src/mage/cards/d/Deicide.java +++ b/Mage.Sets/src/mage/cards/d/Deicide.java @@ -63,7 +63,7 @@ class DeicideExileEffect extends SearchTargetGraveyardHandLibraryForCardNameAndE controller.moveCardToExileWithInfo(targetEnchantment, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true); // 4/26/2014 // Deicide looks at the card in exile, not the permanent that was exiled, to determine - // if it is a God. For each of the Gods in the Theros block, it won’t matter what your + // if it is a God. For each of the Gods in the Theros block, it won't matter what your // devotion to its color(s) was. The card is a God card when not on the battlefield. Card cardInExile = game.getExile().getCard(targetEnchantment.getId(), game); if (cardInExile != null && cardInExile.hasSubtype(SubType.GOD, game)) { diff --git a/Mage.Sets/src/mage/cards/d/DelayTactic.java b/Mage.Sets/src/mage/cards/d/DelayTactic.java new file mode 100644 index 00000000000..0353df6c847 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DelayTactic.java @@ -0,0 +1,91 @@ +package mage.cards.d; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.DontUntapInPlayersNextUntapStepAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetOpponent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author NinthWorld + */ +public final class DelayTactic extends CardImpl { + + public DelayTactic(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + + // Choose one - + // Creatures you control gain hexproof until end of turn. + 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. + Mode mode = new Mode(); + mode.getEffects().add(new DelayTacticEffect()); + mode.getTargets().add(new TargetOpponent()); + this.getSpellAbility().addMode(mode); + } + + public DelayTactic(final DelayTactic card) { + super(card); + } + + @Override + public DelayTactic copy() { + return new DelayTactic(this); + } +} + +// Based on ManaVaporsEffect +class DelayTacticEffect extends OneShotEffect { + + DelayTacticEffect() { + super(Outcome.Benefit); + this.staticText = "Creatures target opponent controls don't untap during his or her next untap step"; + } + + DelayTacticEffect(final DelayTacticEffect effect) { + super(effect); + } + + @Override + public DelayTacticEffect copy() { + return new DelayTacticEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (targetPlayer != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(targetPlayer.getId())); + ContinuousEffect effect = new DontUntapInPlayersNextUntapStepAllEffect(filter); + effect.setTargetPointer(new FixedTarget(targetPlayer.getId())); + game.addEffect(effect, source); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/Delirium.java b/Mage.Sets/src/mage/cards/d/Delirium.java new file mode 100644 index 00000000000..3a04e3523ae --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Delirium.java @@ -0,0 +1,87 @@ +package mage.cards.d; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.CastOnlyIfConditionIsTrueAbility; +import mage.abilities.condition.common.OnOpponentsTurnCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIsActivePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author noahg + */ +public final class Delirium extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new ControllerIsActivePlayerPredicate()); + } + + public Delirium(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{R}"); + + + // Cast this spell only during an opponent’s turn. + this.addAbility(new CastOnlyIfConditionIsTrueAbility(OnOpponentsTurnCondition.instance, "Cast this spell only during an opponent’s turn.")); + // Tap target creature that player controls. That creature deals damage equal to its power to the player. Prevent all combat damage that would be dealt to and dealt by the creature this turn. + this.getSpellAbility().addEffect(new TapTargetEffect().setText("target creature that player controls")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new DeliriumEffect()); + this.getSpellAbility().addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, true).setText("Prevent all combat damage that would be dealt to")); + this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true).setText("and dealt by the creature this turn.")); + } + + public Delirium(final Delirium card) { + super(card); + } + + @Override + public Delirium copy() { + return new Delirium(this); + } +} + +class DeliriumEffect extends OneShotEffect { + + public DeliriumEffect() { + super(Outcome.Damage); + this.staticText = "that creature deals damage equal to its power to the player"; + } + + public DeliriumEffect(DeliriumEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = game.getPermanent(source.getFirstTarget()); + if (creature != null) { + int amount = creature.getPower().getValue(); + Player controller = game.getPlayer(creature.getControllerId()); + if (controller != null) { + controller.damage(amount, creature.getId(), game, false, true); + return true; + } + } + return false; + } + + @Override + public DeliriumEffect copy() { + return new DeliriumEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DemandingDragon.java b/Mage.Sets/src/mage/cards/d/DemandingDragon.java new file mode 100644 index 00000000000..fcec7897d95 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DemandingDragon.java @@ -0,0 +1,54 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DoUnlessTargetPlayerOrTargetsControllerPaysEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class DemandingDragon extends CardImpl { + + public DemandingDragon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Demanding Dragon enters the battlefield, it deals 5 damage to target opponent unless that player sacrifices a creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new DoUnlessTargetPlayerOrTargetsControllerPaysEffect( + new DamageTargetEffect(5), + new SacrificeTargetCost(new TargetControlledCreaturePermanent( + StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT + )) + ).setText("it deals 5 damage to target opponent unless that player sacrifices a creature")); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public DemandingDragon(final DemandingDragon card) { + super(card); + } + + @Override + public DemandingDragon copy() { + return new DemandingDragon(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DementiaSliver.java b/Mage.Sets/src/mage/cards/d/DementiaSliver.java index b1c1fe3ea81..b6ed7191236 100644 --- a/Mage.Sets/src/mage/cards/d/DementiaSliver.java +++ b/Mage.Sets/src/mage/cards/d/DementiaSliver.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -10,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.cards.*; import mage.constants.*; @@ -39,7 +38,7 @@ public final class DementiaSliver extends CardImpl { this.toughness = new MageInt(3); // All Slivers have "{T}: Name a card. Target opponent reveals a card at random from their hand. If it's the named card, that player discards it. Activate this ability only during your turn." - Ability gainedAbility = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new NameACardEffect(NameACardEffect.TypeOfName.ALL), new TapSourceCost(), MyTurnCondition.instance); + Ability gainedAbility = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new TapSourceCost(), MyTurnCondition.instance); gainedAbility.addEffect(new DementiaSliverEffect()); gainedAbility.addTarget(new TargetOpponent()); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, @@ -66,7 +65,7 @@ class DementiaSliverEffect extends OneShotEffect { public DementiaSliverEffect() { super(Outcome.Damage); - staticText = "Target opponent reveals a card at random from their hand. If it's the named card, that player discards it"; + staticText = "Target opponent reveals a card at random from their hand. If that card has the chose name, that player discards it"; } public DementiaSliverEffect(final DementiaSliverEffect effect) { @@ -77,7 +76,7 @@ class DementiaSliverEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); MageObject sourceObject = game.getObject(source.getSourceId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (opponent != null && sourceObject != null && !cardName.isEmpty()) { if (!opponent.getHand().isEmpty()) { Cards revealed = new CardsImpl(); diff --git a/Mage.Sets/src/mage/cards/d/DemonOfCatastrophes.java b/Mage.Sets/src/mage/cards/d/DemonOfCatastrophes.java new file mode 100644 index 00000000000..f9c230552c7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DemonOfCatastrophes.java @@ -0,0 +1,47 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class DemonOfCatastrophes extends CardImpl { + + public DemonOfCatastrophes(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + + this.subtype.add(SubType.DEMON); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // As an additional cost to cast this spell, sacrifice a creature. + this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + } + + public DemonOfCatastrophes(final DemonOfCatastrophes card) { + super(card); + } + + @Override + public DemonOfCatastrophes copy() { + return new DemonOfCatastrophes(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/Demonfire.java b/Mage.Sets/src/mage/cards/d/Demonfire.java index 69d48e3da9f..71711b70c12 100644 --- a/Mage.Sets/src/mage/cards/d/Demonfire.java +++ b/Mage.Sets/src/mage/cards/d/Demonfire.java @@ -39,11 +39,11 @@ public final class Demonfire extends CardImpl { this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn)); this.getSpellAbility().addWatcher(new DamagedByWatcher()); - // Hellbent - If you have no cards in hand, Demonfire can't be countered by spells or abilities and the damage can't be prevented. + // 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), HellbentCondition.instance, - "
Hellbent — If you have no cards in hand, {this} can't be countered by spells or abilities and the damage can't be prevented.")); + "
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 Effect effect = new CantBeCounteredSourceEffect(); effect.setText(""); diff --git a/Mage.Sets/src/mage/cards/d/DemonicRising.java b/Mage.Sets/src/mage/cards/d/DemonicRising.java index b1ba4ead5e3..b3547c47d52 100644 --- a/Mage.Sets/src/mage/cards/d/DemonicRising.java +++ b/Mage.Sets/src/mage/cards/d/DemonicRising.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.condition.common.CreatureCountCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class DemonicRising extends CardImpl { // At the beginning of your end step, if you control exactly one creature, create a 5/5 black Demon creature token with flying. TriggeredAbility ability = new BeginningOfYourEndStepTriggeredAbility(new CreateTokenEffect(new DemonToken()), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new CreatureCountCondition(1, TargetController.YOU), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new CreatureCountCondition(1, TargetController.YOU), ruleText)); } public DemonicRising(final DemonicRising card) { diff --git a/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java b/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java new file mode 100644 index 00000000000..b8a94e36205 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java @@ -0,0 +1,80 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.constants.SubType; +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.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.MageInt; + +/** + * + * @author TheElk801 + */ +public final class DepartedDeckhand extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(Predicates.not(new SubtypePredicate(SubType.SPIRIT))); + } + + public DepartedDeckhand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.SPIRIT); + this.subtype.add(SubType.PIRATE); + + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Departed Deckhand becomes the target of a spell, sacrifice it. + this.addAbility(new BecomesTargetTriggeredAbility( + new SacrificeSourceEffect(), + StaticFilters.FILTER_SPELL_A + )); + + // Departed Deckhand can only be blocked by Spirits. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ).setText("{this} can't be blocked except by Spirits") + ); + this.addAbility(ability); + + // {3}{U}: Target creature you control can only be blocked by Spirits this turn. + ability = new SimpleActivatedAbility( + new CantBeBlockedTargetEffect( + filter, Duration.EndOfTurn + ).setText("Another target creature you control can't be blocked this turn except by Spirits"), + new ManaCostsImpl("{3}{U}") + ); + ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); + this.addAbility(ability); + } + + public DepartedDeckhand(final DepartedDeckhand card) { + super(card); + } + + @Override + public DepartedDeckhand copy() { + return new DepartedDeckhand(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java b/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java index 29dd3bf675e..851eff1ffbb 100644 --- a/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java +++ b/Mage.Sets/src/mage/cards/d/DereviEmpyrialTactician.java @@ -87,7 +87,7 @@ class DereviEmpyrialTacticianTriggeredAbility extends TriggeredAbilityImpl { if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DesecratedTomb.java b/Mage.Sets/src/mage/cards/d/DesecratedTomb.java new file mode 100644 index 00000000000..b597b3e36d2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DesecratedTomb.java @@ -0,0 +1,89 @@ +package mage.cards.d; + +import java.util.Set; +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeGroupEvent; +import mage.game.permanent.token.BatToken; + +/** + * + * @author TheElk801 + */ +public final class DesecratedTomb extends CardImpl { + + public DesecratedTomb(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // Whenever one or more creature cards leave your graveyard, create a 1/1 black Bat creature token with flying. + this.addAbility(new DesecratedTombTriggeredAbility()); + } + + public DesecratedTomb(final DesecratedTomb card) { + super(card); + } + + @Override + public DesecratedTomb copy() { + return new DesecratedTomb(this); + } +} + +class DesecratedTombTriggeredAbility extends TriggeredAbilityImpl { + + public DesecratedTombTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new BatToken()), false); + } + + public DesecratedTombTriggeredAbility(final DesecratedTombTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE_GROUP; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event; + if (zEvent != null && Zone.GRAVEYARD == zEvent.getFromZone() + && Zone.GRAVEYARD != zEvent.getToZone() + && zEvent.getCards() != null) { + for (Card card : zEvent.getCards()) { + if (card != null) { + + UUID cardOwnerId = card.getOwnerId(); + Set cardType = card.getCardType(); + + if (cardOwnerId != null + && card.isOwnedBy(getControllerId()) + && cardType != null + && card.isCreature()) { + return true; + } + } + + } + } + return false; + } + + @Override + public DesecratedTombTriggeredAbility copy() { + return new DesecratedTombTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever one or more creature cards leave your graveyard, create a 1/1 black Bat creature token with flying"; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DesertsHold.java b/Mage.Sets/src/mage/cards/d/DesertsHold.java index 6232b4e97f7..eca577bfd75 100644 --- a/Mage.Sets/src/mage/cards/d/DesertsHold.java +++ b/Mage.Sets/src/mage/cards/d/DesertsHold.java @@ -8,7 +8,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.OrCondition; import mage.abilities.condition.common.CardsInControllerGraveCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.combat.CantBlockAttackActivateAttachedEffect; @@ -51,7 +51,7 @@ public final class DesertsHold extends CardImpl { this.addAbility(ability); // When Desert's Hold enters the battlefield, if you control a Desert or there is a Desert card in your graveyard, you gain 3 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)), new OrCondition( new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(filterDesertPermanent)), diff --git a/Mage.Sets/src/mage/cards/d/Despair.java b/Mage.Sets/src/mage/cards/d/Despair.java new file mode 100644 index 00000000000..70bc420db28 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Despair.java @@ -0,0 +1,36 @@ +package mage.cards.d; + +import java.util.UUID; + +import mage.abilities.effects.common.SacrificeControllerEffect; +import mage.abilities.effects.common.SacrificeOpponentsEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterControlledCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Despair extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature"); + + public Despair(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); + + + // Each opponent sacrifices a creature. + this.getSpellAbility().addEffect(new SacrificeOpponentsEffect(filter)); + } + + public Despair(final Despair card) { + super(card); + } + + @Override + public Despair copy() { + return new Despair(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DesperateGambit.java b/Mage.Sets/src/mage/cards/d/DesperateGambit.java index 40d2ab333e4..eb79f9d2627 100644 --- a/Mage.Sets/src/mage/cards/d/DesperateGambit.java +++ b/Mage.Sets/src/mage/cards/d/DesperateGambit.java @@ -156,7 +156,7 @@ class TargetControlledSource extends TargetSource { return true; } } - // 108.4a If anything asks for the controller of a card that doesn’t have one (because it’s not a permanent or spell), use its owner instead. + // 108.4a If anything asks for the controller of a card that doesn't have one (because it's not a permanent or spell), use its owner instead. for (Card card : game.getExile().getAllCards(game)) { if (Objects.equals(card.getOwnerId(), sourceControllerId)) { count++; @@ -189,7 +189,7 @@ class TargetControlledSource extends TargetSource { for (Card card : player.getGraveyard().getCards(game)) { possibleTargets.add(card.getId()); } - // 108.4a If anything asks for the controller of a card that doesn’t have one (because it’s not a permanent or spell), use its owner instead. + // 108.4a If anything asks for the controller of a card that doesn't have one (because it's not a permanent or spell), use its owner instead. for (Card card : game.getExile().getAllCards(game)) { if (Objects.equals(card.getOwnerId(), sourceControllerId)) { possibleTargets.add(card.getId()); diff --git a/Mage.Sets/src/mage/cards/d/DesperateResearch.java b/Mage.Sets/src/mage/cards/d/DesperateResearch.java new file mode 100644 index 00000000000..3fc1f6d2ba4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DesperateResearch.java @@ -0,0 +1,76 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; +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.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class DesperateResearch extends CardImpl { + + public DesperateResearch(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); + + // Choose a card name other than a basic land card name. Reveal the top seven cards of your library and put all of them with that name into your hand. Exile the rest. + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NOT_BASIC_LAND_NAME)); + this.getSpellAbility().addEffect(new DesperateResearchEffect()); + } + + public DesperateResearch(final DesperateResearch card) { + super(card); + } + + @Override + public DesperateResearch copy() { + return new DesperateResearch(this); + } +} + +class DesperateResearchEffect extends OneShotEffect { + + public DesperateResearchEffect() { + super(Outcome.Benefit); + this.staticText = "Reveal the top seven cards of your library and put all of them with that name into your hand. Exile the rest"; + } + + public DesperateResearchEffect(final DesperateResearchEffect effect) { + super(effect); + } + + @Override + public DesperateResearchEffect copy() { + return new DesperateResearchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + Player player = game.getPlayer(source.getControllerId()); + if (player == null || cardName == null) { + return false; + } + Cards cardsToExile = new CardsImpl(player.getLibrary().getTopCards(game, 7)); + player.revealCards(source, cardsToExile, game); + FilterCard filter = new FilterCard(); + filter.add(new NamePredicate(cardName)); + Cards cardsToKeep = new CardsImpl(cardsToExile.getCards(filter, game)); + cardsToExile.removeAll(cardsToKeep); + player.moveCards(cardsToKeep, Zone.HAND, source, game); + player.moveCards(cardsToExile, Zone.EXILED, source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DetectionTower.java b/Mage.Sets/src/mage/cards/d/DetectionTower.java new file mode 100644 index 00000000000..3f0ec089949 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DetectionTower.java @@ -0,0 +1,88 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class DetectionTower extends CardImpl { + + public DetectionTower(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {1}, {T}: Until end of turn, your opponents and creatures with hexproof they control can be the targets of spells and abilities you control as though they didn't have hexproof. + Ability ability = new SimpleActivatedAbility( + new DetectionTowerEffect(), + new GenericManaCost(1) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public DetectionTower(final DetectionTower card) { + super(card); + } + + @Override + public DetectionTower copy() { + return new DetectionTower(this); + } +} + +class DetectionTowerEffect extends AsThoughEffectImpl { + + public DetectionTowerEffect() { + super(AsThoughEffectType.HEXPROOF, Duration.EndOfTurn, Outcome.Benefit); + staticText = "until end of turn, your opponents and " + + "creatures with hexproof they control " + + "can be the targets of spells and abilities " + + "you control as though they didn't have hexproof"; + } + + public DetectionTowerEffect(final DetectionTowerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public DetectionTowerEffect copy() { + return new DetectionTowerEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (affectedControllerId.equals(source.getControllerId())) { + if (game.getOpponents(source.getControllerId()).contains(sourceId)) { + return true; + } + Permanent creature = game.getPermanent(sourceId); + if (creature != null + && game.getOpponents(source.getControllerId()).contains(creature.getControllerId())) { + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DiamondMare.java b/Mage.Sets/src/mage/cards/d/DiamondMare.java new file mode 100644 index 00000000000..a239e90d4a3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DiamondMare.java @@ -0,0 +1,86 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.common.ChooseColorEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.constants.SubType; +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.game.events.GameEvent; +import mage.game.stack.Spell; + +/** + * + * @author TheElk801 + */ +public final class DiamondMare extends CardImpl { + + public DiamondMare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); + + this.subtype.add(SubType.HORSE); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // As Diamond Mare enters the battlefield, choose a color. + this.addAbility(new EntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral))); + + // Whenever you cast a spell of the chosen color, you gain 1 life. + this.addAbility(new DiamondMareTriggeredAbility()); + } + + public DiamondMare(final DiamondMare card) { + super(card); + } + + @Override + public DiamondMare copy() { + return new DiamondMare(this); + } +} + +class DiamondMareTriggeredAbility extends TriggeredAbilityImpl { + + public DiamondMareTriggeredAbility() { + super(Zone.BATTLEFIELD, new GainLifeEffect(1), false); + } + + public DiamondMareTriggeredAbility(final DiamondMareTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(this.getControllerId())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + ObjectColor color = (ObjectColor) game.getState().getValue(getSourceId() + "_color"); + if (spell != null && color != null && spell.getColor(game).shares(color)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast a spell of the chosen color, you gain 1 life."; + } + + @Override + public DiamondMareTriggeredAbility copy() { + return new DiamondMareTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/Dichotomancy.java b/Mage.Sets/src/mage/cards/d/Dichotomancy.java new file mode 100644 index 00000000000..c788c4dc8f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Dichotomancy.java @@ -0,0 +1,98 @@ +package mage.cards.d; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreatureCard; +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.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetOpponent; + +/** + * + * @author noahg + */ +public final class Dichotomancy extends CardImpl { + + public Dichotomancy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{U}{U}"); + + + // For each tapped nonland permanent target opponent controls, search that player’s library for a card with the same name as that permanent and put it onto the battlefield under your control. Then that player shuffles their library. + this.getSpellAbility().addEffect(new DichotomancyEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + + // Suspend 3-{1}{U}{U} + this.addAbility(new SuspendAbility(3, new ManaCostsImpl("{1}{U}{U}"), this)); + } + + public Dichotomancy(final Dichotomancy card) { + super(card); + } + + @Override + public Dichotomancy copy() { + return new Dichotomancy(this); + } +} + +class DichotomancyEffect extends OneShotEffect { + + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent(); + + static { + filter.add(new TappedPredicate()); + } + + public DichotomancyEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "For each tapped nonland permanent target opponent controls, search that player’s library for a card with the same name as that permanent and put it onto the battlefield under your control. Then that player shuffles their library"; + } + + public DichotomancyEffect(DichotomancyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && opponent != null) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, opponent.getId(), game)) { + String name = permanent.getName(); + FilterCard filterCard = new FilterCard("card named \""+name+'"'); + filterCard.add(new NamePredicate(name)); + TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filterCard); + if (controller.searchLibrary(target, game, opponent.getId())) { + controller.moveCards(opponent.getLibrary().getCard(target.getFirstTarget(), game), Zone.BATTLEFIELD, source, game); + } + } + opponent.shuffleLibrary(source, game); + return true; + } + return false; + } + + @Override + public DichotomancyEffect copy() { + return new DichotomancyEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DimensionalBreach.java b/Mage.Sets/src/mage/cards/d/DimensionalBreach.java index b66f823f33a..28131d4099e 100644 --- a/Mage.Sets/src/mage/cards/d/DimensionalBreach.java +++ b/Mage.Sets/src/mage/cards/d/DimensionalBreach.java @@ -6,7 +6,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class DimensionalBreach extends CardImpl { // Exile all permanents. For as long as any of those cards remain exiled, at the beginning of each player's upkeep, that player returns one of the exiled cards he or she owns to the battlefield. this.getSpellAbility().addEffect(new DimensionalBreachExileEffect()); - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.ALL, new DimensionalBreachReturnFromExileEffect(), TargetController.ANY, false, true, null), new CardsStillInExileCondition(), null)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.ALL, new DimensionalBreachReturnFromExileEffect(), TargetController.ANY, false, true, null), new CardsStillInExileCondition(), null)); } diff --git a/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java b/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java index a70951a13da..388d4d7bfbf 100644 --- a/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java +++ b/Mage.Sets/src/mage/cards/d/DimirDoppelganger.java @@ -36,7 +36,7 @@ public final class DimirDoppelganger extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(2); - // {1}{U}{B}: Exile target creature card from a graveyard. Dimir Doppelganger becomes a copy of that card and gains this ability. + // {1}{U}{B}: Exile target creature card from a graveyard. Dimir Doppelganger becomes a copy of that card, except it has this ability. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DimirDoppelgangerEffect(), new ManaCostsImpl("{1}{U}{B}")); ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard"))); this.addAbility(ability); @@ -57,7 +57,7 @@ class DimirDoppelgangerEffect extends OneShotEffect { DimirDoppelgangerEffect() { super(Outcome.Copy); - staticText = "Exile target creature card from a graveyard. {this} becomes a copy of that card and gains this ability"; + staticText = "Exile target creature card from a graveyard. {this} becomes a copy of that card, except it has this ability"; } DimirDoppelgangerEffect(final DimirDoppelgangerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/d/DimirKeyrune.java b/Mage.Sets/src/mage/cards/d/DimirKeyrune.java index 0611879445f..954042ad97e 100644 --- a/Mage.Sets/src/mage/cards/d/DimirKeyrune.java +++ b/Mage.Sets/src/mage/cards/d/DimirKeyrune.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.game.permanent.token.TokenImpl; import mage.game.permanent.token.Token; +import mage.game.permanent.token.custom.CreatureToken; /** * @@ -32,7 +33,12 @@ public final class DimirKeyrune extends CardImpl { this.addAbility(new BlackManaAbility()); // {U}{B}: Dimir Keyrune becomes a 2/2 blue and black Horror and can't be blocked this turn - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new DimirKeyruneToken(), "", Duration.EndOfTurn), new ManaCostsImpl("{U}{B}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect( + new CreatureToken(2, 2, "2/2 blue and black Horror creature that can't be blocked") + .withColor("UB") + .withSubType(SubType.HORROR) + .withAbility(new CantBeBlockedSourceAbility()), + "", Duration.EndOfTurn), new ManaCostsImpl("{U}{B}"))); } public DimirKeyrune(final DimirKeyrune card) { @@ -43,25 +49,4 @@ public final class DimirKeyrune extends CardImpl { public DimirKeyrune copy() { return new DimirKeyrune(this); } - - private static class DimirKeyruneToken extends TokenImpl { - DimirKeyruneToken() { - super("Horror", "2/2 blue and black Horror until end of turn and can't be blocked this turn"); - cardType.add(CardType.ARTIFACT); - cardType.add(CardType.CREATURE); - color.setBlue(true); - color.setBlack(true); - subtype.add(SubType.HORROR); - power = new MageInt(2); - toughness = new MageInt(2); - this.addAbility(new CantBeBlockedSourceAbility()); - } - public DimirKeyruneToken(final DimirKeyruneToken token) { - super(token); - } - - public DimirKeyruneToken copy() { - return new DimirKeyruneToken(this); - } - } } diff --git a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java index 20130a2c615..72fe39f0cae 100644 --- a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java +++ b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java @@ -147,7 +147,7 @@ class DireFleetDaredevilPlayEffect extends AsThoughEffectImpl { UUID targetId = getTargetPointer().getFirst(game, source); if (targetId != null) { return targetId.equals(objectId) - && source.getControllerId().equals(affectedControllerId); + && source.isControlledBy(affectedControllerId); } else { // the target card has changed zone meanwhile, so the effect is no longer needed discard(); @@ -179,7 +179,7 @@ class DireFleetDaredevilSpendAnyManaEffect extends AsThoughEffectImpl implements @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && Objects.equals(objectId, ((FixedTarget) getTargetPointer()).getTarget()) && ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId) && game.getState().getZone(objectId) == Zone.STACK; @@ -210,7 +210,7 @@ class DireFleetDaredevilReplacementEffect 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) { diff --git a/Mage.Sets/src/mage/cards/d/DirectorKrennic.java b/Mage.Sets/src/mage/cards/d/DirectorKrennic.java new file mode 100644 index 00000000000..2a528a3d213 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DirectorKrennic.java @@ -0,0 +1,60 @@ +package mage.cards.d; + +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.CreateTokenEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.game.permanent.token.TrooperToken2; +import mage.target.TargetPermanent; + +/** + * + * @author NinthWorld + */ +public final class DirectorKrennic extends CardImpl { + + private static final FilterPermanent filterLand = new FilterPermanent("basic land"); + + static { + filterLand.add(new CardTypePredicate(CardType.LAND)); + filterLand.add(new SupertypePredicate(SuperType.BASIC)); + } + + public DirectorKrennic(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When Director Krennic enters the battlefield, create two 1/1 black Trooper creature tokens. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TrooperToken2(), 2))); + + // When Director Krennic leaves the battlefield, destroy target basic land. + Ability ability = new LeavesBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); + ability.addTarget(new TargetPermanent(filterLand)); + this.addAbility(ability); + } + + public DirectorKrennic(final DirectorKrennic card) { + super(card); + } + + @Override + public DirectorKrennic copy() { + return new DirectorKrennic(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java b/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java index 4f47406d21e..4d77c40513b 100644 --- a/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java +++ b/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java @@ -88,7 +88,7 @@ class DiregrafCaptainTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { Permanent p = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (p != null && p.getControllerId().equals(this.controllerId) && filter.match(p, game)) { + if (p != null && p.isControlledBy(this.controllerId) && filter.match(p, game)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DismissivePyromancer.java b/Mage.Sets/src/mage/cards/d/DismissivePyromancer.java new file mode 100644 index 00000000000..95b1cacf7a5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DismissivePyromancer.java @@ -0,0 +1,64 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +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.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class DismissivePyromancer extends CardImpl { + + public DismissivePyromancer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {R}, {T}, Discard a card: Draw a card. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(1), + new ManaCostsImpl("{R}") + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + this.addAbility(ability); + + // {2}{R}, {T}, Sacrifice Dismissive Pyromancer: It deals 4 damage to target creature. + ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DamageTargetEffect(4, "it"), + new ManaCostsImpl("{2}{R}") + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public DismissivePyromancer(final DismissivePyromancer card) { + super(card); + } + + @Override + public DismissivePyromancer copy() { + return new DismissivePyromancer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/Dispatch.java b/Mage.Sets/src/mage/cards/d/Dispatch.java index fe769a5fe18..6fd5815ce9e 100644 --- a/Mage.Sets/src/mage/cards/d/Dispatch.java +++ b/Mage.Sets/src/mage/cards/d/Dispatch.java @@ -22,7 +22,7 @@ public final class Dispatch extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); this.getSpellAbility().addEffect(new TapTargetEffect()); - this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ExileTargetEffect(), MetalcraftCondition.instance, "Metalcraft - If you control three or more artifacts, exile that creature")); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ExileTargetEffect(), MetalcraftCondition.instance, "Metalcraft — If you control three or more artifacts, exile that creature")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/d/DispenseJustice.java b/Mage.Sets/src/mage/cards/d/DispenseJustice.java index 16ea025c058..98da9261938 100644 --- a/Mage.Sets/src/mage/cards/d/DispenseJustice.java +++ b/Mage.Sets/src/mage/cards/d/DispenseJustice.java @@ -43,7 +43,7 @@ public final class DispenseJustice extends CardImpl { class DispenseJusticeEffect extends OneShotEffect { private static final String effectText = "Target player sacrifices an attacking creature.\r\n\r\n" - + "Metalcraft - That player sacrifices two attacking creatures instead if you control three or more artifacts"; + + "Metalcraft — That player sacrifices two attacking creatures instead if you control three or more artifacts"; private static final FilterAttackingCreature filter = new FilterAttackingCreature(); diff --git a/Mage.Sets/src/mage/cards/d/DisplayOfDominance.java b/Mage.Sets/src/mage/cards/d/DisplayOfDominance.java index 407864aae39..f80123275b0 100644 --- a/Mage.Sets/src/mage/cards/d/DisplayOfDominance.java +++ b/Mage.Sets/src/mage/cards/d/DisplayOfDominance.java @@ -99,7 +99,7 @@ class DisplayOfDominanceEffect extends ContinuousRuleModifyingEffectImpl { mageObject instanceof Spell && (mageObject.getColor(game).isBlack() || mageObject.getColor(game).isBlue())) { Permanent permanent = game.getPermanent(event.getTargetId()); - return permanent != null && permanent.getControllerId().equals(ability.getControllerId()); + return permanent != null && permanent.isControlledBy(ability.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/d/Dispossess.java b/Mage.Sets/src/mage/cards/d/Dispossess.java index a0d9ef2a647..58569dcca46 100644 --- a/Mage.Sets/src/mage/cards/d/Dispossess.java +++ b/Mage.Sets/src/mage/cards/d/Dispossess.java @@ -3,7 +3,7 @@ package mage.cards.d; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +21,7 @@ public final class Dispossess extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); // Name an artifact card. Search target player's graveyard, hand, and library for any number of cards with that name and exile them. Then that player shuffles their library. - this.getSpellAbility().addEffect((new NameACardEffect(NameACardEffect.TypeOfName.ARTIFACT_NAME))); + this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ARTIFACT_NAME))); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new DispossessEffect()); } @@ -48,7 +48,7 @@ class DispossessEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExi @Override public boolean apply(Game game, Ability source) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); return super.applySearchAndExile(game, source, cardName, targetPointer.getFirst(game, source)); } diff --git a/Mage.Sets/src/mage/cards/d/Disrupt.java b/Mage.Sets/src/mage/cards/d/Disrupt.java index 344b3d7302f..e840314bf91 100644 --- a/Mage.Sets/src/mage/cards/d/Disrupt.java +++ b/Mage.Sets/src/mage/cards/d/Disrupt.java @@ -22,7 +22,7 @@ public final class Disrupt extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}"); // Counter target instant or sorcery spell unless its controller pays {1}. - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(1))); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); diff --git a/Mage.Sets/src/mage/cards/d/DivineDeflection.java b/Mage.Sets/src/mage/cards/d/DivineDeflection.java index b0ffb232d98..9044094c555 100644 --- a/Mage.Sets/src/mage/cards/d/DivineDeflection.java +++ b/Mage.Sets/src/mage/cards/d/DivineDeflection.java @@ -118,12 +118,12 @@ class DivineDeflectionPreventDamageTargetEffect extends PreventionEffectImpl { // check permanent first Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - if (permanent.getControllerId().equals(source.getControllerId())) { + if (permanent.isControlledBy(source.getControllerId())) { return true; } } // check player - if (source.getControllerId().equals(event.getTargetId())) { + if (source.isControlledBy(event.getTargetId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DjeruWithEyesOpen.java b/Mage.Sets/src/mage/cards/d/DjeruWithEyesOpen.java index 1e5e879503b..f29593b7e25 100644 --- a/Mage.Sets/src/mage/cards/d/DjeruWithEyesOpen.java +++ b/Mage.Sets/src/mage/cards/d/DjeruWithEyesOpen.java @@ -87,7 +87,7 @@ class DjeruWithEyesOpenPreventEffect extends PreventionEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java b/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java index e33b08f37e0..bba34f74968 100644 --- a/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java +++ b/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java @@ -81,8 +81,8 @@ class DjinnIlluminatusGainReplicateEffect extends ContinuousEffectImpl { // only spells cast, so no copies of spells if ((stackObject instanceof Spell) && !stackObject.isCopy() - && stackObject.getControllerId().equals(source.getControllerId()) - && djinn.getControllerId().equals(source.getControllerId()) // verify that the controller of the djinn cast that spell + && stackObject.isControlledBy(source.getControllerId()) + && djinn.isControlledBy(source.getControllerId()) // verify that the controller of the djinn cast that spell && !stackObject.getManaCost().isEmpty()) { //handle cases like Ancestral Vision Spell spell = (Spell) stackObject; if (filter.match(stackObject, game)) { diff --git a/Mage.Sets/src/mage/cards/d/Domestication.java b/Mage.Sets/src/mage/cards/d/Domestication.java index e0279047ed7..63f91fba200 100644 --- a/Mage.Sets/src/mage/cards/d/Domestication.java +++ b/Mage.Sets/src/mage/cards/d/Domestication.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.continuous.ControlEnchantedEffect; @@ -46,7 +46,7 @@ public final class Domestication extends CardImpl { // At the beginning of your end step, if enchanted creature's power is 4 or greater, sacrifice Domestication. TriggeredAbility ability2 = new BeginningOfYourEndStepTriggeredAbility(new SacrificeSourceEffect(), false); - this.addAbility(new ConditionalTriggeredAbility(ability2, new DomesticationCondition(), "At the beginning of your end step, if enchanted creature's power is 4 or greater, sacrifice {this}")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new DomesticationCondition(), "At the beginning of your end step, if enchanted creature's power is 4 or greater, sacrifice {this}")); } public Domestication(final Domestication card) { diff --git a/Mage.Sets/src/mage/cards/d/DominatorDrone.java b/Mage.Sets/src/mage/cards/d/DominatorDrone.java index d1c8a863f87..3a06feb1f12 100644 --- a/Mage.Sets/src/mage/cards/d/DominatorDrone.java +++ b/Mage.Sets/src/mage/cards/d/DominatorDrone.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.keyword.DevoidAbility; import mage.abilities.keyword.IngestAbility; @@ -47,7 +47,7 @@ public final class DominatorDrone extends CardImpl { // When Dominator Drone enters the battlefield, if you control another colorless creature, each opponent loses 2 life. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(2)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new PermanentsOnTheBattlefieldCondition(filter), "When {this} enters the battlefield, if you control another colorless creature, each opponent loses 2 life.")); diff --git a/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java b/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java index 8edb4b467d0..5f196a12056 100644 --- a/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java +++ b/Mage.Sets/src/mage/cards/d/DoorOfDestinies.java @@ -75,7 +75,7 @@ class AddCounterAbility extends TriggeredAbilityImpl { if (subType != null) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null - && spell.getControllerId().equals(getControllerId()) + && spell.isControlledBy(getControllerId()) && spell.hasSubtype(subType, game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/d/DosanTheFallingLeaf.java b/Mage.Sets/src/mage/cards/d/DosanTheFallingLeaf.java index ab35abb5230..b8e535ff8e8 100644 --- a/Mage.Sets/src/mage/cards/d/DosanTheFallingLeaf.java +++ b/Mage.Sets/src/mage/cards/d/DosanTheFallingLeaf.java @@ -54,7 +54,7 @@ class DosanTheFallingLeafEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == GameEvent.EventType.CAST_SPELL && !game.getActivePlayerId().equals(event.getPlayerId()); + return event.getType() == GameEvent.EventType.CAST_SPELL && !game.isActivePlayer(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/d/Doublecast.java b/Mage.Sets/src/mage/cards/d/Doublecast.java new file mode 100644 index 00000000000..eee0d791c4c --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Doublecast.java @@ -0,0 +1,83 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class Doublecast extends CardImpl { + + public Doublecast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{R}"); + + // When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy. + this.getSpellAbility().addEffect( + new CreateDelayedTriggeredAbilityEffect(new DoublecastAbility()) + .setText("When you cast your next instant or sorcery spell this turn, " + + "copy that spell. You may choose new targets for the copy") + ); + } + + public Doublecast(final Doublecast card) { + super(card); + } + + @Override + public Doublecast copy() { + return new Doublecast(this); + } +} + +class DoublecastAbility extends DelayedTriggeredAbility { + + public DoublecastAbility() { + super(new CopyTargetSpellEffect(true), Duration.EndOfTurn); + } + + public DoublecastAbility(final DoublecastAbility ability) { + super(ability); + } + + @Override + public DoublecastAbility copy() { + return new DoublecastAbility(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 (event.getPlayerId().equals(this.getControllerId())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && (spell.isInstant() || spell.isSorcery())) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "When you cast your next instant or sorcery spell this turn, " + + "copy that spell. You may choose new targets for the copy."; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DoublingSeason.java b/Mage.Sets/src/mage/cards/d/DoublingSeason.java index 587342dffac..fab6ae021d2 100644 --- a/Mage.Sets/src/mage/cards/d/DoublingSeason.java +++ b/Mage.Sets/src/mage/cards/d/DoublingSeason.java @@ -79,7 +79,7 @@ class DoublingSeasonCounterEffect extends ReplacementEffectImpl { && permanent.isLand()); // a played land is not an effect } return permanent != null - && permanent.getControllerId().equals(source.getControllerId()) + && permanent.isControlledBy(source.getControllerId()) && !landPlayed; // example: gemstone mine being played as a land drop } diff --git a/Mage.Sets/src/mage/cards/d/DraconicDisciple.java b/Mage.Sets/src/mage/cards/d/DraconicDisciple.java new file mode 100644 index 00000000000..64b6572e844 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DraconicDisciple.java @@ -0,0 +1,55 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +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.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.permanent.token.DragonToken2; + +/** + * + * @author TheElk801 + */ +public final class DraconicDisciple extends CardImpl { + + public DraconicDisciple(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + + // {7}, {T}, Sacrifice Draconic Disciple: Create a 5/5 red Dragon creature token with flying. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new CreateTokenEffect(new DragonToken2()), + new GenericManaCost(7) + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public DraconicDisciple(final DraconicDisciple card) { + super(card); + } + + @Override + public DraconicDisciple copy() { + return new DraconicDisciple(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DrafnasRestoration.java b/Mage.Sets/src/mage/cards/d/DrafnasRestoration.java index 0fcaa1f512f..83b5bb36b0c 100644 --- a/Mage.Sets/src/mage/cards/d/DrafnasRestoration.java +++ b/Mage.Sets/src/mage/cards/d/DrafnasRestoration.java @@ -63,7 +63,7 @@ class DrafnasRestorationTarget extends TargetCardInGraveyard { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); MageObject object = game.getObject(sourceId); - if (object != null && object instanceof StackObject) { + if (object instanceof StackObject) { Player targetPlayer = game.getPlayer(((StackObject) object).getStackAbility().getFirstTarget()); if (targetPlayer != null) { for (Card card : targetPlayer.getGraveyard().getCards(filter, sourceId, sourceControllerId, game)) { diff --git a/Mage.Sets/src/mage/cards/d/DragonEgg.java b/Mage.Sets/src/mage/cards/d/DragonEgg.java index f7bf84e88e3..7758179a672 100644 --- a/Mage.Sets/src/mage/cards/d/DragonEgg.java +++ b/Mage.Sets/src/mage/cards/d/DragonEgg.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -20,7 +19,7 @@ public final class DragonEgg extends CardImpl { public DragonEgg(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); - this.subtype.add(SubType.DRAGON); + this.subtype.add(SubType.DRAGON, SubType.EGG); this.power = new MageInt(0); this.toughness = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java b/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java index a33d28d65b6..c24d6985bce 100644 --- a/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java +++ b/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java @@ -78,7 +78,7 @@ class DragonlordDromokaEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (game.getActivePlayerId().equals(source.getControllerId()) && + if (game.isActivePlayer(source.getControllerId()) && game.getPlayer(source.getControllerId()).hasOpponent(event.getPlayerId(), game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java b/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java index 4e85621813f..6ce626db3fa 100644 --- a/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java +++ b/Mage.Sets/src/mage/cards/d/DragonlordsPrerogative.java @@ -47,7 +47,7 @@ public final class DragonlordsPrerogative extends CardImpl { Condition condition = new DragonlordsPrerogativeCondition(); ContinuousRuleModifyingEffect cantBeCountered = new CantBeCounteredSourceEffect(); ConditionalContinuousRuleModifyingEffect conditionalCantBeCountered = new ConditionalContinuousRuleModifyingEffect(cantBeCountered, condition); - conditionalCantBeCountered.setText("
If you revealed a Dragon card or controlled a Dragon as you cast {this}, {this} can't be countered"); + 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); @@ -91,7 +91,7 @@ class DragonlordsPrerogativeCondition implements Condition { if (spell != null && spell.getSpellAbility() != null) { for(Cost cost: spell.getSpellAbility().getCosts()) { if (cost instanceof RevealTargetFromHandCost) { - applies = !((RevealTargetFromHandCost)cost).getTargets().isEmpty(); + applies = !cost.getTargets().isEmpty(); break; } } diff --git a/Mage.Sets/src/mage/cards/d/DragonmasterOutcast.java b/Mage.Sets/src/mage/cards/d/DragonmasterOutcast.java index 16eb9055456..9ae855120e0 100644 --- a/Mage.Sets/src/mage/cards/d/DragonmasterOutcast.java +++ b/Mage.Sets/src/mage/cards/d/DragonmasterOutcast.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -40,7 +40,7 @@ public final class DragonmasterOutcast extends CardImpl { // At the beginning of your upkeep, if you control six or more lands, create a 5/5 red Dragon creature token with flying. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new DragonToken2(), 1), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 5), "At the beginning of your upkeep, if you control six or more lands, create a 5/5 red Dragon creature token with flying.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 5), "At the beginning of your upkeep, if you control six or more lands, create a 5/5 red Dragon creature token with flying.")); } public DragonmasterOutcast(final DragonmasterOutcast card) { diff --git a/Mage.Sets/src/mage/cards/d/DragonsHoard.java b/Mage.Sets/src/mage/cards/d/DragonsHoard.java new file mode 100644 index 00000000000..07c4e3c676e --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DragonsHoard.java @@ -0,0 +1,55 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; + +/** + * + * @author TheElk801 + */ +public final class DragonsHoard extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(SubType.DRAGON, "a Dragon"); + + public DragonsHoard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // Whenever a Dragon enters the battlefield under your control, put a gold counter on Dragon's Hoard. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new AddCountersSourceEffect(CounterType.GOLD.createInstance()), filter + )); + + // {T}, Remove a gold counter from Dragon's Hoard: Draw a card. + Ability ability = new SimpleActivatedAbility( + new DrawCardSourceControllerEffect(1), + new TapSourceCost() + ); + ability.addCost(new RemoveCountersSourceCost(CounterType.GOLD.createInstance())); + this.addAbility(ability); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + } + + public DragonsHoard(final DragonsHoard card) { + super(card); + } + + @Override + public DragonsHoard copy() { + return new DragonsHoard(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DragonsPresence.java b/Mage.Sets/src/mage/cards/d/DragonsPresence.java new file mode 100644 index 00000000000..49ce3041996 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DragonsPresence.java @@ -0,0 +1,32 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetAttackingOrBlockingCreature; + +/** + * + * @author TheElk801 + */ +public final class DragonsPresence extends CardImpl { + + public DragonsPresence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Dragon's Presence deals 5 damage to target attacking or blocking creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(5)); + this.getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature()); + } + + public DragonsPresence(final DragonsPresence card) { + super(card); + } + + @Override + public DragonsPresence copy() { + return new DragonsPresence(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DrainPower.java b/Mage.Sets/src/mage/cards/d/DrainPower.java index 6a21c6cbe1f..e22c3f803d4 100644 --- a/Mage.Sets/src/mage/cards/d/DrainPower.java +++ b/Mage.Sets/src/mage/cards/d/DrainPower.java @@ -78,6 +78,7 @@ class DrainPowerEffect extends OneShotEffect { TargetPermanent target = null; while (true) { + targetPlayer.setPayManaMode(true); manaAbilitiesMap.clear(); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, targetPlayer.getId(), game)) { if (!ignorePermanents.contains(permanent)) { @@ -138,9 +139,10 @@ class DrainPowerEffect extends OneShotEffect { } } } + targetPlayer.setPayManaMode(false); // 106.12. One card (Drain Power) causes one player to lose unspent mana and another to add “the mana lost this way.” (Note that these may be the same player.) - // This empties the former player’s mana pool and causes the mana emptied this way to be put into the latter player’s mana pool. Which permanents, spells, and/or + // This empties the former player's mana pool and causes the mana emptied this way to be put into the latter player's mana pool. Which permanents, spells, and/or // abilities produced that mana are unchanged, as are any restrictions or additional effects associated with any of that mana. List manaItems = targetPlayer.getManaPool().getManaItems(); targetPlayer.getManaPool().emptyPool(game); diff --git a/Mage.Sets/src/mage/cards/d/DreadCacodemon.java b/Mage.Sets/src/mage/cards/d/DreadCacodemon.java index 3a0f8eb6eba..9b8e1ad205d 100644 --- a/Mage.Sets/src/mage/cards/d/DreadCacodemon.java +++ b/Mage.Sets/src/mage/cards/d/DreadCacodemon.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.TapAllEffect; import mage.cards.CardImpl; @@ -45,7 +45,7 @@ public final class DreadCacodemon extends CardImpl { // if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false)); ability.addEffect(new TapAllEffect(otherCreaturesYouControl)); - this.addAbility(new ConditionalTriggeredAbility(ability, CastFromHandSourceCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/cards/d/DreadWanderer.java b/Mage.Sets/src/mage/cards/d/DreadWanderer.java index 9bc5b6c82ad..87b9d1b7682 100644 --- a/Mage.Sets/src/mage/cards/d/DreadWanderer.java +++ b/Mage.Sets/src/mage/cards/d/DreadWanderer.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -34,7 +33,15 @@ public final class DreadWanderer extends CardImpl { // {2}{B}: Return Dread Wanderer from your graveyard to the battlefield. // Activate this ability only any time you could cast a sorcery and only if you have one or fewer cards in hand. - ConditionalActivatedAbility ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl("{2}{B}"), HeckbentCondition.instance); + ConditionalActivatedAbility ability = new ConditionalActivatedAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToBattlefieldEffect(), + new ManaCostsImpl("{2}{B}"), + HeckbentCondition.instance, + "{2}{B}: Return {this} from your graveyard to the battlefield. " + + "Activate this ability only any time you could cast a sorcery " + + "and only if you have one or fewer cards in hand." + ); ability.setTiming(TimingRule.SORCERY); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DreamPillager.java b/Mage.Sets/src/mage/cards/d/DreamPillager.java index 39b74f41392..e0eefc81fe7 100644 --- a/Mage.Sets/src/mage/cards/d/DreamPillager.java +++ b/Mage.Sets/src/mage/cards/d/DreamPillager.java @@ -37,7 +37,7 @@ public final class DreamPillager extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // Whenever Dream Pillager deals combat damage to a player, exile that many cards from the top of your library. Until end of turn, you may cast nonland cards exiled this way. + // Whenever Dream Pillager deals combat damage to a player, exile that many cards from the top of your library. Until end of turn, you may cast nonland cards from among those exiled cards. this.addAbility(new DreamPillagerTriggeredAbility()); } @@ -84,7 +84,7 @@ class DreamPillagerTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, exile that many cards from the top of your library. Until end of turn, you may cast nonland cards exiled this way."; + return "Whenever {this} deals combat damage to a player, exile that many cards from the top of your library. Until end of turn, you may cast nonland cards from among those exiled cards."; } } @@ -92,7 +92,7 @@ class DreamPillagerEffect extends OneShotEffect { public DreamPillagerEffect() { super(Outcome.Benefit); - this.staticText = "exile that many cards from the top of your library. Until end of turn, you may cast nonland cards exiled this way"; + this.staticText = "exile that many cards from the top of your library. Until end of turn, you may cast nonland cards from among those exiled cards"; } public DreamPillagerEffect(final DreamPillagerEffect effect) { @@ -153,7 +153,7 @@ class DreamPillagerCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java b/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java index be11454a285..01d62c7422f 100644 --- a/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java +++ b/Mage.Sets/src/mage/cards/d/DreamcallerSiren.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.CanBlockOnlyFlyingAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FlyingAbility; @@ -56,7 +56,7 @@ public final class DreamcallerSiren extends CardImpl { // When Dreamcaller Siren enters the battlefield, if you control another Pirate, tap up to two nonland permanents. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); ability.addTarget(new TargetNonlandPermanent(0, 2, false)); - this.addAbility(new ConditionalTriggeredAbility(ability, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), "when {this} enters the battlefield, if you control another Pirate, tap up to two target nonland permanents.")); } diff --git a/Mage.Sets/src/mage/cards/d/DreampodDruid.java b/Mage.Sets/src/mage/cards/d/DreampodDruid.java index 21023d9b297..c500aafa138 100644 --- a/Mage.Sets/src/mage/cards/d/DreampodDruid.java +++ b/Mage.Sets/src/mage/cards/d/DreampodDruid.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.EnchantedSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class DreampodDruid extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each upkeep, if Dreampod Druid is enchanted, create a 1/1 green Saproling creature token. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken(), 1), TargetController.ANY, false, false), new EnchantedSourceCondition(), "At the beginning of each upkeep, if Dreampod Druid is enchanted, create a 1/1 green Saproling creature token.")); diff --git a/Mage.Sets/src/mage/cards/d/DreamspoilerWitches.java b/Mage.Sets/src/mage/cards/d/DreamspoilerWitches.java index 3ba0e22b0d2..ac0012c0df8 100644 --- a/Mage.Sets/src/mage/cards/d/DreamspoilerWitches.java +++ b/Mage.Sets/src/mage/cards/d/DreamspoilerWitches.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -12,10 +11,12 @@ 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.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/d/DrogskolCaptain.java b/Mage.Sets/src/mage/cards/d/DrogskolCaptain.java index e549ce5bec0..8d2caa9b78d 100644 --- a/Mage.Sets/src/mage/cards/d/DrogskolCaptain.java +++ b/Mage.Sets/src/mage/cards/d/DrogskolCaptain.java @@ -1,8 +1,8 @@ - package mage.cards.d; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -15,21 +15,17 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.SubtypePredicate; /** * * @author Loki */ public final class DrogskolCaptain extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Spirit"); - static { - filter.add(new SubtypePredicate(SubType.SPIRIT)); - } + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.SPIRIT, "Spirits"); public DrogskolCaptain(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); this.subtype.add(SubType.SPIRIT); this.subtype.add(SubType.SOLDIER); @@ -37,9 +33,21 @@ public final class DrogskolCaptain extends CardImpl { this.toughness = new MageInt(2); this.addAbility(FlyingAbility.getInstance()); + // Other Spirit creatures you control get +1/+1 and have hexproof. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(HexproofAbility.getInstance(), Duration.WhileOnBattlefield, filter, true))); + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, + filter, true + ) + ); + ability.addEffect(new GainAbilityControlledEffect( + HexproofAbility.getInstance(), + Duration.WhileOnBattlefield, + filter, true + ).setText("and have hexproof")); + this.addAbility(ability); } public DrogskolCaptain(final DrogskolCaptain card) { diff --git a/Mage.Sets/src/mage/cards/d/DroidUprising.java b/Mage.Sets/src/mage/cards/d/DroidUprising.java new file mode 100644 index 00000000000..3657276640f --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DroidUprising.java @@ -0,0 +1,46 @@ +package mage.cards.d; + +import java.util.UUID; + +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.TapAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.permanent.token.DroidToken; + +/** + * + * @author NinthWorld + */ +public final class DroidUprising extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creatures"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT))); + } + + public DroidUprising(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}{W}"); + + + // Tap all nonartifact creatures. + this.getSpellAbility().addEffect(new TapAllEffect(filter)); + + // Create two colorless 1/1 Droid artifact creature tokens. + this.getSpellAbility().addEffect(new CreateTokenEffect(new DroidToken(), 2)); + } + + public DroidUprising(final DroidUprising card) { + super(card); + } + + @Override + public DroidUprising copy() { + return new DroidUprising(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DrownInShapelessness.java b/Mage.Sets/src/mage/cards/d/DrownInShapelessness.java new file mode 100644 index 00000000000..d5976837795 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DrownInShapelessness.java @@ -0,0 +1,32 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class DrownInShapelessness extends CardImpl { + + public DrownInShapelessness(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + // Return target creature to its owner's hand. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public DrownInShapelessness(final DrownInShapelessness card) { + super(card); + } + + @Override + public DrownInShapelessness copy() { + return new DrownInShapelessness(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DruidOfHorns.java b/Mage.Sets/src/mage/cards/d/DruidOfHorns.java new file mode 100644 index 00000000000..2478e7fd172 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DruidOfHorns.java @@ -0,0 +1,106 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +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.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.BeastToken; +import mage.game.stack.Spell; +import mage.target.Target; + +/** + * + * @author TheElk801 + */ +public final class DruidOfHorns extends CardImpl { + + public DruidOfHorns(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Whenever you cast an Aura spell that targets Druid of Horns, create a 3/3 green Beast creature token. + this.addAbility(new DruidOfHornsTriggeredAbility()); + } + + public DruidOfHorns(final DruidOfHorns card) { + super(card); + } + + @Override + public DruidOfHorns copy() { + return new DruidOfHorns(this); + } +} + +class DruidOfHornsTriggeredAbility extends TriggeredAbilityImpl { + + public DruidOfHornsTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new BeastToken()), false); + } + + public DruidOfHornsTriggeredAbility(final DruidOfHornsTriggeredAbility ability) { + super(ability); + } + + @Override + public DruidOfHornsTriggeredAbility copy() { + return new DruidOfHornsTriggeredAbility(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 (event.getPlayerId().equals(this.getControllerId())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (checkSpell(spell, game)) { + return true; + } + } + return false; + } + + private boolean checkSpell(Spell spell, Game game) { + if (spell != null && spell.hasSubtype(SubType.AURA, game)) { + SpellAbility sa = spell.getSpellAbility(); + for (UUID modeId : sa.getModes().getSelectedModes()) { + Mode mode = sa.getModes().get(modeId); + for (Target target : mode.getTargets()) { + if (!target.isNotTarget() && target.getTargets().contains(this.getSourceId())) { + return true; + } + } + for (Effect effect : mode.getEffects()) { + for (UUID targetId : effect.getTargetPointer().getTargets(game, sa)) { + if (targetId.equals(this.getSourceId())) { + return true; + } + } + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast an Aura spell that targets {this}, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DryadGreenseeker.java b/Mage.Sets/src/mage/cards/d/DryadGreenseeker.java new file mode 100644 index 00000000000..a35431625a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DryadGreenseeker.java @@ -0,0 +1,87 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.constants.SubType; +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.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class DryadGreenseeker extends CardImpl { + + public DryadGreenseeker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.DRYAD); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // {T}: Look at the top card of your library. If it's a land card, you may reveal it and put it into your hand. + this.addAbility(new SimpleActivatedAbility( + new DryadGreenseekerEffect(), + new TapSourceCost() + )); + } + + public DryadGreenseeker(final DryadGreenseeker card) { + super(card); + } + + @Override + public DryadGreenseeker copy() { + return new DryadGreenseeker(this); + } +} + +class DryadGreenseekerEffect extends OneShotEffect { + + public DryadGreenseekerEffect() { + super(Outcome.DrawCard); + this.staticText = "Look at the top card of your library. " + + "If it's a land card, you may reveal it and put it into your hand."; + } + + public DryadGreenseekerEffect(final DryadGreenseekerEffect effect) { + super(effect); + } + + @Override + public DryadGreenseekerEffect copy() { + return new DryadGreenseekerEffect(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; + } + player.lookAtCards(null, card, game); + if (!card.isLand()) { + return true; + } + if (!player.chooseUse(outcome, "Reveal " + card.getName() + " and put it into your hand?", source, game)) { + return true; + } + player.revealCards(source, new CardsImpl(card), game); + return player.moveCards(card, Zone.HAND, source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DrydenVos.java b/Mage.Sets/src/mage/cards/d/DrydenVos.java new file mode 100644 index 00000000000..f35bcd6b86e --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DrydenVos.java @@ -0,0 +1,57 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.BountyAbility; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class DrydenVos extends CardImpl { + + public DrydenVos(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.ROGUE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Menace + this.addAbility(new MenaceAbility()); + + // When Dryden Vos enters the battlefield, put a bounty counter on target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance())); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // Bounty - Whenever a creature an opponent controls with a bounty counter on it dies, Dryden Vos deals 2 damage to any target. + Ability ability2 = new BountyAbility(new DamageTargetEffect(2)); + ability2.addTarget(new TargetAnyTarget()); + this.addAbility(ability2); + } + + public DrydenVos(final DrydenVos card) { + super(card); + } + + @Override + public DrydenVos copy() { + return new DrydenVos(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DualcasterMage.java b/Mage.Sets/src/mage/cards/d/DualcasterMage.java index 81e24b0e952..84f2d13f568 100644 --- a/Mage.Sets/src/mage/cards/d/DualcasterMage.java +++ b/Mage.Sets/src/mage/cards/d/DualcasterMage.java @@ -33,7 +33,7 @@ public final class DualcasterMage extends CardImpl { // When Dualcaster Mage enters the battlefield, copy target instant or sorcery spell. You may choose new targets for the copy. Ability ability = new EntersBattlefieldTriggeredAbility(new CopyTargetSpellEffect(), false); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DuergarHedgeMage.java b/Mage.Sets/src/mage/cards/d/DuergarHedgeMage.java index 1084c128b8c..c1f81adb810 100644 --- a/Mage.Sets/src/mage/cards/d/DuergarHedgeMage.java +++ b/Mage.Sets/src/mage/cards/d/DuergarHedgeMage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -43,12 +43,12 @@ public final class DuergarHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Duergar Hedge-Mage enters the battlefield, if you control two or more Mountains, you may destroy target artifact. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); // When Duergar Hedge-Mage enters the battlefield, if you control two or more Plains, you may destroy target enchantment. - Ability ability2 = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); + Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); ability2.addTarget(new TargetEnchantmentPermanent()); this.addAbility(ability2); diff --git a/Mage.Sets/src/mage/cards/d/DuneriderOutlaw.java b/Mage.Sets/src/mage/cards/d/DuneriderOutlaw.java index 58c95ad22e3..5d5504b7e12 100644 --- a/Mage.Sets/src/mage/cards/d/DuneriderOutlaw.java +++ b/Mage.Sets/src/mage/cards/d/DuneriderOutlaw.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.DealtDamageToAnOpponent; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class DuneriderOutlaw extends CardImpl { this.addAbility(ProtectionAbility.from(ObjectColor.GREEN)); // At the beginning of each end step, if Dunerider Outlaw dealt damage to an opponent this turn, put a +1/+1 counter on it. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); - this.addAbility(new ConditionalTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText)); } public DuneriderOutlaw(final DuneriderOutlaw card) { diff --git a/Mage.Sets/src/mage/cards/d/DungeonGeists.java b/Mage.Sets/src/mage/cards/d/DungeonGeists.java index c6b2fa5afbf..ca1adb97464 100644 --- a/Mage.Sets/src/mage/cards/d/DungeonGeists.java +++ b/Mage.Sets/src/mage/cards/d/DungeonGeists.java @@ -89,7 +89,7 @@ class DungeonGeistsEffect extends ContinuousRuleModifyingEffectImpl { // the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL // event will happen before this effect is applied ever) MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (!(sourceObject instanceof Permanent) || !((Permanent) sourceObject).getControllerId().equals(source.getControllerId())) { + if (!(sourceObject instanceof Permanent) || !((Permanent) sourceObject).isControlledBy(source.getControllerId())) { discard(); return false; } @@ -109,7 +109,7 @@ class DungeonGeistsEffect extends ContinuousRuleModifyingEffectImpl { if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getTargetId().equals(targetPointer.getFirst(game, source))) { Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source)); if (targetCreature != null) { - return targetCreature.getControllerId().equals(game.getActivePlayerId()); + return targetCreature.isControlledBy(game.getActivePlayerId()); } else { discard(); return false; diff --git a/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java b/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java index 071348a81b7..c790d01d342 100644 --- a/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java +++ b/Mage.Sets/src/mage/cards/d/DuskwatchRecruiter.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -49,7 +49,7 @@ public final class DuskwatchRecruiter extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Duskwatch Recruiter. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public DuskwatchRecruiter(final DuskwatchRecruiter card) { diff --git a/Mage.Sets/src/mage/cards/d/DustOfMoments.java b/Mage.Sets/src/mage/cards/d/DustOfMoments.java index eb1fec5dbf1..de75c254c02 100644 --- a/Mage.Sets/src/mage/cards/d/DustOfMoments.java +++ b/Mage.Sets/src/mage/cards/d/DustOfMoments.java @@ -18,6 +18,7 @@ import mage.counters.Counter; import mage.counters.CounterType; import mage.filter.Filter; import mage.filter.FilterCard; +import mage.filter.FilterPermanent; import mage.filter.predicate.permanent.CardCounterPredicate; import mage.filter.predicate.permanent.CounterPredicate; import mage.game.Game; @@ -59,13 +60,13 @@ public final class DustOfMoments extends CardImpl { public abstract static class DustOfMomentsEffect extends OneShotEffect { private final Counter counter; - private final Filter permFilter; + private final Filter permFilter; private final Filter exiledFilter; public DustOfMomentsEffect() { super(Outcome.Benefit); this.counter = new Counter(CounterType.TIME.getName(), 2); - this.permFilter = new FilterCard("permanent and each suspended card"); + this.permFilter = new FilterPermanent("permanent and each suspended card"); permFilter.add(new CounterPredicate(CounterType.TIME)); this.exiledFilter = new FilterCard("permanent and each suspended card"); diff --git a/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java b/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java new file mode 100644 index 00000000000..3443e2074ef --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java @@ -0,0 +1,86 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.filter.predicate.permanent.ControllerControlsIslandPredicate; +import mage.game.Game; +import mage.target.common.TargetAttackingOrBlockingCreature; + +/** + * + * @author noahg + */ +public final class DwarvenSeaClan extends CardImpl { + + private static final FilterAttackingOrBlockingCreature filter = new FilterAttackingOrBlockingCreature(); + + static { + filter.add(new ControllerControlsIslandPredicate()); + } + + public DwarvenSeaClan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.DWARF); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {tap}: Choose target attacking or blocking creature whose controller controls an Island. Dwarven Sea Clan deals 2 damage to that creature at end of combat. Activate this ability only before the end of combat step. + Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DamageTargetEffect(2, true, "that creature"))); + effect.setText("Choose target attacking or blocking creature whose controller controls an Island. Dwarven Sea Clan deals 2 damage to that creature at end of combat."); + Ability ability = new ActivateIfConditionActivatedAbility( + Zone.BATTLEFIELD, + effect, + new TapSourceCost(), + BeforeEndCombatCondition.getInstance() + ); + ability.addTarget(new TargetAttackingOrBlockingCreature(1, 1, filter, false)); + addAbility(ability); + } + + public DwarvenSeaClan(final DwarvenSeaClan card) { + super(card); + } + + @Override + public DwarvenSeaClan copy() { + return new DwarvenSeaClan(this); + } +} + +class BeforeEndCombatCondition implements Condition { + private static final BeforeEndCombatCondition instance = new BeforeEndCombatCondition(); + + public static Condition getInstance() { + return instance; + } + + @Override + public boolean apply(Game game, Ability source) { + PhaseStep phaseStep = game.getStep().getType(); + if(phaseStep.getIndex() < PhaseStep.END_COMBAT.getIndex()) { + return true; + } + return false; + } + + @Override + public String toString() { + return "before the end of combat step"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DwarvenSoldier.java b/Mage.Sets/src/mage/cards/d/DwarvenSoldier.java index 73f29e88af0..b15c4d3a726 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenSoldier.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenSoldier.java @@ -1,9 +1,8 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; +import mage.abilities.common.BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,6 +11,8 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import java.util.UUID; + /** * * @author MarcoMarin @@ -26,7 +27,7 @@ public final class DwarvenSoldier extends CardImpl { this.toughness = new MageInt(1); // Whenever Dwarven Soldier blocks or becomes blocked by one or more Orcs, Dwarven Soldier gets +0/+2 until end of turn. - this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(0, 2, Duration.EndOfTurn), new FilterCreaturePermanent(SubType.ORC, "Orc creature"), false)); + this.addAbility(new BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(new BoostSourceEffect(0, 2, Duration.EndOfTurn), new FilterCreaturePermanent(SubType.ORC, "Orcs"), false)); } public DwarvenSoldier(final DwarvenSoldier card) { diff --git a/Mage.Sets/src/mage/cards/d/DwynensElite.java b/Mage.Sets/src/mage/cards/d/DwynensElite.java index a04728d187b..394a7071b5c 100644 --- a/Mage.Sets/src/mage/cards/d/DwynensElite.java +++ b/Mage.Sets/src/mage/cards/d/DwynensElite.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -40,7 +40,7 @@ public final class DwynensElite extends CardImpl { // When Dwynen's Elite enters the battlefield, if you control another Elf, create a 1/1 green Elf Warrior creature token. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ElfToken())); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new PermanentsOnTheBattlefieldCondition(filter), "When {this} enters the battlefield, if you control another Elf, create a 1/1 green Elf Warrior creature token.")); diff --git a/Mage.Sets/src/mage/cards/e/EarthOriginYak.java b/Mage.Sets/src/mage/cards/e/EarthOriginYak.java new file mode 100644 index 00000000000..02ea1ea81ec --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthOriginYak.java @@ -0,0 +1,38 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; + +/** + * + * @author TheElk801 + */ +public final class EarthOriginYak extends CardImpl { + + public EarthOriginYak(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.OX); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // When Earth-Origin Yak enters the battlefield, creatures you control get +1/+1 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new BoostControlledEffect(1, 1, Duration.EndOfTurn))); + } + + public EarthOriginYak(final EarthOriginYak card) { + super(card); + } + + @Override + public EarthOriginYak copy() { + return new EarthOriginYak(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java b/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java index c08b14c74ec..0d399a8ab4e 100644 --- a/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java +++ b/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java @@ -102,9 +102,9 @@ class EarthshakerKhenraEffect extends OneShotEffect { 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. + 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); diff --git a/Mage.Sets/src/mage/cards/e/EarthshakingSi.java b/Mage.Sets/src/mage/cards/e/EarthshakingSi.java new file mode 100644 index 00000000000..6218aac5814 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthshakingSi.java @@ -0,0 +1,37 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class EarthshakingSi extends CardImpl { + + public EarthshakingSi(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + } + + public EarthshakingSi(final EarthshakingSi card) { + super(card); + } + + @Override + public EarthshakingSi copy() { + return new EarthshakingSi(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EarwigSquad.java b/Mage.Sets/src/mage/cards/e/EarwigSquad.java index 43182df461f..41c6b6c225a 100644 --- a/Mage.Sets/src/mage/cards/e/EarwigSquad.java +++ b/Mage.Sets/src/mage/cards/e/EarwigSquad.java @@ -7,7 +7,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ProwlCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.ProwlAbility; import mage.cards.Card; @@ -42,7 +42,7 @@ public final class EarwigSquad extends CardImpl { // When Earwig Squad enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles their library. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new EarwigSquadEffect(), false); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalTriggeredAbility(ability, ProwlCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCondition.instance, "When {this} enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles their library.")); } diff --git a/Mage.Sets/src/mage/cards/e/EchoMage.java b/Mage.Sets/src/mage/cards/e/EchoMage.java index ef957d16003..28acd87fd5b 100644 --- a/Mage.Sets/src/mage/cards/e/EchoMage.java +++ b/Mage.Sets/src/mage/cards/e/EchoMage.java @@ -46,7 +46,7 @@ public final class EchoMage extends LevelerCard { // {U}{U}, {tap}: Copy target instant or sorcery spell. You may choose new targets for the copy. Abilities abilities1 = new AbilitiesImpl<>(); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CopyTargetSpellEffect(), new ManaCostsImpl("{U}{U}")); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); ability.addCost(new TapSourceCost()); abilities1.add(ability); // LEVEL 4+ @@ -54,7 +54,7 @@ public final class EchoMage extends LevelerCard { // {U}{U}, {tap}: Copy target instant or sorcery spell twice. You may choose new targets for the copies. Abilities abilities2 = new AbilitiesImpl<>(); ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EchoMageEffect(), new ManaCostsImpl("{U}{U}")); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); ability.addCost(new TapSourceCost()); abilities2.add(ability); diff --git a/Mage.Sets/src/mage/cards/e/EchoStorm.java b/Mage.Sets/src/mage/cards/e/EchoStorm.java new file mode 100644 index 00000000000..3a7277c482d --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EchoStorm.java @@ -0,0 +1,36 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.keyword.CommanderStormAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetArtifactPermanent; + +/** + * + * @author TheElk801 + */ +public final class EchoStorm extends CardImpl { + + public EchoStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); + + // When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies. + this.addAbility(new CommanderStormAbility()); + + // Create a token that's a copy of target artifact. + this.getSpellAbility().addEffect(new CreateTokenCopyTargetEffect()); + this.getSpellAbility().addTarget(new TargetArtifactPermanent()); + } + + public EchoStorm(final EchoStorm card) { + super(card); + } + + @Override + public EchoStorm copy() { + return new EchoStorm(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EdgarMarkov.java b/Mage.Sets/src/mage/cards/e/EdgarMarkov.java index a5310fd5d94..19f8f9ce3a7 100644 --- a/Mage.Sets/src/mage/cards/e/EdgarMarkov.java +++ b/Mage.Sets/src/mage/cards/e/EdgarMarkov.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldOrCommandZoneCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -49,7 +49,7 @@ public final class EdgarMarkov extends CardImpl { this.toughness = new MageInt(4); // Eminence - Whenever you cast another Vampire spell, if Edgar Markov is in the command zone or on the battlefield, create a 1/1 black Vampire creature token. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new SpellCastControllerTriggeredAbility(Zone.ALL, new CreateTokenEffect(new EdgarMarkovToken()), filter2, false, false), SourceOnBattlefieldOrCommandZoneCondition.instance, "Eminence — Whenever you cast another Vampire spell, if {this} is in the command zone or on the battlefield, create a 1/1 black Vampire creature token."); diff --git a/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java b/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java index 27b95e5d19b..9ee96ef7838 100644 --- a/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java +++ b/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java @@ -117,7 +117,7 @@ class EdificeOfAuthorityRestrictionEffect extends RestrictionEffect { public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) { - if (game.getActivePlayerId().equals(source.getControllerId()) + if (game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { Permanent permanent = game.getPermanent(targetId); diff --git a/Mage.Sets/src/mage/cards/e/EightfoldMaze.java b/Mage.Sets/src/mage/cards/e/EightfoldMaze.java index 1580470b97c..e23440a8966 100644 --- a/Mage.Sets/src/mage/cards/e/EightfoldMaze.java +++ b/Mage.Sets/src/mage/cards/e/EightfoldMaze.java @@ -26,7 +26,7 @@ public final class EightfoldMaze extends CardImpl { // Cast Eightfold Maze only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/e/ElderwoodScion.java b/Mage.Sets/src/mage/cards/e/ElderwoodScion.java index e099cab1e4b..778ffb55e52 100644 --- a/Mage.Sets/src/mage/cards/e/ElderwoodScion.java +++ b/Mage.Sets/src/mage/cards/e/ElderwoodScion.java @@ -73,7 +73,7 @@ class ElderwoodScionCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { diff --git a/Mage.Sets/src/mage/cards/e/Electropotence.java b/Mage.Sets/src/mage/cards/e/Electropotence.java index f556ab2bf34..ebaa86d2cfc 100644 --- a/Mage.Sets/src/mage/cards/e/Electropotence.java +++ b/Mage.Sets/src/mage/cards/e/Electropotence.java @@ -64,7 +64,7 @@ class ElectropotenceTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature() - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { this.getEffects().get(0).setValue("damageSource", event.getTargetId()); return true; } diff --git a/Mage.Sets/src/mage/cards/e/Electryte.java b/Mage.Sets/src/mage/cards/e/Electryte.java index 1b0b5305200..6fa756cb171 100644 --- a/Mage.Sets/src/mage/cards/e/Electryte.java +++ b/Mage.Sets/src/mage/cards/e/Electryte.java @@ -25,7 +25,7 @@ public final class Electryte extends CardImpl { public Electryte(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); - this.subtype.add(SubType.BEAST); + this.subtype.add(SubType.BEAST, SubType.TRILOBITE); this.power = new MageInt(3); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/e/ElkinBottle.java b/Mage.Sets/src/mage/cards/e/ElkinBottle.java index 972c8ca29f5..5ace27859f0 100644 --- a/Mage.Sets/src/mage/cards/e/ElkinBottle.java +++ b/Mage.Sets/src/mage/cards/e/ElkinBottle.java @@ -97,7 +97,7 @@ class ElkinBottleCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) { - if (!sameStep && game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { return true; } } else { @@ -113,7 +113,7 @@ class ElkinBottleCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && sourceId.equals(getTargetPointer().getFirst(game, source)); } diff --git a/Mage.Sets/src/mage/cards/e/ElvishClancaller.java b/Mage.Sets/src/mage/cards/e/ElvishClancaller.java new file mode 100644 index 00000000000..9be147e6757 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ElvishClancaller.java @@ -0,0 +1,75 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +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.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author TheElk801 + */ +public final class ElvishClancaller extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Elves"); + private static final FilterCard filter2 = new FilterCard("card named Elvish Clancaller"); + + static { + filter.add(new SubtypePredicate(SubType.ELF)); + filter2.add(new NamePredicate("Elvish Clancaller")); + } + + public ElvishClancaller(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Other Elves you control get +1/+1. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, + filter, true + ) + )); + + // {4}{G}{G}, {T}: Search your library for a card named Elvish Clancaller, put it onto the battlefield, then shuffle your library. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new SearchLibraryPutInPlayEffect( + new TargetCardInLibrary(filter2), + false + ), + new ManaCostsImpl("{4}{G}{G}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public ElvishClancaller(final ElvishClancaller card) { + super(card); + } + + @Override + public ElvishClancaller copy() { + return new ElvishClancaller(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ElvishRejuvenator.java b/Mage.Sets/src/mage/cards/e/ElvishRejuvenator.java new file mode 100644 index 00000000000..61fddd83fef --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ElvishRejuvenator.java @@ -0,0 +1,94 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.constants.SubType; +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.filter.common.FilterLandCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; + +/** + * + * @author TheElk801 + */ +public final class ElvishRejuvenator extends CardImpl { + + public ElvishRejuvenator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Elvish Rejuvenator enters the battlefield, look at the top five cards of your library. You may put a land card from among them onto the battlefield tapped. Put the rest on the bottom of your library in a random order. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ElvishRejuvenatorEffect(), false)); + } + + public ElvishRejuvenator(final ElvishRejuvenator card) { + super(card); + } + + @Override + public ElvishRejuvenator copy() { + return new ElvishRejuvenator(this); + } +} + +class ElvishRejuvenatorEffect extends OneShotEffect { + + public ElvishRejuvenatorEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "look at the top five cards of your library. " + + "You may put a land card from among them onto the battlefield tapped. " + + "Put the rest on the bottom of your library in a random order"; + } + + public ElvishRejuvenatorEffect(final ElvishRejuvenatorEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, 5)); + if (!cards.isEmpty()) { + TargetCard target = new TargetCard( + Zone.LIBRARY, + new FilterLandCard("land card to put on the battlefield") + ); + if (controller.choose(Outcome.PutCardInPlay, cards, target, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null); + } + } + if (!cards.isEmpty()) { + controller.putCardsOnBottomOfLibrary(cards, game, source, false); + } + } + return true; + } + + @Override + public ElvishRejuvenatorEffect copy() { + return new ElvishRejuvenatorEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EmbermawHellion.java b/Mage.Sets/src/mage/cards/e/EmbermawHellion.java index 42ae1cdbcb6..9bc75994f26 100644 --- a/Mage.Sets/src/mage/cards/e/EmbermawHellion.java +++ b/Mage.Sets/src/mage/cards/e/EmbermawHellion.java @@ -74,7 +74,7 @@ class EmbermawHellionEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if(source.getControllerId().equals(game.getControllerId(event.getSourceId()))) { + if(source.isControlledBy(game.getControllerId(event.getSourceId()))) { MageObject sourceObject; Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); if(sourcePermanent == null) { diff --git a/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java b/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java new file mode 100644 index 00000000000..9bd4c2fa1f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java @@ -0,0 +1,116 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.RevealSecretOpponentCost; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseSecretOpponentEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +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.game.stack.StackObject; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetStackObject; + +import java.util.UUID; + +/** + * + * @author credman0 + */ +public class EmissaryOfGrudges extends CardImpl { + + public EmissaryOfGrudges(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}"); + + this.subtype.add(SubType.EFREET); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + + // flying + this.addAbility(FlyingAbility.getInstance()); + // haste + this.addAbility(HasteAbility.getInstance()); + + // As Emissary of Grudges enters the battlefield, secretly choose an opponent. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new ChooseSecretOpponentEffect(),"As {this} enters the battlefield, secretly choose an opponent."))); + // Choose new targets for target spell or ability if it’s controlled by the chosen player and if it targets you + // or a permanent you control. Activate this ability only once. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EmissaryOfGrudgesEffect(), new RevealSecretOpponentCost()); + ability.addTarget(new TargetStackObject()); + this.addAbility(ability); + } + + public EmissaryOfGrudges(final EmissaryOfGrudges card) { + super(card); + } + + @Override + public EmissaryOfGrudges copy() { + return new EmissaryOfGrudges(this); + } +} + +class EmissaryOfGrudgesEffect extends OneShotEffect { + + public EmissaryOfGrudgesEffect() { + super(Outcome.Neutral); + this.staticText = "Choose new targets for target spell or ability if it’s controlled by the chosen player and" + + " if it targets you or a permanent you control. Activate this ability only once."; + } + + public EmissaryOfGrudgesEffect(final EmissaryOfGrudgesEffect effect) { + super(effect); + } + + @Override + public EmissaryOfGrudgesEffect copy() { + return new EmissaryOfGrudgesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); + if (stackObject != null) { + UUID opponentId = (UUID) game.getState().getValue(source.getSourceId() + ChooseSecretOpponentEffect.SECRET_OPPONENT); + if (opponentId != null && opponentId.equals(stackObject.getControllerId())) { + // find if it targets you or a permanent you control + boolean targetsYouOrAPermanentYouControl = false; + for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) { + Mode mode = stackObject.getStackAbility().getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetId : target.getTargets()) { + if (source.getControllerId().equals(targetId)) { + targetsYouOrAPermanentYouControl = true; + } + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && source.getControllerId().equals(permanent.getControllerId())) { + targetsYouOrAPermanentYouControl = true; + } + } + } + } + if (targetsYouOrAPermanentYouControl){ + return stackObject.chooseNewTargets(game, source.getControllerId(), false, false, null); + } + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EmissaryOfTheSleepless.java b/Mage.Sets/src/mage/cards/e/EmissaryOfTheSleepless.java index 20be9866b36..7871e1a48c3 100644 --- a/Mage.Sets/src/mage/cards/e/EmissaryOfTheSleepless.java +++ b/Mage.Sets/src/mage/cards/e/EmissaryOfTheSleepless.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -32,7 +32,7 @@ public final class EmissaryOfTheSleepless extends CardImpl { // When Emissary of the Sleepless enters the battlefield, if a creature died this turn, create a 1/1 white Spirit creature token with flying. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())); - this.addAbility(new ConditionalTriggeredAbility(ability, MorbidCondition.instance, "When {this} enters the battlefield, if a creature died this turn, create a 1/1 white Spirit creature token with flying.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, "When {this} enters the battlefield, if a creature died this turn, create a 1/1 white Spirit creature token with flying.")); } public EmissaryOfTheSleepless(final EmissaryOfTheSleepless card) { diff --git a/Mage.Sets/src/mage/cards/e/EmpyrialStorm.java b/Mage.Sets/src/mage/cards/e/EmpyrialStorm.java new file mode 100644 index 00000000000..1b96845f052 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmpyrialStorm.java @@ -0,0 +1,35 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.CommanderStormAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.AngelToken; + +/** + * + * @author TheElk801 + */ +public final class EmpyrialStorm extends CardImpl { + + public EmpyrialStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}{W}"); + + // When you cast this spell, copy it for each time you've cast your commander from the command zone this game. + this.addAbility(new CommanderStormAbility()); + + // Create a 4/4 white Angel creature token with flying. + this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken())); + } + + public EmpyrialStorm(final EmpyrialStorm card) { + super(card); + } + + @Override + public EmpyrialStorm copy() { + return new EmpyrialStorm(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EnchantersBane.java b/Mage.Sets/src/mage/cards/e/EnchantersBane.java new file mode 100644 index 00000000000..1faac01ac74 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnchantersBane.java @@ -0,0 +1,79 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetEnchantmentPermanent; + +/** + * + * @author TheElk801 + */ +public final class EnchantersBane extends CardImpl { + + public EnchantersBane(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + + // At the beginning of your end step, target enchantment deals damage equal to its converted mana cost to its controller unless that player sacrifices it. + Ability ability = new BeginningOfEndStepTriggeredAbility( + new EnchantersBaneEffect(), TargetController.YOU, false + ); + ability.addTarget(new TargetEnchantmentPermanent()); + this.addAbility(ability); + } + + public EnchantersBane(final EnchantersBane card) { + super(card); + } + + @Override + public EnchantersBane copy() { + return new EnchantersBane(this); + } +} + +class EnchantersBaneEffect extends OneShotEffect { + + public EnchantersBaneEffect() { + super(Outcome.Benefit); + this.staticText = "target enchantment deals damage equal to " + + "its converted mana cost to its controller " + + "unless that player sacrifices it"; + } + + public EnchantersBaneEffect(final EnchantersBaneEffect effect) { + super(effect); + } + + @Override + public EnchantersBaneEffect copy() { + return new EnchantersBaneEffect(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; + } + if (player.chooseUse(Outcome.GainLife, "Sacrifice " + permanent.getLogName() + "?", source, game)) { + permanent.sacrifice(source.getSourceId(), game); + } else { + player.damage(permanent.getConvertedManaCost(), permanent.getId(), game, false, true); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EncirclingFissure.java b/Mage.Sets/src/mage/cards/e/EncirclingFissure.java index a022c29835b..ca9f6b61ebc 100644 --- a/Mage.Sets/src/mage/cards/e/EncirclingFissure.java +++ b/Mage.Sets/src/mage/cards/e/EncirclingFissure.java @@ -66,7 +66,7 @@ class EncirclingFissurePreventEffect extends PreventionEffectImpl { Permanent permanent = game.getPermanent(damageEvent.getSourceId()); if (permanent != null && permanent.isCreature() - && permanent.getControllerId().equals(getTargetPointer().getFirst(game, source))) { + && permanent.isControlledBy(getTargetPointer().getFirst(game, source))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/e/EndlessAtlas.java b/Mage.Sets/src/mage/cards/e/EndlessAtlas.java new file mode 100644 index 00000000000..022cb4b44e3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EndlessAtlas.java @@ -0,0 +1,74 @@ +package mage.cards.e; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class EndlessAtlas extends CardImpl { + + public EndlessAtlas(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + // {2}, {T}: Draw a card. Activate this ability only if you control three or more lands with the same name. + Ability ability = new ActivateIfConditionActivatedAbility( + Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(1), + new GenericManaCost(2), + new EndlessAtlasCondition() + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public EndlessAtlas(final EndlessAtlas card) { + super(card); + } + + @Override + public EndlessAtlas copy() { + return new EndlessAtlas(this); + } +} + +class EndlessAtlasCondition implements Condition { + + @Override + public boolean apply(Game game, Ability source) { + Map landMap = new HashMap(); + for (Permanent land : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, + source.getControllerId(), game + )) { + if (land != null) { + int landCount = landMap.getOrDefault(land.getName(), 0); + if (landCount > 1) { + return true; + } + landMap.put(land.getName(), landCount + 1); + } + } + return false; + } + + @Override + public String toString() { + return "you control three or more lands with the same name"; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EndlessSands.java b/Mage.Sets/src/mage/cards/e/EndlessSands.java index 71ba3740534..402bf570a8a 100644 --- a/Mage.Sets/src/mage/cards/e/EndlessSands.java +++ b/Mage.Sets/src/mage/cards/e/EndlessSands.java @@ -32,8 +32,8 @@ public final class EndlessSands extends CardImpl { exileAbility.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(exileAbility); - // {4}, {T}, Sacrifice Endless Sands: Return each creature card exiled with Endless Sands to the battlefield under its owner’s control. - ReturnCreaturesFromExileEffect returnFromExileEffect = new ReturnCreaturesFromExileEffect(this.getId(), true, "Return each creature card exiled with {this} to the battlefield under its owner’s control."); + // {4}, {T}, Sacrifice Endless Sands: Return each creature card exiled with Endless Sands to the battlefield under its owner's control. + ReturnCreaturesFromExileEffect returnFromExileEffect = new ReturnCreaturesFromExileEffect(this.getId(), true, "Return each creature card exiled with {this} to the battlefield under its owner's control."); Ability returnAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, returnFromExileEffect, new ManaCostsImpl("{4}")); returnAbility.addCost(new TapSourceCost()); returnAbility.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/cards/e/EnduringScalelord.java b/Mage.Sets/src/mage/cards/e/EnduringScalelord.java index f315c98fec3..663f0f9cfe3 100644 --- a/Mage.Sets/src/mage/cards/e/EnduringScalelord.java +++ b/Mage.Sets/src/mage/cards/e/EnduringScalelord.java @@ -76,7 +76,7 @@ class EnduringScalelordTriggeredAbility extends TriggeredAbilityImpl { return (permanent != null && !event.getTargetId().equals(this.getSourceId()) && permanent.isCreature() - && permanent.getControllerId().equals(this.getControllerId())); + && permanent.isControlledBy(this.getControllerId())); } return false; } diff --git a/Mage.Sets/src/mage/cards/e/EnergyStorm.java b/Mage.Sets/src/mage/cards/e/EnergyStorm.java index 67f0bdc1029..e56b8fd6b0a 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyStorm.java +++ b/Mage.Sets/src/mage/cards/e/EnergyStorm.java @@ -38,7 +38,7 @@ public final class EnergyStorm extends CardImpl { // Prevent all damage that would be dealt by instant and sorcery spells. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new PreventAllDamageByAllObjectsEffect(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELLS, Duration.WhileOnBattlefield, false) + new PreventAllDamageByAllObjectsEffect(StaticFilters.FILTER_SPELLS_INSTANT_OR_SORCERY, Duration.WhileOnBattlefield, false) )); // Creatures with flying don't untap during their controllers' untap steps. diff --git a/Mage.Sets/src/mage/cards/e/EnergyTap.java b/Mage.Sets/src/mage/cards/e/EnergyTap.java index 0fd2502cc22..ef1aaadbf82 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyTap.java +++ b/Mage.Sets/src/mage/cards/e/EnergyTap.java @@ -1,4 +1,3 @@ - package mage.cards.e; import java.util.UUID; @@ -23,7 +22,7 @@ import mage.target.common.TargetControlledCreaturePermanent; */ public final class EnergyTap extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you crontrol"); + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { filter.add(Predicates.not(new TappedPredicate())); diff --git a/Mage.Sets/src/mage/cards/e/EnfysNest.java b/Mage.Sets/src/mage/cards/e/EnfysNest.java new file mode 100644 index 00000000000..0fb3a495b8f --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnfysNest.java @@ -0,0 +1,88 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetOpponentsCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class EnfysNest extends CardImpl { + + public EnfysNest(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever Enfys Nest enters the battlefield, you may exile target creature an opponent controls. If you do, that player gains life equal to that creature's power. + Ability ability = new EntersBattlefieldTriggeredAbility(new EnfysNestEffect(), true); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + public EnfysNest(final EnfysNest card) { + super(card); + } + + @Override + public EnfysNest copy() { + return new EnfysNest(this); + } +} + +class EnfysNestEffect extends ExileTargetEffect { + + public EnfysNestEffect() { + super(); + staticText = "you may exile target creature an opponent controls. If you do, that player gains life equal to that creature's power"; + } + + public EnfysNestEffect(final EnfysNestEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); + if(permanent != null) { + // you may exile target creature an opponent controls + if(!super.apply(game, source)) { + return false; + } + + // If you do, that player gains life equal to that creature's power. + Player player = game.getPlayer(permanent.getControllerId()); + player.gainLife(permanent.getPower().getValue(), game, source); + + return true; + } + return false; + } + + @Override + public EnfysNestEffect copy() { + return new EnfysNestEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EnigmaSphinx.java b/Mage.Sets/src/mage/cards/e/EnigmaSphinx.java index 7b988de1da3..ddeb27ac4e3 100644 --- a/Mage.Sets/src/mage/cards/e/EnigmaSphinx.java +++ b/Mage.Sets/src/mage/cards/e/EnigmaSphinx.java @@ -90,7 +90,7 @@ class EnigmaSphinxTriggeredAbility extends TriggeredAbilityImpl { && permanent.getId().equals(this.getSourceId()) && // 5/1/2009 If you control an Enigma Sphinx that's owned by another player, it's put into that player's // graveyard from the battlefield, so Enigma Sphinx's middle ability won't trigger. - permanent.getOwnerId().equals(permanent.getControllerId())) { + permanent.isOwnedBy(permanent.getControllerId())) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/e/EnterTheInfinite.java b/Mage.Sets/src/mage/cards/e/EnterTheInfinite.java index 536676ee668..5b725d6d0ae 100644 --- a/Mage.Sets/src/mage/cards/e/EnterTheInfinite.java +++ b/Mage.Sets/src/mage/cards/e/EnterTheInfinite.java @@ -123,7 +123,7 @@ class MaximumHandSizeEffect extends MaximumHandSizeControllerEffect { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) { - if (game.getActivePlayerId().equals(source.getControllerId())) { + if (game.isActivePlayer(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/e/EntreatTheDead.java b/Mage.Sets/src/mage/cards/e/EntreatTheDead.java new file mode 100644 index 00000000000..86d76b7b4a5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EntreatTheDead.java @@ -0,0 +1,59 @@ +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; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.target.Target; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author TheElk801 + */ +public final class EntreatTheDead extends CardImpl { + + public EntreatTheDead(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{B}{B}{B}"); + + // 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)); + + // 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) { + super(card); + } + + @Override + public EntreatTheDead copy() { + return new EntreatTheDead(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java b/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java index 9fe3a744dda..01c303b520b 100644 --- a/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java +++ b/Mage.Sets/src/mage/cards/e/EpharaGodOfThePolis.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.DevotionCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -36,12 +36,14 @@ public final class EpharaGodOfThePolis extends CardImpl { // Indestructible this.addAbility(IndestructibleAbility.getInstance()); + // As long as your devotion to white and blue is less than seven, Ephara isn't a creature. Effect effect = new LoseCreatureTypeSourceEffect(new DevotionCount(ColoredManaSymbol.W, ColoredManaSymbol.U), 7); effect.setText("As long as your devotion to white and blue is less than seven, Ephara isn't a creature"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + // At the beginning of each upkeep, if you had another creature enter the battlefield under your control last turn, draw a card. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), TargetController.ANY, false, false), HadAnotherCreatureEnterTheBattlefieldCondition.instance, "At the beginning of each upkeep, if you had another creature enter the battlefield under your control last turn, draw a card."), diff --git a/Mage.Sets/src/mage/cards/e/EpicStruggle.java b/Mage.Sets/src/mage/cards/e/EpicStruggle.java index 31b01940d44..70eb7db01e1 100644 --- a/Mage.Sets/src/mage/cards/e/EpicStruggle.java +++ b/Mage.Sets/src/mage/cards/e/EpicStruggle.java @@ -4,7 +4,7 @@ package mage.cards.e; import java.util.UUID; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class EpicStruggle extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}{G}"); // At the beginning of your upkeep, if you control twenty or more creatures, you win the game. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 19), "At the beginning of your upkeep, if you control twenty or more creatures, you win the game.")); diff --git a/Mage.Sets/src/mage/cards/e/EpicureOfBlood.java b/Mage.Sets/src/mage/cards/e/EpicureOfBlood.java new file mode 100644 index 00000000000..e0e519fa937 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EpicureOfBlood.java @@ -0,0 +1,37 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.GainLifeControllerTriggeredAbility; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class EpicureOfBlood extends CardImpl { + + public EpicureOfBlood(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever you gain life, each opponent loses 1 life. + this.addAbility(new GainLifeControllerTriggeredAbility(new LoseLifeOpponentsEffect(1), false)); + } + + public EpicureOfBlood(final EpicureOfBlood card) { + super(card); + } + + @Override + public EpicureOfBlood copy() { + return new EpicureOfBlood(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ErgRaiders.java b/Mage.Sets/src/mage/cards/e/ErgRaiders.java index 8154fc30247..fbf0ea92e35 100644 --- a/Mage.Sets/src/mage/cards/e/ErgRaiders.java +++ b/Mage.Sets/src/mage/cards/e/ErgRaiders.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class ErgRaiders extends CardImpl { this.toughness = new MageInt(3); // At the beginning of your end step, if Erg Raiders didn't attack this turn, Erg Raiders deals 2 damage to you unless it came under your control this turn. - TriggeredAbility ability = new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility(new DamageControllerEffect(2), TargetController.YOU, false), + TriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility(new DamageControllerEffect(2), TargetController.YOU, false), new ErgRaidersCondition(), "At the beginning of your end step, if {this} didn't attack this turn, {this} deals 2 damage to you unless it came under your control this turn."); ability.addWatcher(new AttackedThisTurnWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/e/EssenceLeak.java b/Mage.Sets/src/mage/cards/e/EssenceLeak.java new file mode 100644 index 00000000000..de8fa2ea548 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EssenceLeak.java @@ -0,0 +1,100 @@ +package mage.cards.e; + +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.OrCondition; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.costs.Cost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +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.TargetPermanent; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class EssenceLeak extends CardImpl { + + public EssenceLeak(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant permanent + TargetPermanent auraTarget = new TargetPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.UnboostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // As long as enchanted permanent is red or green, it has "At the beginning of your upkeep, sacrifice this permanent unless you pay its mana cost." + Ability sacAbility =new BeginningOfUpkeepTriggeredAbility(new EssenceLeakEffect(), TargetController.YOU, false); + ContinuousEffect isRedOrGreenAbility = new GainAbilityAttachedEffect(sacAbility, AttachmentType.AURA); + SimpleStaticAbility ifRedOrGreenAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(isRedOrGreenAbility, + new OrCondition(new EnchantedCreatureColorCondition(ObjectColor.RED), new EnchantedCreatureColorCondition(ObjectColor.GREEN)), + "As long as enchanted permanent is red or green, it has \"At the beginning of your upkeep, sacrifice this permanent unless you pay its mana cost.\"")); + this.addAbility(ifRedOrGreenAbility); + } + + public EssenceLeak(final EssenceLeak card) { + super(card); + } + + @Override + public EssenceLeak copy() { + return new EssenceLeak(this); + } +} + +class EssenceLeakEffect extends OneShotEffect { + + public EssenceLeakEffect() { + super(Outcome.Sacrifice); + staticText = "sacrifice this permanent unless you pay its mana cost"; + } + + public EssenceLeakEffect(final EssenceLeakEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (player != null && permanent != null) { + + String message = CardUtil.replaceSourceName("Pay {this}'s mana cost?", permanent.getLogName()); + Cost cost = permanent.getManaCost().copy(); + if (player.chooseUse(Outcome.Benefit, message, source, game)) { + cost.clearPaid(); + if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { + return true; + } + } + permanent.sacrifice(source.getSourceId(), game); + return true; + } + return false; + } + + @Override + public EssenceLeakEffect copy() { + return new EssenceLeakEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EssenceOfTheWild.java b/Mage.Sets/src/mage/cards/e/EssenceOfTheWild.java index 7dd16294548..2d1a030d4d1 100644 --- a/Mage.Sets/src/mage/cards/e/EssenceOfTheWild.java +++ b/Mage.Sets/src/mage/cards/e/EssenceOfTheWild.java @@ -66,7 +66,7 @@ class EssenceOfTheWildEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent perm = ((EntersTheBattlefieldEvent) event).getTarget(); - return perm != null && perm.isCreature() && perm.getControllerId().equals(source.getControllerId()); + return perm != null && perm.isCreature() && perm.isControlledBy(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/e/EstridTheMasked.java b/Mage.Sets/src/mage/cards/e/EstridTheMasked.java new file mode 100644 index 00000000000..485d0ea89ad --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EstridTheMasked.java @@ -0,0 +1,162 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.CanBeYourCommanderAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect; +import mage.abilities.effects.common.UntapAllControllerEffect; +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.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterEnchantmentCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.MaskToken; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class EstridTheMasked extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(); + private static final FilterPermanent filter2 = new FilterPermanent("another permanent"); + + static { + filter.add(new EnchantedPredicate()); + filter2.add(new AnotherPredicate()); + } + + public EstridTheMasked(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{G}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ESTRID); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); + + // +2: Untap each enchanted permanent you control. + this.addAbility(new LoyaltyAbility(new UntapAllControllerEffect( + filter, "untap each enchanted permanent you control" + ), 2)); + + // -1: Create a white Aura enchantment token named Mask attached to another target permanent. The token has enchant permanent and totem armor. + Ability ability = new LoyaltyAbility( + new EstridTheMaskedTokenEffect(), -1 + ); + ability.addTarget(new TargetPermanent(filter2)); + this.addAbility(ability); + + // -7: Put the top seven cards of your library into your graveyard. Return all non-Aura enchantment cards from your graveyard to the battlefield, then do the same for Aura cards. + this.addAbility(new LoyaltyAbility( + new EstridTheMaskedGraveyardEffect(), -7 + )); + + // Estrid, the Masked can be your commander. + this.addAbility(CanBeYourCommanderAbility.getInstance()); + } + + public EstridTheMasked(final EstridTheMasked card) { + super(card); + } + + @Override + public EstridTheMasked copy() { + return new EstridTheMasked(this); + } +} + +class EstridTheMaskedTokenEffect extends OneShotEffect { + + public EstridTheMaskedTokenEffect() { + super(Outcome.Benefit); + this.staticText = "create a white Aura enchantment token named Mask " + + "attached to another target permanent. " + + "The token has enchant permanent and totem armor"; + } + + public EstridTheMaskedTokenEffect(final EstridTheMaskedTokenEffect effect) { + super(effect); + } + + @Override + public EstridTheMaskedTokenEffect copy() { + return new EstridTheMaskedTokenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + CreateTokenEffect effect = new CreateTokenEffect(new MaskToken()); + effect.apply(game, source); + for (UUID tokenId : effect.getLastAddedTokenIds()) { + Permanent token = game.getPermanent(tokenId); + if (token == null) { + continue; + } + token.getAbilities().get(0).getTargets().get(0).add(source.getFirstTarget(), game); + token.getAbilities().get(0).getEffects().get(0).apply(game, token.getAbilities().get(0)); + // token.attachTo(source.getFirstTarget(), game); + } + return true; + } +} + +class EstridTheMaskedGraveyardEffect extends OneShotEffect { + + private static final FilterEnchantmentCard filter + = new FilterEnchantmentCard(); + private static final FilterEnchantmentCard filter2 + = new FilterEnchantmentCard(); + + static { + filter.add(Predicates.not(new SubtypePredicate(SubType.AURA))); + filter.add(new SubtypePredicate(SubType.AURA)); + } + + public EstridTheMaskedGraveyardEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "put the top seven cards of your library " + + "into your graveyard. Return all non-Aura enchantment cards " + + "from your graveyard to the battlefield, " + + "then do the same for Aura cards"; + } + + public EstridTheMaskedGraveyardEffect(final EstridTheMaskedGraveyardEffect effect) { + super(effect); + } + + @Override + public EstridTheMaskedGraveyardEffect copy() { + return new EstridTheMaskedGraveyardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + new PutTopCardOfLibraryIntoGraveControllerEffect(7).apply(game, source); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + controller.moveCards(controller.getGraveyard().getCards( + filter, source.getSourceId(), source.getControllerId(), game + ), Zone.BATTLEFIELD, source, game); + controller.moveCards(controller.getGraveyard().getCards( + filter2, source.getSourceId(), source.getControllerId(), game + ), Zone.BATTLEFIELD, source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EstridsInvocation.java b/Mage.Sets/src/mage/cards/e/EstridsInvocation.java new file mode 100644 index 00000000000..0f6094c73a0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EstridsInvocation.java @@ -0,0 +1,105 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CopyPermanentEffect; +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.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.functions.ApplyToPermanent; + +/** + * + * @author TheElk801 + */ +public final class EstridsInvocation extends CardImpl { + + public EstridsInvocation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // You may have Estrid's Invocation enter the battlefield as a copy of any enchantment you control, except it gains "At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control." + this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect( + StaticFilters.FILTER_ENCHANTMENT_PERMANENT, + new EstridsInvocationApplier() + ).setText("as a copy of any enchantment you control, except it gains " + + "\"At the beginning of your upkeep, " + + "you may exile this enchantment. " + + "If you do, return it to the battlefield " + + "under its owner's control.\""), true + )); + } + + public EstridsInvocation(final EstridsInvocation card) { + super(card); + } + + @Override + public EstridsInvocation copy() { + return new EstridsInvocation(this); + } +} + +class EstridsInvocationApplier extends ApplyToPermanent { + + @Override + public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) { + // At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control. + permanent.addAbility(new BeginningOfUpkeepTriggeredAbility( + new EstridsInvocationEffect(), TargetController.YOU, true + ), source.getSourceId(), game); + return true; + } + + @Override + public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) { + // At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control. + mageObject.getAbilities().add(new BeginningOfUpkeepTriggeredAbility( + new EstridsInvocationEffect(), TargetController.YOU, true + )); + return true; + } + +} + +class EstridsInvocationEffect extends OneShotEffect { + + public EstridsInvocationEffect() { + super(Outcome.Neutral); + this.staticText = "you may exile this enchantment. " + + "If you do, return it to the battlefield under its owner's control"; + } + + public EstridsInvocationEffect(final EstridsInvocationEffect effect) { + super(effect); + } + + @Override + public EstridsInvocationEffect copy() { + return new EstridsInvocationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if (permanent.moveToExile(source.getSourceId(), "Estrid's Invocation", source.getSourceId(), game)) { + Card card = game.getExile().getCard(source.getSourceId(), game); + if (card != null) { + return card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EternalFlame.java b/Mage.Sets/src/mage/cards/e/EternalFlame.java index 1c1db58e141..5942d62f7a5 100644 --- a/Mage.Sets/src/mage/cards/e/EternalFlame.java +++ b/Mage.Sets/src/mage/cards/e/EternalFlame.java @@ -12,7 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.target.common.TargetOpponent; +import mage.target.common.TargetOpponentOrPlaneswalker; /** * @@ -32,7 +32,7 @@ public final class EternalFlame extends CardImpl { // Eternal Flame deals X damage to target opponent, where X is the number of Mountains you control. It deals half X damage, rounded up, to you.); this.getSpellAbility().addEffect(new DamageTargetEffect(new PermanentsOnBattlefieldCount(filter)).setText("{this} deals X damage to target opponent, where X is the number of Mountains you control")); this.getSpellAbility().addEffect(new DamageControllerEffect(new HalfValue(new PermanentsOnBattlefieldCount(filter), true)).setText("It deals half X damage, rounded up, to you")); - this.getSpellAbility().addTarget(new TargetOpponent()); + this.getSpellAbility().addTarget(new TargetOpponentOrPlaneswalker()); } public EternalFlame(final EternalFlame card) { diff --git a/Mage.Sets/src/mage/cards/e/EternalScourge.java b/Mage.Sets/src/mage/cards/e/EternalScourge.java index 4dc83fce265..b226e01a859 100644 --- a/Mage.Sets/src/mage/cards/e/EternalScourge.java +++ b/Mage.Sets/src/mage/cards/e/EternalScourge.java @@ -71,7 +71,7 @@ class EternalScourgePlayEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(source.getSourceId()); - if (card != null && card.getOwnerId().equals(affectedControllerId) && game.getState().getZone(source.getSourceId()) == Zone.EXILED) { + if (card != null && card.isOwnedBy(affectedControllerId) && game.getState().getZone(source.getSourceId()) == Zone.EXILED) { return true; } } diff --git a/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java b/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java index f4ca2c87794..1daf99900dc 100644 --- a/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java +++ b/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java @@ -103,7 +103,7 @@ class EunuchsIntriguesRestrictionEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - if (permanent.getControllerId().equals(source.getFirstTarget())) { + if (permanent.isControlledBy(source.getFirstTarget())) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/e/EverWatchingThreshold.java b/Mage.Sets/src/mage/cards/e/EverWatchingThreshold.java new file mode 100644 index 00000000000..64cf1a648ab --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EverWatchingThreshold.java @@ -0,0 +1,81 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class EverWatchingThreshold extends CardImpl { + + public EverWatchingThreshold(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // Whenever an opponent attacks you and/or a planeswalker you control with one or more creatures, draw a card. + this.addAbility(new EverWatchingThresholdTriggeredAbility()); + } + + public EverWatchingThreshold(final EverWatchingThreshold card) { + super(card); + } + + @Override + public EverWatchingThreshold copy() { + return new EverWatchingThreshold(this); + } +} + +class EverWatchingThresholdTriggeredAbility extends TriggeredAbilityImpl { + + public EverWatchingThresholdTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false); + } + + public EverWatchingThresholdTriggeredAbility(final EverWatchingThresholdTriggeredAbility ability) { + super(ability); + } + + @Override + public EverWatchingThresholdTriggeredAbility copy() { + return new EverWatchingThresholdTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player player = game.getPlayer(this.getControllerId()); + if (player == null) { + return false; + } + for (UUID attacker : game.getCombat().getAttackers()) { + Permanent creature = game.getPermanent(attacker); + if (creature != null + && player.hasOpponent(creature.getControllerId(), game) + && player.getId().equals(game.getCombat().getDefendingPlayerId(attacker, game))) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent attacks you " + + "and/or a planeswalker you control " + + "with one or more creatures, draw a card."; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EvilTwin.java b/Mage.Sets/src/mage/cards/e/EvilTwin.java index 150e3251b32..51a77803e5e 100644 --- a/Mage.Sets/src/mage/cards/e/EvilTwin.java +++ b/Mage.Sets/src/mage/cards/e/EvilTwin.java @@ -39,9 +39,9 @@ public final class EvilTwin extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - // You may have Evil Twin enter the battlefield as a copy of any creature on the battlefield except it gains "{U}{B}, {T}: Destroy target creature with the same name as this creature." + // You may have Evil Twin enter the battlefield as a copy of any creature on the battlefield, except it has "{U}{B}, {T}: Destroy target creature with the same name as this creature." Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new EvilTwinApplyToPermanent()); - effect.setText("a copy of any creature on the battlefield except it gains \"{U}{B}, {T}: Destroy target creature with the same name as this creature.\""); + effect.setText("as a copy of any creature on the battlefield, except it has \"{U}{B}, {T}: Destroy target creature with the same name as this creature.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); } diff --git a/Mage.Sets/src/mage/cards/e/ExcavationElephant.java b/Mage.Sets/src/mage/cards/e/ExcavationElephant.java index c38416ecf2b..189d10c4064 100644 --- a/Mage.Sets/src/mage/cards/e/ExcavationElephant.java +++ b/Mage.Sets/src/mage/cards/e/ExcavationElephant.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.constants.SubType; @@ -35,7 +35,7 @@ public final class ExcavationElephant extends CardImpl { // When Excavation Elephant enters the battlefield, if it was kicked, return target artifact card from your graveyard to your hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); ability.addTarget(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard"))); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, " + "return target artifact card from your graveyard to your hand." diff --git a/Mage.Sets/src/mage/cards/e/ExclusionMage.java b/Mage.Sets/src/mage/cards/e/ExclusionMage.java new file mode 100644 index 00000000000..e72addba9bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ExclusionMage.java @@ -0,0 +1,43 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class ExclusionMage extends CardImpl { + + public ExclusionMage(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(2); + this.toughness = new MageInt(2); + + // When Exclusion Mage enters the battlefield, return target creature an opponent controls to its owner's hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); + ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.addAbility(ability); + } + + public ExclusionMage(final ExclusionMage card) { + super(card); + } + + @Override + public ExclusionMage copy() { + return new ExclusionMage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ExileIntoDarkness.java b/Mage.Sets/src/mage/cards/e/ExileIntoDarkness.java index a59e0c6180d..67b8a557cc7 100644 --- a/Mage.Sets/src/mage/cards/e/ExileIntoDarkness.java +++ b/Mage.Sets/src/mage/cards/e/ExileIntoDarkness.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.MoreCardsInHandThanOpponentsCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.effects.common.SacrificeEffect; import mage.cards.CardImpl; @@ -40,7 +40,7 @@ public final class ExileIntoDarkness extends CardImpl { // At the beginning of your upkeep, if you have more cards in hand than each opponent, you may return Exile into Darkness from your graveyard to your hand. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), TargetController.YOU, true), diff --git a/Mage.Sets/src/mage/cards/e/ExquisiteFirecraft.java b/Mage.Sets/src/mage/cards/e/ExquisiteFirecraft.java index 0cc9a7c3d52..f7721325543 100644 --- a/Mage.Sets/src/mage/cards/e/ExquisiteFirecraft.java +++ b/Mage.Sets/src/mage/cards/e/ExquisiteFirecraft.java @@ -28,10 +28,10 @@ public final class ExquisiteFirecraft extends CardImpl { this.getSpellAbility().addTarget(new TargetAnyTarget()); this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered by spells or abilities. + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered. ContinuousRuleModifyingEffect cantBeCountered = new CantBeCounteredSourceEffect(); ConditionalContinuousRuleModifyingEffect conditionalCantBeCountered = new ConditionalContinuousRuleModifyingEffect(cantBeCountered, SpellMasteryCondition.instance); - conditionalCantBeCountered.setText("
If there are two or more instant and/or sorcery cards in your graveyard, {this} can't be countered by spells or abilities"); + conditionalCantBeCountered.setText("
If there are two or more instant and/or sorcery cards in your graveyard, this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, conditionalCantBeCountered); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ExtravagantSpirit.java b/Mage.Sets/src/mage/cards/e/ExtravagantSpirit.java new file mode 100644 index 00000000000..ac2d168c111 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ExtravagantSpirit.java @@ -0,0 +1,76 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class ExtravagantSpirit extends CardImpl { + + public ExtravagantSpirit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of your upkeep, sacrifice Extravagant Spirit unless you pay {1} for each card in your hand. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ExtravagantSpiritEffect(), TargetController.YOU, false)); + } + + public ExtravagantSpirit(final ExtravagantSpirit card) { + super(card); + } + + @Override + public ExtravagantSpirit copy() { + return new ExtravagantSpirit(this); + } +} + +class ExtravagantSpiritEffect extends OneShotEffect { + + public ExtravagantSpiritEffect() { + super(Outcome.Sacrifice); + this.staticText = "sacrifice {this} unless you pay {1} for each card in your hand"; + } + + public ExtravagantSpiritEffect(final ExtravagantSpiritEffect effect) { + super(effect); + } + + @Override + public ExtravagantSpiritEffect copy() { + return new ExtravagantSpiritEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + return new SacrificeSourceUnlessPaysEffect( + new GenericManaCost(player.getHand().size()) + ).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java index f3c1c2f580a..1322d056ffa 100644 --- a/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java +++ b/Mage.Sets/src/mage/cards/e/ExtricatorOfSin.java @@ -7,7 +7,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.TransformSourceEffect; @@ -51,7 +51,7 @@ public final class ExtricatorOfSin extends CardImpl { // Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, transform Extricator of Sin. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new TransformSourceEffect(true), TargetController.YOU, false), DeliriumCondition.instance, "Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java index 470f8cc1061..2860e35ddf2 100644 --- a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java +++ b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java @@ -111,7 +111,7 @@ class EyeOfTheStormEffect1 extends OneShotEffect { Card card = spell.getCard(); if (spellController == null || card == null - || !StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL.match(spell, game)) { + || !StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY.match(spell, game)) { return false; } if (!noLongerOnStack) {// the spell is still on the stack, so exile it diff --git a/Mage.Sets/src/mage/cards/e/EyesOfTheWisent.java b/Mage.Sets/src/mage/cards/e/EyesOfTheWisent.java index 991f00d20a3..ac2641cda72 100644 --- a/Mage.Sets/src/mage/cards/e/EyesOfTheWisent.java +++ b/Mage.Sets/src/mage/cards/e/EyesOfTheWisent.java @@ -1,7 +1,6 @@ package mage.cards.e; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; @@ -15,6 +14,8 @@ import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.permanent.token.EyesOfTheWisentElementalToken; +import java.util.UUID; + /** * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/e/EzurisBrigade.java b/Mage.Sets/src/mage/cards/e/EzurisBrigade.java index 1235e8f298a..1602de0fe62 100644 --- a/Mage.Sets/src/mage/cards/e/EzurisBrigade.java +++ b/Mage.Sets/src/mage/cards/e/EzurisBrigade.java @@ -24,7 +24,7 @@ import mage.constants.Zone; * @author Loki */ public final class EzurisBrigade extends CardImpl { - private static final String text = "Metalcraft - As long as you control three or more artifacts, Ezuri's Brigade gets +4/+4 and has trample"; + private static final String text = "Metalcraft — As long as you control three or more artifacts, Ezuri's Brigade gets +4/+4 and has trample"; public EzurisBrigade (UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); diff --git a/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java b/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java index 836e8f32117..bedb618045e 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java +++ b/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -45,7 +45,7 @@ public final class FaerieMiscreant extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Faerie Miscreant enters the battlefield, if you control another creature named Faerie Miscreant, draw a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false), new PermanentsOnTheBattlefieldCondition(filter), "When Faerie Miscreant enters the battlefield, if you control another creature named Faerie Miscreant, draw a card"); diff --git a/Mage.Sets/src/mage/cards/f/FaerieTauntings.java b/Mage.Sets/src/mage/cards/f/FaerieTauntings.java index 79140b0b23e..2d27389b7e0 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieTauntings.java +++ b/Mage.Sets/src/mage/cards/f/FaerieTauntings.java @@ -1,7 +1,6 @@ package mage.cards.f; -import java.util.UUID; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.OnOpponentsTurnCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; @@ -11,6 +10,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * * @author Styxo diff --git a/Mage.Sets/src/mage/cards/f/FailureComply.java b/Mage.Sets/src/mage/cards/f/FailureComply.java index 9dfb6e7238f..1dc66399d62 100644 --- a/Mage.Sets/src/mage/cards/f/FailureComply.java +++ b/Mage.Sets/src/mage/cards/f/FailureComply.java @@ -6,7 +6,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.AftermathAbility; import mage.cards.CardImpl; @@ -38,7 +38,7 @@ public final class FailureComply extends SplitCard { // 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)); - Effect effect = new NameACardEffect(NameACardEffect.TypeOfName.ALL); + Effect effect = new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL); effect.setText("Choose a card name"); getRightHalfCard().getSpellAbility().addEffect(effect); getRightHalfCard().getSpellAbility().addEffect(new ComplyCantCastEffect()); @@ -74,7 +74,7 @@ class ComplyCantCastEffect extends ContinuousRuleModifyingEffectImpl { public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); if (mageObject != null) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); return "You may not cast a card named " + cardName + " (" + mageObject.getIdName() + ")."; } return null; @@ -87,7 +87,7 @@ class ComplyCantCastEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object.getName().equals(cardName)) { diff --git a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java index 6335cba663f..8a4959443ba 100644 --- a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java +++ b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java @@ -8,7 +8,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class FairgroundsTrumpeter extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on Fairgrounds Trumpeter. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.ANY, false), FairgroundsTrumpeterCondition.instance, "At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on {this}."), diff --git a/Mage.Sets/src/mage/cards/f/FaithfulSquire.java b/Mage.Sets/src/mage/cards/f/FaithfulSquire.java index 00ad372609d..95c31d5eebb 100644 --- a/Mage.Sets/src/mage/cards/f/FaithfulSquire.java +++ b/Mage.Sets/src/mage/cards/f/FaithfulSquire.java @@ -37,7 +37,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FlipSourceEffect; import mage.abilities.effects.common.PreventDamageToTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -74,7 +74,7 @@ public final class FaithfulSquire extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.KI.createInstance()), StaticFilters.SPIRIT_OR_ARCANE_CARD, true)); // At the beginning of the end step, if there are two or more ki counters on Faithful Squire, you may flip it - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new KaisoMemoryOfLoyaltyToken()), true), new SourceHasCounterCondition(CounterType.KI, 2, Integer.MAX_VALUE), "At the beginning of the end step, if there are two or more ki counters on {this}, you may flip it.")); diff --git a/Mage.Sets/src/mage/cards/f/FaithsFetters.java b/Mage.Sets/src/mage/cards/f/FaithsFetters.java index d5fd0ecc6e3..42327c282a5 100644 --- a/Mage.Sets/src/mage/cards/f/FaithsFetters.java +++ b/Mage.Sets/src/mage/cards/f/FaithsFetters.java @@ -86,7 +86,7 @@ class FaithsFettersEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo().equals(event.getSourceId())) { + if (enchantment != null && enchantment.isAttachedTo(event.getSourceId())) { Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); if (ability.isPresent() && ability.get().getAbilityType() != AbilityType.MANA) { return true; diff --git a/Mage.Sets/src/mage/cards/f/FaithsReward.java b/Mage.Sets/src/mage/cards/f/FaithsReward.java index 1c34dec0802..cf449635657 100644 --- a/Mage.Sets/src/mage/cards/f/FaithsReward.java +++ b/Mage.Sets/src/mage/cards/f/FaithsReward.java @@ -61,7 +61,7 @@ class FaithsRewardEffect extends OneShotEffect { if (watcher != null) { for (UUID id : watcher.cards) { Card c = game.getCard(id); - if (c != null && c.getOwnerId().equals(source.getControllerId()) && game.getState().getZone(id) == Zone.GRAVEYARD) { + if (c != null && c.isOwnedBy(source.getControllerId()) && game.getState().getZone(id) == Zone.GRAVEYARD) { c.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); } } diff --git a/Mage.Sets/src/mage/cards/f/FalkenrathGorger.java b/Mage.Sets/src/mage/cards/f/FalkenrathGorger.java index 1d4ebb34ab9..5a9aac019f7 100644 --- a/Mage.Sets/src/mage/cards/f/FalkenrathGorger.java +++ b/Mage.Sets/src/mage/cards/f/FalkenrathGorger.java @@ -32,14 +32,14 @@ public final class FalkenrathGorger extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); /** - * 4/8/2016 Falkenrath Gorger’s ability only applies while it’s on the - * battlefield. If you discard it, it won’t give itself madness. + * 4/8/2016 Falkenrath Gorger's ability only applies while it's on the + * battlefield. If you discard it, it won't give itself madness. * 4/8/2016 If Falkenrath Gorger leaves the battlefield before the * madness trigger has resolved for a Vampire card that gained madness * with its ability, the madness ability will still let you cast that * Vampire card for the appropriate cost even though it no longer has * madness. 4/8/2016 If you discard a Vampire creature card that already - * has a madness ability, you’ll choose which madness ability exiles it. + * has a madness ability, you'll choose which madness ability exiles it. * You may choose either the one it normally has or the one it gains * from Falkenrath Gorger. */ @@ -99,7 +99,7 @@ class FalkenrathGorgerEffect extends ContinuousEffectImpl { // Exile for (Card card : game.getExile().getAllCards(game)) { if (filter.match(card, source.getSourceId(), controller.getId(), game)) { - if (card.getOwnerId().equals(controller.getId())) { + if (card.isOwnedBy(controller.getId())) { addMadnessToCard(game, card, usedMadnessAbilities); } } diff --git a/Mage.Sets/src/mage/cards/f/FalseOrders.java b/Mage.Sets/src/mage/cards/f/FalseOrders.java index dd6eb3e2e8d..f4c8066db61 100644 --- a/Mage.Sets/src/mage/cards/f/FalseOrders.java +++ b/Mage.Sets/src/mage/cards/f/FalseOrders.java @@ -48,7 +48,7 @@ public final class FalseOrders extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Cast False Orders only during the declare blockers step. - this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast {this} only during the declare blockers step")); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast this spell only during the declare blockers step")); // Remove target creature defending player controls from combat. Creatures it was blocking that had become blocked by only that creature this combat become unblocked. You may have it block an attacking creature of your choice. this.getSpellAbility().addTarget(new TargetPermanent(filter)); @@ -156,7 +156,7 @@ class FalseOrdersUnblockEffect extends OneShotEffect { if (chosenGroup != null) { // Relevant ruling for Balduvian Warlord: // 7/15/2006 If an attacking creature has an ability that triggers “When this creature becomes blocked,” - // it triggers when a creature blocks it due to the Warlord’s ability only if it was unblocked at that point. + // it triggers when a creature blocks it due to the Warlord's ability only if it was unblocked at that point. boolean notYetBlocked = chosenGroup.getBlockers().isEmpty(); chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game); game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h diff --git a/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java b/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java index 16a9193bab0..416a8c1c61b 100644 --- a/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java +++ b/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; @@ -39,7 +39,7 @@ public final class FanaticOfXenagos extends CardImpl { // When Fanatic of Xenagos enters the battlefield, if its tribute wasn't paid, it gets +1/+1 and gains haste until end of turn. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect(1,1, Duration.EndOfTurn)); ability.addEffect( new GainAbilitySourceEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn))); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, it gets +1/+1 and gains haste until end of turn.")); } diff --git a/Mage.Sets/src/mage/cards/f/Fathier.java b/Mage.Sets/src/mage/cards/f/Fathier.java new file mode 100644 index 00000000000..c2efdc0e860 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/Fathier.java @@ -0,0 +1,40 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.MonstrosityAbility; +import mage.constants.SubType; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author NinthWorld + */ +public final class Fathier extends CardImpl { + + public Fathier(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // {4}{R}{R}: Monstrosity 2. + this.addAbility(new MonstrosityAbility("{4}{R}{R}", 2)); + } + + public Fathier(final Fathier card) { + super(card); + } + + @Override + public Fathier copy() { + return new Fathier(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java b/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java index 2e223ba171a..d4f6bf40264 100644 --- a/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java +++ b/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.keyword.MenaceAbility; @@ -47,7 +47,7 @@ public final class FathomFleetCaptain extends CardImpl { this.addAbility(new MenaceAbility()); // Whenever Fathom Fleet Captain attacks, if you control another nontoken Pirate, you may pay {2}. If you do, creature a 2/2 black Pirate creature token with menace. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new DoIfCostPaid(new CreateTokenEffect(new PirateToken()), new GenericManaCost(2)), false), new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks, if you control another nontoken Pirate, you may pay {2}. If you do, create a 2/2 black Pirate creature token with menace")); diff --git a/Mage.Sets/src/mage/cards/f/FavorableDestiny.java b/Mage.Sets/src/mage/cards/f/FavorableDestiny.java index 3f585e83d94..d5a237d635b 100644 --- a/Mage.Sets/src/mage/cards/f/FavorableDestiny.java +++ b/Mage.Sets/src/mage/cards/f/FavorableDestiny.java @@ -90,7 +90,7 @@ class FavorableDestinyCondition implements Condition { Player controller = game.getPlayer(creature.getControllerId()); if (controller != null) { for (Permanent perm : game.getBattlefield().getActivePermanents(controller.getId(), game)) { - if (perm.getControllerId().equals(controller.getId()) + if (perm.isControlledBy(controller.getId()) && perm.isCreature() && !perm.equals(creature)) { return true; diff --git a/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java b/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java index fce074f39fe..22d1800804d 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java +++ b/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,7 +28,7 @@ public final class FeastOnTheFallen extends CardImpl { // At the beginning of each upkeep, if an opponent lost life last turn, put a +1/+1 counter on target creature you control. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), TargetController.ANY, false), diff --git a/Mage.Sets/src/mage/cards/f/FeiyiSnake.java b/Mage.Sets/src/mage/cards/f/FeiyiSnake.java new file mode 100644 index 00000000000..c330cd74baf --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FeiyiSnake.java @@ -0,0 +1,37 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class FeiyiSnake extends CardImpl { + + public FeiyiSnake(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.SNAKE); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + } + + public FeiyiSnake(final FeiyiSnake card) { + super(card); + } + + @Override + public FeiyiSnake copy() { + return new FeiyiSnake(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FelidarSovereign.java b/Mage.Sets/src/mage/cards/f/FelidarSovereign.java index fd4494c1fe4..6ba372102fa 100644 --- a/Mage.Sets/src/mage/cards/f/FelidarSovereign.java +++ b/Mage.Sets/src/mage/cards/f/FelidarSovereign.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.VigilanceAbility; @@ -36,7 +36,7 @@ public final class FelidarSovereign extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // At the beginning of your upkeep, if you have 40 or more life, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new FortyOrMoreLifeCondition(), "At the beginning of your upkeep, if you have 40 or more life, you win the game.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new FortyOrMoreLifeCondition(), "At the beginning of your upkeep, if you have 40 or more life, you win the game.")); } diff --git a/Mage.Sets/src/mage/cards/f/FellShepherd.java b/Mage.Sets/src/mage/cards/f/FellShepherd.java index e8197945ca2..626237217f5 100644 --- a/Mage.Sets/src/mage/cards/f/FellShepherd.java +++ b/Mage.Sets/src/mage/cards/f/FellShepherd.java @@ -87,7 +87,7 @@ class FellShepherdWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { MageObject card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (card != null && ((Card) card).getOwnerId().equals(this.controllerId) && card.isCreature()) { + if (card != null && ((Card) card).isOwnedBy(this.controllerId) && card.isCreature()) { creatureIds.add(card.getId()); } } diff --git a/Mage.Sets/src/mage/cards/f/FellSpecter.java b/Mage.Sets/src/mage/cards/f/FellSpecter.java new file mode 100644 index 00000000000..8675bcf28ca --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FellSpecter.java @@ -0,0 +1,56 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiscardsACardOpponentTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class FellSpecter extends CardImpl { + + public FellSpecter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.SPECTER); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Fell Specter enters the battlefield, target opponent discards a card. + Ability ability = new EntersBattlefieldTriggeredAbility( + new DiscardTargetEffect(1) + ); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + + // Whenever an opponent discards a card, that player loses 2 life. + this.addAbility(new DiscardsACardOpponentTriggeredAbility( + new LoseLifeTargetEffect(2), false, + SetTargetPointer.PLAYER + )); + } + + public FellSpecter(final FellSpecter card) { + super(card); + } + + @Override + public FellSpecter copy() { + return new FellSpecter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FerociousZheng.java b/Mage.Sets/src/mage/cards/f/FerociousZheng.java new file mode 100644 index 00000000000..1d581317785 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FerociousZheng.java @@ -0,0 +1,33 @@ +package mage.cards.f; + +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 FerociousZheng extends CardImpl { + + public FerociousZheng(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + } + + public FerociousZheng(final FerociousZheng card) { + super(card); + } + + @Override + public FerociousZheng copy() { + return new FerociousZheng(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/Ferocity.java b/Mage.Sets/src/mage/cards/f/Ferocity.java new file mode 100644 index 00000000000..e607d59004c --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/Ferocity.java @@ -0,0 +1,96 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.counter.AddCountersAttachedEffect; +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.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class Ferocity extends CardImpl { + + public Ferocity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + 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); + + // Whenever enchanted creature blocks or becomes blocked, you may put a +1/+1 counter on it. + this.addAbility(new FerocityTriggeredAbility()); + } + + public Ferocity(final Ferocity card) { + super(card); + } + + @Override + public Ferocity copy() { + return new Ferocity(this); + } +} + +class FerocityTriggeredAbility extends TriggeredAbilityImpl { + + public FerocityTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersAttachedEffect(CounterType.P1P1.createInstance(), "it"), true); + } + + public FerocityTriggeredAbility(final FerocityTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.BLOCKER_DECLARED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent aura = game.getPermanent(sourceId); + if (aura == null || aura.getAttachedTo() == null) { + return false; + } + if (event.getSourceId().equals(aura.getAttachedTo())) { + Permanent blocks = game.getPermanent(event.getTargetId()); + return blocks != null; + } + if (event.getTargetId().equals(aura.getAttachedTo())) { + Permanent blockedBy = game.getPermanent(event.getSourceId()); + return blockedBy != null; + } + return false; + } + + @Override + public String getRule() { + return "Whenever enchanted creature blocks or becomes blocked, " + + "you may put a +1/+1 counter on it"; + } + + @Override + public FerocityTriggeredAbility copy() { + return new FerocityTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FerocityOfTheUnderworld.java b/Mage.Sets/src/mage/cards/f/FerocityOfTheUnderworld.java index 41b09cf2448..e846026f4db 100644 --- a/Mage.Sets/src/mage/cards/f/FerocityOfTheUnderworld.java +++ b/Mage.Sets/src/mage/cards/f/FerocityOfTheUnderworld.java @@ -39,7 +39,7 @@ public final class FerocityOfTheUnderworld extends CardImpl { // Copy target instant or sorcery spell. You may choose new targets for the copy. Mode mode = new Mode(); mode.getEffects().add(new CopyTargetSpellEffect()); - mode.getTargets().add(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + mode.getTargets().add(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.getSpellAbility().addMode(mode); // Return target card from your graveyard to your hand. diff --git a/Mage.Sets/src/mage/cards/f/FertileGround.java b/Mage.Sets/src/mage/cards/f/FertileGround.java index d5544513c1d..708bd5d9c05 100644 --- a/Mage.Sets/src/mage/cards/f/FertileGround.java +++ b/Mage.Sets/src/mage/cards/f/FertileGround.java @@ -86,6 +86,6 @@ class FertileGroundTriggeredAbility extends TriggeredManaAbility { @Override public String getRule() { - return "Whenever enchanted land is tapped for mana, its controller adds one mana of any color"; + return "Whenever enchanted land is tapped for mana, its controller adds an additional one mana of any color."; } } diff --git a/Mage.Sets/src/mage/cards/f/FertileImagination.java b/Mage.Sets/src/mage/cards/f/FertileImagination.java new file mode 100644 index 00000000000..f25b42bef30 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FertileImagination.java @@ -0,0 +1,125 @@ +package mage.cards.f; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + +import mage.MageObject; +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.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.SaprolingToken; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author noahg + */ +public final class FertileImagination extends CardImpl { + + public FertileImagination(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}{G}"); + + + // Choose a card type. Target opponent reveals their hand. Create two 1/1 green Saproling creature tokens for each card of the chosen type revealed this way. + this.getSpellAbility().addEffect(new FertileImaginationEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public FertileImagination(final FertileImagination card) { + super(card); + } + + @Override + public FertileImagination copy() { + return new FertileImagination(this); + } +} + +class FertileImaginationEffect extends OneShotEffect { + + private static final Set choice = new LinkedHashSet<>(); + + static { + choice.add(CardType.ARTIFACT.toString()); + choice.add(CardType.CREATURE.toString()); + choice.add(CardType.ENCHANTMENT.toString()); + choice.add(CardType.INSTANT.toString()); + choice.add(CardType.LAND.toString()); + choice.add(CardType.PLANESWALKER.toString()); + choice.add(CardType.SORCERY.toString()); + choice.add(CardType.TRIBAL.toString()); + } + + public FertileImaginationEffect() { + super(Outcome.Benefit); + staticText = "Choose a card type. Target opponent reveals their hand. Create two 1/1 green Saproling creature tokens for each card of the chosen type revealed this way"; + } + + public FertileImaginationEffect(final FertileImaginationEffect effect) { + super(effect); + } + + @Override + public FertileImaginationEffect copy() { + return new FertileImaginationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = game.getObject(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(source.getFirstTarget()); + if (player != null && opponent != null && sourceObject != null) { + Choice choiceImpl = new ChoiceImpl(); + choiceImpl.setChoices(choice); + if (player.choose(Outcome.Neutral, choiceImpl, game)) { + CardType type = null; + String choosenType = choiceImpl.getChoice(); + + if (choosenType.equals(CardType.ARTIFACT.toString())) { + type = CardType.ARTIFACT; + } else if (choosenType.equals(CardType.LAND.toString())) { + type = CardType.LAND; + } else if (choosenType.equals(CardType.CREATURE.toString())) { + type = CardType.CREATURE; + } else if (choosenType.equals(CardType.ENCHANTMENT.toString())) { + type = CardType.ENCHANTMENT; + } else if (choosenType.equals(CardType.INSTANT.toString())) { + type = CardType.INSTANT; + } else if (choosenType.equals(CardType.SORCERY.toString())) { + type = CardType.SORCERY; + } else if (choosenType.equals(CardType.PLANESWALKER.toString())) { + type = CardType.PLANESWALKER; + } else if (choosenType.equals(CardType.TRIBAL.toString())) { + type = CardType.TRIBAL; + } + if (type != null) { + Cards hand = opponent.getHand(); + SaprolingToken saprolingToken = new SaprolingToken(); + opponent.revealCards(sourceObject.getIdName(), hand, game); + Set cards = hand.getCards(game); + int tokensToMake = 0; + for (Card card : cards) { + if (card != null && card.getCardType().contains(type)) { + tokensToMake += 2; + } + } + game.informPlayers(sourceObject.getLogName() + " creates " + (tokensToMake == 0 ? "no" : "" + tokensToMake) + " 1/1 green Saproling creature tokens."); + saprolingToken.putOntoBattlefield(tokensToMake, game, source.getId(), source.getControllerId()); + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/f/FesterhideBoar.java b/Mage.Sets/src/mage/cards/f/FesterhideBoar.java index fb053b0f709..9e80b1494ad 100644 --- a/Mage.Sets/src/mage/cards/f/FesterhideBoar.java +++ b/Mage.Sets/src/mage/cards/f/FesterhideBoar.java @@ -28,7 +28,7 @@ public final class FesterhideBoar extends CardImpl { this.toughness = new MageInt(3); this.addAbility(TrampleAbility.getInstance()); - // Morbid - Festerhide Boar enters the battlefield with two +1/+1 counters on it if a creature died this turn. + // Morbid — Festerhide Boar enters the battlefield with two +1/+1 counters on it if a creature died this turn. this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), MorbidCondition.instance, ""), "with two +1/+1 counters on it if a creature died this turn")); } diff --git a/Mage.Sets/src/mage/cards/f/Festival.java b/Mage.Sets/src/mage/cards/f/Festival.java index 75d82911efe..4a92bc17604 100644 --- a/Mage.Sets/src/mage/cards/f/Festival.java +++ b/Mage.Sets/src/mage/cards/f/Festival.java @@ -23,7 +23,7 @@ public final class Festival extends CardImpl { // Cast Festival only during an opponent's upkeep. this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.UPKEEP, OnOpponentsTurnCondition.instance, - "Cast {this} only during an opponent's upkeep")); + "Cast this spell only during an opponent's upkeep")); // Creatures can't attack this turn. this.getSpellAbility().addEffect(new CantAttackAnyPlayerAllEffect(Duration.EndOfTurn, FILTER_PERMANENT_CREATURES)); diff --git a/Mage.Sets/src/mage/cards/f/FieldOfRuin.java b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java index 0e9318a6ca3..3b559ff471d 100644 --- a/Mage.Sets/src/mage/cards/f/FieldOfRuin.java +++ b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java @@ -91,7 +91,7 @@ class FieldOfRuinEffect extends OneShotEffect { if (player != null) { TargetCardInLibrary target = new TargetCardInLibrary(0, 1, StaticFilters.FILTER_CARD_BASIC_LAND); if (player.searchLibrary(target, game)) { - player.moveCards(new CardsImpl(target.getTargets()), Zone.BATTLEFIELD, source, game); + player.moveCards(new CardsImpl(target.getTargets()).getCards(game), Zone.BATTLEFIELD, source, game); player.shuffleLibrary(source, game); } } diff --git a/Mage.Sets/src/mage/cards/f/FiendBinder.java b/Mage.Sets/src/mage/cards/f/FiendBinder.java index 9a3509467df..64a65b75064 100644 --- a/Mage.Sets/src/mage/cards/f/FiendBinder.java +++ b/Mage.Sets/src/mage/cards/f/FiendBinder.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.UUID; @@ -11,8 +10,7 @@ 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; /** @@ -21,10 +19,14 @@ import mage.target.common.TargetCreaturePermanent; */ public final class FiendBinder extends CardImpl { - private final UUID originalId; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(new DefendingPlayerControlsPredicate()); + } public FiendBinder(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.SOLDIER); this.power = new MageInt(3); @@ -32,26 +34,12 @@ public final class FiendBinder extends CardImpl { // Whenever Fiend Binder attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } - @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); - } - } - public FiendBinder(final FiendBinder card) { super(card); - this.originalId = card.originalId; } @Override diff --git a/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java b/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java index d1687d6fef9..3749823252d 100644 --- a/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java +++ b/Mage.Sets/src/mage/cards/f/FiendslayerPaladin.java @@ -97,7 +97,7 @@ class FiendslayerPaladinEffect extends ContinuousRuleModifyingEffectImpl { StackObject 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.getControllerId().equals(source.getControllerId()) + if (!stackObject.isControlledBy(source.getControllerId()) && stackObject.isInstant() || stackObject.isSorcery()) { return true; diff --git a/Mage.Sets/src/mage/cards/f/FieryFinish.java b/Mage.Sets/src/mage/cards/f/FieryFinish.java new file mode 100644 index 00000000000..3864890b6e9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FieryFinish.java @@ -0,0 +1,32 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class FieryFinish extends CardImpl { + + public FieryFinish(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}"); + + // Fiery Finish deals 7 damage to target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(7)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public FieryFinish(final FieryFinish card) { + super(card); + } + + @Override + public FieryFinish copy() { + return new FieryFinish(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FinestHour.java b/Mage.Sets/src/mage/cards/f/FinestHour.java index 87b8adea5ed..2163788f4bc 100644 --- a/Mage.Sets/src/mage/cards/f/FinestHour.java +++ b/Mage.Sets/src/mage/cards/f/FinestHour.java @@ -74,7 +74,7 @@ class FinestHourAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.isActivePlayer(this.controllerId)) { if (game.getCombat().attacksAlone()) { for (Effect effect: this.getEffects()) { effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); diff --git a/Mage.Sets/src/mage/cards/f/Finn.java b/Mage.Sets/src/mage/cards/f/Finn.java new file mode 100644 index 00000000000..b4429e90ae7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/Finn.java @@ -0,0 +1,59 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Finn extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("{this} or another nontoken creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(new TokenPredicate())); + } + + public Finn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever Finn or another nontoken creature you control enters the battlefield under your control, you gain 1 life for each nontoken creature you control. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, + new GainLifeEffect(new PermanentsOnBattlefieldCount(filter)) + .setText("you gain 1 life for each nontoken creature you control"), + filter, false)); + } + + public Finn(final Finn card) { + super(card); + } + + @Override + public Finn copy() { + return new Finn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FireOmenCrane.java b/Mage.Sets/src/mage/cards/f/FireOmenCrane.java new file mode 100644 index 00000000000..b0f00f940ff --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireOmenCrane.java @@ -0,0 +1,46 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetOpponentsCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class FireOmenCrane extends CardImpl { + + public FireOmenCrane(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever Fire-Omen Crane attacks, it deals 1 damage to target creature an opponent controls. + Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(1, "it"), false); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + public FireOmenCrane(final FireOmenCrane card) { + super(card); + } + + @Override + public FireOmenCrane copy() { + return new FireOmenCrane(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FireServant.java b/Mage.Sets/src/mage/cards/f/FireServant.java index 432634db048..5cd9c2c04a9 100644 --- a/Mage.Sets/src/mage/cards/f/FireServant.java +++ b/Mage.Sets/src/mage/cards/f/FireServant.java @@ -74,7 +74,7 @@ class FireServantEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { StackObject spell = game.getStack().getStackObject(event.getSourceId()); return spell != null && - spell.getControllerId().equals(source.getControllerId()) && + spell.isControlledBy(source.getControllerId()) && spell.getColor(game).isRed() && (spell.isInstant() || spell.isSorcery()); } diff --git a/Mage.Sets/src/mage/cards/f/FiremaneAngel.java b/Mage.Sets/src/mage/cards/f/FiremaneAngel.java index 10b9debc7e2..7bb07a7f2b2 100644 --- a/Mage.Sets/src/mage/cards/f/FiremaneAngel.java +++ b/Mage.Sets/src/mage/cards/f/FiremaneAngel.java @@ -9,7 +9,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -41,7 +41,7 @@ public final class FiremaneAngel extends CardImpl { // Firststrike this.addAbility(FirstStrikeAbility.getInstance()); // At the beginning of your upkeep, if Firemane Angel is in your graveyard or on the battlefield, you may gain 1 life. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.ALL, new GainLifeEffect(1), TargetController.YOU, true), SourceOnBattlefieldOrGraveyardCondition.instance, "At the beginning of your upkeep, if {this} is in your graveyard or on the battlefield, you may gain 1 life"); diff --git a/Mage.Sets/src/mage/cards/f/FirstOrderDreadnought.java b/Mage.Sets/src/mage/cards/f/FirstOrderDreadnought.java new file mode 100644 index 00000000000..631141df286 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FirstOrderDreadnought.java @@ -0,0 +1,49 @@ +package mage.cards.f; + +import java.util.UUID; +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.DestroyTargetEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class FirstOrderDreadnought extends CardImpl { + + public FirstOrderDreadnought(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{B}{B}"); + + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(5); + this.toughness = new MageInt(6); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // {2}{B}, {T}: Destroy target creature. + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl("{2}{B}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public FirstOrderDreadnought(final FirstOrderDreadnought card) { + super(card); + } + + @Override + public FirstOrderDreadnought copy() { + return new FirstOrderDreadnought(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FirstResponse.java b/Mage.Sets/src/mage/cards/f/FirstResponse.java index 05c8646d35f..bce1070dd7a 100644 --- a/Mage.Sets/src/mage/cards/f/FirstResponse.java +++ b/Mage.Sets/src/mage/cards/f/FirstResponse.java @@ -4,7 +4,7 @@ package mage.cards.f; import java.util.UUID; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.LiveLostLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -22,7 +22,7 @@ public final class FirstResponse extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); // At the beginning of each upkeep, if you lost life last turn, create a 1/1 white Soldier creature token. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new SoldierToken()), TargetController.ANY, false), LiveLostLastTurnCondition.instance, "At the beginning of each upkeep, if you lost life last turn, create a 1/1 white Soldier creature token.")); diff --git a/Mage.Sets/src/mage/cards/f/FlameTrooper.java b/Mage.Sets/src/mage/cards/f/FlameTrooper.java new file mode 100644 index 00000000000..1dd4adb8db8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FlameTrooper.java @@ -0,0 +1,50 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.constants.Duration; +import mage.constants.SubType; +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.mageobject.SubtypePredicate; + +/** + * + * @author NinthWorld + */ +public final class FlameTrooper extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Trooper creatures"); + + static { + filter.add(new SubtypePredicate(SubType.TROOPER)); + } + + public FlameTrooper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Trooper creatures you control have menace. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new MenaceAbility(), Duration.WhileOnBattlefield, filter, false))); + } + + public FlameTrooper(final FlameTrooper card) { + super(card); + } + + @Override + public FlameTrooper copy() { + return new FlameTrooper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FlameWave.java b/Mage.Sets/src/mage/cards/f/FlameWave.java index 955bd71eba1..abfd025d4d6 100644 --- a/Mage.Sets/src/mage/cards/f/FlameWave.java +++ b/Mage.Sets/src/mage/cards/f/FlameWave.java @@ -23,7 +23,7 @@ public final class FlameWave extends CardImpl { this.getSpellAbility().addEffect(new DamageTargetEffect(4)); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(4, new FilterCreaturePermanent()) - .setText("and each creature that player or that planeswalker’s controller controls") + .setText("and each creature that player or that planeswalker's controller controls") ); } diff --git a/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java b/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java index 2fac24a57aa..e3a72038456 100644 --- a/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java +++ b/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -41,7 +41,7 @@ public final class FlameWreathedPhoenix extends CardImpl { TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield)); Effect effect = new GainAbilitySourceEffect(new DiesTriggeredAbility(new ReturnToHandSourceEffect())); ability.addEffect(effect); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, it gains haste and \"When this creature dies, return it to its owner's hand.\"")); } diff --git a/Mage.Sets/src/mage/cards/f/FlamebladeAngel.java b/Mage.Sets/src/mage/cards/f/FlamebladeAngel.java index 4558dfcf55e..ef69d3eaddf 100644 --- a/Mage.Sets/src/mage/cards/f/FlamebladeAngel.java +++ b/Mage.Sets/src/mage/cards/f/FlamebladeAngel.java @@ -78,7 +78,7 @@ class FlamebladeAngelTriggeredAbility extends TriggeredAbilityImpl { result = true; } else { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent != null && getControllerId().equals(permanent.getControllerId())) { + if (permanent != null && isControlledBy(permanent.getControllerId())) { result = true; } } diff --git a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java index 177799f745e..05ebb2bfe67 100644 --- a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java +++ b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -41,7 +41,7 @@ public final class FlameheartWerewolf extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Flameheart Werewolf. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public FlameheartWerewolf(final FlameheartWerewolf card) { diff --git a/Mage.Sets/src/mage/cards/f/FlamesOfRemembrance.java b/Mage.Sets/src/mage/cards/f/FlamesOfRemembrance.java index 01d71f30101..8c80d6be9c2 100644 --- a/Mage.Sets/src/mage/cards/f/FlamesOfRemembrance.java +++ b/Mage.Sets/src/mage/cards/f/FlamesOfRemembrance.java @@ -111,6 +111,6 @@ class FlamesOfRemembranceMayPlayExiledEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) && this.getTargetPointer().getTargets(game, source).contains(objectId); + return source.isControlledBy(affectedControllerId) && this.getTargetPointer().getTargets(game, source).contains(objectId); } } diff --git a/Mage.Sets/src/mage/cards/f/FlamewakePhoenix.java b/Mage.Sets/src/mage/cards/f/FlamewakePhoenix.java index 3f54c7c3645..5f806e65068 100644 --- a/Mage.Sets/src/mage/cards/f/FlamewakePhoenix.java +++ b/Mage.Sets/src/mage/cards/f/FlamewakePhoenix.java @@ -7,7 +7,7 @@ import mage.abilities.common.AttacksEachCombatStaticAbility; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.FerociousCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -39,7 +39,7 @@ public final class FlamewakePhoenix extends CardImpl { this.addAbility(new AttacksEachCombatStaticAbility()); // Ferocious — At the beginning of combat on your turn, if you control a creature with power 4 or greater, you may pay {R}. If you do, return Flamewake Phoenix from your graveyard to the battlefield. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfCombatTriggeredAbility( Zone.GRAVEYARD, new DoIfCostPaid(new ReturnToBattlefieldUnderOwnerControlSourceEffect(), new ManaCostsImpl("{R}")), diff --git a/Mage.Sets/src/mage/cards/f/FlashFoliage.java b/Mage.Sets/src/mage/cards/f/FlashFoliage.java new file mode 100644 index 00000000000..2460dffc863 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FlashFoliage.java @@ -0,0 +1,101 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.condition.common.AfterBlockersAreDeclaredCondition; +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.TurnPhase; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.SaprolingToken; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.common.FilterCreatureAttackingYou; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author noahg + */ +public final class FlashFoliage extends CardImpl { + + public FlashFoliage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); + + + // Cast Flash Foliage only during combat after blockers are declared. + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(TurnPhase.COMBAT, AfterBlockersAreDeclaredCondition.instance)); + + // Create a 1/1 green Saproling creature token that’s blocking target creature attacking you. + this.getSpellAbility().addEffect(new FlashFoliageEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreatureAttackingYou())); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public FlashFoliage(final FlashFoliage card) { + super(card); + } + + @Override + public FlashFoliage copy() { + return new FlashFoliage(this); + } +} + +class FlashFoliageEffect extends OneShotEffect { + + public FlashFoliageEffect() { + super(Outcome.Benefit); + this.staticText = "create a 1/1 green Saproling creature token that’s blocking target creature attacking you"; + } + + public FlashFoliageEffect(final FlashFoliageEffect effect) { + super(effect); + } + + @Override + public FlashFoliageEffect copy() { + return new FlashFoliageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + + if (controller != null) { + Token token = new SaprolingToken(); + token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); + Permanent attackingCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (attackingCreature != null && game.getState().getCombat() != null) { + // Possible ruling (see Aetherplasm) + // The token you created is blocking the attacking creature, + // even if the block couldn't legally be declared (for example, if that creature + // enters the battlefield tapped, or it can't block, or the attacking creature + // has protection from it) + CombatGroup combatGroup = game.getState().getCombat().findGroup(attackingCreature.getId()); + if (combatGroup != null) { + for (UUID tokenId : token.getLastAddedTokenIds()) { + Permanent saprolingToken = game.getPermanent(tokenId); + if (saprolingToken != null) { + combatGroup.addBlocker(tokenId, source.getControllerId(), game); + game.getCombat().addBlockingGroup(tokenId, attackingCreature.getId(), controller.getId(), game); + } + } + combatGroup.pickBlockerOrder(attackingCreature.getControllerId(), game); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java b/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java index 768c7fb74c9..b51a555a73a 100644 --- a/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java +++ b/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java @@ -72,7 +72,7 @@ class FlayerTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (((EntersTheBattlefieldEvent) event).getFromZone() == Zone.GRAVEYARD - && permanent.getOwnerId().equals(controllerId) + && permanent.isOwnedBy(controllerId) && permanent.isCreature()) { Effect effect = this.getEffects().get(0); effect.setValue("damageSource", event.getTargetId()); diff --git a/Mage.Sets/src/mage/cards/f/Flickerform.java b/Mage.Sets/src/mage/cards/f/Flickerform.java index 042640a62dc..550ae27ce61 100644 --- a/Mage.Sets/src/mage/cards/f/Flickerform.java +++ b/Mage.Sets/src/mage/cards/f/Flickerform.java @@ -182,7 +182,7 @@ class FlickerformReturnEffect extends OneShotEffect { if (!toBattlefieldAttached.isEmpty()) { controller.moveCards(toBattlefieldAttached, Zone.BATTLEFIELD, source, game); for (Card card : toBattlefieldAttached) { - if (game.getState().getZone(card.getId()).equals(Zone.BATTLEFIELD)) { + if (game.getState().getZone(card.getId()) == Zone.BATTLEFIELD) { newPermanent.addAttachment(card.getId(), game); } } diff --git a/Mage.Sets/src/mage/cards/f/Fluctuator.java b/Mage.Sets/src/mage/cards/f/Fluctuator.java index db73ce83db4..7554bb482b8 100644 --- a/Mage.Sets/src/mage/cards/f/Fluctuator.java +++ b/Mage.Sets/src/mage/cards/f/Fluctuator.java @@ -43,7 +43,7 @@ public final class Fluctuator extends CardImpl { class FluctuatorEffect extends CostModificationEffectImpl { - private static final String effectText = "Cycling abilities you activate cost you up to {2} less to activate"; + private static final String effectText = "Cycling abilities you activate cost up to {2} less to activate"; public FluctuatorEffect() { super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); @@ -56,7 +56,7 @@ class FluctuatorEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify.getControllerId().equals(source.getControllerId()) + return abilityToModify.isControlledBy(source.getControllerId()) && (abilityToModify instanceof CyclingAbility); } diff --git a/Mage.Sets/src/mage/cards/f/Flusterstorm.java b/Mage.Sets/src/mage/cards/f/Flusterstorm.java index 46355337b22..08c8085c0cd 100644 --- a/Mage.Sets/src/mage/cards/f/Flusterstorm.java +++ b/Mage.Sets/src/mage/cards/f/Flusterstorm.java @@ -22,7 +22,7 @@ public final class Flusterstorm extends CardImpl { // Counter target instant or sorcery spell unless its controller pays {1}. this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManaCostsImpl("{1}"))); - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); // Storm this.addAbility(new StormAbility()); } diff --git a/Mage.Sets/src/mage/cards/f/Fluxcharger.java b/Mage.Sets/src/mage/cards/f/Fluxcharger.java index 21d236251da..fecfe06e928 100644 --- a/Mage.Sets/src/mage/cards/f/Fluxcharger.java +++ b/Mage.Sets/src/mage/cards/f/Fluxcharger.java @@ -29,7 +29,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_INSTANT_OR_SORCERY_SPELL, true)); + this.addAbility(new SpellCastControllerTriggeredAbility(new SwitchPowerToughnessSourceEffect(Duration.EndOfTurn), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, true)); } diff --git a/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java b/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java index 08619da0bd7..b66dd9c48a5 100644 --- a/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java +++ b/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java @@ -91,7 +91,7 @@ class FoeRazerRegentTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); - if (permanent != null && permanent.getControllerId().equals(getControllerId())) { + if (permanent != null && permanent.isControlledBy(getControllerId())) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(permanent, game)); } diff --git a/Mage.Sets/src/mage/cards/f/FogPatch.java b/Mage.Sets/src/mage/cards/f/FogPatch.java index 778f368e369..7c62a881193 100644 --- a/Mage.Sets/src/mage/cards/f/FogPatch.java +++ b/Mage.Sets/src/mage/cards/f/FogPatch.java @@ -25,7 +25,7 @@ public final class FogPatch extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Cast Fog Patch only during the declare blockers step. - this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast {this} only during the declare blockers step")); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast this spell only during the declare blockers step")); // Attacking creatures become blocked. this.getSpellAbility().addEffect(new FogPatchEffect()); diff --git a/Mage.Sets/src/mage/cards/f/ForbiddenCrypt.java b/Mage.Sets/src/mage/cards/f/ForbiddenCrypt.java index 97f42256d0c..06678f2232e 100644 --- a/Mage.Sets/src/mage/cards/f/ForbiddenCrypt.java +++ b/Mage.Sets/src/mage/cards/f/ForbiddenCrypt.java @@ -149,7 +149,7 @@ class ForbiddenCryptPutIntoYourGraveyardReplacementEffect extends ReplacementEff public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(source.getControllerId())) { + if (card != null && card.isOwnedBy(source.getControllerId())) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent == null || !(permanent instanceof PermanentToken)) { return true; diff --git a/Mage.Sets/src/mage/cards/f/ForbiddenOrchard.java b/Mage.Sets/src/mage/cards/f/ForbiddenOrchard.java index ff8aeaed186..ebf3b785375 100644 --- a/Mage.Sets/src/mage/cards/f/ForbiddenOrchard.java +++ b/Mage.Sets/src/mage/cards/f/ForbiddenOrchard.java @@ -1,5 +1,5 @@ /* - * + * * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -25,7 +25,7 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. - * + * */ package mage.cards.f; @@ -48,17 +48,17 @@ import mage.target.common.TargetOpponent; */ public final class ForbiddenOrchard extends CardImpl { - public ForbiddenOrchard (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},null); - + public ForbiddenOrchard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, null); + // {T}: Add one mana of any color. this.addAbility(new AnyColorManaAbility()); - + // Whenever you tap Forbidden Orchard for mana, create a 1/1 colorless Spirit creature token under target opponent's control. this.addAbility(new ForbiddenOrchardTriggeredAbility()); } - public ForbiddenOrchard (final ForbiddenOrchard card) { + public ForbiddenOrchard(final ForbiddenOrchard card) { super(card); } @@ -83,7 +83,7 @@ class ForbiddenOrchardTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.TAPPED_FOR_MANA; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { return event.getSourceId().equals(getSourceId()); @@ -91,7 +91,7 @@ class ForbiddenOrchardTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return new StringBuilder("Whenever you tap {this} for mana, ").append(super.getRule()).toString() ; + return "Whenever you tap {this} for mana, " + super.getRule(); } @Override diff --git a/Mage.Sets/src/mage/cards/f/ForceProjection.java b/Mage.Sets/src/mage/cards/f/ForceProjection.java new file mode 100644 index 00000000000..a29ec11982c --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForceProjection.java @@ -0,0 +1,95 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.keyword.ScryEffect; +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.filter.FilterSpell; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author NinthWorld + */ +public final class ForceProjection extends CardImpl { + + public ForceProjection(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}"); + + + // Create a token that is a copy of target creature you control except that it is an Illusion in addition to its other types and gains "When this creature becomes the target of a spell, sacrifice it." + this.getSpellAbility().addEffect(new ForceProjectionEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + + // Scry 2. + this.getSpellAbility().addEffect(new ScryEffect(2)); + } + + public ForceProjection(final ForceProjection card) { + super(card); + } + + @Override + public ForceProjection copy() { + return new ForceProjection(this); + } +} + +class ForceProjectionEffect extends OneShotEffect { + + public ForceProjectionEffect() { + super(Outcome.Copy); + this.staticText = "Create a token that is a copy of target creature you control except that it is an Illusion " + + "in addition to its other types and gains \"When this creature becomes the target of a spell, sacrifice it.\""; + } + + public ForceProjectionEffect(final ForceProjectionEffect effect) { + super(effect); + } + + @Override + public ForceProjectionEffect copy() { + return new ForceProjectionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + // Create a token that is a copy of target creature + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true); + effect.setTargetPointer(new FixedTarget(permanent, game)); + + // except that it is an Illusion in addition to its other types + effect.setAdditionalSubType(SubType.SPIRIT); + effect.apply(game, source); + + // and gains "When this creature becomes the target of a spell, sacrifice it." + Effect sacrificeEffect = new SacrificeSourceEffect(); + sacrificeEffect.setTargetPointer(new FixedTarget(effect.getAddedPermanent().get(0), game)); + TriggeredAbility ability = new BecomesTargetTriggeredAbility(sacrificeEffect, new FilterSpell()); + game.addTriggeredAbility(ability); + + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForceProtection.java b/Mage.Sets/src/mage/cards/f/ForceProtection.java new file mode 100644 index 00000000000..62209502361 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForceProtection.java @@ -0,0 +1,36 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.GainProtectionFromColorTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class ForceProtection extends CardImpl { + + public ForceProtection(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + + // Target creature you control gains protection from color of your choice until end of turn. Scry 1. + this.getSpellAbility().addEffect(new GainProtectionFromColorTargetEffect(Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new ScryEffect(1)); + } + + public ForceProtection(final ForceProtection card) { + super(card); + } + + @Override + public ForceProtection copy() { + return new ForceProtection(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForceStasis.java b/Mage.Sets/src/mage/cards/f/ForceStasis.java new file mode 100644 index 00000000000..ed4e6e25aee --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForceStasis.java @@ -0,0 +1,59 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.Mode; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.TargetSpell; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class ForceStasis extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("instant or sorcery spell you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + filter.add(new CardTypePredicate(CardType.INSTANT)); + filter.add(new CardTypePredicate(CardType.SORCERY)); + } + + public ForceStasis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + + // Choose one - + // Tap target creature. It doesn't untap during its controller's next untap step. + getSpellAbility().addEffect(new TapTargetEffect()); + getSpellAbility().addEffect(new DontUntapInControllersNextUntapStepTargetEffect() + .setText("It doesn't untap during its controller's next untap step")); + getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Return target instant or sorcery spell you don't control to its owner's hand. + Mode mode = new Mode(); + mode.getEffects().add(new ReturnToHandTargetEffect()); + mode.getTargets().add(new TargetSpell(filter)); + this.getSpellAbility().addMode(mode); + } + + public ForceStasis(final ForceStasis card) { + super(card); + } + + @Override + public ForceStasis copy() { + return new ForceStasis(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForceTelepathy.java b/Mage.Sets/src/mage/cards/f/ForceTelepathy.java new file mode 100644 index 00000000000..44c666abf2f --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForceTelepathy.java @@ -0,0 +1,38 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.effects.common.RevealHandTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.TargetPlayer; + +/** + * + * @author NinthWorld + */ +public final class ForceTelepathy extends CardImpl { + + public ForceTelepathy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U/B}"); + + + // Target player reveals his or her hand. + this.getSpellAbility().addEffect(new RevealHandTargetEffect().setText("Target player reveals his or her hand")); + this.getSpellAbility().addTarget(new TargetPlayer()); + + // Scry 2 + this.getSpellAbility().addEffect(new ScryEffect(2)); + } + + public ForceTelepathy(final ForceTelepathy card) { + super(card); + } + + @Override + public ForceTelepathy copy() { + return new ForceTelepathy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForebearsBlade.java b/Mage.Sets/src/mage/cards/f/ForebearsBlade.java index ba5b8eb1035..19651821925 100644 --- a/Mage.Sets/src/mage/cards/f/ForebearsBlade.java +++ b/Mage.Sets/src/mage/cards/f/ForebearsBlade.java @@ -50,7 +50,7 @@ public final class ForebearsBlade extends CardImpl { ability.addEffect(effect); this.addAbility(ability); - // Whenever equipped creature dies, attach Forebear’s Blade to target creature you control. + // Whenever equipped creature dies, attach Forebear's Blade to target creature you control. ability = new DiesAttachedTriggeredAbility( new AttachEffect(Outcome.Neutral, "attach {this} to target creature you control"), "equipped creature", false); ability.addTarget(new TargetControlledCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/f/Foreshadow.java b/Mage.Sets/src/mage/cards/f/Foreshadow.java index bdb5322e25e..6299ff05b75 100644 --- a/Mage.Sets/src/mage/cards/f/Foreshadow.java +++ b/Mage.Sets/src/mage/cards/f/Foreshadow.java @@ -7,7 +7,7 @@ import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbili import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,7 +28,7 @@ public final class Foreshadow extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); // 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 NameACardEffect(NameACardEffect.TypeOfName.ALL)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); this.getSpellAbility().addEffect(new ForeshadowEffect()); this.getSpellAbility().addTarget(new TargetOpponent()); @@ -67,7 +67,7 @@ class ForeshadowEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(source.getFirstTarget()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) { Card card = targetPlayer.getLibrary().getFromTop(game); if (card != null) { diff --git a/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java b/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java new file mode 100644 index 00000000000..e3e24edaa2c --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForgeOfHeroes.java @@ -0,0 +1,98 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.CommanderPredicate; +import mage.filter.predicate.permanent.EnteredThisTurnPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class ForgeOfHeroes extends CardImpl { + + private static final FilterPermanent filter + = new FilterPermanent("commander that entered the battlefield this turn"); + + static { + filter.add(new CommanderPredicate()); + filter.add(new EnteredThisTurnPredicate()); + } + + public ForgeOfHeroes(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {T}: Choose target commander that entered the battlefield this turn. Put a +1/+1 counter on it if it's a creature and a loyalty counter on it if it's a planeswalker. + Ability ability = new SimpleActivatedAbility( + new ForgeOfHeroesEffect(), + new TapSourceCost() + ); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public ForgeOfHeroes(final ForgeOfHeroes card) { + super(card); + } + + @Override + public ForgeOfHeroes copy() { + return new ForgeOfHeroes(this); + } +} + +class ForgeOfHeroesEffect extends OneShotEffect { + + public ForgeOfHeroesEffect() { + super(Outcome.Benefit); + this.staticText = "choose target commander that entered the battlefield this turn. " + + "Put a +1/+1 counter on it if it's a creature " + + "and a loyalty counter on it if it's a planeswalker"; + } + + public ForgeOfHeroesEffect(final ForgeOfHeroesEffect effect) { + super(effect); + } + + @Override + public ForgeOfHeroesEffect copy() { + return new ForgeOfHeroesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + if (permanent.isCreature()) { + new AddCountersTargetEffect( + CounterType.P1P1.createInstance() + ).apply(game, source); + } else if (permanent.isPlaneswalker()) { + new AddCountersTargetEffect( + CounterType.LOYALTY.createInstance() + ).apply(game, source); + } else { + return false; + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/f/Fork.java b/Mage.Sets/src/mage/cards/f/Fork.java index 17ae9c9952e..3c1e610ac81 100644 --- a/Mage.Sets/src/mage/cards/f/Fork.java +++ b/Mage.Sets/src/mage/cards/f/Fork.java @@ -29,7 +29,7 @@ public final class Fork extends CardImpl { // Copy target instant or sorcery spell, except that the copy is red. You may choose new targets for the copy. this.getSpellAbility().addEffect(new ForkEffect()); - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); } diff --git a/Mage.Sets/src/mage/cards/f/FoundryHornet.java b/Mage.Sets/src/mage/cards/f/FoundryHornet.java index ec1acfbe3ed..dc9eb22f34f 100644 --- a/Mage.Sets/src/mage/cards/f/FoundryHornet.java +++ b/Mage.Sets/src/mage/cards/f/FoundryHornet.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -49,7 +49,7 @@ public final class FoundryHornet extends CardImpl { // When Foundry Hornet enters the battlefield, if you control a creature with a +1/+1 counter on it, creatures your opponents control get -1/-1 until end of turn. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn, filterOpponent, false), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); } public FoundryHornet(final FoundryHornet card) { diff --git a/Mage.Sets/src/mage/cards/f/FountainOfRenewal.java b/Mage.Sets/src/mage/cards/f/FountainOfRenewal.java new file mode 100644 index 00000000000..f8e3d26c066 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FountainOfRenewal.java @@ -0,0 +1,43 @@ +package mage.cards.f; + +import java.util.UUID; +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.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class FountainOfRenewal extends CardImpl { + + public FountainOfRenewal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + + // At the beginning of your upkeep, you gain 1 life. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1), TargetController.YOU, false)); + + // {3}, Sacrifice Fountain of Renewal: Draw a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(3)); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public FountainOfRenewal(final FountainOfRenewal card) { + super(card); + } + + @Override + public FountainOfRenewal copy() { + return new FountainOfRenewal(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FracturedLoyalty.java b/Mage.Sets/src/mage/cards/f/FracturedLoyalty.java index 27e81fe492a..260c148e634 100644 --- a/Mage.Sets/src/mage/cards/f/FracturedLoyalty.java +++ b/Mage.Sets/src/mage/cards/f/FracturedLoyalty.java @@ -71,7 +71,7 @@ public final class FracturedLoyalty extends CardImpl { if (enchantedCreature != null) { Player controller = game.getPlayer(enchantedCreature.getControllerId()); if (enchantment.getAttachedTo() != null) { - if (controller != null && !enchantedCreature.getControllerId().equals(this.getTargetPointer().getFirst(game, source))) { + if (controller != null && !enchantedCreature.isControlledBy(this.getTargetPointer().getFirst(game, source))) { ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, this.getTargetPointer().getFirst(game, source)); effect.setTargetPointer(new FixedTarget(enchantment.getAttachedTo())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/f/FrayingOmnipotence.java b/Mage.Sets/src/mage/cards/f/FrayingOmnipotence.java new file mode 100644 index 00000000000..fb3bbc6bb45 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FrayingOmnipotence.java @@ -0,0 +1,107 @@ +package mage.cards.f; + +import java.util.UUID; +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.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class FrayingOmnipotence extends CardImpl { + + public FrayingOmnipotence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}"); + + // Each player loses half their life, then discards half the cards in their hand, then sacrifices half the creatures they control. Round up each time. + this.getSpellAbility().addEffect(new FrayingOmnipotenceEffect()); + } + + public FrayingOmnipotence(final FrayingOmnipotence card) { + super(card); + } + + @Override + public FrayingOmnipotence copy() { + return new FrayingOmnipotence(this); + } +} + +class FrayingOmnipotenceEffect extends OneShotEffect { + + FrayingOmnipotenceEffect() { + super(Outcome.Detriment); + this.staticText = "Each player loses half their life, " + + "then discards half the cards in their hand, " + + "then sacrifices half the creatures they control. " + + "Round up each time."; + } + + FrayingOmnipotenceEffect(final FrayingOmnipotenceEffect effect) { + super(effect); + } + + @Override + public FrayingOmnipotenceEffect copy() { + return new FrayingOmnipotenceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + // Each player loses half of their life, + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + int lifeToLose = (int) Math.ceil(player.getLife() / 2.0); + player.loseLife(lifeToLose, game, false); + } + // then discards half of the cards in their hand, + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + int cardsToDiscard = (int) Math.ceil(player.getHand().size() / 2.0); + if (cardsToDiscard > 0) { + player.discard(cardsToDiscard, false, source, game); + } + } + // then sacrifices half of the creatures they controls, + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + int creaturesToSacrifice = (int) Math.ceil(game.getBattlefield().count(filter, source.getSourceId(), player.getId(), game) / 2.0); + if (creaturesToSacrifice == 0) { + continue; + } + Target target = new TargetControlledCreaturePermanent(creaturesToSacrifice, creaturesToSacrifice, filter, true); + target.chooseTarget(Outcome.Sacrifice, playerId, source, game); + for (UUID permanentId : target.getTargets()) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/f/FreneticEfreet.java b/Mage.Sets/src/mage/cards/f/FreneticEfreet.java index 836e1fd82e7..b2f407420be 100644 --- a/Mage.Sets/src/mage/cards/f/FreneticEfreet.java +++ b/Mage.Sets/src/mage/cards/f/FreneticEfreet.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.UUID; @@ -25,16 +24,20 @@ import mage.players.Player; public final class FreneticEfreet extends CardImpl { public FreneticEfreet(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); this.subtype.add(SubType.EFREET); this.power = new MageInt(2); this.toughness = new MageInt(1); // Flying this.addAbility(FlyingAbility.getInstance()); - + // {0}: Flip a coin. If you win the flip, Frenetic Efreet phases out. If you lose the flip, sacrifice Frenetic Efreet. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new FreneticEfreetEffect(), new GenericManaCost(0))); + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new FreneticEfreetEffect(), + new GenericManaCost(0) + )); } public FreneticEfreet(final FreneticEfreet card) { @@ -50,8 +53,9 @@ public final class FreneticEfreet extends CardImpl { class FreneticEfreetEffect extends OneShotEffect { public FreneticEfreetEffect() { - super(Outcome.Damage); - staticText = "Flip a coin. If you win the flip, {this} phases out. If you lose the flip, sacrifice {this}"; + super(Outcome.Neutral); + staticText = "Flip a coin. If you win the flip, " + + "{this} phases out. If you lose the flip, sacrifice {this}"; } public FreneticEfreetEffect(FreneticEfreetEffect effect) { @@ -62,15 +66,19 @@ class FreneticEfreetEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && permanent != null) { - if (controller.flipCoin(game)) { - return permanent.phaseOut(game); - } else { - permanent.sacrifice(source.getSourceId(), game); - return true; - } + if (controller == null) { + return false; + } + boolean flip = controller.flipCoin(game); + if (permanent == null) { + return false; + } + if (flip) { + return permanent.phaseOut(game); + } else { + permanent.sacrifice(source.getSourceId(), game); + return true; } - return false; } @Override diff --git a/Mage.Sets/src/mage/cards/f/FreneticSliver.java b/Mage.Sets/src/mage/cards/f/FreneticSliver.java index ad29911cddd..6655f21dbd4 100644 --- a/Mage.Sets/src/mage/cards/f/FreneticSliver.java +++ b/Mage.Sets/src/mage/cards/f/FreneticSliver.java @@ -1,13 +1,11 @@ - package mage.cards.f; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.common.SourceOnBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileReturnBattlefieldOwnerNextEndStepSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; @@ -26,19 +24,26 @@ import mage.players.Player; public final class FreneticSliver extends CardImpl { private static final FilterPermanent filter = new FilterPermanent(SubType.SLIVER, "All Slivers"); + private static final String rule = "All Slivers have \"{0}: If this permanent is on the battlefield, " + + "flip a coin. If you win the flip, exile this permanent and return it to the battlefield " + + "under its owner's control at the beginning of the next end step. If you lose the flip, sacrifice it.\""; public FreneticSliver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); this.subtype.add(SubType.SLIVER); this.power = new MageInt(2); this.toughness = new MageInt(2); // All Slivers have "{0}: If this permanent is on the battlefield, flip a coin. If you win the flip, exile this permanent and return it to the battlefield under its owner's control at the beginning of the next end step. If you lose the flip, sacrifice it." - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new FreneticSliverEffect(), new ManaCostsImpl("{0}"), SourceOnBattlefieldCondition.instance, "{0}: If this permanent is on the battlefield, flip a coin. If you win the flip, exile this permanent and return it to the battlefield under its owner's control at the beginning of the next end step. If you lose the flip, sacrifice it."); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter, "All Slivers have \"{0}: If this permanent is on the battlefield, flip a coin. If you win the flip, exile this permanent and return it to the battlefield under its owner's control at the beginning of the next end step. If you lose the flip, sacrifice it.\""))); + new GainAbilityAllEffect( + new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new FreneticSliverEffect(), + new ManaCostsImpl("{0}") + ), Duration.WhileOnBattlefield, filter, rule + ) + )); } public FreneticSliver(final FreneticSliver card) { @@ -55,7 +60,9 @@ class FreneticSliverEffect extends OneShotEffect { public FreneticSliverEffect() { super(Outcome.Neutral); - staticText = "Flip a coin. If you win the flip, exile this permanent and return it to the battlefield under its owner's control at the beginning of the next end step. If you lose the flip, sacrifice it"; + staticText = "if this permanent is on the battlefield, flip a coin. If you win the flip, " + + "exile this permanent and return it to the battlefield under its owner's control " + + "at the beginning of the next end step. If you lose the flip, sacrifice it"; } public FreneticSliverEffect(final FreneticSliverEffect effect) { @@ -65,18 +72,15 @@ class FreneticSliverEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - if (player.flipCoin(game)) { - return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true).apply(game, source); - } else { - Permanent perm = game.getPermanent(source.getSourceId()); - if (perm != null) { - perm.sacrifice(source.getSourceId(), game); - } - return true; - } + Permanent perm = game.getPermanent(source.getSourceId()); + if (player == null || perm == null) { + return false; + } + if (player.flipCoin(game)) { + return new ExileReturnBattlefieldOwnerNextEndStepSourceEffect(true).apply(game, source); + } else { + return perm.sacrifice(source.getSourceId(), game); } - return false; } @Override diff --git a/Mage.Sets/src/mage/cards/f/FrontierSiege.java b/Mage.Sets/src/mage/cards/f/FrontierSiege.java index b3a478cbca4..6674c0568f0 100644 --- a/Mage.Sets/src/mage/cards/f/FrontierSiege.java +++ b/Mage.Sets/src/mage/cards/f/FrontierSiege.java @@ -1,7 +1,6 @@ package mage.cards.f; -import java.util.UUID; import mage.Mana; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; @@ -10,8 +9,8 @@ import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.condition.common.ModeChoiceSourceCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.effects.common.ChooseModeEffect; +import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -24,6 +23,8 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/f/Fumble.java b/Mage.Sets/src/mage/cards/f/Fumble.java index e75a587e8af..cddbed62612 100644 --- a/Mage.Sets/src/mage/cards/f/Fumble.java +++ b/Mage.Sets/src/mage/cards/f/Fumble.java @@ -1,4 +1,3 @@ - package mage.cards.f; import java.util.ArrayList; @@ -34,6 +33,7 @@ public final class Fumble extends CardImpl { // Return target creature to its owner's hand. Gain control of all Auras and Equipment that were attached to it, then attach them to another creature. this.getSpellAbility().addEffect(new FumbleEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } public Fumble(final Fumble card) { @@ -66,7 +66,7 @@ class FumbleEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget()); Player player = game.getPlayer(source.getControllerId()); if (player == null || permanent == null) { return false; @@ -75,24 +75,30 @@ class FumbleEffect extends OneShotEffect { for (UUID permId : permanent.getAttachments()) { Permanent attachment = game.getPermanent(permId); if (attachment != null) { - attachments.add(permanent); + if (attachment.hasSubtype(SubType.AURA, game) || attachment.hasSubtype(SubType.EQUIPMENT, game)) { + attachments.add(attachment); + } } } + new ReturnToHandTargetEffect().apply(game, source); - Target target = new TargetCreaturePermanent(1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, true); - Permanent newCreature = null; - if (player.choose(Outcome.BoostCreature, target, source.getSourceId(), game)) { - newCreature = game.getPermanent(target.getFirstTarget()); - } - for (Permanent attachment : attachments) { - if (!attachment.hasSubtype(SubType.AURA, game) && !attachment.hasSubtype(SubType.EQUIPMENT, game)) { - continue; + + if (!attachments.isEmpty()) { + Target target = new TargetCreaturePermanent(1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, true); + Permanent newCreature = null; + if (player.choose(Outcome.BoostCreature, target, source.getSourceId(), game)) { + newCreature = game.getPermanent(target.getFirstTarget()); } - ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, player.getId()); - effect.setTargetPointer(new FixedTarget(attachment, game)); - game.addEffect(effect, source); - if (newCreature != null) { - attachment.attachTo(newCreature.getId(), game); + for (Permanent attachment : attachments) { + if (!attachment.hasSubtype(SubType.AURA, game) && !attachment.hasSubtype(SubType.EQUIPMENT, game)) { + continue; + } + ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, player.getId()); + effect.setTargetPointer(new FixedTarget(attachment, game)); + game.addEffect(effect, source); + if (newCreature != null) { + attachment.attachTo(newCreature.getId(), game); + } } } return true; diff --git a/Mage.Sets/src/mage/cards/f/FurnaceDragon.java b/Mage.Sets/src/mage/cards/f/FurnaceDragon.java index 06b3ffee262..22303f5a720 100644 --- a/Mage.Sets/src/mage/cards/f/FurnaceDragon.java +++ b/Mage.Sets/src/mage/cards/f/FurnaceDragon.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAllEffect; import mage.abilities.keyword.AffinityForArtifactsAbility; import mage.abilities.keyword.FlyingAbility; @@ -42,7 +42,7 @@ public final class FurnaceDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Furnace Dragon enters the battlefield, if you cast it from your hand, exile all artifacts. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ExileAllEffect(filter), false), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, exile all artifacts."), diff --git a/Mage.Sets/src/mage/cards/f/FuryStorm.java b/Mage.Sets/src/mage/cards/f/FuryStorm.java new file mode 100644 index 00000000000..ce1ad8bd1ef --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FuryStorm.java @@ -0,0 +1,37 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.effects.common.CopyTargetSpellEffect; +import mage.abilities.keyword.CommanderStormAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.TargetSpell; + +/** + * + * @author TheElk801 + */ +public final class FuryStorm extends CardImpl { + + public FuryStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{R}"); + + // When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies. + this.addAbility(new CommanderStormAbility()); + + // Copy target instant or sorcery spell. You may choose new targets for the copy. + this.getSpellAbility().addEffect(new CopyTargetSpellEffect()); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); + } + + public FuryStorm(final FuryStorm card) { + super(card); + } + + @Override + public FuryStorm copy() { + return new FuryStorm(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GabrielAngelfire.java b/Mage.Sets/src/mage/cards/g/GabrielAngelfire.java index 83a1c2357b4..a820735811a 100644 --- a/Mage.Sets/src/mage/cards/g/GabrielAngelfire.java +++ b/Mage.Sets/src/mage/cards/g/GabrielAngelfire.java @@ -77,7 +77,7 @@ class GabrielAngelfireGainAbilityEffect extends GainAbilitySourceEffect { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) { - if (!sameStep && game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { return true; } } else { diff --git a/Mage.Sets/src/mage/cards/g/GallantCavalry.java b/Mage.Sets/src/mage/cards/g/GallantCavalry.java new file mode 100644 index 00000000000..8301a61e56e --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GallantCavalry.java @@ -0,0 +1,43 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.SubType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.KnightToken; + +/** + * + * @author TheElk801 + */ +public final class GallantCavalry extends CardImpl { + + public GallantCavalry(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // When Gallant Cavalry enters the battlefield, create a 2/2 white Knight creature token with vigilance. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KnightToken()))); + } + + public GallantCavalry(final GallantCavalry card) { + super(card); + } + + @Override + public GallantCavalry copy() { + return new GallantCavalry(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GalvanicBlast.java b/Mage.Sets/src/mage/cards/g/GalvanicBlast.java index 6f18df57d98..6c696f13df9 100644 --- a/Mage.Sets/src/mage/cards/g/GalvanicBlast.java +++ b/Mage.Sets/src/mage/cards/g/GalvanicBlast.java @@ -16,14 +16,14 @@ import mage.target.common.TargetAnyTarget; */ public final class GalvanicBlast extends CardImpl { - private static final String effectText = "{this} deals 2 damage to anytarget.
Metalcraft - {this} deals 4 damage to that permanent or player instead if you control three or more artifacts"; + private static final String effectText = "{this} deals 2 damage to anytarget.
Metalcraft — {this} deals 4 damage to that permanent or player instead if you control three or more artifacts"; public GalvanicBlast(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); this.color.setRed(true); // Galvanic Blast deals 2 damage to any target. - // Metalcraft - Galvanic Blast deals 4 damage to that creature or player instead if you control three or more artifacts. + // Metalcraft — Galvanic Blast deals 4 damage to that creature or player instead if you control three or more artifacts. this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DamageTargetEffect(4), new DamageTargetEffect(2), MetalcraftCondition.instance, effectText)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java b/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java index fac88ce9315..74585b1ffe8 100644 --- a/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java +++ b/Mage.Sets/src/mage/cards/g/GarnaTheBloodflame.java @@ -85,7 +85,7 @@ class GarnaTheBloodflameEffect extends OneShotEffect { Set toHand = new HashSet<>(); for (UUID cardId : watcher.getCardsPutToGraveyardThisTurn()) { Card card = game.getCard(cardId); - if (card != null && card.getOwnerId().equals(source.getControllerId()) && game.getState().getZone(cardId) == Zone.GRAVEYARD) { + if (card != null && card.isOwnedBy(source.getControllerId()) && game.getState().getZone(cardId) == Zone.GRAVEYARD) { toHand.add(card); } } @@ -119,7 +119,7 @@ class GarnaTheBloodflameWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone().equals(Zone.GRAVEYARD)) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); if (card != null && card.isCreature()) { cards.add(event.getTargetId()); diff --git a/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java b/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java index 2bcaece617e..37c6769aa90 100644 --- a/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java +++ b/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -44,7 +44,7 @@ public final class GatekeeperOfMalakir extends CardImpl { // When Gatekeeper of Malakir enters the battlefield, if it was kicked, target player sacrifices a creature. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SacrificeEffect(filter, 1, "target player")); - Ability conditionalAbility = new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, target player sacrifices a creature."); + Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, target player sacrifices a creature."); conditionalAbility.addTarget(new TargetPlayer()); this.addAbility(conditionalAbility); } diff --git a/Mage.Sets/src/mage/cards/g/GatstafArsonists.java b/Mage.Sets/src/mage/cards/g/GatstafArsonists.java index 3e851a3faa8..0f028bc29cb 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafArsonists.java +++ b/Mage.Sets/src/mage/cards/g/GatstafArsonists.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class GatstafArsonists extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Gatstaf Arsonists. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public GatstafArsonists(final GatstafArsonists card) { diff --git a/Mage.Sets/src/mage/cards/g/GatstafHowler.java b/Mage.Sets/src/mage/cards/g/GatstafHowler.java index 57137ce67a6..cbe3566139b 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafHowler.java +++ b/Mage.Sets/src/mage/cards/g/GatstafHowler.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.IntimidateAbility; import mage.abilities.keyword.TransformAbility; @@ -37,7 +37,7 @@ public final class GatstafHowler extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Gatstaf Howler. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public GatstafHowler(final GatstafHowler card) { diff --git a/Mage.Sets/src/mage/cards/g/GatstafRavagers.java b/Mage.Sets/src/mage/cards/g/GatstafRavagers.java index 9d881aab163..6c7473553d7 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafRavagers.java +++ b/Mage.Sets/src/mage/cards/g/GatstafRavagers.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.TransformAbility; @@ -37,7 +37,7 @@ public final class GatstafRavagers extends CardImpl { this.addAbility(new MenaceAbility()); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Gatstaf Ravagers. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public GatstafRavagers(final GatstafRavagers card) { diff --git a/Mage.Sets/src/mage/cards/g/GatstafShepherd.java b/Mage.Sets/src/mage/cards/g/GatstafShepherd.java index b37569a194d..53cc66b9922 100644 --- a/Mage.Sets/src/mage/cards/g/GatstafShepherd.java +++ b/Mage.Sets/src/mage/cards/g/GatstafShepherd.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class GatstafShepherd extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Gatstaf Shepherd. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public GatstafShepherd(final GatstafShepherd card) { diff --git a/Mage.Sets/src/mage/cards/g/GauntletOfPower.java b/Mage.Sets/src/mage/cards/g/GauntletOfPower.java index 62d0bb6eae7..9d14044b086 100644 --- a/Mage.Sets/src/mage/cards/g/GauntletOfPower.java +++ b/Mage.Sets/src/mage/cards/g/GauntletOfPower.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.UUID; @@ -164,7 +163,8 @@ class TapForManaAllTriggeredAbility extends TriggeredManaAbility { @Override public String getRule() { - return "Whenever " + filter.getMessage() + " for mana, " + super.getRule(); + return "Whenever a basic land is tapped for mana of the chosen color, " + + "its controller adds an additional one mana of that color."; } } @@ -172,7 +172,7 @@ class GauntletOfPowerEffectEffect2 extends ManaEffect { public GauntletOfPowerEffectEffect2() { super(); - staticText = "its controller adds one mana of that color"; + staticText = "its controller adds one additional mana of that color"; } public GauntletOfPowerEffectEffect2(final GauntletOfPowerEffectEffect2 effect) { diff --git a/Mage.Sets/src/mage/cards/g/GearsmithGuardian.java b/Mage.Sets/src/mage/cards/g/GearsmithGuardian.java new file mode 100644 index 00000000000..cd8930af5b2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GearsmithGuardian.java @@ -0,0 +1,58 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class GearsmithGuardian extends CardImpl { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("a blue creature"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + } + + public GearsmithGuardian(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + + this.subtype.add(SubType.CONSTRUCT); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Gearsmith Guardian gets +2/+0 as long as you control a blue creature. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} gets +2/+0 as long as you control a blue creature" + ) + )); + } + + public GearsmithGuardian(final GearsmithGuardian card) { + super(card); + } + + @Override + public GearsmithGuardian copy() { + return new GearsmithGuardian(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GeierReachBandit.java b/Mage.Sets/src/mage/cards/g/GeierReachBandit.java index 4c3cc0ab09c..d1d7d42b1a9 100644 --- a/Mage.Sets/src/mage/cards/g/GeierReachBandit.java +++ b/Mage.Sets/src/mage/cards/g/GeierReachBandit.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TransformAbility; @@ -40,7 +40,7 @@ public final class GeierReachBandit extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Geier Reach Bandit. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public GeierReachBandit(final GeierReachBandit card) { diff --git a/Mage.Sets/src/mage/cards/g/GemstoneCaverns.java b/Mage.Sets/src/mage/cards/g/GemstoneCaverns.java index 18a15d5ae64..ee2b7c14662 100644 --- a/Mage.Sets/src/mage/cards/g/GemstoneCaverns.java +++ b/Mage.Sets/src/mage/cards/g/GemstoneCaverns.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.UUID; @@ -121,6 +120,7 @@ class GemstoneCavernsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + boolean result = false; Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { Card card = game.getCard(source.getSourceId()); @@ -133,13 +133,12 @@ class GemstoneCavernsEffect extends OneShotEffect { if (permanent != null) { Cost cost = new ExileFromHandCost(new TargetCardInHand()); if (cost.canPay(source, source.getSourceId(), source.getControllerId(), game)) { - cost.pay(source, game, source.getSourceId(), source.getControllerId(), true, null); + result = cost.pay(source, game, source.getSourceId(), source.getControllerId(), true, null); } } } } - return true; } - return false; + return result; } } diff --git a/Mage.Sets/src/mage/cards/g/GeneralHux.java b/Mage.Sets/src/mage/cards/g/GeneralHux.java new file mode 100644 index 00000000000..653a5381f2a --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GeneralHux.java @@ -0,0 +1,62 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; + +/** + * + * @author NinthWorld + */ +public final class GeneralHux extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("{this} or another nontoken creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(new TokenPredicate())); + } + + public GeneralHux(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever General Hux or another nontoken creature enters the battlefield under your control, until end of turn, target creature gains "{B}: This creature gets +1/+1 until end of turn." + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new BoostSourceEffect(1, 1, Duration.EndOfTurn) + .setText("This creature gets +1/+1 until end of turn"), + new ManaCostsImpl("{B}")); + Effect effect = new GainAbilitySourceEffect(ability, Duration.EndOfTurn); + effect.setText("until end of turn, target creature gains"); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, effect, filter, false)); + } + + public GeneralHux(final GeneralHux card) { + super(card); + } + + @Override + public GeneralHux copy() { + return new GeneralHux(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GenerousPatron.java b/Mage.Sets/src/mage/cards/g/GenerousPatron.java index 16be2b30f61..ccbfaa40354 100644 --- a/Mage.Sets/src/mage/cards/g/GenerousPatron.java +++ b/Mage.Sets/src/mage/cards/g/GenerousPatron.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.UUID; @@ -63,12 +62,16 @@ class GenerousPatronTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { + if (!isControlledBy(game.getControllerId(event.getSourceId()))) { + return false; + } Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - return event.getPlayerId().equals(this.getControllerId()) - && permanent != null + if (permanent == null) { + permanent = game.getPermanentEntering(event.getTargetId()); + } + return permanent != null && permanent.isCreature() - && !permanent.getControllerId().equals(getControllerId()) - && event.getAmount() > 0; + && !permanent.isControlledBy(getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/g/GenesisChamber.java b/Mage.Sets/src/mage/cards/g/GenesisChamber.java index 5dfc6c23585..709aa2b5237 100644 --- a/Mage.Sets/src/mage/cards/g/GenesisChamber.java +++ b/Mage.Sets/src/mage/cards/g/GenesisChamber.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class GenesisChamber extends CardImpl { // Whenever a nontoken creature enters the battlefield, if Genesis Chamber is untapped, that creature's controller creates a 1/1 colorless Myr artifact creature token. TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new GenesisChamberEffect(), filter, false, SetTargetPointer.PERMANENT, ""); - this.addAbility(new ConditionalTriggeredAbility(ability, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, SourceUntappedCondition.instance, "Whenever a nontoken creature enters the battlefield, " + "if {this} is untapped, " diff --git a/Mage.Sets/src/mage/cards/g/GenesisStorm.java b/Mage.Sets/src/mage/cards/g/GenesisStorm.java new file mode 100644 index 00000000000..48528b01284 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GenesisStorm.java @@ -0,0 +1,91 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.CommanderStormAbility; +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; + +/** + * + * @author TheElk801 + */ +public final class GenesisStorm extends CardImpl { + + public GenesisStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}"); + + // When you cast this spell, copy it for each time you've cast your commander from the command zone this game. + this.addAbility(new CommanderStormAbility()); + + // Reveal cards from the top of your library until you reveal a nonland permanent card. You may put that card onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new GenesisStormEffect()); + } + + public GenesisStorm(final GenesisStorm card) { + super(card); + } + + @Override + public GenesisStorm copy() { + return new GenesisStorm(this); + } +} + +class GenesisStormEffect extends OneShotEffect { + + public GenesisStormEffect() { + super(Outcome.PlayForFree); + this.staticText = "reveal cards from the top of your library " + + "until you reveal a nonland permanent card. " + + "You may put that card onto the battlefield. " + + "Then put all cards revealed this way " + + "that weren't put onto the battlefield " + + "on the bottom of your library in a random order"; + } + + public GenesisStormEffect(GenesisStormEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards toReveal = new CardsImpl(); + Card nonLandCard = null; + for (Card card : controller.getLibrary().getCards(game)) { + toReveal.add(card); + if (card.isPermanent() && !card.isLand()) { + nonLandCard = card; + break; + } + } + controller.revealCards(source, toReveal, game); + if (nonLandCard != null && controller.chooseUse( + outcome, "Put " + nonLandCard.getLogName() + + " onto the battlefield?", source, game + )) { + controller.moveCards(nonLandCard, Zone.BATTLEFIELD, source, game); + toReveal.remove(nonLandCard); + } + controller.putCardsOnBottomOfLibrary(toReveal, game, source, false); + return true; + } + + @Override + public GenesisStormEffect copy() { + return new GenesisStormEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GeodeGolem.java b/Mage.Sets/src/mage/cards/g/GeodeGolem.java new file mode 100644 index 00000000000..f4842176da5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GeodeGolem.java @@ -0,0 +1,107 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.TrampleAbility; +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.players.Player; + +/** + * + * @author spjspj + */ +public final class GeodeGolem extends CardImpl { + + public GeodeGolem(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(5); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Whenever Geode Golem deals combat damage to a player, you may cast your commander from the command zone without paying its mana cost. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new GeodeGolemEffect(), true)); + } + + public GeodeGolem(final GeodeGolem card) { + super(card); + } + + @Override + public GeodeGolem copy() { + return new GeodeGolem(this); + } +} + +class GeodeGolemEffect extends OneShotEffect { + + public GeodeGolemEffect() { + super(Outcome.PlayForFree); + staticText = "you may cast your commander from the command zone without paying its mana cost"; + } + + public GeodeGolemEffect(final GeodeGolemEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + 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(); + newAbility.getCosts().clear(); + + Integer castCount = (Integer) game.getState().getValue(commander.getId() + "_castCount"); + Cost cost = null; + if (castCount > 0) { + cost = new GenericManaCost(castCount * 2); + } + + if ((castCount == 0 || castCount > 0 && cost.pay(source, game, source.getSourceId(), controller.getId(), false, null)) + && controller.cast(newAbility, game, true, new MageObjectReference(source.getSourceObject(game), game))) { + // save amount of times commander was cast + if (castCount == null) { + castCount = 1; + } else { + castCount++; + } + game.getState().setValue(commander.getId() + "_castCount", castCount); + return true; + } + } + } + } + + return true; + } + return false; + } + + @Override + public GeodeGolemEffect copy() { + return new GeodeGolemEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GerrerasRevolutionary.java b/Mage.Sets/src/mage/cards/g/GerrerasRevolutionary.java new file mode 100644 index 00000000000..88de831f128 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GerrerasRevolutionary.java @@ -0,0 +1,37 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksEachCombatStaticAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author NinthWorld + */ +public final class GerrerasRevolutionary extends CardImpl { + + public GerrerasRevolutionary(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); + + this.subtype.add(SubType.BARABEL); + this.subtype.add(SubType.REBEL); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Gerrera's Revolutionary attacks each turn if able. + this.addAbility(new AttacksEachCombatStaticAbility()); + } + + public GerrerasRevolutionary(final GerrerasRevolutionary card) { + super(card); + } + + @Override + public GerrerasRevolutionary copy() { + return new GerrerasRevolutionary(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/Gerrymandering.java b/Mage.Sets/src/mage/cards/g/Gerrymandering.java new file mode 100644 index 00000000000..20877e5077a --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/Gerrymandering.java @@ -0,0 +1,98 @@ + +package mage.cards.g; + +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; +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.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author L_J + */ +public final class Gerrymandering extends CardImpl { + + public Gerrymandering(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}"); + + // Exile all lands. Give each player a number of those cards chosen at random equal to the number of those cards the player controlled. Each player returns those cards to the battlefield under their control. + this.getSpellAbility().addEffect(new GerrymanderingEffect()); + } + + public Gerrymandering(final Gerrymandering card) { + super(card); + } + + @Override + public Gerrymandering copy() { + return new Gerrymandering(this); + } +} + +class GerrymanderingEffect extends OneShotEffect { + + GerrymanderingEffect() { + super(Outcome.Benefit); + this.staticText = "Exile all lands. Give each player a number of those cards chosen at random equal to the number of those cards the player controlled. Each player returns those cards to the battlefield under their control"; + } + + GerrymanderingEffect(final GerrymanderingEffect effect) { + super(effect); + } + + @Override + public GerrymanderingEffect copy() { + return new GerrymanderingEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Map playerLandCount = new HashMap<>(); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + // Exile all lands. + Cards exiledCards = new CardsImpl(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS, source.getControllerId(), source.getSourceId(), game)) { + exiledCards.add(permanent); + playerLandCount.putIfAbsent(permanent.getControllerId(), 0); + playerLandCount.put(permanent.getControllerId(), playerLandCount.get(permanent.getControllerId()) + 1); + controller.moveCardsToExile(permanent, source, game, true, CardUtil.getCardExileZoneId(game, source.getSourceId()), "Gerrymandering"); + } + + // Give each player a number of those cards chosen at random equal to the number of those cards the player controlled. + // Each player returns those cards to the battlefield under their control. + for (UUID playerId : playerLandCount.keySet()) { + if (exiledCards.isEmpty()) { + break; + } + Player player = game.getPlayer(playerId); + if (player != null) { + for (int i = 1; i <= playerLandCount.get(playerId); i++) { + Card card = exiledCards.getRandom(game); + exiledCards.remove(card); + player.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, false, null); + if (exiledCards.isEmpty()) { + break; + } + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GhalmasWarden.java b/Mage.Sets/src/mage/cards/g/GhalmasWarden.java index d6db8e9c294..22f8bb494b8 100644 --- a/Mage.Sets/src/mage/cards/g/GhalmasWarden.java +++ b/Mage.Sets/src/mage/cards/g/GhalmasWarden.java @@ -22,7 +22,7 @@ import mage.constants.Zone; */ public final class GhalmasWarden extends CardImpl { - private static final String text = "Metalcraft - Ghalma's Warden gets +2/+2 as long as you control three or more artifacts"; + private static final String text = "Metalcraft — Ghalma's Warden gets +2/+2 as long as you control three or more artifacts"; public GhalmasWarden (UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); diff --git a/Mage.Sets/src/mage/cards/g/GhastbarkTwins.java b/Mage.Sets/src/mage/cards/g/GhastbarkTwins.java new file mode 100644 index 00000000000..d1c51e7be96 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GhastbarkTwins.java @@ -0,0 +1,42 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureEffect; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class GhastbarkTwins extends CardImpl { + + public GhastbarkTwins(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); + + this.subtype.add(SubType.TREEFOLK); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Ghastbark Twins can block an additional creature each combat. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAdditionalCreatureEffect())); + } + + public GhastbarkTwins(final GhastbarkTwins card) { + super(card); + } + + @Override + public GhastbarkTwins copy() { + return new GhastbarkTwins(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java b/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java index b7deec05374..c3cb70df3a2 100644 --- a/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java +++ b/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.effects.common.continuous.PlayAdditionalLandsAllEffect; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class GhirapurOrrery extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayAdditionalLandsAllEffect())); // At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(3), TargetController.ANY, false, true), new GhirapurOrreryCondition(), "At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.")); diff --git a/Mage.Sets/src/mage/cards/g/GhituChronicler.java b/Mage.Sets/src/mage/cards/g/GhituChronicler.java index 0b76adf9448..a879a8ac588 100644 --- a/Mage.Sets/src/mage/cards/g/GhituChronicler.java +++ b/Mage.Sets/src/mage/cards/g/GhituChronicler.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.constants.SubType; @@ -36,7 +36,7 @@ public final class GhituChronicler extends CardImpl { // When Ghitu Chronicler enters the battlefield, if it was kicked, return target instant or sorcery card from your graveyard to your hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); ability.addTarget(new TargetCardInYourGraveyard(new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard"))); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, " + "return target instant or sorcery card from your graveyard to your hand." diff --git a/Mage.Sets/src/mage/cards/g/GhituJourneymage.java b/Mage.Sets/src/mage/cards/g/GhituJourneymage.java index 0c106572618..2c7c677c62f 100644 --- a/Mage.Sets/src/mage/cards/g/GhituJourneymage.java +++ b/Mage.Sets/src/mage/cards/g/GhituJourneymage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -40,7 +40,7 @@ public final class GhituJourneymage extends CardImpl { // When Ghitu Journeymage enters the battlefield, if you control another Wizard, Ghitu Journeymage deals 2 damage to each opponent. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(2, TargetController.OPPONENT)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new PermanentsOnTheBattlefieldCondition(filter), "When {this} enters the battlefield, if you control another Wizard, {this} deals 2 damage to each opponent." diff --git a/Mage.Sets/src/mage/cards/g/GiantAlbatross.java b/Mage.Sets/src/mage/cards/g/GiantAlbatross.java new file mode 100644 index 00000000000..d2c05f3e8cd --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GiantAlbatross.java @@ -0,0 +1,101 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.List; +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class GiantAlbatross extends CardImpl { + + public GiantAlbatross(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.BIRD); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Giant Albatross dies, you may pay {1}{U}. If you do, for each creature that dealt damage to Giant Albatross this turn, destroy that creature unless its controller pays 2 life. A creature destroyed this way can't be regenerated. + Ability ability = new DiesTriggeredAbility(new DoIfCostPaid(new GiantAlbatrossEffect(), new ManaCostsImpl("{1}{U}"))); + this.addAbility(ability); + } + + public GiantAlbatross(final GiantAlbatross card) { + super(card); + } + + @Override + public GiantAlbatross copy() { + return new GiantAlbatross(this); + } +} + +class GiantAlbatrossEffect extends OneShotEffect { + + public GiantAlbatrossEffect() { + super(Outcome.Detriment); + this.staticText = "for each creature that dealt damage to {this} this turn, destroy that creature unless its controller pays 2 life. A creature destroyed this way can’t be regenerated"; + } + + public GiantAlbatrossEffect(final GiantAlbatrossEffect effect) { + super(effect); + } + + @Override + public GiantAlbatrossEffect copy() { + return new GiantAlbatrossEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourcePermanent != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + List creatures = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game); + + Cost cost = new PayLifeCost(2); + for (Permanent creature : creatures) { + if (sourcePermanent.getDealtDamageByThisTurn().contains(new MageObjectReference(creature.getId(), game))) { + final StringBuilder sb = new StringBuilder("Pay 2 life? (Otherwise ").append(creature.getName()).append(" will be destroyed)"); + if (cost.canPay(source, creature.getControllerId(), creature.getControllerId(), game) && player.chooseUse(Outcome.Benefit, sb.toString(), source, game)) { + cost.pay(source, game, creature.getControllerId(), creature.getControllerId(), true, null); + } + if (!cost.isPaid()) { + creature.destroy(source.getSourceId(), game, true); + } + } + } + } + } + } + + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GiantOyster.java b/Mage.Sets/src/mage/cards/g/GiantOyster.java new file mode 100644 index 00000000000..05617d00dca --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GiantOyster.java @@ -0,0 +1,164 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.common.delayed.AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DontUntapAsLongAsSourceTappedEffect; +import mage.abilities.effects.common.RemoveDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.common.counter.RemoveAllCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +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.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class GiantOyster extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(new TappedPredicate()); + } + + public GiantOyster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + + this.subtype.add(SubType.OYSTER); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // You may choose not to untap Giant Oyster during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + + // {tap}: For as long as Giant Oyster remains tapped, target tapped creature doesn't untap during its controller's untap step, and at the beginning of each of your draw steps, put a -1/-1 counter on that creature. When Giant Oyster leaves the battlefield or becomes untapped, remove all -1/-1 counters from the creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GiantOysterDontUntapAsLongAsSourceTappedEffect(), new TapSourceCost()); + ability.addEffect(new GiantOysterCreateDelayedTriggerEffects()); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public GiantOyster(final GiantOyster card) { + super(card); + } + + @Override + public GiantOyster copy() { + return new GiantOyster(this); + } +} + +class GiantOysterDontUntapAsLongAsSourceTappedEffect extends DontUntapAsLongAsSourceTappedEffect { + + public GiantOysterDontUntapAsLongAsSourceTappedEffect() { + super(); + staticText = "For as long as {source} remains tapped, target tapped creature doesn't untap during its controller's untap step"; + } + + public GiantOysterDontUntapAsLongAsSourceTappedEffect(final GiantOysterDontUntapAsLongAsSourceTappedEffect effect) { + super(effect); + } + + @Override + public GiantOysterDontUntapAsLongAsSourceTappedEffect copy() { + return new GiantOysterDontUntapAsLongAsSourceTappedEffect(this); + } +} + +class GiantOysterCreateDelayedTriggerEffects extends OneShotEffect { + + public GiantOysterCreateDelayedTriggerEffects() { + super(Outcome.Detriment); + this.staticText = "at the beginning of each of your draw steps, put a -1/-1 counter on that creature. When {this} leaves the battlefield or becomes untapped, remove all -1/-1 counters from the creature."; + } + + public GiantOysterCreateDelayedTriggerEffects(final GiantOysterCreateDelayedTriggerEffects effect) { + super(effect); + } + + @Override + public GiantOysterCreateDelayedTriggerEffects copy() { + return new GiantOysterCreateDelayedTriggerEffects(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent oyster = game.getPermanent(source.getSourceId()); + Permanent tappedCreature = game.getPermanent(source.getFirstTarget()); + if (oyster != null && tappedCreature != null) { + Effect addCountersEffect = new AddCountersTargetEffect(CounterType.M1M1.createInstance(1)); + addCountersEffect.setTargetPointer(getTargetPointer().getFixedTarget(game, source)); + DelayedTriggeredAbility drawStepAbility = new AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility(addCountersEffect, Duration.Custom, false); + drawStepAbility.setSourceObject(oyster, game); + drawStepAbility.setControllerId(source.getControllerId()); + UUID drawStepAbilityUUID = game.addDelayedTriggeredAbility(drawStepAbility, source); + + DelayedTriggeredAbility leaveUntapDelayedTriggeredAbility = new GiantOysterLeaveUntapDelayedTriggeredAbility(drawStepAbilityUUID); + leaveUntapDelayedTriggeredAbility.getEffects().get(0).setTargetPointer(new FixedTarget(tappedCreature, game)); + game.addDelayedTriggeredAbility(leaveUntapDelayedTriggeredAbility, source); + return true; + } + } + return false; + } +} + +class GiantOysterLeaveUntapDelayedTriggeredAbility extends DelayedTriggeredAbility { + + public GiantOysterLeaveUntapDelayedTriggeredAbility(UUID abilityToCancel) { + super(new RemoveAllCountersTargetEffect(CounterType.M1M1), Duration.EndOfGame, true, false); + this.addEffect(new RemoveDelayedTriggeredAbilityEffect(abilityToCancel)); + } + + public GiantOysterLeaveUntapDelayedTriggeredAbility(GiantOysterLeaveUntapDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.UNTAPPED) || event.getType().equals(GameEvent.EventType.ZONE_CHANGE); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType().equals(GameEvent.EventType.UNTAPPED) && event.getTargetId() != null + && event.getTargetId().equals(getSourceId())) { + System.out.println("Untapped"); + return true; + } + return event.getType().equals(GameEvent.EventType.ZONE_CHANGE) && event.getTargetId() != null + && event.getTargetId().equals(getSourceId()) && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD; + } + + @Override + public GiantOysterLeaveUntapDelayedTriggeredAbility copy() { + return new GiantOysterLeaveUntapDelayedTriggeredAbility(this); + } + + @Override + public String getRule() { + return "When {this} leaves the battlefield or becomes untapped, remove all -1/-1 counters from the creature."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GibberingFiend.java b/Mage.Sets/src/mage/cards/g/GibberingFiend.java index 3f035187496..024fd71faa5 100644 --- a/Mage.Sets/src/mage/cards/g/GibberingFiend.java +++ b/Mage.Sets/src/mage/cards/g/GibberingFiend.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class GibberingFiend extends CardImpl { // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // Gibbering Fiend deals 1 damage to that player. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), TargetController.OPPONENT, false, true), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java index 9971f9973de..95072064241 100644 --- a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java +++ b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java @@ -138,7 +138,7 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect { if (targetPermanent == null) { return true; } - if (nextTurnTargetController == 0 && startingTurn != game.getTurnNum() && game.getActivePlayerId().equals(targetPermanent.getControllerId())) { + if (nextTurnTargetController == 0 && startingTurn != game.getTurnNum() && game.isActivePlayer(targetPermanent.getControllerId())) { nextTurnTargetController = game.getTurnNum(); } return game.getPhase().getType() == TurnPhase.END && nextTurnTargetController > 0 && game.getTurnNum() > nextTurnTargetController; @@ -157,7 +157,7 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(getTargetPointer().getFirst(game, source))) { - if (game.getActivePlayerId().equals(permanent.getControllerId())) { + if (game.isActivePlayer(permanent.getControllerId())) { Permanent planeswalker = game.getPermanent(source.getSourceId()); if (planeswalker != null) { return true; diff --git a/Mage.Sets/src/mage/cards/g/GideonJura.java b/Mage.Sets/src/mage/cards/g/GideonJura.java index 1e1c44adabc..d4890e31143 100644 --- a/Mage.Sets/src/mage/cards/g/GideonJura.java +++ b/Mage.Sets/src/mage/cards/g/GideonJura.java @@ -122,14 +122,14 @@ class GideonJuraEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - return permanent.getControllerId().equals(source.getFirstTarget()); + return permanent.isControlledBy(source.getFirstTarget()); } @Override public boolean isInactive(Ability source, Game game) { return (startingTurn != game.getTurnNum() && (game.getPhase().getType() == TurnPhase.END - && game.getActivePlayerId().equals(source.getFirstTarget()))) + && game.isActivePlayer(source.getFirstTarget()))) || // 6/15/2010: If a creature controlled by the affected player can't attack Gideon Jura (because he's no longer on the battlefield, for example), that player may have it attack you, another one of your planeswalkers, or nothing at all. creatingPermanent.getPermanent(game) == null; } diff --git a/Mage.Sets/src/mage/cards/g/GideonsIntervention.java b/Mage.Sets/src/mage/cards/g/GideonsIntervention.java index cbea3ec00ef..91e539b291e 100644 --- a/Mage.Sets/src/mage/cards/g/GideonsIntervention.java +++ b/Mage.Sets/src/mage/cards/g/GideonsIntervention.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.PreventionEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -31,7 +31,7 @@ public final class GideonsIntervention extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // As Gideon's Intervention enters the battlefield, choose a card name. - Effect effect = new NameACardEffect(NameACardEffect.TypeOfName.ALL); + Effect effect = new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL); effect.setText("choose a card name"); this.addAbility(new AsEntersBattlefieldAbility(effect)); @@ -72,7 +72,7 @@ class GideonsInterventionCantCastEffect extends ContinuousRuleModifyingEffectImp public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); if (mageObject != null) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); return "You may not cast a card named " + cardName + " (" + mageObject.getIdName() + ")."; } return null; @@ -85,7 +85,7 @@ class GideonsInterventionCantCastEffect extends ContinuousRuleModifyingEffectImp @Override public boolean applies(GameEvent event, Ability source, Game game) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object.getName().equals(cardName)) { @@ -137,9 +137,9 @@ class GideonsInterventionPreventAllDamageEffect extends PreventionEffectImpl { if (object != null && (event.getType() == GameEvent.EventType.DAMAGE_PLAYER || targetPerm != null && (event.getType() == GameEvent.EventType.DAMAGE_CREATURE || event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER))) { - if (object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY)) + if (object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY)) && (event.getTargetId().equals(source.getControllerId()) - || targetPerm != null && targetPerm.getControllerId().equals(source.getControllerId()))) { + || targetPerm != null && targetPerm.isControlledBy(source.getControllerId()))) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/cards/g/GiftofGrowth.java b/Mage.Sets/src/mage/cards/g/GiftOfGrowth.java similarity index 84% rename from Mage.Sets/src/mage/cards/g/GiftofGrowth.java rename to Mage.Sets/src/mage/cards/g/GiftOfGrowth.java index 0dedf15bd09..2e599b32362 100644 --- a/Mage.Sets/src/mage/cards/g/GiftofGrowth.java +++ b/Mage.Sets/src/mage/cards/g/GiftOfGrowth.java @@ -4,7 +4,6 @@ package mage.cards.g; import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -20,9 +19,9 @@ import java.util.UUID; * * @author rscoates */ -public final class GiftofGrowth extends CardImpl { +public final class GiftOfGrowth extends CardImpl { - public GiftofGrowth(UUID ownerId, CardSetInfo setInfo) { + public GiftOfGrowth(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); // Kicker {2} @@ -36,12 +35,12 @@ public final class GiftofGrowth extends CardImpl { "It gets +2/+2 until end of turn. If this spell was kicked, that creature gets +4/+4 until end of turn instead.")); } - public GiftofGrowth(final GiftofGrowth card) { + public GiftOfGrowth(final GiftOfGrowth card) { super(card); } @Override - public GiftofGrowth copy() { - return new GiftofGrowth(this); + public GiftOfGrowth copy() { + return new GiftOfGrowth(this); } } diff --git a/Mage.Sets/src/mage/cards/g/Gigantiform.java b/Mage.Sets/src/mage/cards/g/Gigantiform.java index 879a0513acc..35c5f5742da 100644 --- a/Mage.Sets/src/mage/cards/g/Gigantiform.java +++ b/Mage.Sets/src/mage/cards/g/Gigantiform.java @@ -7,7 +7,7 @@ import mage.abilities.StaticAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; @@ -49,7 +49,7 @@ public final class Gigantiform extends CardImpl { // Enchanted creature has base power and toughness 8/8 and has trample. this.addAbility(new GigantiformAbility()); // When Gigantiform enters the battlefield, if it was kicked, you may search your library for a card named Gigantiform, put it onto the battlefield, then shuffle your library. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GigantiformEffect(), true), KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, you may search your library for a card named Gigantiform, put it onto the battlefield, then shuffle your library.")); diff --git a/Mage.Sets/src/mage/cards/g/Gigantoplasm.java b/Mage.Sets/src/mage/cards/g/Gigantoplasm.java index 92e79d7f10f..2b0eab220b3 100644 --- a/Mage.Sets/src/mage/cards/g/Gigantoplasm.java +++ b/Mage.Sets/src/mage/cards/g/Gigantoplasm.java @@ -37,9 +37,9 @@ public final class Gigantoplasm extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - // You may have Gigantoplasm enter the battlefield as a copy of any creature on the battlefield except it gains "{X}: This creature has base power and toughness X/X." + // You may have Gigantoplasm enter the battlefield as a copy of any creature on the battlefield, except it has "{X}: This creature has base power and toughness X/X." Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new GigantoplasmApplyToPermanent()); - effect.setText("a copy of any creature on the battlefield except it gains \"{X}: This creature has base power and toughness X/X.\""); + effect.setText("a copy of any creature on the battlefield, except it has \"{X}: This creature has base power and toughness X/X.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); } diff --git a/Mage.Sets/src/mage/cards/g/Gigantosaurus.java b/Mage.Sets/src/mage/cards/g/Gigantosaurus.java new file mode 100644 index 00000000000..ab50a75af45 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/Gigantosaurus.java @@ -0,0 +1,32 @@ +package mage.cards.g; + +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 Gigantosaurus extends CardImpl { + + public Gigantosaurus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}{G}{G}{G}"); + + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(10); + this.toughness = new MageInt(10); + } + + public Gigantosaurus(final Gigantosaurus card) { + super(card); + } + + @Override + public Gigantosaurus copy() { + return new Gigantosaurus(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GildedCerodon.java b/Mage.Sets/src/mage/cards/g/GildedCerodon.java index 396d5681b24..c2abfda6960 100644 --- a/Mage.Sets/src/mage/cards/g/GildedCerodon.java +++ b/Mage.Sets/src/mage/cards/g/GildedCerodon.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class GildedCerodon extends CardImpl { this.toughness = new MageInt(4); // Whenever Gilded Cerodon attacks, if you control a Desert or there is a Desert card in your graveyard, target creature can't block this turn. - Ability ability = new ConditionalTriggeredAbility(new AttacksTriggeredAbility(new CantBlockTargetEffect(Duration.EndOfTurn), false), new GildedCerodonCondition(), rule); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility(new CantBlockTargetEffect(Duration.EndOfTurn), false), new GildedCerodonCondition(), rule); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java b/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java index c88f1150fe2..66e7d23cbd8 100644 --- a/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java +++ b/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java @@ -81,7 +81,7 @@ class GisaAndGeralfContinuousEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (!game.getActivePlayerId().equals(player.getId())) { + if (!game.isActivePlayer(player.getId())) { return false; } for (Card card : player.getGraveyard().getCards(filter, game)) { diff --git a/Mage.Sets/src/mage/cards/g/GiselaBladeOfGoldnight.java b/Mage.Sets/src/mage/cards/g/GiselaBladeOfGoldnight.java index 29578aca461..79dd93dfd96 100644 --- a/Mage.Sets/src/mage/cards/g/GiselaBladeOfGoldnight.java +++ b/Mage.Sets/src/mage/cards/g/GiselaBladeOfGoldnight.java @@ -106,7 +106,7 @@ class GiselaBladeOfGoldnightDoubleDamageEffect extends ReplacementEffectImpl { case DAMAGE_PLANESWALKER: Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - if (permanent.getControllerId().equals(source.getControllerId())) { + if (permanent.isControlledBy(source.getControllerId())) { preventDamage(event, source, permanent.getId(), game); } else if (game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) { event.setAmount(CardUtil.addWithOverflowCheck(event.getAmount(), event.getAmount())); diff --git a/Mage.Sets/src/mage/cards/g/GiselaTheBrokenBlade.java b/Mage.Sets/src/mage/cards/g/GiselaTheBrokenBlade.java index ee08affcbf3..20d3a59a600 100644 --- a/Mage.Sets/src/mage/cards/g/GiselaTheBrokenBlade.java +++ b/Mage.Sets/src/mage/cards/g/GiselaTheBrokenBlade.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.MeldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.MeldEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FlyingAbility; @@ -43,7 +43,7 @@ public final class GiselaTheBrokenBlade extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // At the beginning of your end step, if you both own and control Gisela, the Broken Blade and a creature named Bruna, the Fading Light, exile them, then meld them into Brisela, Voice of Nightmares. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility( new MeldEffect("Bruna, the Fading Light", new BriselaVoiceOfNightmares(ownerId, diff --git a/Mage.Sets/src/mage/cards/g/GladehartCavalry.java b/Mage.Sets/src/mage/cards/g/GladehartCavalry.java index 08a97e5be10..df612eb6e01 100644 --- a/Mage.Sets/src/mage/cards/g/GladehartCavalry.java +++ b/Mage.Sets/src/mage/cards/g/GladehartCavalry.java @@ -74,7 +74,7 @@ class GladehartCavalryTriggeredAbility extends TriggeredAbilityImpl { && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); if (permanent != null - && permanent.getControllerId().equals(this.getControllerId()) + && permanent.isControlledBy(this.getControllerId()) && permanent.isCreature() && permanent.getCounters(game).getCount(CounterType.P1P1) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/g/Gleancrawler.java b/Mage.Sets/src/mage/cards/g/Gleancrawler.java index 648dc92902e..9b183e132c5 100644 --- a/Mage.Sets/src/mage/cards/g/Gleancrawler.java +++ b/Mage.Sets/src/mage/cards/g/Gleancrawler.java @@ -82,7 +82,7 @@ class GleancrawlerEffect extends OneShotEffect { if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { Card card = game.getCard(mor.getSourceId()); if (card != null && card.isCreature() - && card.getOwnerId().equals(source.getControllerId())) { + && card.isOwnedBy(source.getControllerId())) { cardsToHand.add(card); } } diff --git a/Mage.Sets/src/mage/cards/g/GlenElendraPranksters.java b/Mage.Sets/src/mage/cards/g/GlenElendraPranksters.java index 1da7b04ccc1..e91b8115b69 100644 --- a/Mage.Sets/src/mage/cards/g/GlenElendraPranksters.java +++ b/Mage.Sets/src/mage/cards/g/GlenElendraPranksters.java @@ -1,7 +1,6 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -15,6 +14,8 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** * * @author Markedagain diff --git a/Mage.Sets/src/mage/cards/g/Glimmervoid.java b/Mage.Sets/src/mage/cards/g/Glimmervoid.java index a15f52778e7..494bd30195d 100644 --- a/Mage.Sets/src/mage/cards/g/Glimmervoid.java +++ b/Mage.Sets/src/mage/cards/g/Glimmervoid.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; @@ -26,7 +26,7 @@ public final class Glimmervoid extends CardImpl { // At the beginning of the end step, if you control no artifacts, sacrifice Glimmervoid. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(triggered, new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent(), ComparisonType.FEWER_THAN, 1), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent(), ComparisonType.FEWER_THAN, 1), "At the beginning of the end step, if you control no artifacts, sacrifice {this}.")); // {tap}: Add one mana of any color. this.addAbility(new AnyColorManaAbility()); diff --git a/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java b/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java index 8bffdf7a7e2..1bf09ba7a5a 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; @@ -41,7 +41,7 @@ public final class GoblinBushwhacker extends CardImpl { Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES )); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, KickedCondition.instance, "When {this} enters the battlefield, " diff --git a/Mage.Sets/src/mage/cards/g/GoblinLyre.java b/Mage.Sets/src/mage/cards/g/GoblinLyre.java index 7842ab62b2d..e06192a2a50 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinLyre.java +++ b/Mage.Sets/src/mage/cards/g/GoblinLyre.java @@ -48,7 +48,7 @@ class GoblinLyreEffect extends OneShotEffect { public GoblinLyreEffect() { super(Outcome.Damage); this.staticText = "Flip a coin. If you win the flip, {this} deals damage to target opponent or planeswalker equal to the number of creatures you control. " - + "If you lose the flip, Goblin Lyre deals damage to you equal to the number of creatures that opponent or that planeswalker’s controller controls"; + + "If you lose the flip, Goblin Lyre deals damage to you equal to the number of creatures that opponent or that planeswalker's controller controls"; } public GoblinLyreEffect(final GoblinLyreEffect effect) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinRockSled.java b/Mage.Sets/src/mage/cards/g/GoblinRockSled.java index 15bc0cb8b6f..fa2d9fd3782 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRockSled.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRockSled.java @@ -95,7 +95,7 @@ class DontUntapIfAttackedLastTurnSourceEffect extends ContinuousRuleModifyingEff if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getTargetId().equals(source.getSourceId())) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.getControllerId().equals(game.getActivePlayerId())) { + if (permanent != null && permanent.isControlledBy(game.getActivePlayerId())) { AttackedLastTurnWatcher watcher = (AttackedLastTurnWatcher) game.getState().getWatchers().get(AttackedLastTurnWatcher.class.getSimpleName()); if (watcher != null) { Set attackingCreatures = watcher.getAttackedLastTurnCreatures(permanent.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java b/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java index c844724d524..5a55da8c4ea 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java @@ -6,7 +6,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.KickerAbility; @@ -40,7 +40,7 @@ public final class GoblinRuinblaster extends CardImpl { // When Goblin Ruinblaster enters the battlefield, if it was kicked, destroy target nonbasic land. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetNonBasicLandPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target nonbasic land.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target nonbasic land.")); } public GoblinRuinblaster(final GoblinRuinblaster card) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinTrashmaster.java b/Mage.Sets/src/mage/cards/g/GoblinTrashmaster.java new file mode 100644 index 00000000000..33393cc98f9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinTrashmaster.java @@ -0,0 +1,69 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.target.common.TargetArtifactPermanent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class GoblinTrashmaster extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent(SubType.GOBLIN, "Goblins you control"); + private static final FilterControlledCreaturePermanent filter2 + = new FilterControlledCreaturePermanent(SubType.GOBLIN, "a Goblin"); + + public GoblinTrashmaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Other Goblins you control get +1/+1. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, + filter, true + ) + )); + + // Sacrifice a Goblin: Destroy target artifact. + Ability ability = new SimpleActivatedAbility( + new DestroyTargetEffect(), + new SacrificeTargetCost( + new TargetControlledPermanent(filter2) + ) + ); + ability.addTarget(new TargetArtifactPermanent()); + this.addAbility(ability); + } + + public GoblinTrashmaster(final GoblinTrashmaster card) { + super(card); + } + + @Override + public GoblinTrashmaster copy() { + return new GoblinTrashmaster(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinWarCry.java b/Mage.Sets/src/mage/cards/g/GoblinWarCry.java index f1e4518365b..d4479c84759 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinWarCry.java +++ b/Mage.Sets/src/mage/cards/g/GoblinWarCry.java @@ -103,7 +103,7 @@ class GoblinWarCryRestrictionEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - if (permanent.getControllerId().equals(source.getFirstTarget())) { + if (permanent.isControlledBy(source.getFirstTarget())) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/g/GoblinWelder.java b/Mage.Sets/src/mage/cards/g/GoblinWelder.java index a5eaa4a6b79..8df331165b3 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinWelder.java +++ b/Mage.Sets/src/mage/cards/g/GoblinWelder.java @@ -75,7 +75,7 @@ public final class GoblinWelder extends CardImpl { && artifact.isArtifact() && card.isArtifact() && currentZone == Zone.GRAVEYARD - && card.getOwnerId().equals(artifact.getControllerId())) { + && card.isOwnedBy(artifact.getControllerId())) { boolean sacrifice = artifact.sacrifice(source.getSourceId(), game); boolean putOnBF = owner.moveCards(card, Zone.BATTLEFIELD, source, game); if (sacrifice || putOnBF) { diff --git a/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java b/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java new file mode 100644 index 00000000000..efd00af6f04 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java @@ -0,0 +1,75 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author TheElk801 + */ +public final class GoreclawTerrorOfQalSisma extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard(); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + filter2.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public GoreclawTerrorOfQalSisma(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.BEAR); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Creature spells you cast with power 4 or greater cost {2} less to cast. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new SpellsCostReductionControllerEffect(filter, 2) + .setText("Creature spells you cast with power 4 or greater cost {2} less to cast") + )); + + // Whenever Goreclaw, Terror of Qal Sisma attacks, each creature you control with power 4 or greater gets +1/+1 and gains trample until end of turn. + Ability ability = new AttacksTriggeredAbility( + new BoostControlledEffect( + 1, 1, Duration.EndOfTurn, filter2 + ).setText("each creature you control with power 4 or greater gets +1/+1"), false + ); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), + Duration.EndOfTurn, filter2 + ).setText("and gains trample until end of turn")); + this.addAbility(ability); + } + + public GoreclawTerrorOfQalSisma(final GoreclawTerrorOfQalSisma card) { + super(card); + } + + @Override + public GoreclawTerrorOfQalSisma copy() { + return new GoreclawTerrorOfQalSisma(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GormTheGreat.java b/Mage.Sets/src/mage/cards/g/GormTheGreat.java new file mode 100644 index 00000000000..7678dad9dba --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GormTheGreat.java @@ -0,0 +1,52 @@ + +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.abilities.keyword.PartnerWithAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author L_J + */ +public final class GormTheGreat extends CardImpl { + + public GormTheGreat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.GIANT); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(7); + + // Partner with Virtus the Veiled (When this creature enters the battlefield, target player may put Virtus into their hand from their library, then shuffle.) + this.addAbility(new PartnerWithAbility("Virtus the Veiled", true)); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Gorm the Great must be blocked if able, and Gorm must be blocked by two or more creatures if able. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MustBeBlockedByAtLeastOneSourceEffect(Duration.WhileOnBattlefield, 2) + .setText("{this} must be blocked if able, and {this} must be blocked by two or more creatures if able"))); + } + + public GormTheGreat(final GormTheGreat card) { + super(card); + } + + @Override + public GormTheGreat copy() { + return new GormTheGreat(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GrafRats.java b/Mage.Sets/src/mage/cards/g/GrafRats.java index 477eed7ee2d..339fa36f5b2 100644 --- a/Mage.Sets/src/mage/cards/g/GrafRats.java +++ b/Mage.Sets/src/mage/cards/g/GrafRats.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.MeldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.MeldEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,8 +28,7 @@ public final class GrafRats extends CardImpl { this.toughness = new MageInt(1); // At the beginning of combat on your turn, if you both own and control Graf Rats and a creature named Midnight Scavengers, exile them, then meld them into Chittering Host. - - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfCombatTriggeredAbility(new MeldEffect("Midnight Scavengers", new ChitteringHost(ownerId, new CardSetInfo("Chittering Host", "EMN", "96", Rarity.COMMON))), TargetController.YOU, false), new MeldCondition("Midnight Scavengers"), "At the beginning of combat on your turn, if you both own and control {this} and a creature named Midnight Scavengers, exile them, then meld them into Chittering Host.")); diff --git a/Mage.Sets/src/mage/cards/g/GrandAbolisher.java b/Mage.Sets/src/mage/cards/g/GrandAbolisher.java index 2f557aaace5..e9c05daf965 100644 --- a/Mage.Sets/src/mage/cards/g/GrandAbolisher.java +++ b/Mage.Sets/src/mage/cards/g/GrandAbolisher.java @@ -85,7 +85,7 @@ class GrandAbolisherEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (game.getActivePlayerId().equals(source.getControllerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + if (game.isActivePlayer(source.getControllerId()) && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { switch(event.getType()) { case CAST_SPELL: return true; diff --git a/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java b/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java index 0a426b135cd..508844bc913 100644 --- a/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java +++ b/Mage.Sets/src/mage/cards/g/GrandWarlordRadha.java @@ -120,7 +120,7 @@ class GrandWarlordRadhaTriggeredAbility extends TriggeredAbilityImpl { Permanent creature = game.getPermanent(attacker); if (creature != null && creature.getControllerId() != null - && creature.getControllerId().equals(this.getControllerId())) { + && creature.isControlledBy(this.getControllerId())) { return true; } } @@ -157,7 +157,7 @@ class GrandWarlordRadhaEffect extends OneShotEffect { if (watcher != null) { int attackingCreatures = 0; for (MageObjectReference attacker : watcher.getAttackedThisTurnCreatures()) { - if (attacker.getPermanentOrLKIBattlefield(game).getControllerId().equals(controller.getId())) { + if (attacker.getPermanentOrLKIBattlefield(game).isControlledBy(controller.getId())) { attackingCreatures++; } } diff --git a/Mage.Sets/src/mage/cards/g/GratuitousViolence.java b/Mage.Sets/src/mage/cards/g/GratuitousViolence.java index 216a6ac5920..b345c48d223 100644 --- a/Mage.Sets/src/mage/cards/g/GratuitousViolence.java +++ b/Mage.Sets/src/mage/cards/g/GratuitousViolence.java @@ -72,7 +72,7 @@ class GratuitousViolenceReplacementEffect extends ReplacementEffectImpl { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); return permanent != null && permanent.isCreature() - && permanent.getControllerId().equals(source.getControllerId()); + && permanent.isControlledBy(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/g/GraveBetrayal.java b/Mage.Sets/src/mage/cards/g/GraveBetrayal.java index 3fdc4bd5e8f..888925283e9 100644 --- a/Mage.Sets/src/mage/cards/g/GraveBetrayal.java +++ b/Mage.Sets/src/mage/cards/g/GraveBetrayal.java @@ -75,7 +75,7 @@ class GraveBetrayalTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent != null && !permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { + if (permanent != null && !permanent.isControlledBy(this.getControllerId()) && permanent.isCreature()) { Card card = (Card) game.getObject(permanent.getId()); if (card != null) { Effect effect = new GraveBetrayalEffect(); diff --git a/Mage.Sets/src/mage/cards/g/GravePact.java b/Mage.Sets/src/mage/cards/g/GravePact.java index 8898367c9ba..c2dd2f4ee53 100644 --- a/Mage.Sets/src/mage/cards/g/GravePact.java +++ b/Mage.Sets/src/mage/cards/g/GravePact.java @@ -69,7 +69,7 @@ class GravePactTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { + if (permanent.isControlledBy(this.getControllerId()) && permanent.isCreature()) { return true; } } diff --git a/Mage.Sets/src/mage/cards/g/GraveScrabbler.java b/Mage.Sets/src/mage/cards/g/GraveScrabbler.java index 2174464a069..a51594e9a77 100644 --- a/Mage.Sets/src/mage/cards/g/GraveScrabbler.java +++ b/Mage.Sets/src/mage/cards/g/GraveScrabbler.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.MadnessAbility; import mage.cards.Card; @@ -32,7 +32,7 @@ public final class GraveScrabbler extends CardImpl { //you may return target creature card from a graveyard to its owner's hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard"))); - this.addAbility(new ConditionalTriggeredAbility(ability, MadnessAbility.GetCondition(), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MadnessAbility.GetCondition(), "When {this} enters the battlefield, if its madness cost was paid, you may return target creature card from a graveyard to its owner's hand.")); } diff --git a/Mage.Sets/src/mage/cards/g/Gravecrawler.java b/Mage.Sets/src/mage/cards/g/Gravecrawler.java index dd5154a31f9..6c119740d8c 100644 --- a/Mage.Sets/src/mage/cards/g/Gravecrawler.java +++ b/Mage.Sets/src/mage/cards/g/Gravecrawler.java @@ -75,7 +75,7 @@ class GravecrawlerPlayEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(source.getSourceId()) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(source.getSourceId()) && source.isControlledBy(affectedControllerId)) { Card card = game.getCard(source.getSourceId()); if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { if (game.getBattlefield().countAll(filter, source.getControllerId(), game) > 0) { diff --git a/Mage.Sets/src/mage/cards/g/GravetillerWurm.java b/Mage.Sets/src/mage/cards/g/GravetillerWurm.java index f4af78c066e..dcd6c349670 100644 --- a/Mage.Sets/src/mage/cards/g/GravetillerWurm.java +++ b/Mage.Sets/src/mage/cards/g/GravetillerWurm.java @@ -28,7 +28,7 @@ public final class GravetillerWurm extends CardImpl { this.toughness = new MageInt(4); this.addAbility(TrampleAbility.getInstance()); - // Morbid - Gravetiller Wurm enters the battlefield with four +1/+1 counters on it if a creature died this turn. + // Morbid — Gravetiller Wurm enters the battlefield with four +1/+1 counters on it if a creature died this turn. this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(4)), MorbidCondition.instance, ""), "with four +1/+1 counters on it if a creature died this turn")); } diff --git a/Mage.Sets/src/mage/cards/g/Gravewaker.java b/Mage.Sets/src/mage/cards/g/Gravewaker.java new file mode 100644 index 00000000000..4821b42e698 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/Gravewaker.java @@ -0,0 +1,54 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author TheElk801 + */ +public final class Gravewaker extends CardImpl { + + public Gravewaker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + + this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {5}{B}{B}: Return target creature card from your graveyard to the battlefield tapped. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new ReturnFromGraveyardToBattlefieldTargetEffect(true) + .setText("return target creature card from your graveyard to the battlefield tapped"), + new ManaCostsImpl("{5}{B}{B}") + ); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + this.addAbility(ability); + } + + public Gravewaker(final Gravewaker card) { + super(card); + } + + @Override + public Gravewaker copy() { + return new Gravewaker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GraveyardMarshal.java b/Mage.Sets/src/mage/cards/g/GraveyardMarshal.java new file mode 100644 index 00000000000..ce5f6caca74 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GraveyardMarshal.java @@ -0,0 +1,59 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileFromGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +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.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.permanent.token.ZombieToken; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author TheElk801 + */ +public final class GraveyardMarshal extends CardImpl { + + private static final FilterCreatureCard filter + = new FilterCreatureCard("a creature card from your graveyard"); + + public GraveyardMarshal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // {2}{B}, Exile a creature card from your graveyard: Create a tapped 2/2 black Zombie creature token. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new CreateTokenEffect( + new ZombieToken(), + 1, true, false + ), + new ManaCostsImpl("{2}{B}") + ); + ability.addCost(new ExileFromGraveCost( + new TargetCardInYourGraveyard(filter) + )); + this.addAbility(ability); + } + + public GraveyardMarshal(final GraveyardMarshal card) { + super(card); + } + + @Override + public GraveyardMarshal copy() { + return new GraveyardMarshal(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GreatbowDoyen.java b/Mage.Sets/src/mage/cards/g/GreatbowDoyen.java index d5906391550..0323b7d343a 100644 --- a/Mage.Sets/src/mage/cards/g/GreatbowDoyen.java +++ b/Mage.Sets/src/mage/cards/g/GreatbowDoyen.java @@ -86,7 +86,7 @@ class GreatbowDoyenTriggeredAbility extends TriggeredAbilityImpl { if (creature != null && damagedCreature != null && creature.isCreature() && creature.hasSubtype(SubType.ARCHER, game) - && creature.getControllerId().equals(controllerId)) { + && creature.isControlledBy(controllerId)) { this.getEffects().get(0).setValue("damageAmount", event.getAmount()); this.getEffects().get(0).setValue("controller", damagedCreature.getControllerId()); this.getEffects().get(0).setValue("source", event.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/g/GreenerPastures.java b/Mage.Sets/src/mage/cards/g/GreenerPastures.java index b90d25158ff..c3c80e67f22 100644 --- a/Mage.Sets/src/mage/cards/g/GreenerPastures.java +++ b/Mage.Sets/src/mage/cards/g/GreenerPastures.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +27,7 @@ public final class GreenerPastures extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // At the beginning of each player's upkeep, if that player controls more lands than each other player, the player creates a 1/1 green Saproling creature token. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility( Zone.BATTLEFIELD, new CreateTokenTargetEffect(new SaprolingToken()), diff --git a/Mage.Sets/src/mage/cards/g/GreenwoodSentinel.java b/Mage.Sets/src/mage/cards/g/GreenwoodSentinel.java new file mode 100644 index 00000000000..ff98d1ed355 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GreenwoodSentinel.java @@ -0,0 +1,38 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class GreenwoodSentinel extends CardImpl { + + public GreenwoodSentinel(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(2); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + } + + public GreenwoodSentinel(final GreenwoodSentinel card) { + super(card); + } + + @Override + public GreenwoodSentinel copy() { + return new GreenwoodSentinel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java b/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java index 674ef59bdd7..f4167607445 100644 --- a/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java +++ b/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java @@ -101,7 +101,7 @@ class GrenzoHavocRaiserTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); if (damagedPlayer != null && permanent != null && ((DamagedEvent) event).isCombatDamage() - && getControllerId().equals(permanent.getControllerId())) { + && isControlledBy(permanent.getControllerId())) { FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + damagedPlayer.getLogName() + " controls"); filter.add(new ControllerIdPredicate(damagedPlayer.getId())); this.getTargets().clear(); @@ -198,7 +198,7 @@ class GrenzoHavocRaiserCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(cardId) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(cardId) && source.isControlledBy(affectedControllerId)) { ExileZone exileZone = game.getState().getExile().getExileZone(exileId); return exileZone != null && exileZone.contains(cardId); } @@ -229,7 +229,7 @@ class GrenzoHavocRaiserSpendAnyManaEffect extends AsThoughEffectImpl implements @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && Objects.equals(objectId, ((FixedTarget) getTargetPointer()).getTarget()) && ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId) && (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId)) diff --git a/Mage.Sets/src/mage/cards/g/GrimFeast.java b/Mage.Sets/src/mage/cards/g/GrimFeast.java new file mode 100644 index 00000000000..ea2bc8f21c2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GrimFeast.java @@ -0,0 +1,100 @@ +package mage.cards.g; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.other.OwnerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class GrimFeast extends CardImpl { + + public GrimFeast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{G}"); + + // At the beginning of your upkeep, Grim Feast deals 1 damage to you. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new DamageControllerEffect(1), + TargetController.YOU, false + )); + + // Whenever a creature is put into an opponent's graveyard from the battlefield, you gain life equal to its toughness. + this.addAbility(new GrimFeastTriggeredAbility()); + } + + public GrimFeast(final GrimFeast card) { + super(card); + } + + @Override + public GrimFeast copy() { + return new GrimFeast(this); + } +} + +class GrimFeastTriggeredAbility extends PutIntoGraveFromBattlefieldAllTriggeredAbility { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature"); + + static { + filter.add(new OwnerPredicate(TargetController.OPPONENT)); + } + + public GrimFeastTriggeredAbility() { + super(new GrimFeastEffect(), false, filter, true, false); + } + + public GrimFeastTriggeredAbility(final GrimFeastTriggeredAbility effect) { + super(effect); + } + + @Override + public GrimFeastTriggeredAbility copy() { + return new GrimFeastTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever a creature is put into an opponent’s graveyard from the battlefield, " + + "you gain life equal to its toughness."; + } +} + +class GrimFeastEffect extends OneShotEffect { + + public GrimFeastEffect() { + super(Outcome.GainLife); + } + + public GrimFeastEffect(final GrimFeastEffect effect) { + super(effect); + } + + @Override + public GrimFeastEffect copy() { + return new GrimFeastEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); + if (creature == null) { + return false; + } + return new GainLifeEffect(creature.getToughness().getValue()).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GrinningTotem.java b/Mage.Sets/src/mage/cards/g/GrinningTotem.java index 37016ec834e..b2fa96eebfe 100644 --- a/Mage.Sets/src/mage/cards/g/GrinningTotem.java +++ b/Mage.Sets/src/mage/cards/g/GrinningTotem.java @@ -124,7 +124,7 @@ class GrinningTotemMayPlayEffect extends AsThoughEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) { - if (!sameStep && game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { return true; } } else { @@ -140,7 +140,7 @@ class GrinningTotemMayPlayEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && sourceId.equals(getTargetPointer().getFirst(game, source)); } @@ -178,7 +178,7 @@ class GrinningTotemDelayedTriggeredAbility extends DelayedTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return game.getActivePlayerId().equals(this.getControllerId()); + return game.isActivePlayer(this.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java b/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java index eeeb8362ec0..d5093a40a92 100644 --- a/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java +++ b/Mage.Sets/src/mage/cards/g/GrizzledOutcasts.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class GrizzledOutcasts extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Grizzled Outcasts. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public GrizzledOutcasts(final GrizzledOutcasts card) { diff --git a/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java b/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java index 0cda5276092..27a39841c3c 100644 --- a/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java +++ b/Mage.Sets/src/mage/cards/g/GrothamaAllDevouring.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.HashMap; @@ -196,14 +195,15 @@ class GrothamaAllDevouringWatcher extends Watcher { if (event.getType() != GameEvent.EventType.DAMAGED_CREATURE) { return; } + UUID damageControllerId = game.getControllerId(event.getSourceId()); Permanent damaged = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (damaged == null) { + if (damaged == null || damageControllerId == null) { return; } MageObjectReference mor = new MageObjectReference(damaged, game); damageMap.putIfAbsent(mor, new HashMap<>()); - damageMap.get(mor).putIfAbsent(event.getPlayerId(), 0); - damageMap.get(mor).compute(event.getPlayerId(), (k, damage) -> damage + event.getAmount()); + damageMap.get(mor).putIfAbsent(damageControllerId, 0); + damageMap.get(mor).compute(damageControllerId, (k, damage) -> damage + event.getAmount()); } @Override diff --git a/Mage.Sets/src/mage/cards/g/GroundPounder.java b/Mage.Sets/src/mage/cards/g/GroundPounder.java index db43efdee49..dcfcf17eb30 100644 --- a/Mage.Sets/src/mage/cards/g/GroundPounder.java +++ b/Mage.Sets/src/mage/cards/g/GroundPounder.java @@ -106,7 +106,7 @@ class GroundPounderTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + if (this.isControlledBy(event.getPlayerId()) && event.getFlag()) { if (event.getAmount() >= 5) { return true; } diff --git a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java index c6252bf309a..b749f1410e0 100644 --- a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java +++ b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java @@ -6,7 +6,7 @@ import java.util.UUID; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -49,7 +49,7 @@ public final class GrowingRitesOfItlimoc extends CardImpl { // At the beginning of your end step, if you control four or more creatures, transform Growing Rites of Itlimoc. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_A_CREATURE, ComparisonType.MORE_THAN, 3), "At the beginning of your end step, if you control four or more creatures, transform {this}")); diff --git a/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java b/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java index 9c9789fd37d..f3221cdf1aa 100644 --- a/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java +++ b/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java @@ -31,12 +31,12 @@ public final class GruesomeDiscovery extends CardImpl { // Target player discards two cards. - // Morbid - If a creature died this turn, instead that player reveals their hand, you choose two cards from it, then that player discards those cards. + // Morbid — If a creature died this turn, instead that player reveals their hand, you choose two cards from it, then that player discards those cards. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new GruesomeDiscoveryEffect(), new DiscardTargetEffect(2), MorbidCondition.instance, - "Target player discards two cards. Morbid - If a creature died this turn, instead that player reveals their hand, you choose two cards from it, then that player discards those cards")); + "Target player discards two cards. Morbid — If a creature died this turn, instead that player reveals their hand, you choose two cards from it, then that player discards those cards")); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/g/GruulRagebeast.java b/Mage.Sets/src/mage/cards/g/GruulRagebeast.java index f5da5a8ed24..7ac876b7ce1 100644 --- a/Mage.Sets/src/mage/cards/g/GruulRagebeast.java +++ b/Mage.Sets/src/mage/cards/g/GruulRagebeast.java @@ -83,7 +83,7 @@ class GruulRagebeastTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { UUID targetId = event.getTargetId(); Permanent permanent = game.getPermanent(targetId); - if (permanent.getControllerId().equals(this.controllerId) + if (permanent.isControlledBy(this.controllerId) && permanent.isCreature() && (targetId.equals(this.getSourceId()) || !targetId.equals(this.getSourceId()))) { diff --git a/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java b/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java index 2a8076d6693..a550fb2d671 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java +++ b/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java @@ -85,7 +85,7 @@ class GuardianOfTazeemTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isLand() - && permanent.getControllerId().equals(getControllerId())) { + && permanent.isControlledBy(getControllerId())) { for (Effect effect : getEffects()) { if (effect instanceof GuardianOfTazeemEffect) { effect.setTargetPointer(new FixedTarget(permanent, game)); diff --git a/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java b/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java index 3cfd76700ec..792cbaca872 100644 --- a/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java +++ b/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java @@ -36,7 +36,7 @@ public final class GuardiansOfKoilos extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - // When Guardians of Koilos enters the battlefield, you may return another target historic permanent you control to its owner’s hand. + // When Guardians of Koilos enters the battlefield, you may return another target historic permanent you control to its owner's hand. this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter) .setText("you may return another target historic permanent you control to its owner's hand. (Artifacts, legendaries, and Sagas are historic.)"), true)); } diff --git a/Mage.Sets/src/mage/cards/g/GuerrillaTactics.java b/Mage.Sets/src/mage/cards/g/GuerrillaTactics.java index d3423f1f58f..a87afc9bea5 100644 --- a/Mage.Sets/src/mage/cards/g/GuerrillaTactics.java +++ b/Mage.Sets/src/mage/cards/g/GuerrillaTactics.java @@ -3,7 +3,7 @@ package mage.cards.g; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.DiscardedByOpponentTriggerAbility; +import mage.abilities.common.DiscardedByOpponentTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -24,7 +24,7 @@ public final class GuerrillaTactics extends CardImpl { this.getSpellAbility().addTarget(new TargetAnyTarget()); // When a spell or ability an opponent controls causes you to discard Guerrilla Tactics, Guerrilla Tactics deals 4 damage to any target. - Ability ability = new DiscardedByOpponentTriggerAbility(new DamageTargetEffect(4)); + Ability ability = new DiscardedByOpponentTriggeredAbility(new DamageTargetEffect(4)); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/Guile.java b/Mage.Sets/src/mage/cards/g/Guile.java index b30d1e541bc..c641c4df146 100644 --- a/Mage.Sets/src/mage/cards/g/Guile.java +++ b/Mage.Sets/src/mage/cards/g/Guile.java @@ -107,6 +107,6 @@ class GuileReplacementEffect extends ReplacementEffectImpl { StackObject counteringObject = game.getStack().getStackObject(event.getSourceId()); return counteredSpell != null && counteringObject != null - && counteringObject.getControllerId().equals(source.getControllerId()); + && counteringObject.isControlledBy(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/g/GutterGrime.java b/Mage.Sets/src/mage/cards/g/GutterGrime.java index 19985966deb..28fa9508b39 100644 --- a/Mage.Sets/src/mage/cards/g/GutterGrime.java +++ b/Mage.Sets/src/mage/cards/g/GutterGrime.java @@ -73,7 +73,7 @@ class GutterGrimeTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = (Permanent) card; ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD - && permanent.getControllerId().equals(this.controllerId) + && permanent.isControlledBy(this.controllerId) && (targetId.equals(this.getSourceId()) || (permanent.isCreature() && !(permanent instanceof PermanentToken)))) { diff --git a/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java b/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java index 7feb832ab03..7a1c568f8e0 100644 --- a/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java +++ b/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; @@ -47,11 +47,11 @@ public final class GwyllionHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Gwyllion Hedge-Mage enters the battlefield, if you control two or more Plains, you may create a 1/1 white Kithkin Soldier creature token. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KithkinToken()), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KithkinToken()), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); this.addAbility(ability); // When Gwyllion Hedge-Mage enters the battlefield, if you control two or more Swamps, you may put a -1/-1 counter on target creature. - Ability ability2 = new ConditionalTriggeredAbility( + Ability ability2 = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); diff --git a/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java b/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java new file mode 100644 index 00000000000..b7224b44243 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GyrusWakerOfCorpses.java @@ -0,0 +1,129 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.dynamicvalue.common.ManaSpentToCastCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +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.SuperType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author Will + */ +public final class GyrusWakerOfCorpses extends CardImpl { + + private static final FilterCreatureCard filter = new FilterCreatureCard("target creature card with lesser power from your graveyard"); + + static { + filter.add(new GyrusWakerOfCorpsesPowerLessThanSourcePredicate()); + } + + public GyrusWakerOfCorpses(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{B}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HYDRA); + this.power = new MageInt(0); + 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.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)); + + // Whenever Gyrus attacks, you may exile target creature card with lesser power from your graveyard. If you do, create a token that’s a copy of that card and that’s tapped and attacking. Exile the token at the end of combat. + Ability ability = new AttacksTriggeredAbility(new GyrusWakerOfCorpsesEffect(), true); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); + } + + public GyrusWakerOfCorpses(final GyrusWakerOfCorpses card) { + super(card); + } + + @Override + public GyrusWakerOfCorpses copy() { + return new GyrusWakerOfCorpses(this); + } +} + +class GyrusWakerOfCorpsesEffect extends OneShotEffect { + + public GyrusWakerOfCorpsesEffect() { + super(Outcome.Copy); + this.staticText = "exile target creature card with lesser power from your graveyard. If you do, create a token that’s a copy of that card and that’s tapped and attacking. Exile the token at the end of combat."; + } + + public GyrusWakerOfCorpsesEffect(final GyrusWakerOfCorpsesEffect effect) { + super(effect); + } + + @Override + public GyrusWakerOfCorpsesEffect copy() { + return new GyrusWakerOfCorpsesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + + Card card = game.getCard(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || card == null) { + return false; + } + controller.moveCards(card, Zone.EXILED, source, game); + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true, 1, true, true); + effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + effect.apply(game, source); + for (Permanent addedToken : effect.getAddedPermanent()) { + Effect exileEffect = new ExileTargetEffect(); + exileEffect.setTargetPointer(new FixedTarget(addedToken, game)); + new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), false).apply(game, source); + } + return true; + } +} + +class GyrusWakerOfCorpsesPowerLessThanSourcePredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(input.getSourceId()); + return sourcePermanent != null && input.getObject().getPower().getValue() < sourcePermanent.getPower().getValue(); + } + + @Override + public String toString() { + return "lesser power"; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java b/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java index bcf84ab249e..edba324a79d 100644 --- a/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java +++ b/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java @@ -156,7 +156,7 @@ class HaakonPlayKnightsFromGraveyardEffect extends AsThoughEffectImpl { Card knightToCast = game.getCard(objectId); if (knightToCast != null && knightToCast.hasSubtype(SubType.KNIGHT, game) - && knightToCast.getOwnerId().equals(source.getControllerId()) + && knightToCast.isOwnedBy(source.getControllerId()) && game.getState().getZone(objectId) == Zone.GRAVEYARD) { return true; } diff --git a/Mage.Sets/src/mage/cards/h/HagHedgeMage.java b/Mage.Sets/src/mage/cards/h/HagHedgeMage.java index b7260cbc97c..ccbc85ed309 100644 --- a/Mage.Sets/src/mage/cards/h/HagHedgeMage.java +++ b/Mage.Sets/src/mage/cards/h/HagHedgeMage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.PutOnLibraryTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; @@ -46,12 +46,12 @@ public final class HagHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Hag Hedge-Mage enters the battlefield, if you control two or more Swamps, you may have target player discard a card. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule); ability.addTarget(new TargetPlayer()); this.addAbility(ability); // When Hag Hedge-Mage enters the battlefield, if you control two or more Forests, you may put target card from your graveyard on top of your library. - Ability ability2 = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new PutOnLibraryTargetEffect(true), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); + Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new PutOnLibraryTargetEffect(true), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); ability2.addTarget(new TargetCardInYourGraveyard()); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java index 4b17ac32df6..ef9f925de72 100644 --- a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java +++ b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java @@ -145,7 +145,7 @@ class HakimLoreweaverCondition implements Condition { } } return PhaseStep.UPKEEP == game.getStep().getType() - && game.getActivePlayerId().equals(source.getControllerId()); + && game.isActivePlayer(source.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/h/HallOfGemstone.java b/Mage.Sets/src/mage/cards/h/HallOfGemstone.java index fe8adda60e9..0f825dd8ef7 100644 --- a/Mage.Sets/src/mage/cards/h/HallOfGemstone.java +++ b/Mage.Sets/src/mage/cards/h/HallOfGemstone.java @@ -93,7 +93,7 @@ class HallOfGemstoneEffect extends ReplacementEffectImpl { if (colorChosen != null) { ManaEvent manaEvent = (ManaEvent) event; Mana mana = manaEvent.getMana(); - // 8/23/2016 Colorless mana added to a player’s mana pool isn’t affected. + // 8/23/2016 Colorless mana added to a player's mana pool isn't affected. int genericAmount = mana.getGeneric(); int colorlessAmount = mana.getColorless(); int coloredAmount = mana.countColored(); diff --git a/Mage.Sets/src/mage/cards/h/HallarTheFirefletcher.java b/Mage.Sets/src/mage/cards/h/HallarTheFirefletcher.java index 7ca188563c3..8eb11c779ac 100644 --- a/Mage.Sets/src/mage/cards/h/HallarTheFirefletcher.java +++ b/Mage.Sets/src/mage/cards/h/HallarTheFirefletcher.java @@ -81,7 +81,7 @@ class HallarTheFirefletcherTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getControllerId().equals(controllerId)) { + if (spell != null && spell.isControlledBy(controllerId)) { for (Ability ability : spell.getAbilities()) { if (ability instanceof KickerAbility && ((KickerAbility) ability).getKickedCounter(game, spell.getSpellAbility()) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java b/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java new file mode 100644 index 00000000000..4fcedfed348 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java @@ -0,0 +1,63 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class HammerheadCorvette extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Starship creature defending player controls"); + + static { + filter.add(new SubtypePredicate(SubType.STARSHIP)); + filter.add(new DefendingPlayerControlsPredicate()); + } + + public HammerheadCorvette(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // Whenever Hammerhead Corvette attacks, you may untap target Starship creature defending player controls and have that creature block Hammerhead Corvette this turn if able. + Effect effect1 = new UntapTargetEffect(); + Effect effect2 = new MustBeBlockedByTargetSourceEffect(Duration.EndOfTurn); + Ability ability = new AttacksTriggeredAbility(effect1, true, + "Whenever {this} attacks, you may uptap target Starship creature defending player controls and have that creature block {this} this turn if able"); + ability.addEffect(effect2); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public HammerheadCorvette(final HammerheadCorvette card) { + super(card); + } + + @Override + public HammerheadCorvette copy() { + return new HammerheadCorvette(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java b/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java new file mode 100644 index 00000000000..9508f8e3189 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java @@ -0,0 +1,102 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.*; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.PartnerWithAbility; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class HanSoloScrumrat extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); + + static { + filter.add(new AnotherPredicate()); + } + + public HanSoloScrumrat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Partner with Chewbacca, the Beast + this.addAbility(new PartnerWithAbility("Chewbacca, the Beast")); + + // R: Han Solo, Scrumrat gains first strike until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + + // Whenever Han Solo, Scrumrat deals damage during your turn, put a +1/+1 counter on another target creature you control. + Ability ability = new HanSoloScrumratTriggeredAbility(); + ability.addTarget(new TargetControlledCreaturePermanent(filter)); + this.addAbility(ability); + } + + public HanSoloScrumrat(final HanSoloScrumrat card) { + super(card); + } + + @Override + public HanSoloScrumrat copy() { + return new HanSoloScrumrat(this); + } +} + +class HanSoloScrumratTriggeredAbility extends TriggeredAbilityImpl { + + public HanSoloScrumratTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); + } + + public HanSoloScrumratTriggeredAbility(final HanSoloScrumratTriggeredAbility ability) { + super(ability); + } + + @Override + public HanSoloScrumratTriggeredAbility copy() { + return new HanSoloScrumratTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_CREATURE + || event.getType() == GameEvent.EventType.DAMAGED_PLAYER + || event.getType() == GameEvent.EventType.DAMAGED_PLANESWALKER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent source = game.getPermanent(this.getSourceId()); + return source != null + && game.isActivePlayer(source.getControllerId()) + && event.getSourceId().equals(this.getSourceId()); + } + + @Override + public String getRule() { + return "Whenever {this} creature deals damage during your turn, " + super.getRule(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java index 7d4ab40a90a..26b44fac7b8 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java +++ b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class HanweirMilitiaCaptain extends CardImpl { // At the beginning of your upkeep, if you control four or more creatures, transform Hanweir Militia Captain. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3), "At the beginning of your upkeep, if you control four or more creatures, transform {this}")); diff --git a/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java b/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java index 47f24ca9895..463a9b84094 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java +++ b/Mage.Sets/src/mage/cards/h/HanweirWatchkeep.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.TransformAbility; @@ -38,7 +38,7 @@ public final class HanweirWatchkeep extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Hanweir Watchkeep. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public HanweirWatchkeep(final HanweirWatchkeep card) { diff --git a/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java b/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java index 2f356f4cab1..f41fd10dbe1 100644 --- a/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java +++ b/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java @@ -1,4 +1,3 @@ - package mage.cards.h; import java.util.List; @@ -7,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.cards.CardImpl; @@ -45,7 +44,7 @@ public final class HaphazardBombardment extends CardImpl { FilterPermanent filter = new FilterPermanent("if two or more permanents you don't control have an aim counter on them"); filter.add(new ControllerPredicate(TargetController.NOT_YOU)); filter.add(new CounterPredicate(CounterType.AIM)); - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfYourEndStepTriggeredAbility(new HaphazardBombardmentEndOfTurnEffect(), false), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfYourEndStepTriggeredAbility(new HaphazardBombardmentEndOfTurnEffect(), false), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1, false), "At the beginning of your end step, if two or more permanents you don't control have an aim counter on them, destroy one of those permanents at random")); } @@ -86,7 +85,7 @@ class HaphazardBombardmentEffect extends OneShotEffect { List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); if (permanents.size() > 4) { permanents.clear(); - TargetPermanent target = new TargetPermanent(4, filter); + TargetPermanent target = new TargetPermanent(4, 4, filter, true); controller.chooseTarget(outcome, target, source, game); for (UUID targetId : target.getTargets()) { Permanent permanent = game.getPermanent(targetId); @@ -126,15 +125,17 @@ class HaphazardBombardmentEndOfTurnEffect extends OneShotEffect { // 4/27/2018 If one or more of the permanents with aim counters on them have indestructible, // select the permanent destroyed at random from among the permanents with aim counters - // that don’t have indestructible. + // that don't have indestructible. FilterPermanent filter = new FilterPermanent("if two or more permanents you don't control have an aim counter on them"); filter.add(new ControllerPredicate(TargetController.NOT_YOU)); filter.add(new CounterPredicate(CounterType.AIM)); filter.add(Predicates.not(new AbilityPredicate(IndestructibleAbility.class))); List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - Permanent permanent = permanents.get(RandomUtil.nextInt(permanents.size())); - if (permanent != null) { - permanent.destroy(source.getSourceId(), game, false); + if (!permanents.isEmpty()) { + Permanent permanent = permanents.get(RandomUtil.nextInt(permanents.size())); + if (permanent != null) { + permanent.destroy(source.getSourceId(), game, false); + } } return true; } diff --git a/Mage.Sets/src/mage/cards/h/HardenedBerserker.java b/Mage.Sets/src/mage/cards/h/HardenedBerserker.java index 80804e74ae8..5793f80ee18 100644 --- a/Mage.Sets/src/mage/cards/h/HardenedBerserker.java +++ b/Mage.Sets/src/mage/cards/h/HardenedBerserker.java @@ -84,7 +84,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI } } if (abilityToModify instanceof SpellAbility) { - return abilityToModify.getControllerId().equals(source.getControllerId()); + return abilityToModify.isControlledBy(source.getControllerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/h/HardenedScaleArmor.java b/Mage.Sets/src/mage/cards/h/HardenedScaleArmor.java new file mode 100644 index 00000000000..efb9882142e --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HardenedScaleArmor.java @@ -0,0 +1,49 @@ +package mage.cards.h; + +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.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +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.Zone; + +/** + * + * @author TheElk801 + */ +public final class HardenedScaleArmor extends CardImpl { + + public HardenedScaleArmor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + + 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 gets +3/+3. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield))); + } + + public HardenedScaleArmor(final HardenedScaleArmor card) { + super(card); + } + + @Override + public HardenedScaleArmor copy() { + return new HardenedScaleArmor(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HardenedScales.java b/Mage.Sets/src/mage/cards/h/HardenedScales.java index 6e72fb04dc8..ce764544f94 100644 --- a/Mage.Sets/src/mage/cards/h/HardenedScales.java +++ b/Mage.Sets/src/mage/cards/h/HardenedScales.java @@ -73,7 +73,7 @@ class HardenedScalesEffect extends ReplacementEffectImpl { if (permanent == null) { permanent = game.getPermanentEntering(event.getTargetId()); } - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) + if (permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.isCreature()) { return true; } diff --git a/Mage.Sets/src/mage/cards/h/HarmsWay.java b/Mage.Sets/src/mage/cards/h/HarmsWay.java index 3f0c5a544ea..a6df836e323 100644 --- a/Mage.Sets/src/mage/cards/h/HarmsWay.java +++ b/Mage.Sets/src/mage/cards/h/HarmsWay.java @@ -86,7 +86,7 @@ class HarmsWayPreventDamageTargetEffect extends RedirectionEffect { // check permanent first Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - if (permanent.getControllerId().equals(source.getControllerId())) { + if (permanent.isControlledBy(source.getControllerId())) { // it's your permanent return true; } diff --git a/Mage.Sets/src/mage/cards/h/HarshJustice.java b/Mage.Sets/src/mage/cards/h/HarshJustice.java index 59a8f97193d..6f763f7f431 100644 --- a/Mage.Sets/src/mage/cards/h/HarshJustice.java +++ b/Mage.Sets/src/mage/cards/h/HarshJustice.java @@ -39,7 +39,7 @@ public final class HarshJustice extends CardImpl { // Cast Harsh Justice only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HavengulLich.java b/Mage.Sets/src/mage/cards/h/HavengulLich.java index b48b5bb0b65..8c1c4a4896e 100644 --- a/Mage.Sets/src/mage/cards/h/HavengulLich.java +++ b/Mage.Sets/src/mage/cards/h/HavengulLich.java @@ -91,7 +91,7 @@ class HavengulLichPlayEffect extends AsThoughEffectImpl { UUID targetId = getTargetPointer().getFirst(game, source); if (targetId != null) { return targetId.equals(objectId) - && source.getControllerId().equals(affectedControllerId) + && source.isControlledBy(affectedControllerId) && Zone.GRAVEYARD == game.getState().getZone(objectId); } else { // the target card has changed zone meanwhile, so the effect is no longer needed diff --git a/Mage.Sets/src/mage/cards/h/HavocDevils.java b/Mage.Sets/src/mage/cards/h/HavocDevils.java new file mode 100644 index 00000000000..ff7c618bf0d --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HavocDevils.java @@ -0,0 +1,37 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class HavocDevils extends CardImpl { + + public HavocDevils(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.DEVIL); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + } + + public HavocDevils(final HavocDevils card) { + super(card); + } + + @Override + public HavocDevils copy() { + return new HavocDevils(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HeartOfBogardan.java b/Mage.Sets/src/mage/cards/h/HeartOfBogardan.java index 56dcfd0c9b4..77562d849d3 100644 --- a/Mage.Sets/src/mage/cards/h/HeartOfBogardan.java +++ b/Mage.Sets/src/mage/cards/h/HeartOfBogardan.java @@ -77,7 +77,7 @@ class HeartOfBogardanTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "When a player doesn't pay {this}'s cumulative upkeep, " + "{this} deals X damage to target player or planeswalker " - + "and each creature that player or that planeswalker’s controller controls," + + "and each creature that player or that planeswalker's controller controls," + " where X is twice the number of age counters on {this} minus 2."; } } @@ -87,7 +87,7 @@ class HeartOfBogardanEffect extends OneShotEffect { public HeartOfBogardanEffect() { super(Outcome.Damage); staticText = "{this} deals X damage to target player or planeswalker " - + "and each creature that player or that planeswalker’s controller controls, " + + "and each creature that player or that planeswalker's controller controls, " + "where X is twice the number of age counters on {this} minus 2"; } diff --git a/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java b/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java index aab2013c72f..ecf355dea2d 100644 --- a/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java +++ b/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java @@ -1,27 +1,24 @@ - package mage.cards.h; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.SendOptionUsedEventEffect; import mage.abilities.keyword.EmbalmAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.StaticFilters; 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.Target; @@ -41,13 +38,11 @@ public final class HeartPiercerManticore extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(3); - // When Heart-Piercer Manticore enters the battlefield, you may sacrifice another creature. - Ability firstAbility = new EntersBattlefieldTriggeredAbility(new HeartPiercerManticoreSacrificeEffect(), true); - this.addAbility(firstAbility); - // When you do, Heart-Piercer Manticore deals damage equal to that creature's power to any target. - Ability secondAbility = new HeartPiercerManticoreSacrificeTriggeredAbility(firstAbility.getOriginalId()); - secondAbility.addTarget(new TargetAnyTarget()); - this.addAbility(secondAbility); + // When Heart-Piercer Manticore enters the battlefield, you may sacrifice another creature. When you do, Heart-Piercer Manticore deals damage equal to that creature's power to any target. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new HeartPiercerManticoreSacrificeEffect(), true + )); + // Embalm {5}{R} this.addAbility(new EmbalmAbility(new ManaCostsImpl("{5}{R}"), this)); @@ -67,7 +62,8 @@ class HeartPiercerManticoreSacrificeEffect extends OneShotEffect { public HeartPiercerManticoreSacrificeEffect() { super(Outcome.Damage); - this.staticText = "you may sacrifice another creature"; + this.staticText = "sacrifice another creature. When you do, " + + "{this} deals damage equal to that creature's power to any target"; } public HeartPiercerManticoreSacrificeEffect(final HeartPiercerManticoreSacrificeEffect effect) { @@ -87,8 +83,11 @@ class HeartPiercerManticoreSacrificeEffect extends OneShotEffect { if (controller.choose(outcome, target, source.getSourceId(), game)) { Permanent toSacrifice = game.getPermanent(target.getFirstTarget()); if (toSacrifice != null) { - toSacrifice.sacrifice(source.getSourceId(), game); - return new SendOptionUsedEventEffect(toSacrifice.getPower().getValue()).apply(game, source); + DelayedTriggeredAbility trigger = new HeartPiercerManticoreReflexiveTriggeredAbility(toSacrifice.getPower().getValue()); + if (toSacrifice.sacrifice(source.getSourceId(), game)) { + game.addDelayedTriggeredAbility(trigger, source); + return new SendOptionUsedEventEffect().apply(game, source); + } } } return true; @@ -97,44 +96,36 @@ class HeartPiercerManticoreSacrificeEffect extends OneShotEffect { } } -class HeartPiercerManticoreSacrificeTriggeredAbility extends TriggeredAbilityImpl { +class HeartPiercerManticoreReflexiveTriggeredAbility extends DelayedTriggeredAbility { - private final UUID relatedTriggerdAbilityOriginalId; - - public HeartPiercerManticoreSacrificeTriggeredAbility(UUID relatedTriggerdAbilityOriginalId) { - super(Zone.BATTLEFIELD, new InfoEffect("{this} deals damage equal to that creature's power to any target")); - this.relatedTriggerdAbilityOriginalId = relatedTriggerdAbilityOriginalId; + public HeartPiercerManticoreReflexiveTriggeredAbility(int damage) { + super(new DamageTargetEffect(damage), Duration.OneUse, true); + this.addTarget(new TargetAnyTarget()); } - public HeartPiercerManticoreSacrificeTriggeredAbility(final HeartPiercerManticoreSacrificeTriggeredAbility ability) { + public HeartPiercerManticoreReflexiveTriggeredAbility(final HeartPiercerManticoreReflexiveTriggeredAbility ability) { super(ability); - this.relatedTriggerdAbilityOriginalId = ability.relatedTriggerdAbilityOriginalId; } @Override - public HeartPiercerManticoreSacrificeTriggeredAbility copy() { - return new HeartPiercerManticoreSacrificeTriggeredAbility(this); + public HeartPiercerManticoreReflexiveTriggeredAbility copy() { + return new HeartPiercerManticoreReflexiveTriggeredAbility(this); } @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.OPTION_USED; + return event.getType() == GameEvent.EventType.OPTION_USED; } @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId().equals(this.getControllerId()) - && event.getTargetId().equals(relatedTriggerdAbilityOriginalId) - && event.getSourceId().equals(getSourceId())) { - getEffects().clear(); - getEffects().add(new DamageTargetEffect(event.getAmount())); - return true; - } - return false; + return event.getPlayerId().equals(this.getControllerId()) + && event.getSourceId().equals(this.getSourceId()); } @Override public String getRule() { - return "When you do, {this} deals damage equal to that creature's power to any target."; + return "When you sacrifice a creature to {this}'s ability, " + + "{this} deals damage equal to that creature's power to any target"; } } diff --git a/Mage.Sets/src/mage/cards/h/HeartWolf.java b/Mage.Sets/src/mage/cards/h/HeartWolf.java new file mode 100644 index 00000000000..7409660149e --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeartWolf.java @@ -0,0 +1,106 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.IsPhaseCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ExileGraveyardAllTargetPlayerEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.constants.*; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.turn.Phase; +import mage.target.Target; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author noahg + */ +public final class HeartWolf extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new SubtypePredicate(SubType.DWARF)); + } + + public HeartWolf(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.WOLF); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // {tap}: Target Dwarf creature gets +2/+0 and gains first strike until end of turn. When that creature leaves the battlefield this turn, sacrifice Heart Wolf. Activate this ability only during combat. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("Target Dwarf creature gets +2/+0"), new TapSourceCost(), new IsPhaseCondition(TurnPhase.COMBAT)); + ability.addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), + Duration.EndOfTurn).setText("and gains first strike until end of turn")); + ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new HeartWolfDelayedTriggeredAbility(), true)); + this.addAbility(ability); + } + + public HeartWolf(final HeartWolf card) { + super(card); + } + + @Override + public HeartWolf copy() { + return new HeartWolf(this); + } +} + +class HeartWolfDelayedTriggeredAbility extends DelayedTriggeredAbility { + + public HeartWolfDelayedTriggeredAbility() { + super(new SacrificeSourceEffect(), Duration.EndOfTurn, false); + } + + public HeartWolfDelayedTriggeredAbility(HeartWolfDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getTarget() != null && zEvent.getTargetId().equals(getTargets().getFirstTarget())) { + this.getTargets().clear(); // else spell fizzles because target creature died + return true; + } + return false; + } + + @Override + public HeartWolfDelayedTriggeredAbility copy() { + return new HeartWolfDelayedTriggeredAbility(this); + } + + @Override + public String getRule() { + return "When that creature leaves the battlefield this turn, sacrifice {this}."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java b/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java index 10672d441bb..ac6ff037ae0 100644 --- a/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java +++ b/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -38,7 +38,7 @@ public final class HeartstabberMosquito extends CardImpl { // When Heartstabber Mosquito enters the battlefield, if it was kicked, destroy target creature. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target creature.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target creature.")); } public HeartstabberMosquito(final HeartstabberMosquito card) { diff --git a/Mage.Sets/src/mage/cards/h/HeartwoodDryad.java b/Mage.Sets/src/mage/cards/h/HeartwoodDryad.java index 3fe01db33eb..88c2bc0c894 100644 --- a/Mage.Sets/src/mage/cards/h/HeartwoodDryad.java +++ b/Mage.Sets/src/mage/cards/h/HeartwoodDryad.java @@ -6,6 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.common.CanBlockAsThoughtItHadShadowEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AsThoughEffectType; @@ -29,7 +30,7 @@ public final class HeartwoodDryad extends CardImpl { this.toughness = new MageInt(1); // Heartwood Dryad can block creatures with shadow as though Heartwood Dryad had shadow. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAsThoughtIthadShadowEffect(Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAsThoughtItHadShadowEffect(Duration.WhileOnBattlefield))); } public HeartwoodDryad(final HeartwoodDryad card) { @@ -40,32 +41,4 @@ public final class HeartwoodDryad extends CardImpl { public HeartwoodDryad copy() { return new HeartwoodDryad(this); } -} - -class CanBlockAsThoughtIthadShadowEffect extends AsThoughEffectImpl { - - public CanBlockAsThoughtIthadShadowEffect(Duration duration) { - super(AsThoughEffectType.BLOCK_SHADOW, duration, Outcome.Benefit); - staticText = "{this} can block creatures with shadow as though {this} had shadow"; - } - - public CanBlockAsThoughtIthadShadowEffect(final CanBlockAsThoughtIthadShadowEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public CanBlockAsThoughtIthadShadowEffect copy() { - return new CanBlockAsThoughtIthadShadowEffect(this); - } - - @Override - public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return sourceId.equals(source.getSourceId()); - } - } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HeatShimmer.java b/Mage.Sets/src/mage/cards/h/HeatShimmer.java index 2f86cafcd4e..e0e8cb79caa 100644 --- a/Mage.Sets/src/mage/cards/h/HeatShimmer.java +++ b/Mage.Sets/src/mage/cards/h/HeatShimmer.java @@ -27,7 +27,7 @@ public final class HeatShimmer extends CardImpl { public HeatShimmer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); - // Create a token that's a copy of target creature. That token has haste and "At the beginning of the end step, exile this permanent." + //Create a token that's a copy of target creature, except it has haste and "At the beginning of the end step, exile this permanent." this.getSpellAbility().addEffect(new HeatShimmerEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } @@ -46,7 +46,7 @@ class HeatShimmerEffect extends OneShotEffect { public HeatShimmerEffect() { super(Outcome.Copy); - this.staticText = "Create a token that's a copy of target creature. That token has haste and \"At the beginning of the end step, exile this permanent.\""; + this.staticText = "Create a token that's a copy of target creature, except it has haste and \"At the beginning of the end step, exile this permanent.\""; } public HeatShimmerEffect(final HeatShimmerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/h/HeatStroke.java b/Mage.Sets/src/mage/cards/h/HeatStroke.java index e2b04db1869..130b465e313 100644 --- a/Mage.Sets/src/mage/cards/h/HeatStroke.java +++ b/Mage.Sets/src/mage/cards/h/HeatStroke.java @@ -1,35 +1,46 @@ package mage.cards.h; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.UUID; + +import mage.MageObjectReference; +import mage.abilities.Ability; import mage.abilities.common.EndOfCombatTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.BlockedPredicate; import mage.filter.predicate.permanent.BlockingPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.watchers.common.BlockedThisTurnWatcher; +import mage.watchers.common.WasBlockedThisTurnWatcher; /** * @author dustinroepsch */ public final class HeatStroke extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(Predicates.or(new BlockedPredicate(), new BlockingPredicate())); - } - public HeatStroke(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // At end of combat, destroy each creature that blocked or was blocked this turn. - this.addAbility(new EndOfCombatTriggeredAbility(new DestroyAllEffect(filter) - .setText("destroy each creature that blocked or was blocked this turn"), false)); + Ability ability = new EndOfCombatTriggeredAbility(new HeatStrokeEffect(), false); + ability.addWatcher(new BlockedThisTurnWatcher()); + ability.addWatcher(new WasBlockedThisTurnWatcher()); + this.addAbility(ability); } public HeatStroke(final HeatStroke card) { @@ -41,3 +52,45 @@ public final class HeatStroke extends CardImpl { return new HeatStroke(this); } } + +class HeatStrokeEffect extends OneShotEffect { + + public HeatStrokeEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "destroy each creature that blocked or was blocked this turn"; + } + + public HeatStrokeEffect(HeatStrokeEffect effect) { + super(effect); + } + + @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()); + Set inROI = new HashSet<>(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)); + boolean toRet = false; + Set toDestroy = new HashSet<>(); + + if (blockedWatcher != null){ + toDestroy.addAll(blockedWatcher.getBlockedThisTurnCreatures()); + } + if (wasBlockedThisTurnWatcher != null){ + toDestroy.addAll(wasBlockedThisTurnWatcher.getWasBlockedThisTurnCreatures()); + } + + for (MageObjectReference mor : toDestroy) { + Permanent permanent = mor.getPermanent(game); + if (permanent != null && permanent.isCreature() && inROI.contains(permanent)){ + permanent.destroy(source.getSourceId(), game, false); + toRet = true; + } + } + return toRet; + } + + @Override + public HeatStrokeEffect copy() { + return new HeatStrokeEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/h/HeavenlyBlademaster.java b/Mage.Sets/src/mage/cards/h/HeavenlyBlademaster.java new file mode 100644 index 00000000000..20303b9d383 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeavenlyBlademaster.java @@ -0,0 +1,139 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.AdditiveDynamicValue; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.AuraAttachedCount; +import mage.abilities.dynamicvalue.common.EquipmentAttachedCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +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.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class HeavenlyBlademaster extends CardImpl { + + public HeavenlyBlademaster(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(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Double strike + this.addAbility(DoubleStrikeAbility.getInstance()); + + // When Heavenly Blademaster enters the battlefield, you may attach any number of Auras and Equipment you control to it. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new HeavenlyBlademasterEffect(), true + )); + + // Other creatures you control get +1/+1 for each Aura and Equipment attached to Heavenly Blademaster. + DynamicValue totalAmount = new AdditiveDynamicValue( + new EquipmentAttachedCount(1), + new AuraAttachedCount(1) + ); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + totalAmount, totalAmount, Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENT_CREATURES, true + ).setText("Other creatures you control get +1/+1 for each Aura and Equipment attached to {this}") + )); + } + + public HeavenlyBlademaster(final HeavenlyBlademaster card) { + super(card); + } + + @Override + public HeavenlyBlademaster copy() { + return new HeavenlyBlademaster(this); + } +} + +class HeavenlyBlademasterEffect extends OneShotEffect { + + private static final FilterPermanent filter + = new FilterControlledPermanent("Aura or Equipment you control"); + + static { + filter.add(Predicates.or( + new SubtypePredicate(SubType.AURA), + new SubtypePredicate(SubType.EQUIPMENT) + )); + } + + public HeavenlyBlademasterEffect() { + super(Outcome.Benefit); + staticText = "you may attach any number of Auras and Equipment you control to it"; + } + + public HeavenlyBlademasterEffect(final HeavenlyBlademasterEffect effect) { + super(effect); + } + + @Override + public HeavenlyBlademasterEffect copy() { + return new HeavenlyBlademasterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + if (sourcePermanent == null || player == null) { + return false; + } + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + if (!player.choose(outcome, target, source.getSourceId(), game)) { + return false; + } + target.getTargets().stream().map( + attachmentId -> game.getPermanent(attachmentId) + ).filter( + attachment -> attachment != null + ).forEachOrdered((attachment) -> { + if (!sourcePermanent.cantBeAttachedBy(attachment, game)) { + if (attachment.getAttachedTo() != sourcePermanent.getId()) { + if (attachment.getAttachedTo() != null) { + Permanent fromPermanent = game.getPermanent(attachment.getAttachedTo()); + if (fromPermanent != null) { + fromPermanent.removeAttachment(attachment.getId(), game); + } + } + } + sourcePermanent.addAttachment(attachment.getId(), game); + game.informPlayers(attachment.getLogName() + " was attached to " + sourcePermanent.getLogName()); + } + }); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java b/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java new file mode 100644 index 00000000000..853fb730b87 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeavenlyQilin.java @@ -0,0 +1,59 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +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.Duration; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class HeavenlyQilin extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another target creature you control"); + + static { + filter.add(new AnotherPredicate()); + } + + public HeavenlyQilin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.KIRIN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenenver Heavenly Qilin attacks, another target creature you control gains flying until end of turn. + Ability ability = new AttacksTriggeredAbility( + new GainAbilityTargetEffect( + FlyingAbility.getInstance(), + Duration.EndOfTurn + ), false + ); + ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, true)); + this.addAbility(ability); + } + + public HeavenlyQilin(final HeavenlyQilin card) { + super(card); + } + + @Override + public HeavenlyQilin copy() { + return new HeavenlyQilin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HeavyFog.java b/Mage.Sets/src/mage/cards/h/HeavyFog.java index 679b037a814..b668356383d 100644 --- a/Mage.Sets/src/mage/cards/h/HeavyFog.java +++ b/Mage.Sets/src/mage/cards/h/HeavyFog.java @@ -31,7 +31,7 @@ public final class HeavyFog extends CardImpl { // Cast Deep Wood only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HedronFieldPurists.java b/Mage.Sets/src/mage/cards/h/HedronFieldPurists.java index 602fc6d9b77..21d86be5120 100644 --- a/Mage.Sets/src/mage/cards/h/HedronFieldPurists.java +++ b/Mage.Sets/src/mage/cards/h/HedronFieldPurists.java @@ -90,7 +90,7 @@ class HedronFieldPuristsEffect extends PreventionEffectImpl { if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java b/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java index 9e6bdb85379..83b21abffcb 100644 --- a/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java +++ b/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.FerociousCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.DeathtouchAbility; import mage.cards.CardImpl; @@ -32,7 +32,7 @@ public final class HeirOfTheWilds extends CardImpl { // Deathtouch this.addAbility(DeathtouchAbility.getInstance()); // Ferocious - Whenever Heir of the Wilds attacks, if you control a creature with power 4 or greater, Heir of the Wilds gets +1/+1 until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new BoostSourceEffect(1,1,Duration.EndOfTurn), false), FerociousCondition.instance, "Ferocious — Whenever {this} attacks, if you control a creature with power 4 or greater, {this} gets +1/+1 until end of turn." diff --git a/Mage.Sets/src/mage/cards/h/HelixPinnacle.java b/Mage.Sets/src/mage/cards/h/HelixPinnacle.java index a2075898c30..dc62fe13770 100644 --- a/Mage.Sets/src/mage/cards/h/HelixPinnacle.java +++ b/Mage.Sets/src/mage/cards/h/HelixPinnacle.java @@ -6,7 +6,7 @@ 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.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -38,7 +38,7 @@ public final class HelixPinnacle extends CardImpl { new ManaCostsImpl("{X}"))); // At the beginning of your upkeep, if there are 100 or more tower counters on Helix Pinnacle, you win the game. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new WinGameSourceControllerEffect(), TargetController.YOU, false), new SourceHasCounterCondition(CounterType.TOWER, 100, Integer.MAX_VALUE), rule)); diff --git a/Mage.Sets/src/mage/cards/h/Hellfire.java b/Mage.Sets/src/mage/cards/h/Hellfire.java index 3d7076eda0d..b12ebf4b684 100644 --- a/Mage.Sets/src/mage/cards/h/Hellfire.java +++ b/Mage.Sets/src/mage/cards/h/Hellfire.java @@ -66,7 +66,7 @@ class HellfireEffect extends OneShotEffect { filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); for (Permanent creature : game.getState().getBattlefield().getActivePermanents(filter, controller.getId(), game)) { if (creature.destroy(source.getSourceId(), game, false) - && game.getState().getZone(creature.getId()).equals(Zone.GRAVEYARD)) { // If a commander is replaced to command zone, the creature does not die) { + && game.getState().getZone(creature.getId()) == Zone.GRAVEYARD) { // If a commander is replaced to command zone, the creature does not die) { destroyedCreature++; } } diff --git a/Mage.Sets/src/mage/cards/h/HellfireMongrel.java b/Mage.Sets/src/mage/cards/h/HellfireMongrel.java index e2c4d45a9d9..14f5824c2b4 100644 --- a/Mage.Sets/src/mage/cards/h/HellfireMongrel.java +++ b/Mage.Sets/src/mage/cards/h/HellfireMongrel.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,7 +32,7 @@ public final class HellfireMongrel extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, Hellfire Mongrel deals 2 damage to him or her. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), TargetController.OPPONENT, false, true), new CardsInActivePlayersHandCondition(), "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 2 damage to him or her." diff --git a/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java b/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java index 51402c13f7e..d39feaeecfc 100644 --- a/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java +++ b/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java @@ -9,7 +9,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; @@ -56,7 +56,7 @@ public final class HellkiteTyrant extends CardImpl { // At the beginning of your upkeep, if you control twenty or more artifacts, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, new PermanentsOnTheBattlefieldCondition(new FilterArtifactPermanent(), ComparisonType.MORE_THAN, 19), "At the beginning of your upkeep, if you control twenty or more artifacts, you win the game.")); diff --git a/Mage.Sets/src/mage/cards/h/Hellrider.java b/Mage.Sets/src/mage/cards/h/Hellrider.java index b80643d47eb..91ebfa5e2d7 100644 --- a/Mage.Sets/src/mage/cards/h/Hellrider.java +++ b/Mage.Sets/src/mage/cards/h/Hellrider.java @@ -68,7 +68,7 @@ class HellriderTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent source = game.getPermanent(event.getSourceId()); - if (source != null && source.getControllerId().equals(controllerId)) { + if (source != null && source.isControlledBy(controllerId)) { UUID defendingPlayerId = game.getCombat().getDefenderId(event.getSourceId()); this.getEffects().get(0).setTargetPointer(new FixedTarget(defendingPlayerId)); return true; @@ -78,6 +78,6 @@ class HellriderTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a creature you control attacks, {this} deals 1 damage to the player or planeswalker it’s attacking."; + return "Whenever a creature you control attacks, {this} deals 1 damage to the player or planeswalker it's attacking."; } } diff --git a/Mage.Sets/src/mage/cards/h/HelmOfTheHost.java b/Mage.Sets/src/mage/cards/h/HelmOfTheHost.java index dcfd329c2e1..81a4be8046b 100644 --- a/Mage.Sets/src/mage/cards/h/HelmOfTheHost.java +++ b/Mage.Sets/src/mage/cards/h/HelmOfTheHost.java @@ -31,7 +31,7 @@ public final class HelmOfTheHost extends CardImpl { this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); - // At the beginning of combat on your turn, create a token that’s a copy of equipped creature, except the token isn’t legendary if equipped creature is legendary. That token gains haste. + // At the beginning of combat on your turn, create a token that's a copy of equipped creature, except the token isn't legendary if equipped creature is legendary. That token gains haste. TriggeredAbility ability = new BeginningOfCombatTriggeredAbility( new HelmOfTheHostEffect(), TargetController.YOU, diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfFaith.java b/Mage.Sets/src/mage/cards/h/HeraldOfFaith.java new file mode 100644 index 00000000000..02b4255b59e --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeraldOfFaith.java @@ -0,0 +1,41 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +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; + +/** + * + * @author TheElk801 + */ +public final class HeraldOfFaith extends CardImpl { + + public HeraldOfFaith(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Herald of Faith attacks, you gain 2 life. + this.addAbility(new AttacksTriggeredAbility(new GainLifeEffect(2), false)); + } + + public HeraldOfFaith(final HeraldOfFaith card) { + super(card); + } + + @Override + public HeraldOfFaith copy() { + return new HeraldOfFaith(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfWar.java b/Mage.Sets/src/mage/cards/h/HeraldOfWar.java index c8e55bf6ba4..4ab890792c6 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldOfWar.java +++ b/Mage.Sets/src/mage/cards/h/HeraldOfWar.java @@ -79,7 +79,7 @@ class HeraldOfWarCostReductionEffect extends CostModificationEffectImpl { public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); - if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.hasSubtype(SubType.ANGEL, game) || sourceCard.hasSubtype(SubType.HUMAN, game))) { + if (sourceCard != null && abilityToModify.isControlledBy(source.getControllerId()) && (sourceCard.hasSubtype(SubType.ANGEL, game) || sourceCard.hasSubtype(SubType.HUMAN, game))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/h/HeraldsHorn.java b/Mage.Sets/src/mage/cards/h/HeraldsHorn.java index 7172601b325..1dfbd2b6ec3 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldsHorn.java +++ b/Mage.Sets/src/mage/cards/h/HeraldsHorn.java @@ -79,7 +79,7 @@ class HeraldsHornEffect extends OneShotEffect { // If it's a creature card of the chosen type, you may reveal it and put it into your hand. FilterCreatureCard filter = new FilterCreatureCard("creature card of the chosen type"); - filter.add(new ChosenSubtypePredicate(source.getSourceId())); + filter.add(new ChosenSubtypePredicate()); String message = "Reveal the top card of your library and put that card into your hand?"; if (card != null) { if (filter.match(card, game) && controller.chooseUse(Outcome.Benefit, message, source, game)) { diff --git a/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java b/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java index b1dce2f6f53..d59c7c88943 100644 --- a/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/cards/h/HermitOfTheNatterknolls.java @@ -8,6 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; @@ -46,7 +47,7 @@ public final class HermitOfTheNatterknolls extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Hermit of the Natterknolls. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public HermitOfTheNatterknolls(final HermitOfTheNatterknolls card) { diff --git a/Mage.Sets/src/mage/cards/h/HeroicReinforcements.java b/Mage.Sets/src/mage/cards/h/HeroicReinforcements.java new file mode 100644 index 00000000000..9db9048c74b --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HeroicReinforcements.java @@ -0,0 +1,48 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; +import mage.game.permanent.token.SoldierToken; + +/** + * + * @author TheElk801 + */ +public final class HeroicReinforcements extends CardImpl { + + public HeroicReinforcements(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{W}"); + + // Create two 1/1 white Soldier creature tokens. Until end of turn, creatures you control get +1/+1 and gain haste. + this.getSpellAbility().addEffect(new CreateTokenEffect( + new SoldierToken(), 2 + )); + this.getSpellAbility().addEffect(new BoostControlledEffect( + 1, 1, Duration.EndOfTurn + ).setText("Until end of turn, creatures you control get +1/+1")); + this.getSpellAbility().addEffect( + new GainAbilityControlledEffect( + HasteAbility.getInstance(), + Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURE + ).setText("and gain haste") + ); + } + + public HeroicReinforcements(final HeroicReinforcements card) { + super(card); + } + + @Override + public HeroicReinforcements copy() { + return new HeroicReinforcements(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HiddenAncients.java b/Mage.Sets/src/mage/cards/h/HiddenAncients.java index 492565d8c98..63b9ac7d8f1 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenAncients.java +++ b/Mage.Sets/src/mage/cards/h/HiddenAncients.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class HiddenAncients extends CardImpl { // When an opponent casts an enchantment spell, if Hidden Ancients is an enchantment, Hidden Ancients becomes a 5/5 Treefolk creature. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenAncientsTreefolkToken(), "", Duration.WhileOnBattlefield, true, false), filter, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts an enchantment spell, if {this} is an enchantment, {this} becomes a 5/5 Treefolk creature.")); } diff --git a/Mage.Sets/src/mage/cards/h/HiddenGibbons.java b/Mage.Sets/src/mage/cards/h/HiddenGibbons.java index 3f247e3b50b..d65cb33853f 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenGibbons.java +++ b/Mage.Sets/src/mage/cards/h/HiddenGibbons.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -16,7 +16,6 @@ import mage.filter.FilterSpell; import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -39,7 +38,7 @@ public final class HiddenGibbons extends CardImpl { // When an opponent casts an instant spell, if Hidden Gibbons is an enchantment, Hidden Gibbons becomes a 4/4 Ape creature. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenGibbonsApe(), "", Duration.WhileOnBattlefield, true, false), filter, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts an instant spell, if {this} is an enchantment, {this} becomes a 4/4 Ape creature.")); } diff --git a/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java b/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java index b573f2d32b6..c9f7febb40d 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java +++ b/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -16,7 +16,6 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterArtifactSpell; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -33,7 +32,7 @@ public final class HiddenGuerrillas extends CardImpl { // When an opponent casts an artifact spell, if Hidden Guerrillas is an enchantment, Hidden Guerrillas becomes a 5/3 Soldier creature with trample. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenGuerrillasSoldier(), "", Duration.WhileOnBattlefield, true, false), new FilterArtifactSpell(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts an artifact spell, if {this} is an enchantment, {this} becomes a 5/3 Soldier creature with trample.")); } diff --git a/Mage.Sets/src/mage/cards/h/HiddenHerbalists.java b/Mage.Sets/src/mage/cards/h/HiddenHerbalists.java index 200e555d2a3..479d5ddc122 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenHerbalists.java +++ b/Mage.Sets/src/mage/cards/h/HiddenHerbalists.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.Mana; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.mana.BasicManaEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class HiddenHerbalists extends CardImpl { // Revolt &mdash When Hidden Herbalists enters the battlefield, if a permanent you controlled left the battlefield this turn, add {G}{G}; this.addAbility( - new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new BasicManaEffect(Mana.GreenMana(2)), false), RevoltCondition.instance, "Revolt — When {this} enters the battlefield, if a permanent you controlled left" + " the battlefield this turn, add {G}{G}."), diff --git a/Mage.Sets/src/mage/cards/h/HiddenHerd.java b/Mage.Sets/src/mage/cards/h/HiddenHerd.java index 32cf8031e22..1917dc61179 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenHerd.java +++ b/Mage.Sets/src/mage/cards/h/HiddenHerd.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -19,7 +19,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; /** * @@ -31,7 +30,7 @@ public final class HiddenHerd extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); // When an opponent plays a nonbasic land, if Hidden Herd is an enchantment, Hidden Herd becomes a 3/3 Beast creature. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new HiddenHerdAbility(), new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent plays a nonbasic land, if {this} is an enchantment, {this} becomes a 3/3 Beast creature." diff --git a/Mage.Sets/src/mage/cards/h/HiddenSpider.java b/Mage.Sets/src/mage/cards/h/HiddenSpider.java index 4da45f95340..549cf2fdf27 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenSpider.java +++ b/Mage.Sets/src/mage/cards/h/HiddenSpider.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ReachAbility; @@ -18,7 +18,6 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureSpell; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -41,7 +40,7 @@ public final class HiddenSpider extends CardImpl { // When an opponent casts a creature spell with flying, if Hidden Spider is an enchantment, Hidden Spider becomes a 3/5 Spider creature with reach. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenSpiderToken(), "", Duration.WhileOnBattlefield, true, false), filter, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts a creature spell with flying, if {this} is an enchantment, {this} becomes a 3/5 Spider creature with reach.")); } diff --git a/Mage.Sets/src/mage/cards/h/HiddenStockpile.java b/Mage.Sets/src/mage/cards/h/HiddenStockpile.java index 68daf02699e..9094f3d0958 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenStockpile.java +++ b/Mage.Sets/src/mage/cards/h/HiddenStockpile.java @@ -8,7 +8,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.RevoltCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class HiddenStockpile extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{B}"); // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, create a 1/1 colorless Servo artifact creature token. - Ability ability = new ConditionalTriggeredAbility(new BeginningOfYourEndStepTriggeredAbility(new CreateTokenEffect(new ServoToken()), false), RevoltCondition.instance, + Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfYourEndStepTriggeredAbility(new CreateTokenEffect(new ServoToken()), false), RevoltCondition.instance, "Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, create a 1/1 colorless Servo artifact creature token"); ability.setAbilityWord(AbilityWord.REVOLT); ability.addWatcher(new RevoltWatcher()); diff --git a/Mage.Sets/src/mage/cards/h/HieromancersCage.java b/Mage.Sets/src/mage/cards/h/HieromancersCage.java new file mode 100644 index 00000000000..500f420a1f8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HieromancersCage.java @@ -0,0 +1,51 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class HieromancersCage extends CardImpl { + + private final static FilterNonlandPermanent filter = new FilterNonlandPermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public HieromancersCage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + + // When Hieromancer's Cage enters the battlefield, exile target nonland permanent an opponent controls until Hieromancer's Cage leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility( + new ExileUntilSourceLeavesEffect(filter.getMessage()) + ); + ability.addTarget(new TargetPermanent(filter)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect( + new OnLeaveReturnExiledToBattlefieldAbility()) + ); + this.addAbility(ability); + } + + public HieromancersCage(final HieromancersCage card) { + super(card); + } + + @Override + public HieromancersCage copy() { + return new HieromancersCage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java index 922837d71c3..745149db0bb 100644 --- a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java +++ b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java @@ -46,7 +46,7 @@ class HintOfInsanityEffect extends OneShotEffect { public HintOfInsanityEffect() { super(Outcome.Discard); - this.staticText = "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"; + this.staticText = "Target player reveals their hand. That player discards all nonland cards with the same name as another card in their hand"; } public HintOfInsanityEffect(final HintOfInsanityEffect effect) { diff --git a/Mage.Sets/src/mage/cards/h/HinterlandHermit.java b/Mage.Sets/src/mage/cards/h/HinterlandHermit.java index 69832fe723b..256dc16650b 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandHermit.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandHermit.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class HinterlandHermit extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Hinterland Hermit. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public HinterlandHermit(final HinterlandHermit card) { diff --git a/Mage.Sets/src/mage/cards/h/HinterlandLogger.java b/Mage.Sets/src/mage/cards/h/HinterlandLogger.java index fe8f5c1730f..6634e00414a 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandLogger.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandLogger.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class HinterlandLogger extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Hinterland Logger. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public HinterlandLogger(final HinterlandLogger card) { diff --git a/Mage.Sets/src/mage/cards/h/HinterlandScourge.java b/Mage.Sets/src/mage/cards/h/HinterlandScourge.java index 910866a282c..8e51404854f 100644 --- a/Mage.Sets/src/mage/cards/h/HinterlandScourge.java +++ b/Mage.Sets/src/mage/cards/h/HinterlandScourge.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -41,7 +41,7 @@ public final class HinterlandScourge extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Hinterland Scourge. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public HinterlandScourge(final HinterlandScourge card) { diff --git a/Mage.Sets/src/mage/cards/h/HiredBlade.java b/Mage.Sets/src/mage/cards/h/HiredBlade.java new file mode 100644 index 00000000000..aa83966e647 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HiredBlade.java @@ -0,0 +1,38 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class HiredBlade extends CardImpl { + + public HiredBlade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ASSASSIN); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + } + + public HiredBlade(final HiredBlade card) { + super(card); + } + + @Override + public HiredBlade copy() { + return new HiredBlade(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HiredMuscle.java b/Mage.Sets/src/mage/cards/h/HiredMuscle.java index c8b871f78bf..b5eeb8a4ea1 100644 --- a/Mage.Sets/src/mage/cards/h/HiredMuscle.java +++ b/Mage.Sets/src/mage/cards/h/HiredMuscle.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FlipSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -25,7 +25,6 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.events.GameEvent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import mage.target.common.TargetCreaturePermanent; /** @@ -48,7 +47,7 @@ public final class HiredMuscle extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.KI.createInstance()), StaticFilters.SPIRIT_OR_ARCANE_CARD, true)); // At the beginning of the end step, if there are two or more ki counters on Hired Muscle, you may flip it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new Scarmaker()), true), new SourceHasCounterCondition(CounterType.KI, 2, Integer.MAX_VALUE), "At the beginning of the end step, if there are two or more ki counters on {this}, you may flip it.")); diff --git a/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java b/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java index bf5678c6bd8..887bd3203e9 100644 --- a/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java +++ b/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java @@ -9,7 +9,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -43,7 +43,7 @@ public final class HollowbornBarghest extends CardImpl { // At the beginning of your upkeep, if you have no cards in hand, each opponent loses 2 life. Condition condition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 0); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new HollowbornBarghestEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, condition, rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule)); // At the beginning of each opponent's upkeep, if that player has no cards in hand, he or she loses 2 life. this.addAbility(new HollowbornBarghestTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java b/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java index ed249b386fb..0da64ee8dbd 100644 --- a/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java +++ b/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -19,7 +19,7 @@ import mage.constants.SubType; */ public final class HollowhengeScavenger extends CardImpl { - private static final String staticText = "Morbid - When {this} enters the battlefield, if a creature died this turn, you gain 5 life."; + private static final String staticText = "Morbid — When {this} enters the battlefield, if a creature died this turn, you gain 5 life."; public HollowhengeScavenger(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); @@ -28,9 +28,9 @@ public final class HollowhengeScavenger extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(5); - // Morbid - When Hollowhenge Scavenger enters the battlefield, if a creature died this turn, you gain 5 life. + // Morbid — When Hollowhenge Scavenger enters the battlefield, if a creature died this turn, you gain 5 life. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5)); - this.addAbility(new ConditionalTriggeredAbility(ability, MorbidCondition.instance, staticText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText)); } public HollowhengeScavenger(final HollowhengeScavenger card) { diff --git a/Mage.Sets/src/mage/cards/h/HomewardPath.java b/Mage.Sets/src/mage/cards/h/HomewardPath.java index d4c99489ec9..f6773fe9638 100644 --- a/Mage.Sets/src/mage/cards/h/HomewardPath.java +++ b/Mage.Sets/src/mage/cards/h/HomewardPath.java @@ -89,7 +89,7 @@ class HomewardPathControlEffect extends ContinuousEffectImpl { for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { Permanent creature = it.next().getPermanent(game); if (creature != null) { - if (!creature.getControllerId().equals(creature.getOwnerId())) { + if (!creature.isControlledBy(creature.getOwnerId())) { creature.changeControllerId(creature.getOwnerId(), game); } } else { diff --git a/Mage.Sets/src/mage/cards/h/Hostility.java b/Mage.Sets/src/mage/cards/h/Hostility.java index 723b368c98f..a9cfc57da29 100644 --- a/Mage.Sets/src/mage/cards/h/Hostility.java +++ b/Mage.Sets/src/mage/cards/h/Hostility.java @@ -86,7 +86,7 @@ class HostilityEffect extends PreventionEffectImpl { if (super.applies(event, source, game)) { if (game.getOpponents(source.getControllerId()).contains(event.getTargetId())) { Spell spell = game.getStack().getSpell(event.getSourceId()); - if (spell != null && spell.getControllerId().equals(source.getControllerId())) { + if (spell != null && spell.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java b/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java index 702430ee20b..7bb5d623438 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackAlpha.java @@ -10,6 +10,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; @@ -59,7 +60,7 @@ public final class HowlpackAlpha extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Howlpack Alpha. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public HowlpackAlpha(final HowlpackAlpha card) { diff --git a/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java b/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java index 1573b2b8ab6..d5f9f2a1a33 100644 --- a/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java +++ b/Mage.Sets/src/mage/cards/h/HowlpackOfEstwald.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class HowlpackOfEstwald extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Howlpack of Estwald. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public HowlpackOfEstwald(final HowlpackOfEstwald card) { diff --git a/Mage.Sets/src/mage/cards/h/HungerOfTheHowlpack.java b/Mage.Sets/src/mage/cards/h/HungerOfTheHowlpack.java index 5995ac16c07..c29819bd733 100644 --- a/Mage.Sets/src/mage/cards/h/HungerOfTheHowlpack.java +++ b/Mage.Sets/src/mage/cards/h/HungerOfTheHowlpack.java @@ -22,13 +22,13 @@ public final class HungerOfTheHowlpack extends CardImpl { // Put a +1/+1 counter on target creature. - // Morbid - Put three +1/+1 counters on that creature instead if a creature died this turn. + // Morbid — Put three +1/+1 counters on that creature instead if a creature died this turn. this.getSpellAbility().addEffect( new ConditionalOneShotEffect( new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)), new AddCountersTargetEffect(CounterType.P1P1.createInstance()), MorbidCondition.instance, - "Put a +1/+1 counter on target creature. Morbid - Put three +1/+1 counters on that creature instead if a creature died this turn")); + "Put a +1/+1 counter on target creature. Morbid — Put three +1/+1 counters on that creature instead if a creature died this turn")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/h/HungeringHydra.java b/Mage.Sets/src/mage/cards/h/HungeringHydra.java new file mode 100644 index 00000000000..91137cb6f27 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HungeringHydra.java @@ -0,0 +1,89 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealtDamageToSourceTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByMoreThanOneSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; + +/** + * + * @author TheElk801 + */ +public final class HungeringHydra extends CardImpl { + + public HungeringHydra(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{G}"); + + this.subtype.add(SubType.HYDRA); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Hungering Hydra enters the battlefield with X +1/+1 counters on it. + this.addAbility(new EntersBattlefieldAbility( + new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()) + )); + + // Hungering Hydra can't be blocked by more than one creature. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByMoreThanOneSourceEffect() + )); + + // Whenever damage is dealt to Hungering Hydra, put that many +1/+1 counters on it. + this.addAbility(new DealtDamageToSourceTriggeredAbility( + Zone.BATTLEFIELD, new HungeringHydraEffect(), + false, false, true + )); + } + + public HungeringHydra(final HungeringHydra card) { + super(card); + } + + @Override + public HungeringHydra copy() { + return new HungeringHydra(this); + } +} + +class HungeringHydraEffect extends OneShotEffect { + + public HungeringHydraEffect() { + super(Outcome.Benefit); + this.staticText = "put that many +1/+1 counters on it"; + } + + public HungeringHydraEffect(final HungeringHydraEffect effect) { + super(effect); + } + + @Override + public HungeringHydraEffect copy() { + return new HungeringHydraEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int damage = (int) this.getValue("damage"); + if (damage == 0) { + return false; + } + return new AddCountersSourceEffect( + CounterType.P1P1.createInstance(damage) + ).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java index 879cb39d551..9da3929dfe7 100644 --- a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java +++ b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.TransformSourceEffect; @@ -44,7 +44,7 @@ public final class HuntmasterOfTheFells extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public HuntmasterOfTheFells(final HuntmasterOfTheFells card) { diff --git a/Mage.Sets/src/mage/cards/h/Hypnox.java b/Mage.Sets/src/mage/cards/h/Hypnox.java index 44290f82062..41e0be205ec 100644 --- a/Mage.Sets/src/mage/cards/h/Hypnox.java +++ b/Mage.Sets/src/mage/cards/h/Hypnox.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; @@ -43,7 +43,7 @@ public final class Hypnox extends CardImpl { // When Hypnox enters the battlefield, if you cast it from your hand, exile all cards from target opponent's hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new HypnoxExileEffect()); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalTriggeredAbility(ability, CastFromHandSourceCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, exile all cards from target opponent's hand."), new CastFromHandWatcher()); // When Hypnox leaves the battlefield, return the exiled cards to their owner's hand. diff --git a/Mage.Sets/src/mage/cards/i/IcefallRegent.java b/Mage.Sets/src/mage/cards/i/IcefallRegent.java index 0280b8b847b..8e21b7bf10d 100644 --- a/Mage.Sets/src/mage/cards/i/IcefallRegent.java +++ b/Mage.Sets/src/mage/cards/i/IcefallRegent.java @@ -111,7 +111,7 @@ class IcefallRegentEffect extends ContinuousRuleModifyingEffectImpl { // the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL // event will happen before this effect is applied ever) Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent == null || !sourcePermanent.getControllerId().equals(source.getControllerId())) { + if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { discard(); return false; } @@ -132,7 +132,7 @@ class IcefallRegentEffect extends ContinuousRuleModifyingEffectImpl { if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP) { if (event.getTargetId().equals(targetPointer.getFirst(game, source))) { Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source)); - return targetCreature != null && game.getActivePlayerId().equals(targetCreature.getControllerId()); + return targetCreature != null && game.isActivePlayer(targetCreature.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/i/IkraShidiqiTheUsurper.java b/Mage.Sets/src/mage/cards/i/IkraShidiqiTheUsurper.java index 1b76006a71e..2a44a903b35 100644 --- a/Mage.Sets/src/mage/cards/i/IkraShidiqiTheUsurper.java +++ b/Mage.Sets/src/mage/cards/i/IkraShidiqiTheUsurper.java @@ -79,7 +79,7 @@ class IkraShidiqiTheUsurperTriggeredAbility extends TriggeredAbilityImpl { DamagedEvent damageEvent = (DamagedEvent) event; if (damageEvent.isCombatDamage()) { Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && permanent.isCreature() && permanent.getControllerId().equals(this.getControllerId())) { + if (permanent != null && permanent.isCreature() && permanent.isControlledBy(this.getControllerId())) { this.getEffects().clear(); this.getEffects().add(new GainLifeEffect(permanent.getToughness().getValue())); return true; diff --git a/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java b/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java index 8e73dee5b4b..389d705645c 100644 --- a/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java +++ b/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java @@ -72,7 +72,7 @@ class AbilityActivatedTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent equipment = game.getPermanent(this.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null && equipment.getAttachedTo().equals(event.getSourceId())) { + if (equipment != null && equipment.isAttachedTo(event.getSourceId())) { StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); if (!(stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl)) { Effect effect = this.getEffects().get(0); diff --git a/Mage.Sets/src/mage/cards/i/IllusionistsGambit.java b/Mage.Sets/src/mage/cards/i/IllusionistsGambit.java index e381280918a..b624891e7a2 100644 --- a/Mage.Sets/src/mage/cards/i/IllusionistsGambit.java +++ b/Mage.Sets/src/mage/cards/i/IllusionistsGambit.java @@ -180,7 +180,7 @@ class IllusionistsGambitRestrictionEffect extends RestrictionEffect { } // planeswalker Permanent permanent = game.getPermanent(defenderId); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) + if (permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.isPlaneswalker()) { return false; } diff --git a/Mage.Sets/src/mage/cards/i/ImaginaryPet.java b/Mage.Sets/src/mage/cards/i/ImaginaryPet.java index 16c2920e3fd..96cf4fa0e11 100644 --- a/Mage.Sets/src/mage/cards/i/ImaginaryPet.java +++ b/Mage.Sets/src/mage/cards/i/ImaginaryPet.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class ImaginaryPet extends CardImpl { // At the beginning of your upkeep, if you have a card in hand, return Imaginary Pet to its owner's hand. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new CardsInHandCondition(ComparisonType.MORE_THAN, 0), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new CardsInHandCondition(ComparisonType.MORE_THAN, 0), "At the beginning of your upkeep, if you have a card in hand, return {this} to its owner's hand.")); } diff --git a/Mage.Sets/src/mage/cards/i/Immerwolf.java b/Mage.Sets/src/mage/cards/i/Immerwolf.java index ea7c0b63dd2..ebc726beb07 100644 --- a/Mage.Sets/src/mage/cards/i/Immerwolf.java +++ b/Mage.Sets/src/mage/cards/i/Immerwolf.java @@ -90,7 +90,7 @@ class ImmerwolfEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); return permanent != null && - permanent.getControllerId().equals(source.getControllerId()) && + permanent.isControlledBy(source.getControllerId()) && filter.match(permanent, game) ; } } diff --git a/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java b/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java index 2757a7aa3c1..ca3610f9618 100644 --- a/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java +++ b/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class ImpendingDisaster extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU, false); ability.addEffect(new DestroyAllEffect(new FilterLandPermanent())); ImpendingDisasterCondition contition = new ImpendingDisasterCondition(); - this.addAbility(new ConditionalTriggeredAbility(ability, contition, "At the beginning of your upkeep, if there are seven or more lands on the battlefield, sacrifice {this} and destroy all lands")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, contition, "At the beginning of your upkeep, if there are seven or more lands on the battlefield, sacrifice {this} and destroy all lands")); } diff --git a/Mage.Sets/src/mage/cards/i/ImperialHovertank.java b/Mage.Sets/src/mage/cards/i/ImperialHovertank.java new file mode 100644 index 00000000000..e1160654c27 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/ImperialHovertank.java @@ -0,0 +1,84 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author NinthWorld + */ +public final class ImperialHovertank extends CardImpl { + + public ImperialHovertank(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{W}{B}"); + + this.subtype.add(SubType.TROOPER); + this.subtype.add(SubType.CONSTRUCT); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever a Trooper creature you control attacks, defending player loses 1 life and you gain 1 life. + this.addAbility(new ImperialHovertankTriggeredAbility()); + } + + public ImperialHovertank(final ImperialHovertank card) { + super(card); + } + + @Override + public ImperialHovertank copy() { + return new ImperialHovertank(this); + } +} + +class ImperialHovertankTriggeredAbility extends TriggeredAbilityImpl { + + public ImperialHovertankTriggeredAbility() { + super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(1)); + this.addEffect(new GainLifeEffect(1)); + } + + public ImperialHovertankTriggeredAbility(final ImperialHovertankTriggeredAbility ability) { + super(ability); + } + + @Override + public ImperialHovertankTriggeredAbility copy() { + return new ImperialHovertankTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent source = game.getPermanent(event.getSourceId()); + if (source != null && source.isControlledBy(controllerId) && source.hasSubtype(SubType.TROOPER, game)) { + UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(event.getSourceId(), game); + this.getEffects().get(0).setTargetPointer(new FixedTarget(defendingPlayerId)); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever a Trooper creature you control attacks, defending player loses 1 life and you gain 1 life."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/ImperialMask.java b/Mage.Sets/src/mage/cards/i/ImperialMask.java index 95f549ebd03..11b2f5b0a1e 100644 --- a/Mage.Sets/src/mage/cards/i/ImperialMask.java +++ b/Mage.Sets/src/mage/cards/i/ImperialMask.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; import mage.abilities.keyword.HexproofAbility; @@ -34,7 +34,7 @@ public final class ImperialMask extends CardImpl { // When Imperial Mask enters the battlefield, if it's not a token, each of your teammates puts a token that's a copy of Imperial Mask onto the battlefield. // No implementation of teammates currently, so no effect needed - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new InfoEffect("each of your teammates puts a token that's a copy of {this} onto the battlefield"), false), new SourceMatchesFilterCondition(filter), "When {this} enters the battlefield, if it's not a token, " diff --git a/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java b/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java index ca5aa37e245..418cb142f60 100644 --- a/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java +++ b/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java @@ -11,7 +11,7 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil import mage.abilities.condition.common.SourceOnBattlefieldOrCommandZoneCondition; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ExileTargetEffect; @@ -65,7 +65,7 @@ public final class InallaArchmageRitualist extends CardImpl { this.toughness = new MageInt(5); // Eminence - Whenever another nontoken Wizard enters the battlefield under your control, if Inalla, Archmage Ritualist is in the command zone or on the battlefield, you may pay {1}. If you do, create a token that's a copy of that Wizard. The token gains haste. Exile it at the beginning of the next end step. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldControlledTriggeredAbility(Zone.ALL, new DoIfCostPaid( new InallaArchmageRitualistEffect(), new ManaCostsImpl("{1}"), "Pay {1} to create a token copy?"), filter, false, SetTargetPointer.PERMANENT, ""), diff --git a/Mage.Sets/src/mage/cards/i/InameAsOne.java b/Mage.Sets/src/mage/cards/i/InameAsOne.java index 595ae5bf80f..25b0162cc3e 100644 --- a/Mage.Sets/src/mage/cards/i/InameAsOne.java +++ b/Mage.Sets/src/mage/cards/i/InameAsOne.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileSourceEffect; @@ -50,7 +50,7 @@ public final class InameAsOne extends CardImpl { this.toughness = new MageInt(8); // When Iname as One enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter)), true), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library."), diff --git a/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java b/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java index 39dacafdb6f..fc62cc74c37 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingAmbition.java @@ -30,7 +30,7 @@ public final class IncreasingAmbition extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}"); - // Search your library for a card and put that card into your hand. If Increasing Ambition was cast from a graveyard, instead search your library for two cards and put those cards into your hand. Then shuffle your library. + // Search your library for a card and put that card into your hand. If this spell was cast from a graveyard, instead search your library for two cards and put those cards into your hand. Then shuffle your library. this.getSpellAbility().addEffect(new IncreasingAmbitionEffect()); // Flashback {7}{B} @@ -51,7 +51,7 @@ class IncreasingAmbitionEffect extends SearchEffect { public IncreasingAmbitionEffect() { super(new TargetCardInLibrary(), Outcome.DrawCard); - staticText = "Search your library for a card and put that card into your hand. If {this} was cast from a graveyard, instead search your library for two cards and put those cards into your hand. Then shuffle your library"; + staticText = "Search your library for a card and put that card into your hand. If this spell was cast from a graveyard, instead search your library for two cards and put those cards into your hand. Then shuffle your library"; } public IncreasingAmbitionEffect(final IncreasingAmbitionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java index d3016def504..909f4ec7c0c 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java @@ -24,7 +24,7 @@ public final class IncreasingConfusion extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}"); - // Target player puts the top X cards of their library into their graveyard. If Increasing Confusion was cast from a graveyard, that player puts twice that many cards into their graveyard instead. + // Target player puts the top X cards of their library into their graveyard. If this spell was cast from a graveyard, that player puts twice that many cards into their graveyard instead. this.getSpellAbility().addEffect(new IncreasingConfusionEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); @@ -46,7 +46,7 @@ class IncreasingConfusionEffect extends OneShotEffect { public IncreasingConfusionEffect() { super(Outcome.Detriment); - staticText = "Target player puts the top X cards of their library into their graveyard. If {this} was cast from a graveyard, that player puts twice that many cards into their graveyard instead"; + staticText = "Target player puts the top X cards of their library into their graveyard. If this spell was cast from a graveyard, that player puts twice that many cards into their graveyard instead"; } public IncreasingConfusionEffect(final IncreasingConfusionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java b/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java index 757ab3cbd39..2c211667979 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingDevotion.java @@ -25,7 +25,7 @@ public final class IncreasingDevotion extends CardImpl { public IncreasingDevotion(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}"); - // Create five 1/1 white Human creature tokens. If Increasing Devotion was cast from a graveyard, create ten of those tokens instead. + // Create five 1/1 white Human creature tokens. If this spell was cast from a graveyard, create ten of those tokens instead. this.getSpellAbility().addEffect(new IncreasingDevotionEffect()); // Flashback {7}{W}{W} @@ -48,7 +48,7 @@ class IncreasingDevotionEffect extends OneShotEffect { public IncreasingDevotionEffect() { super(Outcome.PutCreatureInPlay); - staticText = "Create five 1/1 white Human creature tokens. If {this} was cast from a graveyard, create ten of those tokens instead"; + staticText = "Create five 1/1 white Human creature tokens. If this spell was cast from a graveyard, create ten of those tokens instead"; } public IncreasingDevotionEffect(final IncreasingDevotionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java b/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java index 898083bedc8..82cf03b321e 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingSavagery.java @@ -25,7 +25,7 @@ public final class IncreasingSavagery extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}{G}"); - // Put five +1/+1 counters on target creature. If Increasing Savagery was cast from a graveyard, put ten +1/+1 counters on that creature instead. + // Put five +1/+1 counters on target creature. If this spell was cast from a graveyard, put ten +1/+1 counters on that creature instead. this.getSpellAbility().addEffect(new IncreasingSavageryEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -47,7 +47,7 @@ class IncreasingSavageryEffect extends OneShotEffect { public IncreasingSavageryEffect() { super(Outcome.BoostCreature); - staticText = "Put five +1/+1 counters on target creature. If Increasing Savagery was cast from a graveyard, put ten +1/+1 counters on that creature instead"; + staticText = "Put five +1/+1 counters on target creature. If this spell was cast from a graveyard, put ten +1/+1 counters on that creature instead"; } public IncreasingSavageryEffect(final IncreasingSavageryEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java b/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java index b9966b8a7e9..11e1d70dbb4 100644 --- a/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java +++ b/Mage.Sets/src/mage/cards/i/IncreasingVengeance.java @@ -38,7 +38,7 @@ public final class IncreasingVengeance extends CardImpl { public IncreasingVengeance(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}{R}"); - // Copy target instant or sorcery spell you control. If Increasing Vengeance was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies. + // Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies. this.getSpellAbility().addEffect(new IncreasingVengeanceEffect()); Target target = new TargetSpell(filter); this.getSpellAbility().addTarget(target); @@ -61,7 +61,7 @@ class IncreasingVengeanceEffect extends OneShotEffect { public IncreasingVengeanceEffect() { super(Outcome.BoostCreature); - staticText = "Copy target instant or sorcery spell you control. If Increasing Vengeance was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies"; + staticText = "Copy target instant or sorcery spell you control. If this spell was cast from a graveyard, copy that spell twice instead. You may choose new targets for the copies"; } public IncreasingVengeanceEffect(final IncreasingVengeanceEffect effect) { @@ -75,14 +75,14 @@ class IncreasingVengeanceEffect extends OneShotEffect { Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source)); if (spell != null) { StackObject stackObjectCopy = spell.createCopyOnStack(game, source, source.getControllerId(), true); - if (stackObjectCopy != null && stackObjectCopy instanceof Spell) { + if (stackObjectCopy instanceof Spell) { game.informPlayers(new StringBuilder(controller.getLogName()).append(((Spell) stackObjectCopy).getActivatedMessage(game)).toString()); } Spell sourceSpell = (Spell) game.getStack().getStackObject(source.getSourceId()); if (sourceSpell != null) { if (sourceSpell.getFromZone() == Zone.GRAVEYARD) { stackObjectCopy = spell.createCopyOnStack(game, source, source.getControllerId(), true); - if (stackObjectCopy != null && stackObjectCopy instanceof Spell) { + if (stackObjectCopy instanceof Spell) { game.informPlayers(new StringBuilder(controller.getLogName()).append(((Spell) stackObjectCopy).getActivatedMessage(game)).toString()); } } diff --git a/Mage.Sets/src/mage/cards/i/IndomitableArchangel.java b/Mage.Sets/src/mage/cards/i/IndomitableArchangel.java index edc9cec8cb2..2a1e889e73d 100644 --- a/Mage.Sets/src/mage/cards/i/IndomitableArchangel.java +++ b/Mage.Sets/src/mage/cards/i/IndomitableArchangel.java @@ -25,7 +25,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public final class IndomitableArchangel extends CardImpl { - private static final String rule = "Metalcraft - Artifacts you control have shroud as long as you control three or more artifacts."; + private static final String rule = "Metalcraft — Artifacts you control have shroud as long as you control three or more artifacts."; private static final FilterPermanent filter = new FilterPermanent("Artifacts"); diff --git a/Mage.Sets/src/mage/cards/i/InexorableBlob.java b/Mage.Sets/src/mage/cards/i/InexorableBlob.java index 1eeaa64850e..2d2a1d64eff 100644 --- a/Mage.Sets/src/mage/cards/i/InexorableBlob.java +++ b/Mage.Sets/src/mage/cards/i/InexorableBlob.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,9 +25,9 @@ public final class InexorableBlob extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - // Delirium — Whenever Inexorable Blob attacks and there are at least four card types among cards in your graveyard, - // create a 3/3 green Ooze creature token tapped and attacking. - this.addAbility(new ConditionalTriggeredAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new InexorableBlobOozeToken(), 1, true, true), false), + // Delirium — Whenever Inexorable Blob attacks, if there are four or more card types among cards + // in your graveyard, create a 3/3 green Ooze creature token that’s tapped and attacking. + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new InexorableBlobOozeToken(), 1, true, true), false), DeliriumCondition.instance, "Delirium — Whenever {this} attacks and there are at least four card types among cards in your graveyard, " + "create a 3/3 green Ooze creature token tapped and attacking.")); diff --git a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java index c1a5a54fdcc..555dc866bd6 100644 --- a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java +++ b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java @@ -87,7 +87,7 @@ class InfectiousCurseAbility extends TriggeredAbilityImpl { Permanent enchantment = game.getPermanent(this.sourceId); if (enchantment != null && enchantment.getAttachedTo() != null) { Player player = game.getPlayer(enchantment.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId())) { + if (player != null && game.isActivePlayer(player.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); return true; } @@ -122,7 +122,7 @@ class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (source.getControllerId().equals(abilityToModify.getControllerId())) { + if (source.isControlledBy(abilityToModify.getControllerId())) { for (UUID modeId : abilityToModify.getModes().getSelectedModes()) { Mode mode = abilityToModify.getModes().get(modeId); for (Target target : mode.getTargets()) { diff --git a/Mage.Sets/src/mage/cards/i/InfernalReckoning.java b/Mage.Sets/src/mage/cards/i/InfernalReckoning.java new file mode 100644 index 00000000000..6c2a2146024 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InfernalReckoning.java @@ -0,0 +1,76 @@ +package mage.cards.i; + +import java.util.UUID; +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.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorlessPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class InfernalReckoning extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("colorless creature"); + + static { + filter.add(new ColorlessPredicate()); + } + + public InfernalReckoning(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); + + // Exile target colorless creature. You gain life equal to its power. + this.getSpellAbility().addEffect(new InfernalJudgmentEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public InfernalReckoning(final InfernalReckoning card) { + super(card); + } + + @Override + public InfernalReckoning copy() { + return new InfernalReckoning(this); + } +} + +class InfernalJudgmentEffect extends OneShotEffect { + + public InfernalJudgmentEffect() { + super(Outcome.GainLife); + staticText = "exile target colorless creature. You gain life equal to its power"; + } + + public InfernalJudgmentEffect(final InfernalJudgmentEffect effect) { + super(effect); + } + + @Override + public InfernalJudgmentEffect copy() { + return new InfernalJudgmentEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + Player player = game.getPlayer(source.getControllerId()); + if (permanent == null || player == null) { + return false; + } + int creaturePower = permanent.getPower().getValue(); + permanent.moveToExile(null, null, source.getSourceId(), game); + game.applyEffects(); + player.gainLife(creaturePower, game, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/i/InfernalTutor.java b/Mage.Sets/src/mage/cards/i/InfernalTutor.java index bae25f79701..eb4b152f66a 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalTutor.java +++ b/Mage.Sets/src/mage/cards/i/InfernalTutor.java @@ -1,4 +1,3 @@ - package mage.cards.i; import java.util.UUID; @@ -17,6 +16,7 @@ import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.FilterCard; +import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.players.Player; @@ -37,7 +37,7 @@ public final class InfernalTutor extends CardImpl { this.getSpellAbility().addEffect(new InfernalTutorEffect()); // Hellbent - If you have no cards in hand, instead search your library for a card, put it into your hand, then shuffle your library. Effect effect = new ConditionalOneShotEffect( - new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterCard()), false, true), + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD), false, true), HellbentCondition.instance, "

Hellbent — If you have no cards in hand, instead search your library for a card, put it into your hand, then shuffle your library"); this.getSpellAbility().addEffect(effect); @@ -78,7 +78,7 @@ class InfernalTutorEffect extends OneShotEffect { if (!controller.getHand().isEmpty()) { Card cardToReveal = null; if (controller.getHand().size() > 1) { - Target target = new TargetCardInHand(new FilterCard()); + Target target = new TargetCardInHand(StaticFilters.FILTER_CARD); target.setNotTarget(true); if (controller.chooseTarget(outcome, target, source, game)) { cardToReveal = game.getCard(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/i/InfernoHellion.java b/Mage.Sets/src/mage/cards/i/InfernoHellion.java new file mode 100644 index 00000000000..ed2b3254f70 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InfernoHellion.java @@ -0,0 +1,78 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.watchers.common.AttackedThisTurnWatcher; +import mage.watchers.common.BlockedThisTurnWatcher; + +/** + * + * @author TheElk801 + */ +public final class InfernoHellion extends CardImpl { + + public InfernoHellion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.HELLION); + this.power = new MageInt(7); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // At the beginning of each end step, if Inferno Hellion attacked or blocked this turn, its owner shuffles it into their library. + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new BeginningOfEndStepTriggeredAbility( + new ShuffleIntoLibrarySourceEffect(), + TargetController.ANY, false + ), + InfernoHellionCondition.instance, + "At the beginning of each end step, " + + "if {this} attacked or blocked this turn, " + + "its owner shuffles it into their library." + ); + ability.addWatcher(new AttackedThisTurnWatcher()); + ability.addWatcher(new BlockedThisTurnWatcher()); + this.addAbility(ability); + } + + public InfernoHellion(final InfernoHellion card) { + super(card); + } + + @Override + public InfernoHellion copy() { + return new InfernoHellion(this); + } +} + +enum InfernoHellionCondition implements Condition { + + instance; + + @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()); + MageObjectReference mor = new MageObjectReference(source.getSourceId(), game); + if (watcherAttacked == null || watcherBlocked == null) { + return false; + } + return watcherAttacked.getAttackedThisTurnCreatures().contains(mor) + || watcherBlocked.getBlockedThisTurnCreatures().contains(mor); + } +} diff --git a/Mage.Sets/src/mage/cards/i/InfiniteReflection.java b/Mage.Sets/src/mage/cards/i/InfiniteReflection.java index 597a9f36eac..50643266bae 100644 --- a/Mage.Sets/src/mage/cards/i/InfiniteReflection.java +++ b/Mage.Sets/src/mage/cards/i/InfiniteReflection.java @@ -117,7 +117,7 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - return permanent != null && permanent.getControllerId().equals(source.getControllerId()) + return permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.isCreature() && !(permanent instanceof PermanentToken); } diff --git a/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java b/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java index 0f4759bab34..3628872503c 100644 --- a/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java +++ b/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java @@ -1,27 +1,25 @@ - package mage.cards.i; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.NinjutsuAbility; -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.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; @@ -32,7 +30,7 @@ import mage.target.common.TargetCardInGraveyard; public final class InkEyesServantOfOni extends CardImpl { public InkEyesServantOfOni(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.RAT); this.subtype.add(SubType.NINJA); addSuperType(SuperType.LEGENDARY); @@ -44,7 +42,7 @@ public final class InkEyesServantOfOni extends CardImpl { this.addAbility(new NinjutsuAbility(new ManaCostsImpl("{3}{B}{B}"))); // Whenever Ink-Eyes, Servant of Oni deals combat damage to a player, you may put target creature card from that player's graveyard onto the battlefield under your control. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new InkEyesServantOfOniEffect(), true, true)); + this.addAbility(new InkEyesServantOfOniTriggeredAbility()); // {1}{B}: Regenerate Ink-Eyes. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{B}"))); @@ -60,39 +58,48 @@ public final class InkEyesServantOfOni extends CardImpl { } } -class InkEyesServantOfOniEffect extends OneShotEffect { +class InkEyesServantOfOniTriggeredAbility extends TriggeredAbilityImpl { - public InkEyesServantOfOniEffect() { - super(Outcome.PutCreatureInPlay); - this.staticText = "you may put target creature card from that player's graveyard onto the battlefield under your control"; + public InkEyesServantOfOniTriggeredAbility() { + super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), true); } - public InkEyesServantOfOniEffect(final InkEyesServantOfOniEffect effect) { - super(effect); + public InkEyesServantOfOniTriggeredAbility(final InkEyesServantOfOniTriggeredAbility ability) { + super(ability); } @Override - public InkEyesServantOfOniEffect copy() { - return new InkEyesServantOfOniEffect(this); + public InkEyesServantOfOniTriggeredAbility copy() { + return new InkEyesServantOfOniTriggeredAbility(this); } @Override - public boolean apply(Game game, Ability source) { - Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - Player you = game.getPlayer(source.getControllerId()); - FilterCard filter = new FilterCard("creature in that player's graveyard"); + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterCard("creature in " + damagedPlayer.getName() + "'s graveyard"); filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new OwnerIdPredicate(damagedPlayer.getId())); TargetCardInGraveyard target = new TargetCardInGraveyard(filter); - if (target.canChoose(source.getSourceId(), you.getId(), game)) { - if (you.chooseTarget(Outcome.PutCreatureInPlay, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - you.moveCards(card, Zone.BATTLEFIELD, source, game); - return true; - } - } - } - return false; + this.getTargets().clear(); + this.addTarget(target); + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may put target creature card from that player's " + + "graveyard onto the battlefield under your control"; } } diff --git a/Mage.Sets/src/mage/cards/i/InnerDemon.java b/Mage.Sets/src/mage/cards/i/InnerDemon.java index 72615de8c56..621e2c52fd6 100644 --- a/Mage.Sets/src/mage/cards/i/InnerDemon.java +++ b/Mage.Sets/src/mage/cards/i/InnerDemon.java @@ -57,7 +57,7 @@ public final class InnerDemon extends CardImpl { effect.setText(", has flying"); ability.addEffect(effect); effect = new AddCardSubtypeAttachedEffect(SubType.DEMON, Duration.WhileOnBattlefield, AttachmentType.AURA); - effect.setText(", and is an Demon in addition to its other types"); + effect.setText(", and is a Demon in addition to its other types"); ability.addEffect(effect); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/i/InsidiousWill.java b/Mage.Sets/src/mage/cards/i/InsidiousWill.java index 92351aee006..48904be3766 100644 --- a/Mage.Sets/src/mage/cards/i/InsidiousWill.java +++ b/Mage.Sets/src/mage/cards/i/InsidiousWill.java @@ -38,7 +38,7 @@ public final class InsidiousWill extends CardImpl { // Copy target instant or sorcery spell. You may choose new targets for the copy. mode = new Mode(); mode.getEffects().add(new CopyTargetSpellEffect()); - mode.getTargets().add(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + mode.getTargets().add(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.getSpellAbility().getModes().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/i/Insist.java b/Mage.Sets/src/mage/cards/i/Insist.java index e312208e106..5c79086b5ef 100644 --- a/Mage.Sets/src/mage/cards/i/Insist.java +++ b/Mage.Sets/src/mage/cards/i/Insist.java @@ -26,7 +26,7 @@ public final class Insist extends CardImpl { public Insist(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); - // The next creature spell you cast this turn can't be countered by spells or abilities. + // The next creature spell you cast this turn can't be countered. this.getSpellAbility().addEffect(new InsistEffect()); this.getSpellAbility().addWatcher(new InsistWatcher()); @@ -50,7 +50,7 @@ class InsistEffect extends ContinuousRuleModifyingEffectImpl { InsistEffect() { super(Duration.EndOfTurn, Outcome.Benefit); - staticText = "The next creature spell you cast this turn can't be countered by spells or abilities"; + staticText = "The next creature spell you cast this turn can't be countered"; } InsistEffect(final InsistEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/Inspire.java b/Mage.Sets/src/mage/cards/i/Inspire.java new file mode 100644 index 00000000000..05aeea299b0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/Inspire.java @@ -0,0 +1,39 @@ +package mage.cards.i; + +import java.util.UUID; + +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Inspire extends CardImpl { + + public Inspire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + + // Untap target creature. + this.getSpellAbility().addEffect(new UntapTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public Inspire(final Inspire card) { + super(card); + } + + @Override + public Inspire copy() { + return new Inspire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/InstigatorGang.java b/Mage.Sets/src/mage/cards/i/InstigatorGang.java index e8ed7864c4f..acd165ce41e 100644 --- a/Mage.Sets/src/mage/cards/i/InstigatorGang.java +++ b/Mage.Sets/src/mage/cards/i/InstigatorGang.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.TransformAbility; @@ -44,7 +44,7 @@ public final class InstigatorGang extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Instigator Gang. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public InstigatorGang(final InstigatorGang card) { diff --git a/Mage.Sets/src/mage/cards/i/InstillEnergy.java b/Mage.Sets/src/mage/cards/i/InstillEnergy.java index f884141e318..a1c89de4009 100644 --- a/Mage.Sets/src/mage/cards/i/InstillEnergy.java +++ b/Mage.Sets/src/mage/cards/i/InstillEnergy.java @@ -80,6 +80,6 @@ class CanAttackAsThoughItHadHasteEnchantedEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - return enchantment != null && enchantment.getAttachedTo() != null && enchantment.getAttachedTo().equals(objectId); + return enchantment != null && enchantment.isAttachedTo(objectId); } } diff --git a/Mage.Sets/src/mage/cards/i/Interdict.java b/Mage.Sets/src/mage/cards/i/Interdict.java index ab43941f2af..0e590cd6d30 100644 --- a/Mage.Sets/src/mage/cards/i/Interdict.java +++ b/Mage.Sets/src/mage/cards/i/Interdict.java @@ -19,6 +19,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; +import mage.target.common.TargetActivatedAbility; import mage.target.common.TargetActivatedOrTriggeredAbility; import mage.target.targetpointer.FixedTarget; @@ -39,7 +40,7 @@ public final class Interdict extends CardImpl { // Counter target activated ability from an artifact, creature, enchantment, or land. That permanent's activated abilities can't be activated this turn. this.getSpellAbility().addEffect(new InterdictCounterEffect()); - this.getSpellAbility().addTarget(new TargetActivatedOrTriggeredAbility(filter)); + this.getSpellAbility().addTarget(new TargetActivatedAbility(filter)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).setText("

Draw a card")); @@ -55,15 +56,15 @@ public final class Interdict extends CardImpl { } } -class InterdictPredicate implements Predicate { +class InterdictPredicate implements Predicate { public InterdictPredicate() { } @Override - public boolean apply(Ability input, Game game) { - if (input instanceof StackAbility && input.getAbilityType() == AbilityType.ACTIVATED) { - MageObject sourceObject = input.getSourceObject(game); + public boolean apply(StackObject input, Game game) { + if (input instanceof StackAbility && ((StackAbility) input).getAbilityType() == AbilityType.ACTIVATED) { + MageObject sourceObject = ((StackAbility) input).getSourceObject(game); if (sourceObject != null) { return (sourceObject.isArtifact() || sourceObject.isEnchantment() diff --git a/Mage.Sets/src/mage/cards/i/IreShaman.java b/Mage.Sets/src/mage/cards/i/IreShaman.java index cc7055ab6f7..8d0cbda7bca 100644 --- a/Mage.Sets/src/mage/cards/i/IreShaman.java +++ b/Mage.Sets/src/mage/cards/i/IreShaman.java @@ -115,7 +115,7 @@ class IreShamanCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java b/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java index 152169b6da6..60232b0c503 100644 --- a/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java +++ b/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; @@ -28,7 +28,7 @@ public final class IronFistOfTheEmpire extends CardImpl { // Hate — At the beggining of each end step, if opponent lost life from a source other than combat damage this turn, you gain 2 life and create a 2/2 red Soldier creature token with first strike name Royal Guard. TriggeredAbility triggeredAbility = new BeginningOfEndStepTriggeredAbility(new GainLifeEffect(2), TargetController.ANY, false); triggeredAbility.addEffect(new CreateTokenEffect(new RoyalGuardToken())); - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( triggeredAbility, HateCondition.instance, "Hate — At the beggining of each end step, if opponent lost life from a source other than combat damage this turn, you gain 1 life and create a 2/2 red Soldier creature token with first strike named Royal Guard."); diff --git a/Mage.Sets/src/mage/cards/i/Ironfang.java b/Mage.Sets/src/mage/cards/i/Ironfang.java index 1b5bc3b5c33..3f286f4a346 100644 --- a/Mage.Sets/src/mage/cards/i/Ironfang.java +++ b/Mage.Sets/src/mage/cards/i/Ironfang.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TransformAbility; @@ -37,7 +37,7 @@ public final class Ironfang extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ironfang. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public Ironfang(final Ironfang card) { diff --git a/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java b/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java new file mode 100644 index 00000000000..62cf6c7eff7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java @@ -0,0 +1,223 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.SendOptionUsedEventEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.Card; +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.counters.CounterType; +import mage.counters.Counters; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author TheElk801 + */ +public final class IsarethTheAwakener extends CardImpl { + + public IsarethTheAwakener(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Whenever Isareth the Awakener attacks, you may pay {X}. When you do, return target creature card with converted mana cost X from your graveyard to the battlefield with a corpse counter on it. If that creature would leave the battlefield, exile it instead of putting it anywhere else. + this.addAbility(new AttacksTriggeredAbility(new IsarethTheAwakenerCreateReflexiveTriggerEffect(), false)); + } + + public IsarethTheAwakener(final IsarethTheAwakener card) { + super(card); + } + + @Override + public IsarethTheAwakener copy() { + return new IsarethTheAwakener(this); + } +} + +class IsarethTheAwakenerCreateReflexiveTriggerEffect extends OneShotEffect { + + public IsarethTheAwakenerCreateReflexiveTriggerEffect() { + super(Outcome.Benefit); + this.staticText = "you may pay {X}. When you do, return target creature card " + + "with converted mana cost X from your graveyard to the battlefield " + + "with a corpse counter on it. If that creature would leave the battlefield, " + + "exile it instead of putting it anywhere else."; + } + + public IsarethTheAwakenerCreateReflexiveTriggerEffect(final IsarethTheAwakenerCreateReflexiveTriggerEffect effect) { + super(effect); + } + + @Override + public IsarethTheAwakenerCreateReflexiveTriggerEffect copy() { + return new IsarethTheAwakenerCreateReflexiveTriggerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + ManaCosts cost = new ManaCostsImpl("{X}"); + if (player == null + || !player.chooseUse(Outcome.BoostCreature, "Pay " + cost.getText() + "?", source, game)) { + return false; + } + int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source); + cost.add(new GenericManaCost(costX)); + if (!cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { + return false; + } + game.addDelayedTriggeredAbility(new IsarethTheAwakenerReflexiveTriggeredAbility(), source); + return new SendOptionUsedEventEffect(costX).apply(game, source); + } +} + +class IsarethTheAwakenerReflexiveTriggeredAbility extends DelayedTriggeredAbility { + + public IsarethTheAwakenerReflexiveTriggeredAbility() { + super(new IsarethTheAwakenerEffect(), Duration.OneUse, true); + this.addEffect(new IsarethTheAwakenerReplacementEffect()); + } + + public IsarethTheAwakenerReflexiveTriggeredAbility(final IsarethTheAwakenerReflexiveTriggeredAbility ability) { + super(ability); + } + + @Override + public IsarethTheAwakenerReflexiveTriggeredAbility copy() { + return new IsarethTheAwakenerReflexiveTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.OPTION_USED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getPlayerId().equals(this.getControllerId()) + || !event.getSourceId().equals(this.getSourceId())) { + return false; + } + FilterCard filter = new FilterCreatureCard( + "creature card with converted mana cost " + + event.getAmount() + + " or less from your graveyard" + ); + filter.add(new ConvertedManaCostPredicate( + ComparisonType.FEWER_THAN, event.getAmount() + 1 + )); + this.getTargets().clear(); + this.addTarget(new TargetCardInYourGraveyard(filter)); + return true; + } + + @Override + public String getRule() { + return "When you pay {X}, return target creature card " + + "with converted mana cost X from your graveyard to the battlefield " + + "with a corpse counter on it. If that creature would leave the battlefield, " + + "exile it instead of putting it anywhere else."; + } +} + +class IsarethTheAwakenerEffect extends OneShotEffect { + + public IsarethTheAwakenerEffect() { + super(Outcome.PutCreatureInPlay); + } + + public IsarethTheAwakenerEffect(final IsarethTheAwakenerEffect effect) { + super(effect); + } + + @Override + public IsarethTheAwakenerEffect copy() { + return new IsarethTheAwakenerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || card == null) { + return false; + } + Counters countersToAdd = new Counters(); + countersToAdd.addCounter(CounterType.CORPSE.createInstance()); + game.setEnterWithCounters(source.getSourceId(), countersToAdd); + return controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } +} + +class IsarethTheAwakenerReplacementEffect extends ReplacementEffectImpl { + + public IsarethTheAwakenerReplacementEffect() { + super(Duration.Custom, Outcome.Exile); + } + + public IsarethTheAwakenerReplacementEffect(final IsarethTheAwakenerReplacementEffect effect) { + super(effect); + } + + @Override + public IsarethTheAwakenerReplacementEffect copy() { + return new IsarethTheAwakenerReplacementEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + ((ZoneChangeEvent) event).setToZone(Zone.EXILED); + 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) { + if (event.getTargetId().equals(source.getFirstTarget()) + && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD + && ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) { + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java b/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java index 4a9b01705ad..c130b759ab2 100644 --- a/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java +++ b/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java @@ -8,7 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; @@ -48,7 +48,7 @@ public final class IshkanahGrafwidow extends CardImpl { // Delirium &mdash When Ishkanah, Grafwidow enters the battlefield, if there are four or more card types among cards in your graveyard, // create three 1/2 green Spider creature tokens with reach. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiderToken(), 3), false), DeliriumCondition.instance, "Delirium — When {this} enters the battlefield, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/i/IslandSanctuary.java b/Mage.Sets/src/mage/cards/i/IslandSanctuary.java index 6cec4f2d425..aabf94d6899 100644 --- a/Mage.Sets/src/mage/cards/i/IslandSanctuary.java +++ b/Mage.Sets/src/mage/cards/i/IslandSanctuary.java @@ -81,7 +81,7 @@ class IslandSanctuaryEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()) && game.getTurn().getStepType() == PhaseStep.DRAW; + return source.isControlledBy(event.getPlayerId()) && game.getTurn().getStepType() == PhaseStep.DRAW; } @Override diff --git a/Mage.Sets/src/mage/cards/i/Isolate.java b/Mage.Sets/src/mage/cards/i/Isolate.java new file mode 100644 index 00000000000..a1276405f69 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/Isolate.java @@ -0,0 +1,41 @@ +package mage.cards.i; + +import java.util.UUID; +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.predicate.mageobject.ConvertedManaCostPredicate; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class Isolate extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("permanent with converted mana cost 1"); + + static { + filter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, 1)); + } + + public Isolate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + // Exile target permanent with converted mana cost 1. + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + } + + public Isolate(final Isolate card) { + super(card); + } + + @Override + public Isolate copy() { + return new Isolate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java b/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java new file mode 100644 index 00000000000..e21c382fbd7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java @@ -0,0 +1,118 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.Card; +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.StaticFilters; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class IsolatedWatchtower extends CardImpl { + + public IsolatedWatchtower(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {2}, {T}: Scry 1, then you may reveal the top card of your library. If a basic land card is revealed this way, put it onto the battlefield tapped. Activate this ability only if an opponent controls at least two more lands than you. + Ability ability = new ConditionalActivatedAbility( + Zone.BATTLEFIELD, + new IsolatedWatchtowerEffect(), + new GenericManaCost(2), + new IsolatedWatchtowerCondition() + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public IsolatedWatchtower(final IsolatedWatchtower card) { + super(card); + } + + @Override + public IsolatedWatchtower copy() { + return new IsolatedWatchtower(this); + } +} + +class IsolatedWatchtowerEffect extends OneShotEffect { + + public IsolatedWatchtowerEffect() { + super(Outcome.Benefit); + this.staticText = "scry 1, then you may reveal the top card " + + "of your library. If a basic land card is revealed this way, " + + "put it onto the battlefield tapped"; + } + + public IsolatedWatchtowerEffect(final IsolatedWatchtowerEffect effect) { + super(effect); + } + + @Override + public IsolatedWatchtowerEffect copy() { + return new IsolatedWatchtowerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + player.scry(1, source, game); + if (!player.chooseUse( + outcome, "Reveal the top card of your library?", source, game + )) { + return true; + } + Card card = player.getLibrary().getFromTop(game); + player.revealCards(source, new CardsImpl(card), game); + if (card.isBasic() && card.isLand()) { + player.moveCards( + card, Zone.BATTLEFIELD, source, + game, true, false, true, null + ); + } + return true; + } +} + +class IsolatedWatchtowerCondition implements Condition { + + @Override + public boolean apply(Game game, Ability source) { + int numLands = game.getBattlefield().countAll( + StaticFilters.FILTER_LAND, source.getControllerId(), game + ); + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + if (numLands + 2 <= game.getBattlefield().countAll( + StaticFilters.FILTER_LAND, opponentId, game + )) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "an opponent controls at least two more lands than you"; + } +} diff --git a/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java b/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java index 780652d79af..e417bed22c9 100644 --- a/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java +++ b/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; @@ -41,7 +41,7 @@ public final class IsperiaTheInscrutable extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Isperia the Inscrutable deals combat damage to a player, name a card. That player reveals their hand. If he or she reveals the named card, search your library for a creature card with flying, reveal it, put it into your hand, then shuffle your library. - Effect effect1 = new NameACardEffect(NameACardEffect.TypeOfName.ALL); + Effect effect1 = new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL); Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(effect1, false, true); Effect effect2 = new IsperiaTheInscrutableEffect(); ability.addEffect(effect2); @@ -69,7 +69,7 @@ class IsperiaTheInscrutableEffect extends OneShotEffect { public IsperiaTheInscrutableEffect() { super(Outcome.Neutral); - staticText = "That player reveals their hand. If he or she reveals the named card, search your library for a creature card with flying, reveal it, put it into your hand, then shuffle your library"; + staticText = "That player reveals their hand. If a card with the chosen name is revealed this way, search your library for a creature card with flying, reveal it, put it into your hand, then shuffle your library"; } public IsperiaTheInscrutableEffect(final IsperiaTheInscrutableEffect effect) { @@ -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() + NameACardEffect.INFO_KEY); + Object object = (String) 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; @@ -94,7 +94,7 @@ class IsperiaTheInscrutableEffect extends OneShotEffect { } @Override - public Effect copy() { + public IsperiaTheInscrutableEffect copy() { return new IsperiaTheInscrutableEffect(this); } } diff --git a/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java b/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java index 36b0c37501a..aad52a0c1fa 100644 --- a/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java +++ b/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -26,7 +26,7 @@ public final class IvoryCraneNetsuke extends CardImpl { // At the beginning of your upkeep, if you have seven or more cards in hand, you gain 4 life. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(4), TargetController.YOU, false); CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 6); - this.addAbility(new ConditionalTriggeredAbility(ability, condition, "At the beginning of your upkeep, if you have seven or more cards in hand, you gain 4 life.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, "At the beginning of your upkeep, if you have seven or more cards in hand, you gain 4 life.")); } diff --git a/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java b/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java new file mode 100644 index 00000000000..0cd6c5e37d4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java @@ -0,0 +1,54 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; +import mage.abilities.effects.common.SkipNextDrawStepControllerEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author noahg + */ +public final class IvoryGargoyle extends CardImpl { + + public IvoryGargoyle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); + + this.subtype.add(SubType.GARGOYLE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Ivory Gargoyle dies, return it to the battlefield under its owner's control at the beginning of the next end step and you skip your next draw step. + Ability ability = new DiesTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect()))); + ability.addEffect(new SkipNextDrawStepControllerEffect()); + this.addAbility(ability); + + // {4}{W}: Exile Ivory Gargoyle. + this.addAbility(new SimpleActivatedAbility(new ExileSourceEffect(), new ManaCostsImpl("{4}{W}"))); + } + + public IvoryGargoyle(final IvoryGargoyle card) { + super(card); + } + + @Override + public IvoryGargoyle copy() { + return new IvoryGargoyle(this); + } +} diff --git a/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java b/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java index 639950af6b6..efd444476fe 100644 --- a/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java +++ b/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java @@ -134,7 +134,7 @@ class JaceArchitectOfThoughtDelayedTriggeredAbility extends DelayedTriggeredAbil @Override public boolean isInactive(Game game) { - return game.getActivePlayerId().equals(getControllerId()) && game.getTurnNum() != startingTurn; + return game.isActivePlayer(getControllerId()) && game.getTurnNum() != startingTurn; } @Override @@ -242,7 +242,7 @@ class JaceArchitectOfThoughtEffect3 extends OneShotEffect { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); String playerName = new StringBuilder(player.getLogName()).append("'s").toString(); - if (source.getControllerId().equals(player.getId())) { + if (source.isControlledBy(player.getId())) { playerName = "your"; } TargetCardInLibrary target = new TargetCardInLibrary(new FilterNonlandCard(new StringBuilder("nonland card from ").append(playerName).append(" library").toString())); diff --git a/Mage.Sets/src/mage/cards/j/JaceCunningCastaway.java b/Mage.Sets/src/mage/cards/j/JaceCunningCastaway.java index 160baea0769..e5b52f876da 100644 --- a/Mage.Sets/src/mage/cards/j/JaceCunningCastaway.java +++ b/Mage.Sets/src/mage/cards/j/JaceCunningCastaway.java @@ -112,7 +112,7 @@ class JaceCunningCastawayDamageTriggeredAbility extends DelayedTriggeredAbility if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId) + if (creature != null && creature.isControlledBy(controllerId) && !damagedPlayerIds.contains(event.getTargetId())) { damagedPlayerIds.add(event.getTargetId()); return true; diff --git a/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java b/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java index d2a30b37c56..bf09d707176 100644 --- a/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java +++ b/Mage.Sets/src/mage/cards/j/JaceTheLivingGuildpact.java @@ -1,4 +1,3 @@ - package mage.cards.j; import java.util.UUID; @@ -55,6 +54,7 @@ public final class JaceTheLivingGuildpact extends CardImpl { // -8: Each player shuffles their hand and graveyard into their library. You draw seven cards. ability = new LoyaltyAbility(new ShuffleHandGraveyardAllEffect(), -8); ability.addEffect(new DrawCardSourceControllerEffect(7).setText("You draw seven cards")); + this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JaggedPoppet.java b/Mage.Sets/src/mage/cards/j/JaggedPoppet.java index 28bc808cdbc..00203c6848b 100644 --- a/Mage.Sets/src/mage/cards/j/JaggedPoppet.java +++ b/Mage.Sets/src/mage/cards/j/JaggedPoppet.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealtDamageToSourceTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class JaggedPoppet extends CardImpl { this.addAbility(new DealtDamageToSourceTriggeredAbility(Zone.BATTLEFIELD, new JaggedPoppetDealtDamageEffect(), false, false, true)); // Hellbent - Whenever Jagged Poppet deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage. - Ability hellbentAbility = new ConditionalTriggeredAbility( + Ability hellbentAbility = new ConditionalInterveningIfTriggeredAbility( new DealsCombatDamageToAPlayerTriggeredAbility(new JaggedPoppetDealsDamageEffect(), false, true), HellbentCondition.instance, "Hellbent — Whenever {this} deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage."); diff --git a/Mage.Sets/src/mage/cards/j/JarOfEyeballs.java b/Mage.Sets/src/mage/cards/j/JarOfEyeballs.java index f8076da878f..5ea98a196fc 100644 --- a/Mage.Sets/src/mage/cards/j/JarOfEyeballs.java +++ b/Mage.Sets/src/mage/cards/j/JarOfEyeballs.java @@ -83,7 +83,7 @@ class JarOfEyeballsTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { + if (permanent.isControlledBy(this.getControllerId()) && permanent.isCreature()) { return true; } } diff --git a/Mage.Sets/src/mage/cards/j/JasmineSeer.java b/Mage.Sets/src/mage/cards/j/JasmineSeer.java index fde4f020ddb..ac55a63b3f6 100644 --- a/Mage.Sets/src/mage/cards/j/JasmineSeer.java +++ b/Mage.Sets/src/mage/cards/j/JasmineSeer.java @@ -10,11 +10,11 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; @@ -35,7 +35,7 @@ public final class JasmineSeer extends CardImpl { this.toughness = new MageInt(1); // {2}{W}, {tap}: Reveal any number of white cards in your hand. You gain 2 life for each card revealed this way. - Ability ability = new SimpleActivatedAbility(new JasmineSeerEffect(), new ManaCostsImpl("{2}{WF}")); + Ability ability = new SimpleActivatedAbility(new JasmineSeerEffect(), new ManaCostsImpl("{2}{W}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java b/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java index 8240592a9e7..b1e6320f946 100644 --- a/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java +++ b/Mage.Sets/src/mage/cards/j/JayasImmolatingInferno.java @@ -24,7 +24,7 @@ public final class JayasImmolatingInferno extends CardImpl { // (You may cast a legendary sorcery only if you control a legendary creature or planeswalker.) this.addAbility(new LegendarySpellAbility()); - // Jaya’s Immolating Inferno deals X damage to each of up to three targets. + // Jaya's Immolating Inferno deals X damage to each of up to three targets. Effect effect = new DamageTargetEffect(new ManacostVariableValue()); effect.setText("{this} deals X damage to each of up to three targets"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/j/JeeringInstigator.java b/Mage.Sets/src/mage/cards/j/JeeringInstigator.java index 182b5a8577a..d0c8ab237b8 100644 --- a/Mage.Sets/src/mage/cards/j/JeeringInstigator.java +++ b/Mage.Sets/src/mage/cards/j/JeeringInstigator.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; @@ -46,7 +46,7 @@ public final class JeeringInstigator extends CardImpl { this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{2}{R}"))); // When Jeering Instigator is turned face up, if it's your turn, gain control of another target creature until end of turn. Untap it. That creature gains haste until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new TurnedFaceUpSourceTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn),false, false), MyTurnCondition.instance, "When {this} is turned face up, if it's your turn, gain control of another target creature until end of turn. Untap that creature. It gains haste until end of turn."); diff --git a/Mage.Sets/src/mage/cards/j/Jokulmorder.java b/Mage.Sets/src/mage/cards/j/Jokulmorder.java index 5ce19758477..dfe4138831a 100644 --- a/Mage.Sets/src/mage/cards/j/Jokulmorder.java +++ b/Mage.Sets/src/mage/cards/j/Jokulmorder.java @@ -86,7 +86,7 @@ class JokulmorderTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent land = game.getPermanent(event.getTargetId()); return land.hasSubtype(SubType.ISLAND, game) - && land.getControllerId().equals(this.controllerId); + && land.isControlledBy(this.controllerId); } @Override diff --git a/Mage.Sets/src/mage/cards/j/JorKadeenThePrevailer.java b/Mage.Sets/src/mage/cards/j/JorKadeenThePrevailer.java index 19cde3a53bf..0a9910044d7 100644 --- a/Mage.Sets/src/mage/cards/j/JorKadeenThePrevailer.java +++ b/Mage.Sets/src/mage/cards/j/JorKadeenThePrevailer.java @@ -23,7 +23,7 @@ import mage.filter.StaticFilters; */ public final class JorKadeenThePrevailer extends CardImpl { - private static final String effectText = "Metalcraft - Creatures you control get +3/+0 as long as you control three or more artifacts."; + private static final String effectText = "Metalcraft — Creatures you control get +3/+0 as long as you control three or more artifacts."; public JorKadeenThePrevailer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{W}"); @@ -37,7 +37,7 @@ public final class JorKadeenThePrevailer extends CardImpl { // First strike this.addAbility(FirstStrikeAbility.getInstance()); - // Metalcraft - Creatures you control get +3/+0 as long as you control three or more artifacts. + // Metalcraft — Creatures you control get +3/+0 as long as you control three or more artifacts. ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new BoostControlledEffect(3, 0, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE, false), MetalcraftCondition.instance, effectText); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java b/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java index 4de6ec003a5..b9f4e55732a 100644 --- a/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java +++ b/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java @@ -4,7 +4,7 @@ package mage.cards.j; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.MenaceAbility; @@ -35,7 +35,7 @@ public final class JosuVessLichKnight extends CardImpl { //When Josu Vess, Lich Knight enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieKnightToken(), 8)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace.")); } diff --git a/Mage.Sets/src/mage/cards/j/JourneyForTheElixir.java b/Mage.Sets/src/mage/cards/j/JourneyForTheElixir.java new file mode 100644 index 00000000000..9b3d6d4fa19 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JourneyForTheElixir.java @@ -0,0 +1,123 @@ +package mage.cards.j; + +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.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author TheElk801 + */ +public final class JourneyForTheElixir extends CardImpl { + + public JourneyForTheElixir(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); + + // Search your library and graveyard for a basic land card and a card named Jiang Yanggu, reveal them, put them into your hand, then shuffle your library. + this.getSpellAbility().addEffect(new JourneyForTheElixirEffect()); + } + + public JourneyForTheElixir(final JourneyForTheElixir card) { + super(card); + } + + @Override + public JourneyForTheElixir copy() { + return new JourneyForTheElixir(this); + } +} + +class JourneyForTheElixirEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("card named Jiang Yanggu"); + + static { + filter.add(new NamePredicate("Jiang Yanggu")); + } + + public JourneyForTheElixirEffect() { + super(Outcome.DrawCard); + this.staticText = "search your library and graveyard for a basic land card " + + "and a card named Jiang Yanggu, reveal them, " + + "put them into your hand, then shuffle your library"; + } + + public JourneyForTheElixirEffect(final JourneyForTheElixirEffect effect) { + super(effect); + } + + @Override + public JourneyForTheElixirEffect copy() { + return new JourneyForTheElixirEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + boolean walkerFound = false; + boolean landFound = false; + Cards cardsToHand = new CardsImpl(); + if (player.chooseUse(outcome, "Search your graveyard?", source, game)) { + TargetCardInGraveyard targetWalker = new TargetCardInGraveyard(0, 1, filter); + targetWalker.setNotTarget(true); + if (player.choose(outcome, targetWalker, source.getSourceId(), game)) { + Card card = game.getCard(targetWalker.getFirstTarget()); + if (card != null) { + cardsToHand.add(card); + walkerFound = true; + } + } + TargetCardInGraveyard targetLand = new TargetCardInGraveyard(0, 1, StaticFilters.FILTER_CARD_BASIC_LAND_A); + targetLand.setNotTarget(true); + if (player.choose(outcome, targetLand, source.getSourceId(), game)) { + Card card = game.getCard(targetLand.getFirstTarget()); + if (card != null) { + cardsToHand.add(card); + landFound = true; + } + } + } + if (!walkerFound || !landFound) { + TargetCardInLibrary targetWalker = new TargetCardInLibrary(0, 1, filter); + targetWalker.setNotTarget(true); + if (!walkerFound && player.searchLibrary(targetWalker, game, false)) { + Card card = game.getCard(targetWalker.getFirstTarget()); + if (card != null) { + cardsToHand.add(card); + } + } + TargetCardInLibrary targetLand = new TargetCardInLibrary(0, 1, StaticFilters.FILTER_CARD_BASIC_LAND_A); + targetLand.setNotTarget(true); + if (!landFound && player.searchLibrary(targetLand, game, false)) { + Card card = game.getCard(targetLand.getFirstTarget()); + if (card != null) { + cardsToHand.add(card); + } + } + } + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SEARCHED, player.getId(), player.getId())); + player.revealCards(source, cardsToHand, game); + player.moveCards(cardsToHand, Zone.HAND, source, game); + player.shuffleLibrary(source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java index 1aebd7b437a..365534cf3a5 100644 --- a/Mage.Sets/src/mage/cards/j/JourneyToEternity.java +++ b/Mage.Sets/src/mage/cards/j/JourneyToEternity.java @@ -86,7 +86,7 @@ class JourneyToEternityReturnTransformedSourceEffect extends OneShotEffect { if (card != null && controller != null) { Zone zone = game.getState().getZone(card.getId()); // cards needs to be in public non battlefield zone - if (zone.equals(Zone.BATTLEFIELD) || !zone.isPublicZone()) { + if (zone == Zone.BATTLEFIELD || !zone.isPublicZone()) { return true; } game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); diff --git a/Mage.Sets/src/mage/cards/j/JovensFerrets.java b/Mage.Sets/src/mage/cards/j/JovensFerrets.java new file mode 100644 index 00000000000..a4df82c443c --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JovensFerrets.java @@ -0,0 +1,111 @@ +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; +import mage.abilities.Mode; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EndOfCombatTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.TapAllEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.common.BlockedAttackerWatcher; + +/** + * + * @author noahg + */ +public final class JovensFerrets extends CardImpl { + + public JovensFerrets(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); + + this.subtype.add(SubType.FERRET); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Joven's Ferrets attacks, it gets +0/+2 until end of turn. + Effect boostSourceEffect = new BoostSourceEffect(0, 2, Duration.EndOfTurn); + boostSourceEffect.setText("it gets +0/+2 until end of turn"); + this.addAbility(new AttacksTriggeredAbility(boostSourceEffect, false)); + + // At end of combat, tap all creatures that blocked Joven's Ferrets this turn. They don't untap during their controller's next untap step. + Ability eocAbility = new EndOfCombatTriggeredAbility(new JovensFerretsEffect(), false); + eocAbility.addWatcher(new BlockedAttackerWatcher()); + this.addAbility(eocAbility); + } + + public JovensFerrets(final JovensFerrets card) { + super(card); + } + + @Override + public JovensFerrets copy() { + return new JovensFerrets(this); + } +} + +class JovensFerretsEffect extends OneShotEffect { + + public JovensFerretsEffect() { + super(Outcome.Benefit); + } + + public JovensFerretsEffect(final JovensFerretsEffect effect) { + super(effect); + } + + @Override + public JovensFerretsEffect copy() { + return new JovensFerretsEffect(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) { + BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName()); + if (watcher != null) { + List toTap = new ArrayList<>(); + for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { + if (!creature.getId().equals(source.getSourceId())) { + if (watcher.creatureHasBlockedAttacker(sourcePermanent, creature, game)) { + toTap.add(creature); + } + } + } + for (Permanent creature : toTap) { + creature.tap(game); + DontUntapInControllersNextUntapStepTargetEffect effect = new DontUntapInControllersNextUntapStepTargetEffect(); + effect.setTargetPointer(new FixedTarget(creature.getId())); + game.addEffect(effect, source); + } + return true; + } + } + return false; + } + + @Override + public String getText(Mode mode) { + return "tap all creatures that blocked {this} this turn. They don't untap during their controller's next untap step."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/j/JudgesFamiliar.java b/Mage.Sets/src/mage/cards/j/JudgesFamiliar.java index f8990dc6269..b1fc25e0c9d 100644 --- a/Mage.Sets/src/mage/cards/j/JudgesFamiliar.java +++ b/Mage.Sets/src/mage/cards/j/JudgesFamiliar.java @@ -37,7 +37,7 @@ public final class JudgesFamiliar extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new GenericManaCost(1)), new SacrificeSourceCost()); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JunglebornPioneer.java b/Mage.Sets/src/mage/cards/j/JunglebornPioneer.java index 5bb0e3b7b1d..a3d495e351f 100644 --- a/Mage.Sets/src/mage/cards/j/JunglebornPioneer.java +++ b/Mage.Sets/src/mage/cards/j/JunglebornPioneer.java @@ -25,7 +25,7 @@ public final class JunglebornPioneer extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - // When Jungleborn Pioneer enters the battlefield, create a 1/1 blue Merfolk creature token with hexproof. (It can’t be the target of spells or abilities your opponents control.) + // When Jungleborn Pioneer enters the battlefield, create a 1/1 blue Merfolk creature token with hexproof. (It can't be the target of spells or abilities your opponents control.) Ability ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MerfolkHexproofToken()),false); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JununEfreet.java b/Mage.Sets/src/mage/cards/j/JununEfreet.java index e80a514ea89..7490820e05e 100644 --- a/Mage.Sets/src/mage/cards/j/JununEfreet.java +++ b/Mage.Sets/src/mage/cards/j/JununEfreet.java @@ -27,7 +27,7 @@ public final class JununEfreet extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // At the beginning of your upkeep, sacrifice Junún Efreet unless you pay {B}{B}. + // At the beginning of your upkeep, sacrifice Junun Efreet unless you pay {B}{B}. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{B}{B}")), TargetController.YOU, false)); } diff --git a/Mage.Sets/src/mage/cards/j/JustFate.java b/Mage.Sets/src/mage/cards/j/JustFate.java index dbce85cdc25..7a96e8dba94 100644 --- a/Mage.Sets/src/mage/cards/j/JustFate.java +++ b/Mage.Sets/src/mage/cards/j/JustFate.java @@ -26,7 +26,7 @@ public final class JustFate extends CardImpl { // Cast Just Fate only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/j/Juxtapose.java b/Mage.Sets/src/mage/cards/j/Juxtapose.java index 2adf2dfa6b3..ecc67002684 100644 --- a/Mage.Sets/src/mage/cards/j/Juxtapose.java +++ b/Mage.Sets/src/mage/cards/j/Juxtapose.java @@ -97,7 +97,7 @@ class JuxtaposeEffect extends ContinuousEffectImpl { if (permanent1 != null && permanent2 != null) { // exchange works only for two different controllers - if (permanent1.getControllerId().equals(permanent2.getControllerId())) { + if (permanent1.isControlledBy(permanent2.getControllerId())) { // discard effect if controller of both permanents is the same discard(); return; diff --git a/Mage.Sets/src/mage/cards/j/JynErsoAndCassianAndor.java b/Mage.Sets/src/mage/cards/j/JynErsoAndCassianAndor.java new file mode 100644 index 00000000000..df0a62ed4b5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JynErsoAndCassianAndor.java @@ -0,0 +1,50 @@ +package mage.cards.j; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class JynErsoAndCassianAndor extends CardImpl { + + public JynErsoAndCassianAndor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // At the beginning of combat on your turn, target creature gets +1/+0 and gains haste until end of turn. + Ability ability = new BeginningOfCombatTriggeredAbility( + new BoostTargetEffect(1, 0, Duration.EndOfTurn) + .setText("target creature gets +1/+0"), + TargetController.YOU, false); + ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn) + .setText("and gains haste until end of turn")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public JynErsoAndCassianAndor(final JynErsoAndCassianAndor card) { + super(card); + } + + @Override + public JynErsoAndCassianAndor copy() { + return new JynErsoAndCassianAndor(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KaerveksPurge.java b/Mage.Sets/src/mage/cards/k/KaerveksPurge.java index 6028d89f010..591f109a1b3 100644 --- a/Mage.Sets/src/mage/cards/k/KaerveksPurge.java +++ b/Mage.Sets/src/mage/cards/k/KaerveksPurge.java @@ -76,7 +76,7 @@ class KaerveksPurgeEffect extends OneShotEffect { if (targetCreature != null && targetCreature.destroy(source.getSourceId(), game, false)) { game.applyEffects(); if (targetCreature.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(targetCreature.getId()) - && !game.getState().getZone(targetCreature.getId()).equals(Zone.GRAVEYARD)) { + && game.getState().getZone(targetCreature.getId()) != Zone.GRAVEYARD) { // A replacement effect has moved the card to another zone as graveyard return true; } diff --git a/Mage.Sets/src/mage/cards/k/KalevanStarYacht.java b/Mage.Sets/src/mage/cards/k/KalevanStarYacht.java new file mode 100644 index 00000000000..6886f9d0129 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KalevanStarYacht.java @@ -0,0 +1,50 @@ +package mage.cards.k; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class KalevanStarYacht extends CardImpl { + + public KalevanStarYacht(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // When Kalevan Star Yacht enters the battlefield, lose 1 life, draw a card, and put a bounty counter on up to one target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeSourceControllerEffect(1)); + ability.addEffect(new DrawCardSourceControllerEffect(1)); + ability.addEffect(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance())); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + } + + public KalevanStarYacht(final KalevanStarYacht card) { + super(card); + } + + @Override + public KalevanStarYacht copy() { + return new KalevanStarYacht(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KalitasBloodchiefOfGhet.java b/Mage.Sets/src/mage/cards/k/KalitasBloodchiefOfGhet.java index 551627d15c4..6f54f2debcb 100644 --- a/Mage.Sets/src/mage/cards/k/KalitasBloodchiefOfGhet.java +++ b/Mage.Sets/src/mage/cards/k/KalitasBloodchiefOfGhet.java @@ -74,7 +74,7 @@ class KalitasDestroyEffect extends OneShotEffect { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null && permanent.destroy(source.getSourceId(), game, false)) { // if not destroyed it returns false if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId()) - && !game.getState().getZone(permanent.getId()).equals(Zone.GRAVEYARD)) { + && game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) { // A replacement effect has moved the card to another zone as grvayard return true; } diff --git a/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java b/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java index e0ecedad84f..fcc5372b8c3 100644 --- a/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java +++ b/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; @@ -56,7 +56,7 @@ public final class KangeeAerieKeeper extends CardImpl { // When Kangee, Aerie Keeper enters the battlefield, if it was kicked, put X feather counters on it. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.FEATHER.createInstance(), new KangeeAerieKeeperGetKickerXValue(), true)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, put X feather counters on it.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, put X feather counters on it.")); // Other Bird creatures get +1/+1 for each feather counter on Kangee, Aerie Keeper. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersSourceCount(CounterType.FEATHER), new CountersSourceCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter, true, "Other Bird creatures get +1/+1 for each feather counter on {this}."))); diff --git a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java index 35b7d59bc52..aba7458be3e 100644 --- a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java +++ b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java @@ -111,7 +111,7 @@ class KaradorGhostChieftainContinuousEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (game.getActivePlayerId() == null || !game.getActivePlayerId().equals(player.getId())) { + if (game.getActivePlayerId() == null || !game.isActivePlayer(player.getId())) { return false; } for (Card card : player.getGraveyard().getCards(new FilterCreatureCard(), game)) { diff --git a/Mage.Sets/src/mage/cards/k/KarganDragonrider.java b/Mage.Sets/src/mage/cards/k/KarganDragonrider.java new file mode 100644 index 00000000000..9bc48453a82 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KarganDragonrider.java @@ -0,0 +1,56 @@ +package mage.cards.k; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class KarganDragonrider extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.DRAGON, "a Dragon"); + + public KarganDragonrider(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // As long as you control a Dragon, Kargan Dragonrider has flying. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + FlyingAbility.getInstance(), + Duration.WhileOnBattlefield + ), + new PermanentsOnTheBattlefieldCondition(filter), + "as long as you control a Dragon, {this} has flying" + ) + )); + } + + public KarganDragonrider(final KarganDragonrider card) { + super(card); + } + + @Override + public KarganDragonrider copy() { + return new KarganDragonrider(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KarnLiberated.java b/Mage.Sets/src/mage/cards/k/KarnLiberated.java index 5a4629551fc..dc7a656eab9 100644 --- a/Mage.Sets/src/mage/cards/k/KarnLiberated.java +++ b/Mage.Sets/src/mage/cards/k/KarnLiberated.java @@ -111,7 +111,7 @@ class KarnLiberatedEffect extends OneShotEffect { player.getHand().clear(); player.getLibrary().clear(); for (Card card : game.getCards()) { - if (card.getOwnerId().equals(player.getId()) && !card.isCopy() // no copies + if (card.isOwnedBy(player.getId()) && !card.isCopy() // no copies && !player.getSideboard().contains(card.getId()) && !cards.contains(card)) { // not the exiled cards if (player.getCommandersIds().contains(card.getId())) { diff --git a/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java b/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java index e9589ae4605..7fc485e7150 100644 --- a/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java +++ b/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java @@ -170,7 +170,7 @@ class KarnMinus1Effect extends OneShotEffect { Cards filteredCards = new CardsImpl(); for (Card exileCard : exile) { - if (exileCard.getOwnerId().equals(source.getControllerId()) && filter.match(exileCard, game)) { + if (exileCard.isOwnedBy(source.getControllerId()) && filter.match(exileCard, game)) { filteredCards.add(exileCard); } } diff --git a/Mage.Sets/src/mage/cards/k/KarnsTemporalSundering.java b/Mage.Sets/src/mage/cards/k/KarnsTemporalSundering.java index 17a55ab4dbd..01b2b24c50a 100644 --- a/Mage.Sets/src/mage/cards/k/KarnsTemporalSundering.java +++ b/Mage.Sets/src/mage/cards/k/KarnsTemporalSundering.java @@ -29,7 +29,7 @@ public final class KarnsTemporalSundering extends CardImpl { // (You may cast a legendary sorcery only if you control a legendary creature or planeswalker.) this.addAbility(new LegendarySpellAbility()); - // Target player takes an extra turn after this one. Return up to one target nonland permanent to its owner’s hand. Exile Karn’s Temporal Sundering. + // Target player takes an extra turn after this one. Return up to one target nonland permanent to its owner's hand. Exile Karn's Temporal Sundering. this.getSpellAbility().addEffect(new KarnsTemporalSunderingEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetNonlandPermanent(0, 1, false)); @@ -50,7 +50,7 @@ class KarnsTemporalSunderingEffect extends OneShotEffect { public KarnsTemporalSunderingEffect() { super(Outcome.ExtraTurn); - this.staticText = "Target player takes an extra turn after this one. Return up to one target nonland permanent to its owner’s hand"; + this.staticText = "Target player takes an extra turn after this one. Return up to one target nonland permanent to its owner's hand"; } public KarnsTemporalSunderingEffect(final KarnsTemporalSunderingEffect effect) { diff --git a/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java b/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java index 636f40c80c2..b338d4cf51b 100644 --- a/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java +++ b/Mage.Sets/src/mage/cards/k/KaronaFalseGod.java @@ -86,8 +86,8 @@ class KaronaFalseGodUntapGetControlEffect 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("KaronaFalseGodSourceId"); - UUID controllerId = (UUID) ((GainControlTargetEffect) effect).getValue("KaronaFalseGodControllerId"); + UUID checkId = (UUID) effect.getValue("KaronaFalseGodSourceId"); + UUID controllerId = (UUID) effect.getValue("KaronaFalseGodControllerId"); if (source.getSourceId().equals(checkId) && newController.getId().equals(controllerId)) { effect.discard(); } diff --git a/Mage.Sets/src/mage/cards/k/KarplusanHound.java b/Mage.Sets/src/mage/cards/k/KarplusanHound.java index f7edee0196c..3a476915663 100644 --- a/Mage.Sets/src/mage/cards/k/KarplusanHound.java +++ b/Mage.Sets/src/mage/cards/k/KarplusanHound.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class KarplusanHound extends CardImpl { FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("a Chandra planeswalker"); filter.add(new SubtypePredicate(SubType.CHANDRA)); // Whenever Karplusan Hound attacks, if you control a Chandra planeswalker, this creature deals 2 damage to any target. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new DamageTargetEffect(2), false), new PermanentsOnTheBattlefieldCondition(filter), "if you control a Chandra planeswalker, " diff --git a/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java b/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java index f4ee2af344e..eda2fdad620 100644 --- a/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java +++ b/Mage.Sets/src/mage/cards/k/KarplusanMinotaur.java @@ -103,7 +103,7 @@ class KarplusanMinotaurFlipWinTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return this.getControllerId().equals(event.getPlayerId()) && event.getFlag(); + return this.isControlledBy(event.getPlayerId()) && event.getFlag(); } @Override @@ -134,7 +134,7 @@ class KarplusanMinotaurFlipLoseTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return this.getControllerId().equals(event.getPlayerId()) && !event.getFlag(); + return this.isControlledBy(event.getPlayerId()) && !event.getFlag(); } @Override diff --git a/Mage.Sets/src/mage/cards/k/KazarovSengirPureblood.java b/Mage.Sets/src/mage/cards/k/KazarovSengirPureblood.java index b56ea5a3b06..53a780e8b81 100644 --- a/Mage.Sets/src/mage/cards/k/KazarovSengirPureblood.java +++ b/Mage.Sets/src/mage/cards/k/KazarovSengirPureblood.java @@ -87,7 +87,7 @@ class KazarovSengirPurebloodTriggeredAbility extends TriggeredAbilityImpl { if (permanent == null) { return false; } - if (permanent.getControllerId().equals(this.getControllerId())) { + if (permanent.isControlledBy(this.getControllerId())) { return false; } return true; diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java b/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java index c691e2716a8..6ef30fb6b0b 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedAllEffect; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class KeeperOfKeys extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect(), false)); // At the beginning of your upkeep, if you're the monarch, creatures you control can't be blocked this turn. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CantBeBlockedAllEffect(new FilterControlledCreaturePermanent("creatures you control"), Duration.EndOfTurn), TargetController.YOU, false), MonarchIsSourceControllerCondition.instance, "At the beginning of your upkeep, if you're the monarch, creatures you control can't be blocked this turn.")); diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheBeasts.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheBeasts.java new file mode 100644 index 00000000000..cc4ccc8fcdd --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheBeasts.java @@ -0,0 +1,111 @@ +package mage.cards.k; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +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.CreateTokenEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterOpponent; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.token.BeastToken2; +import mage.game.permanent.token.BeastToken4; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetOpponent; + +/** + * + * @author noahg + */ +public final class KeeperOfTheBeasts extends CardImpl { + + public KeeperOfTheBeasts(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {G}, {tap}: Choose target opponent who controlled more creatures than you did as you activated this ability. Put a 2/2 green Beast creature token onto the battlefield. + Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new BeastToken4()).setText("Choose target opponent who controlled more creatures than you did as you activated this ability. Put a 2/2 green Beast creature token onto the battlefield."), + new ManaCostsImpl("{G}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new KeeperOfTheBeastsTarget()); + this.addAbility(ability); + } + + public KeeperOfTheBeasts(final KeeperOfTheBeasts card) { + super(card); + } + + @Override + public KeeperOfTheBeasts copy() { + return new KeeperOfTheBeasts(this); + } +} + +class KeeperOfTheBeastsTarget extends TargetPlayer { + + public KeeperOfTheBeastsTarget() { + super(1, 1, false, new FilterOpponent("opponent that controls more creatures than you")); + } + + public KeeperOfTheBeastsTarget(final KeeperOfTheBeastsTarget target) { + super(target); + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); + Set possibleTargets = new HashSet<>(); + int creaturesController = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, game); + + for (UUID targetId : availablePossibleTargets) { + if (game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, targetId, game) > creaturesController) { + possibleTargets.add(targetId); + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + int count = 0; + MageObject targetSource = game.getObject(sourceId); + Player controller = game.getPlayer(sourceControllerId); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null + && game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, game) + < game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game) + && !player.hasLeft() + && filter.match(player, sourceId, sourceControllerId, game) + && player.canBeTargetedBy(targetSource, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + } + return false; + } + + @Override + public KeeperOfTheBeastsTarget copy() { + return new KeeperOfTheBeastsTarget(this); + } +} + diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheDead.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheDead.java index eadc6f82a77..3508e2839f3 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheDead.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheDead.java @@ -128,7 +128,7 @@ class KeeperOfTheDeadCreatureTarget extends TargetPermanent { public boolean canTarget(UUID id, Ability source, Game game) { UUID firstTarget = source.getFirstTarget(); Permanent permanent = game.getPermanent(id); - if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + if (firstTarget != null && permanent != null && permanent.isControlledBy(firstTarget)) { return super.canTarget(id, source, game); } return false; @@ -153,7 +153,7 @@ class KeeperOfTheDeadCreatureTarget extends TargetPermanent { UUID playerId = ((StackObject) object).getStackAbility().getFirstTarget(); for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if (permanent != null && nonblackCreaturefilter.match(permanent, game) && permanent.getControllerId().equals(playerId)) { + if (permanent != null && nonblackCreaturefilter.match(permanent, game) && permanent.isControlledBy(playerId)) { possibleTargets.add(targetId); } } diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java new file mode 100644 index 00000000000..087fe044f66 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java @@ -0,0 +1,128 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.k; + +import java.util.UUID; +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.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.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; + +/** + * + * @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}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {U}, {tap}: Choose target opponent who had at least two more cards in hand than you did as you activated this ability. Draw a card. + Effect effect = new DrawCardSourceControllerEffect(1); + 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()); + 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 + public KeeperOfTheMind copy() { + return new KeeperOfTheMind(this); + } +} + +class KeeperOfTheMindPredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Player targetPlayer = input.getObject(); + Player firstPlayer = game.getPlayer(game.getActivePlayerId()); + if (targetPlayer == null + || firstPlayer == null + || !firstPlayer.hasOpponent(targetPlayer.getId(), game)) { + return false; + } + int countHandTargetPlayer = targetPlayer.getHand().size(); + int countHandFirstPlayer = firstPlayer.getHand().size(); + + return countHandTargetPlayer - 2 >= countHandFirstPlayer; + } + + @Override + public String toString() { + return "opponent who had at least two more cards in hand than you did as you activated this ability"; + } +} diff --git a/Mage.Sets/src/mage/cards/k/KeldonBerserker.java b/Mage.Sets/src/mage/cards/k/KeldonBerserker.java index 734dfa41a4e..f2cf9c195ce 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonBerserker.java +++ b/Mage.Sets/src/mage/cards/k/KeldonBerserker.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class KeldonBerserker extends CardImpl { this.toughness = new MageInt(3); // Whenever Keldon Berserker attacks, if you control no untapped lands, it gets +3/+0 until end of turn. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), false), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), "Whenever {this} attacks, if you control no untapped lands, it gets +3/+0 until end of turn." diff --git a/Mage.Sets/src/mage/cards/k/KeldonOverseer.java b/Mage.Sets/src/mage/cards/k/KeldonOverseer.java index 9999e6d4a32..191dcdc371d 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonOverseer.java +++ b/Mage.Sets/src/mage/cards/k/KeldonOverseer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -44,7 +44,7 @@ public final class KeldonOverseer extends CardImpl { ability.addEffect(new UntapTargetEffect()); ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.")); } diff --git a/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java b/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java index 2713e4282d8..3590d941232 100644 --- a/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java +++ b/Mage.Sets/src/mage/cards/k/KeranosGodOfStorms.java @@ -92,7 +92,7 @@ class KeranosGodOfStormsTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(this.getControllerId())) { - if (game.getActivePlayerId().equals(this.getControllerId())) { + if (game.isActivePlayer(this.getControllerId())) { CardsAmountDrawnThisTurnWatcher watcher = (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.class.getSimpleName()); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) != 1) { diff --git a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java index 8eb49369f9c..bc3cc94473f 100644 --- a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java +++ b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java @@ -97,7 +97,7 @@ class KessDissidentMageContinuousEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - if (!game.getActivePlayerId().equals(player.getId())) { + if (!game.isActivePlayer(player.getId())) { return false; } for (Card card : player.getGraveyard().getCards(filter, game)) { @@ -138,7 +138,7 @@ class KessDissidentMageCastFromGraveyardEffect 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())) { - if (game.getActivePlayerId().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(); diff --git a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java index 34f60d6cebf..106b0024a52 100644 --- a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java +++ b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -43,7 +43,7 @@ public final class KessigForgemaster extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Kessig Forgemaster. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java b/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java new file mode 100644 index 00000000000..18f4dfcdc3b --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KestiaTheCultivator.java @@ -0,0 +1,74 @@ +package mage.cards.k; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.BestowAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SetTargetPointer; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.EnchantedPredicate; + +/** + * + * @author TheElk801 + */ +public final class KestiaTheCultivator extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("an enchanted creature or enchantment creature you control"); + + static { + filter.add(Predicates.or( + new EnchantedPredicate(), + new CardTypePredicate(CardType.ENCHANTMENT) + )); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public KestiaTheCultivator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{G}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.NYMPH); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Bestow {3}{G}{W}{U} + this.addAbility(new BestowAbility(this, "{3}{G}{W}{U}")); + + // Enchanted creature gets +4/+4. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostEnchantedEffect(4, 4, Duration.WhileOnBattlefield) + )); + + // Whenever an enchanted creature or enchantment creature you control attacks, draw a card. + this.addAbility(new AttacksAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), + false, filter, SetTargetPointer.NONE, false + )); + } + + public KestiaTheCultivator(final KestiaTheCultivator card) { + super(card); + } + + @Override + public KestiaTheCultivator copy() { + return new KestiaTheCultivator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/Kezzerdrix.java b/Mage.Sets/src/mage/cards/k/Kezzerdrix.java index a9332500362..a27b8dd727c 100644 --- a/Mage.Sets/src/mage/cards/k/Kezzerdrix.java +++ b/Mage.Sets/src/mage/cards/k/Kezzerdrix.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CreatureCountCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class Kezzerdrix extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // At the beginning of your upkeep, if your opponents control no creatures, Kezzerdrix deals 4 damage to you. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageControllerEffect(4), TargetController.YOU, false), new CreatureCountCondition(0, TargetController.OPPONENT), "At the beginning of your upkeep, if your opponents control no creatures, {this} deals 4 damage to you.")); diff --git a/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java b/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java index bc30f9246ab..c5b03a0f078 100644 --- a/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java +++ b/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java @@ -49,7 +49,7 @@ public final class KikiJikiMirrorBreaker extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); - // {tap}: Create a token that's a copy of target nonlegendary creature you control . That token has haste. Sacrifice it at the beginning of the next end step. + // {T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new KikiJikiMirrorBreakerEffect(), new TapSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false)); this.addAbility(ability); @@ -70,7 +70,7 @@ class KikiJikiMirrorBreakerEffect extends OneShotEffect { public KikiJikiMirrorBreakerEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Create a token that's a copy of target nonlegendary creature you control. That token has haste. Sacrifice it at the beginning of the next end step"; + this.staticText = "Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step"; } public KikiJikiMirrorBreakerEffect(final KikiJikiMirrorBreakerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/k/KilnFiend.java b/Mage.Sets/src/mage/cards/k/KilnFiend.java index 37939e51d43..c5243fee8b1 100644 --- a/Mage.Sets/src/mage/cards/k/KilnFiend.java +++ b/Mage.Sets/src/mage/cards/k/KilnFiend.java @@ -1,4 +1,3 @@ - package mage.cards.k; import java.util.UUID; @@ -10,9 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; -import mage.filter.FilterSpell; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; /** * @@ -20,22 +17,19 @@ import mage.filter.predicate.mageobject.CardTypePredicate; */ public final class KilnFiend extends CardImpl { - private static final FilterSpell filter = new FilterSpell("an instant or sorcery spell"); - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY))); - } - public KilnFiend(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.BEAST); this.power = new MageInt(1); this.toughness = new MageInt(2); - this.addAbility(new SpellCastControllerTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), filter, false)); + this.addAbility(new SpellCastControllerTriggeredAbility( + new BoostSourceEffect(3, 0, Duration.EndOfTurn), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false + )); } public KilnFiend(final KilnFiend card) { diff --git a/Mage.Sets/src/mage/cards/k/KindredBoon.java b/Mage.Sets/src/mage/cards/k/KindredBoon.java index a61037e021e..979ade1ccf8 100644 --- a/Mage.Sets/src/mage/cards/k/KindredBoon.java +++ b/Mage.Sets/src/mage/cards/k/KindredBoon.java @@ -42,7 +42,7 @@ public final class KindredBoon extends CardImpl { // {1}{W}: Put a divinity counter on target creature you control of the chosen type. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.DIVINITY.createInstance()), new ManaCostsImpl("{1}{W}")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KindredDiscovery.java b/Mage.Sets/src/mage/cards/k/KindredDiscovery.java index 34ddc649653..9dc8464b32d 100644 --- a/Mage.Sets/src/mage/cards/k/KindredDiscovery.java +++ b/Mage.Sets/src/mage/cards/k/KindredDiscovery.java @@ -27,7 +27,7 @@ public final class KindredDiscovery extends CardImpl { // Whenever a creature you control of the chosen type enters the battlefield or attacks, draw a card. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature you control of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); this.addAbility(new EntersBattlefieldOrAttacksAllTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, false)); } diff --git a/Mage.Sets/src/mage/cards/k/KitesailCorsair.java b/Mage.Sets/src/mage/cards/k/KitesailCorsair.java index f80e1624be3..946239c2a5b 100644 --- a/Mage.Sets/src/mage/cards/k/KitesailCorsair.java +++ b/Mage.Sets/src/mage/cards/k/KitesailCorsair.java @@ -27,12 +27,12 @@ public final class KitesailCorsair extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - // Kitesail Corsair has flying as long as it’s attacking. + // Kitesail Corsair has flying as long as it's attacking. ContinuousEffect gainEffect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( gainEffect, SourceAttackingCondition.instance, - "{this} has flying as long as it’s attacking." + "{this} has flying as long as it's attacking." ))); } diff --git a/Mage.Sets/src/mage/cards/k/KitsuneMystic.java b/Mage.Sets/src/mage/cards/k/KitsuneMystic.java index 04856fb1d74..0685884b6d2 100644 --- a/Mage.Sets/src/mage/cards/k/KitsuneMystic.java +++ b/Mage.Sets/src/mage/cards/k/KitsuneMystic.java @@ -8,7 +8,7 @@ import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.EnchantedSourceCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.FlipSourceEffect; import mage.cards.CardImpl; @@ -21,7 +21,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -42,7 +41,7 @@ public final class KitsuneMystic extends CardImpl { this.flipCardName = "Autumn-Tail, Kitsune Sage"; // At the beginning of the end step, if Kitsune Mystic is enchanted by two or more Auras, flip it. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new AutumnTailKitsuneSage())), new EnchantedSourceCondition(2), "At the beginning of the end step, if {this} is enchanted by two or more Auras, flip it.")); } diff --git a/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java b/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java index d778835c8c6..f352b996234 100644 --- a/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java +++ b/Mage.Sets/src/mage/cards/k/KiyomaroFirstToStand.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; import mage.abilities.effects.Effect; @@ -54,7 +54,7 @@ public final class KiyomaroFirstToStand extends CardImpl { this.addAbility(ability); // Whenever Kiyomaro deals damage, if you have seven or more cards in hand, you gain 7 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new KiyomaroFirstToStandDealsDamageTriggeredAbility(), new CardsInHandCondition(ComparisonType.MORE_THAN, 6), "Whenever {this} deals damage, if you have seven or more cards in hand, you gain 7 life" diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java b/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java index 8069a3b5e50..9aaa09e8c4a 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.constants.SubType; @@ -32,7 +32,7 @@ public final class KjeldoranHomeGuard extends CardImpl { this.toughness = new MageInt(6); // At end of combat, if Kjeldoran Home Guard attacked or blocked this combat, put a -0/-1 counter on Kjeldoran Home Guard and put a 0/1 white Deserter creature token onto the battlefield. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EndOfCombatTriggeredAbility(new AddCountersSourceEffect(new BoostCounter(0, -1)), false), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, if {this} attacked or blocked this combat, put a -0/-1 counter on {this} and create a 0/1 white Deserter creature token."); diff --git a/Mage.Sets/src/mage/cards/k/KnacksawClique.java b/Mage.Sets/src/mage/cards/k/KnacksawClique.java index 9de1b132b83..1b3b4882150 100644 --- a/Mage.Sets/src/mage/cards/k/KnacksawClique.java +++ b/Mage.Sets/src/mage/cards/k/KnacksawClique.java @@ -122,7 +122,7 @@ class KnacksawCliqueCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && sourceId.equals(getTargetPointer().getFirst(game, source)); } diff --git a/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java b/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java index f2cefef40bb..23438bfc9ea 100644 --- a/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java +++ b/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java @@ -6,7 +6,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class KnightOfTheWhiteOrchid extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // When Knight of the White Orchid enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, new FilterBySubtypeCard(SubType.PLAINS)), false), true), new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS), "When {this} enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library")); diff --git a/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java b/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java index 1faaa0d25d7..482ed9506d0 100644 --- a/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java +++ b/Mage.Sets/src/mage/cards/k/KnightsOfTheBlackRose.java @@ -86,7 +86,7 @@ class BecomesMonarchTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkInterveningIfClause(Game game) { MonarchAtTurnStartWatcher watcher = (MonarchAtTurnStartWatcher) game.getState().getWatchers().get(MonarchAtTurnStartWatcher.class.getSimpleName()); - return watcher != null && getControllerId().equals(watcher.getMonarchIdAtTurnStart()); + return watcher != null && isControlledBy(watcher.getMonarchIdAtTurnStart()); } @Override diff --git a/Mage.Sets/src/mage/cards/k/Kookus.java b/Mage.Sets/src/mage/cards/k/Kookus.java index 7facaf44c8a..dadaa25fd9b 100644 --- a/Mage.Sets/src/mage/cards/k/Kookus.java +++ b/Mage.Sets/src/mage/cards/k/Kookus.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ColoredManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.combat.AttacksIfAbleSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; @@ -50,7 +50,7 @@ public final class Kookus extends CardImpl { // At the beginning of your upkeep, if you don't control a creature named Keeper of Kookus, Kookus deals 3 damage to you and attacks this turn if able. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(3), TargetController.YOU, false); ability.addEffect(new AttacksIfAbleSourceEffect(Duration.EndOfTurn)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), "At the beginning of your upkeep, " diff --git a/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java b/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java index 5f8dc1b4414..738f2ffc63c 100644 --- a/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java +++ b/Mage.Sets/src/mage/cards/k/KopalaWardenOfWaves.java @@ -93,7 +93,7 @@ class KopalaWardenOfWavesCostReductionEffect extends CostModificationEffectImpl Permanent creature = game.getPermanent(targetUUID); if (creature != null && filter.match(creature, game) - && creature.getControllerId().equals(source.getControllerId())) { + && creature.isControlledBy(source.getControllerId())) { return true; } } @@ -144,7 +144,7 @@ class KopalaWardenOfWavesCostReductionEffect2 extends CostModificationEffectImpl Permanent creature = game.getPermanent(targetUUID); if (creature != null && filter.match(creature, game) - && creature.getControllerId().equals(source.getControllerId())) { + && creature.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/k/KorAeronaut.java b/Mage.Sets/src/mage/cards/k/KorAeronaut.java index 6eb4d18b613..b104e6d0e4d 100644 --- a/Mage.Sets/src/mage/cards/k/KorAeronaut.java +++ b/Mage.Sets/src/mage/cards/k/KorAeronaut.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -29,15 +29,17 @@ public final class KorAeronaut extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - + + //Kicker {1}{W} (You may pay an additional {1}{W} as you cast this spell.) this.addAbility(new KickerAbility("{1}{W}")); - + //Flying this.addAbility(FlyingAbility.getInstance()); + //When Kor Aeronaut enters the battlefield, if it was kicked, target creature gains flying until end of turn. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), false); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, target creature gains flying until end of turn.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, target creature gains flying until end of turn.")); } public KorAeronaut(final KorAeronaut card) { diff --git a/Mage.Sets/src/mage/cards/k/KorSanctifiers.java b/Mage.Sets/src/mage/cards/k/KorSanctifiers.java index 599ea6fd112..001dfde7840 100644 --- a/Mage.Sets/src/mage/cards/k/KorSanctifiers.java +++ b/Mage.Sets/src/mage/cards/k/KorSanctifiers.java @@ -4,7 +4,7 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class KorSanctifiers extends CardImpl { // When Kor Sanctifiers enters the battlefield, if it was kicked, destroy target artifact or enchantment. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target artifact or enchantment.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target artifact or enchantment.")); } public KorSanctifiers (final KorSanctifiers card) { diff --git a/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java b/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java index 44795b19bb7..693c957fee0 100644 --- a/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java +++ b/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java @@ -10,7 +10,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.CounterTargetEffect; @@ -48,7 +48,7 @@ public final class KozilekTheGreatDistortion extends CardImpl { this.toughness = new MageInt(12); // When you cast Kozilek, the Great Distortion, if you have fewer than seven cards in hand, draw cards equal to the difference. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new CastSourceTriggeredAbility(new KozilekDrawEffect(), false), new CardsInHandCondition(ComparisonType.FEWER_THAN, 7), "When you cast {this}, if you have fewer than seven cards in hand, draw cards equal to the difference.")); diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java b/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java index 6164caecd6a..9da97bde55e 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeHowler.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; import mage.abilities.keyword.TransformAbility; @@ -49,7 +49,7 @@ public final class KrallenhordeHowler extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Krallenhorde Howler. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public KrallenhordeHowler(final KrallenhordeHowler card) { diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java b/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java index ae106b0661e..72afe531b15 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeKiller.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -38,7 +38,7 @@ public final class KrallenhordeKiller extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Krallenhorde Killer. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public KrallenhordeKiller(final KrallenhordeKiller card) { diff --git a/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java b/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java index b499988e5ea..7ba04f05f4a 100644 --- a/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java +++ b/Mage.Sets/src/mage/cards/k/KrallenhordeWantons.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class KrallenhordeWantons extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Krallenhorde Wantons. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public KrallenhordeWantons(final KrallenhordeWantons card) { diff --git a/Mage.Sets/src/mage/cards/k/KrarksOtherThumb.java b/Mage.Sets/src/mage/cards/k/KrarksOtherThumb.java index 1575db39a59..6001ec55995 100644 --- a/Mage.Sets/src/mage/cards/k/KrarksOtherThumb.java +++ b/Mage.Sets/src/mage/cards/k/KrarksOtherThumb.java @@ -82,7 +82,7 @@ class KrarksOtherThumbEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/k/KrarksThumb.java b/Mage.Sets/src/mage/cards/k/KrarksThumb.java index 20a705b886a..3acb3bde5aa 100644 --- a/Mage.Sets/src/mage/cards/k/KrarksThumb.java +++ b/Mage.Sets/src/mage/cards/k/KrarksThumb.java @@ -74,7 +74,7 @@ class KrarksThumbEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java b/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java index 418e49adf94..562c6264002 100644 --- a/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java +++ b/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.EnchantedSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; @@ -36,7 +36,7 @@ public final class KrondTheDawnClad extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Whenever Krond the Dawn-Clad attacks, if it's enchanted, exile target permanent. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new ExileTargetEffect(), false), new EnchantedSourceCondition(), "Whenever {this} attacks, if it's enchanted, exile target permanent."); diff --git a/Mage.Sets/src/mage/cards/k/KrosanDruid.java b/Mage.Sets/src/mage/cards/k/KrosanDruid.java index 03136866af7..13d414e9c51 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanDruid.java +++ b/Mage.Sets/src/mage/cards/k/KrosanDruid.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.KickerAbility; import mage.constants.SubType; @@ -31,7 +31,7 @@ public final class KrosanDruid extends CardImpl { this.addAbility(new KickerAbility("{4}{G}")); // When Krosan Druid enters the battlefield, if it was kicked, you gain 10 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainLifeEffect(10)), KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, you gain 10 life" diff --git a/Mage.Sets/src/mage/cards/k/KrosanWayfarer.java b/Mage.Sets/src/mage/cards/k/KrosanWayfarer.java index bd3a63f9187..3749b8b2a24 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanWayfarer.java +++ b/Mage.Sets/src/mage/cards/k/KrosanWayfarer.java @@ -1,4 +1,3 @@ - package mage.cards.k; import java.util.UUID; @@ -28,7 +27,7 @@ public final class KrosanWayfarer extends CardImpl { // Sacrifice Krosan Wayfarer: You may put a land card from your hand onto the battlefield. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_BASIC_LAND_A), new SacrificeSourceCost())); + new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A), new SacrificeSourceCost())); } public KrosanWayfarer(final KrosanWayfarer card) { diff --git a/Mage.Sets/src/mage/cards/k/KrovikanElementalist.java b/Mage.Sets/src/mage/cards/k/KrovikanElementalist.java new file mode 100644 index 00000000000..a5df0fb8ddd --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KrovikanElementalist.java @@ -0,0 +1,89 @@ +package mage.cards.k; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +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.game.Game; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class KrovikanElementalist extends CardImpl { + + public KrovikanElementalist(UUID ownerId, CardSetInfo setInfo) { + 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(1); + + // {2}{R}: Target creature gets +1/+0 until end of turn. + Ability ability = new SimpleActivatedAbility( + new BoostTargetEffect(1, 0, Duration.EndOfTurn), + new ManaCostsImpl("{2}{R}") + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // {U}{U}: Target creature you control gains flying until end of turn. Sacrifice it at the beginning of the next end step. + ability = new SimpleActivatedAbility(new GainAbilityTargetEffect( + FlyingAbility.getInstance(), + Duration.EndOfTurn + ), new ManaCostsImpl("{U}{U}")); + ability.addEffect(new KrovikanElementalistEffect()); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public KrovikanElementalist(final KrovikanElementalist card) { + super(card); + } + + @Override + public KrovikanElementalist copy() { + return new KrovikanElementalist(this); + } +} + +class KrovikanElementalistEffect extends OneShotEffect { + + public KrovikanElementalistEffect() { + super(Outcome.Sacrifice); + this.staticText = "Sacrifice it at the beginning of the next end step"; + } + + public KrovikanElementalistEffect(final KrovikanElementalistEffect effect) { + super(effect); + } + + @Override + public KrovikanElementalistEffect copy() { + return new KrovikanElementalistEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new SacrificeTargetEffect("sacrifice it", source.getControllerId()) + )).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KruinOutlaw.java b/Mage.Sets/src/mage/cards/k/KruinOutlaw.java index 7864aea44fb..53b0f8b4b66 100644 --- a/Mage.Sets/src/mage/cards/k/KruinOutlaw.java +++ b/Mage.Sets/src/mage/cards/k/KruinOutlaw.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TransformAbility; @@ -39,7 +39,7 @@ public final class KruinOutlaw extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Kruin Outlaw. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public KruinOutlaw(final KruinOutlaw card) { diff --git a/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java b/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java index 278caca7917..37a4218383e 100644 --- a/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java +++ b/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java @@ -37,7 +37,7 @@ public final class KuldothaPhoenix extends CardImpl { this.addAbility(FlyingAbility.getInstance()); this.addAbility(HasteAbility.getInstance()); - // Metalcraft - {4}: Return Kuldotha Phoenix from your graveyard to the battlefield. + // Metalcraft — {4}: Return Kuldotha Phoenix from your graveyard to the battlefield. // Activate this ability only during your upkeep and only if you control three or more artifacts. Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), diff --git a/Mage.Sets/src/mage/cards/k/KumanosBlessing.java b/Mage.Sets/src/mage/cards/k/KumanosBlessing.java index c6873c3cf90..c745c6fd9c6 100644 --- a/Mage.Sets/src/mage/cards/k/KumanosBlessing.java +++ b/Mage.Sets/src/mage/cards/k/KumanosBlessing.java @@ -1,9 +1,6 @@ package mage.cards.k; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -24,15 +21,18 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KumanosBlessing extends CardImpl { public KumanosBlessing(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); this.subtype.add(SubType.AURA); // Flash @@ -77,7 +77,7 @@ class KumanosBlessingEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = ((ZoneChangeEvent)event).getTarget(); + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && permanent != null) { return controller.moveCardToExileWithInfo(permanent, null, null, source.getSourceId(), game, Zone.BATTLEFIELD, true); @@ -89,10 +89,10 @@ class KumanosBlessingEffect 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 zce = (ZoneChangeEvent) event; + ZoneChangeEvent zce = (ZoneChangeEvent) event; if (zce.isDiesEvent()) { DamagedByEnchantedWatcher watcher = (DamagedByEnchantedWatcher) game.getState().getWatchers().get(DamagedByEnchantedWatcher.class.getSimpleName(), source.getSourceId()); if (watcher != null) { @@ -126,16 +126,15 @@ class DamagedByEnchantedWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == EventType.DAMAGED_CREATURE) { Permanent enchantment = game.getPermanent(this.getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - if (enchantment.getAttachedTo().equals(event.getSourceId())) { - MageObjectReference mor = new MageObjectReference(event.getTargetId(), game); - damagedCreatures.add(mor); + if (enchantment != null && enchantment.isAttachedTo(event.getSourceId())) { + MageObjectReference mor = new MageObjectReference(event.getTargetId(), game); + damagedCreatures.add(mor); - } } } } + @Override public void reset() { super.reset(); diff --git a/Mage.Sets/src/mage/cards/k/KyloRen.java b/Mage.Sets/src/mage/cards/k/KyloRen.java new file mode 100644 index 00000000000..19326d19259 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KyloRen.java @@ -0,0 +1,114 @@ +package mage.cards.k; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.AttacksEachCombatStaticAbility; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.IntPlusDynamicValue; +import mage.abilities.dynamicvalue.LockedInDynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.constants.*; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class KyloRen extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(new DefendingPlayerControlsPredicate()); + } + + public KyloRen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SITH); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Kylo Ren attacks each turn if able. + this.addAbility(new AttacksEachCombatStaticAbility()); + + // Whenever Kylo Ren attacks, it gets +1/+0 for each creature in your graveyard and you may tap target creature defending player controls. + CardsInControllerGraveyardCount value = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE); + Effect effect = new BoostSourceEffect(value, new StaticValue(0), Duration.WhileOnBattlefield); + effect.setText("it gets +1/+0 for each creature in your graveyard"); + Ability ability = new AttacksTriggeredAbility(effect, false); + ability.addEffect(new KyloRenTapTargetEffect()); + ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + this.addAbility(ability); + } + + public KyloRen(final KyloRen card) { + super(card); + } + + @Override + public KyloRen copy() { + return new KyloRen(this); + } +} + +class KyloRenTapTargetEffect extends TapTargetEffect { + + public KyloRenTapTargetEffect() { + super(); + } + + public KyloRenTapTargetEffect(final KyloRenTapTargetEffect effect) { + super(effect); + } + + @Override + public KyloRenTapTargetEffect copy() { + return new KyloRenTapTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + if(player != null && permanent != null) { + if(player.chooseUse(outcome, "Tap target creature defending player controls (" + permanent.getLogName() + ")", source, game)) { + super.apply(game, source); + } + } + return false; + } + + @Override + public String getText(Mode mode) { + return "and you may tap target creature defending player controls"; + } +} diff --git a/Mage.Sets/src/mage/cards/k/KyrenLegate.java b/Mage.Sets/src/mage/cards/k/KyrenLegate.java index b77984d1611..1c03329a932 100644 --- a/Mage.Sets/src/mage/cards/k/KyrenLegate.java +++ b/Mage.Sets/src/mage/cards/k/KyrenLegate.java @@ -39,7 +39,7 @@ public final class KyrenLegate extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); - // If an opponent controls a Plains and you control a Mountain, you may cast Kyren Legate without paying its mana cost. + // If an opponent controls a Plains and you control a Mountain, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Plains and you control a Mountain", new OpponentControlsPermanentCondition(filterPlains), new PermanentsOnTheBattlefieldCondition(filterMountain)); diff --git a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java index 655fa05c442..e08d2bb278b 100644 --- a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java +++ b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java @@ -10,7 +10,7 @@ import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAndReturnTransformedSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.IndestructibleAbility; @@ -47,7 +47,7 @@ public final class KytheonHeroOfAkros extends CardImpl { // At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, // then return him to the battlefield transformed under his owner's control. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility(new EndOfCombatTriggeredAbility(new ExileAndReturnTransformedSourceEffect(Gender.MALE), false), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EndOfCombatTriggeredAbility(new ExileAndReturnTransformedSourceEffect(Gender.MALE), false), new KytheonHeroOfAkrosCondition(), "At end of combat, if {this} and at least two other creatures attacked this combat, exile {this}, " + "then return him to the battlefield transformed under his owner's control."), new AttackedOrBlockedThisCombatWatcher()); diff --git a/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java b/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java index 7a8ba666fdf..3176c94b64c 100644 --- a/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java +++ b/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class LagonnaBandElder extends CardImpl { this.toughness = new MageInt(2); // When Lagonna-Band Elder enters the battlefield, if you control an enchantment, you gain 3 life. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When Lagonna-Band Elder enters the battlefield, if you control an enchantment, you gain 3 life"); diff --git a/Mage.Sets/src/mage/cards/l/LambholtButcher.java b/Mage.Sets/src/mage/cards/l/LambholtButcher.java index 663c906d0ad..e24de214799 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtButcher.java +++ b/Mage.Sets/src/mage/cards/l/LambholtButcher.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class LambholtButcher extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Lambholt Butcher. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public LambholtButcher(final LambholtButcher card) { diff --git a/Mage.Sets/src/mage/cards/l/LambholtElder.java b/Mage.Sets/src/mage/cards/l/LambholtElder.java index 01c6c21ec7f..81f15b01a41 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtElder.java +++ b/Mage.Sets/src/mage/cards/l/LambholtElder.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class LambholtElder extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Lambholt Elder. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public LambholtElder(final LambholtElder card) { diff --git a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java index 31941267add..b811c781ff1 100644 --- a/Mage.Sets/src/mage/cards/l/LambholtPacifist.java +++ b/Mage.Sets/src/mage/cards/l/LambholtPacifist.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -48,7 +48,7 @@ public final class LambholtPacifist extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Lambholt Pacifist. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public LambholtPacifist(final LambholtPacifist card) { diff --git a/Mage.Sets/src/mage/cards/l/LammastideWeave.java b/Mage.Sets/src/mage/cards/l/LammastideWeave.java index 1ba1a2ef624..a67cac45851 100644 --- a/Mage.Sets/src/mage/cards/l/LammastideWeave.java +++ b/Mage.Sets/src/mage/cards/l/LammastideWeave.java @@ -1,11 +1,10 @@ - package mage.cards.l; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -26,7 +25,7 @@ public final class LammastideWeave extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Name a card, then target player puts the top card of their library into their graveyard. If that card is the named card, you gain life equal to its converted mana cost. - this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); this.getSpellAbility().addEffect(new LammastideWeaveEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); @@ -50,7 +49,7 @@ class LammastideWeaveEffect extends OneShotEffect { public LammastideWeaveEffect() { super(Outcome.DrawCard); this.staticText = ", then target player puts the top card of their library into their graveyard. " - + "If that card is the named card, you gain life equal to its converted mana cost."; + + "If that card has the chosen name, you gain life equal to its converted mana cost."; } public LammastideWeaveEffect(final LammastideWeaveEffect effect) { @@ -66,7 +65,7 @@ class LammastideWeaveEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(source.getFirstTarget()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) { Card card = targetPlayer.getLibrary().getFromTop(game); if (card != null) { diff --git a/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java b/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java index 49bf924422e..20fcc00fcbf 100644 --- a/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java +++ b/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +39,7 @@ public final class LamplighterOfSelhoff extends CardImpl { // When Lamplighter of Selhoff enters the battlefield, if you control another Zombie, you may a draw card. If you do, discard a card. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DrawDiscardControllerEffect(1,1,true)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new PermanentsOnTheBattlefieldCondition(filter), "When {this} enters the battlefield, if you control another Zombie, you may a draw card. If you do, discard a card.")); diff --git a/Mage.Sets/src/mage/cards/l/LandTax.java b/Mage.Sets/src/mage/cards/l/LandTax.java index a193b62dffe..d25dd644331 100644 --- a/Mage.Sets/src/mage/cards/l/LandTax.java +++ b/Mage.Sets/src/mage/cards/l/LandTax.java @@ -3,7 +3,7 @@ package mage.cards.l; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -24,7 +24,7 @@ public final class LandTax extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); // At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, StaticFilters.FILTER_CARD_BASIC_LAND), true), TargetController.YOU, true), new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS), "At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library" diff --git a/Mage.Sets/src/mage/cards/l/Larceny.java b/Mage.Sets/src/mage/cards/l/Larceny.java index 19279f5e722..297dd135e86 100644 --- a/Mage.Sets/src/mage/cards/l/Larceny.java +++ b/Mage.Sets/src/mage/cards/l/Larceny.java @@ -64,7 +64,7 @@ class LarcenyTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { for(Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); diff --git a/Mage.Sets/src/mage/cards/l/LashknifeBarrier.java b/Mage.Sets/src/mage/cards/l/LashknifeBarrier.java index 77a2b57084f..994ea460f78 100644 --- a/Mage.Sets/src/mage/cards/l/LashknifeBarrier.java +++ b/Mage.Sets/src/mage/cards/l/LashknifeBarrier.java @@ -79,7 +79,7 @@ class LashknifeBarrierEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = game.getPermanent(event.getTargetId()); - return creature.getControllerId().equals(source.getControllerId()); + return creature.isControlledBy(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java b/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java index 4c27a104f56..ca664a65f48 100644 --- a/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java +++ b/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ProwlCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ProwlAbility; @@ -36,7 +36,7 @@ public final class LatchkeyFaerie extends CardImpl { // When Latchkey Faerie enters the battlefield, if its prowl cost was paid, draw a card. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false); - this.addAbility(new ConditionalTriggeredAbility(ability, ProwlCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCondition.instance, "When {this} enters the battlefield, if its prowl cost was paid, draw a card.")); } diff --git a/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java b/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java new file mode 100644 index 00000000000..bdb34d6533b --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LathlissDragonQueen.java @@ -0,0 +1,76 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.DragonToken2; + +/** + * + * @author TheElk801 + */ +public final class LathlissDragonQueen extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("another nontoken Dragon"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("Dragons"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + filter.add(Predicates.not(new TokenPredicate())); + filter.add(new AnotherPredicate()); + filter2.add(new SubtypePredicate(SubType.DRAGON)); + } + + public LathlissDragonQueen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever another nontoken Dragon enters the battlefield under your control, create a 5/5 red Dragon creature token with flying. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new CreateTokenEffect(new DragonToken2()), filter + )); + // {1}{R}: Dragons you control get +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 0, Duration.EndOfTurn, + filter2, false + ), + new ManaCostsImpl("{1}{R}") + )); + } + + public LathlissDragonQueen(final LathlissDragonQueen card) { + super(card); + } + + @Override + public LathlissDragonQueen copy() { + return new LathlissDragonQueen(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LavabornMuse.java b/Mage.Sets/src/mage/cards/l/LavabornMuse.java index 72dd1f47471..79d6e154bdf 100644 --- a/Mage.Sets/src/mage/cards/l/LavabornMuse.java +++ b/Mage.Sets/src/mage/cards/l/LavabornMuse.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class LavabornMuse extends CardImpl { this.toughness = new MageInt(3); // At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, Lavaborn Muse deals 3 damage to him or her. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3), TargetController.OPPONENT, false, true), new CardsInActivePlayersHandCondition(), "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 3 damage to him or her.")); diff --git a/Mage.Sets/src/mage/cards/l/Lavalanche.java b/Mage.Sets/src/mage/cards/l/Lavalanche.java index 1fb16052dbc..bbb74ff71da 100644 --- a/Mage.Sets/src/mage/cards/l/Lavalanche.java +++ b/Mage.Sets/src/mage/cards/l/Lavalanche.java @@ -51,7 +51,7 @@ class LavalancheEffect extends OneShotEffect { public LavalancheEffect(DynamicValue amount) { super(Outcome.Damage); this.amount = amount; - staticText = "{this} deals X damage to target player or planeswalker and each creature that player or that planeswalker’s controller controls"; + staticText = "{this} deals X damage to target player or planeswalker and each creature that player or that planeswalker's controller controls"; } public LavalancheEffect(final LavalancheEffect effect) { @@ -71,7 +71,7 @@ class LavalancheEffect extends OneShotEffect { return false; } targetPlayer.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, true); - FilterPermanent filter = new FilterPermanent("and each creature that player or that planeswalker’s controller controls"); + FilterPermanent filter = new FilterPermanent("and each creature that player or that planeswalker's controller controls"); filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new ControllerIdPredicate(targetPlayer.getId())); List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java b/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java index 4e4abf26111..fcb2eca5f22 100644 --- a/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java +++ b/Mage.Sets/src/mage/cards/l/LazavDimirMastermind.java @@ -38,7 +38,7 @@ public final class LazavDimirMastermind extends CardImpl { // Hexproof this.addAbility(HexproofAbility.getInstance()); - // Whenever a creature card is put into an opponent's graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card except its name is still Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it gains hexproof and this ability. + // Whenever a creature card is put into an opponent's graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card except its name is Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it has hexproof and this ability. this.addAbility(new PutCardIntoGraveFromAnywhereAllTriggeredAbility( new LazavDimirMastermindEffect(), true, new FilterCreatureCard("a creature card"), @@ -59,7 +59,7 @@ class LazavDimirMastermindEffect extends OneShotEffect { LazavDimirMastermindEffect() { super(Outcome.Copy); - staticText = "you may have {this} become a copy of that card except its name is still {this}, it's legendary in addition to its other types, and it gains hexproof and this ability"; + staticText = "you may have {this} become a copy of that card except its name is Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it has hexproof and this ability"; } LazavDimirMastermindEffect(final LazavDimirMastermindEffect effect) { diff --git a/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java b/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java new file mode 100644 index 00000000000..e86a5719636 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LenaSelflessChampion.java @@ -0,0 +1,110 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.constants.SubType; +import mage.constants.SuperType; +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.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.SoldierToken; + +/** + * + * @author TheElk801 + */ +public final class LenaSelflessChampion extends CardImpl { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("nontoken creature you control"); + + static { + filter.add(Predicates.not(new TokenPredicate())); + } + + public LenaSelflessChampion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Lena, Selfless Champion enters the battlefield, create a 1/1 white Soldier creature token for each nontoken creature you control. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect( + new SoldierToken(), + new PermanentsOnBattlefieldCount(filter) + ).setText("create a 1/1 white Soldier creature token " + + "for each nontoken creature you control") + )); + + // Sacrifice Lena: Creatures you control with power less than Lena's power gain indestructible until end of turn. + this.addAbility(new SimpleActivatedAbility( + new LenaSelflessChampionEffect(), + new SacrificeSourceCost() + )); + } + + public LenaSelflessChampion(final LenaSelflessChampion card) { + super(card); + } + + @Override + public LenaSelflessChampion copy() { + return new LenaSelflessChampion(this); + } +} + +class LenaSelflessChampionEffect extends OneShotEffect { + + public LenaSelflessChampionEffect() { + super(Outcome.Benefit); + this.staticText = "Creatures you control with power less than " + + "{this}'s power gain indestructible until end of turn"; + } + + public LenaSelflessChampionEffect(final LenaSelflessChampionEffect effect) { + super(effect); + } + + @Override + public LenaSelflessChampionEffect copy() { + return new LenaSelflessChampionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (permanent == null) { + return false; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, permanent.getPower().getValue())); + game.addEffect(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), + Duration.EndOfTurn, filter + ), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeoninVanguard.java b/Mage.Sets/src/mage/cards/l/LeoninVanguard.java new file mode 100644 index 00000000000..fe1bd4452b9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeoninVanguard.java @@ -0,0 +1,60 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class LeoninVanguard extends CardImpl { + + public LeoninVanguard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // At the beginning of combat on your turn, if you control three or more creatures, Leonin Vanguard gets +1/+1 until end of turn and you gain 1 life. + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new BeginningOfCombatTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + TargetController.YOU, false + ), + new PermanentsOnTheBattlefieldCondition( + StaticFilters.FILTER_CONTROLLED_CREATURES, + ComparisonType.MORE_THAN, 2 + ), + "At the beginning of combat on your turn, " + + "if you control three or more creatures, " + + "{this} gets +1/+1 until end of turn and you gain 1 life." + ); + ability.addEffect(new GainLifeEffect(1)); + this.addAbility(ability); + } + + public LeoninVanguard(final LeoninVanguard card) { + super(card); + } + + @Override + public LeoninVanguard copy() { + return new LeoninVanguard(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeoninWarleader.java b/Mage.Sets/src/mage/cards/l/LeoninWarleader.java new file mode 100644 index 00000000000..09396f6eae3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeoninWarleader.java @@ -0,0 +1,41 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.CatToken2; + +/** + * + * @author TheElk801 + */ +public final class LeoninWarleader extends CardImpl { + + public LeoninWarleader(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); + + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever Leonin Warleader attacks, create two 1/1 white Cat creature tokens with lifelink that are tapped and attacking. + this.addAbility(new AttacksTriggeredAbility( + new CreateTokenEffect(new CatToken2(), 2, true, true), false + )); + } + + public LeoninWarleader(final LeoninWarleader card) { + super(card); + } + + @Override + public LeoninWarleader copy() { + return new LeoninWarleader(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeopardSpottedJiao.java b/Mage.Sets/src/mage/cards/l/LeopardSpottedJiao.java new file mode 100644 index 00000000000..a29c1936486 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeopardSpottedJiao.java @@ -0,0 +1,32 @@ +package mage.cards.l; + +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 LeopardSpottedJiao extends CardImpl { + + public LeopardSpottedJiao(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + } + + public LeopardSpottedJiao(final LeopardSpottedJiao card) { + super(card); + } + + @Override + public LeopardSpottedJiao copy() { + return new LeopardSpottedJiao(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java b/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java index cce548fd280..270e0500530 100644 --- a/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java +++ b/Mage.Sets/src/mage/cards/l/LeovoldEmissaryOfTrest.java @@ -109,7 +109,7 @@ class LeovoldEmissaryOfTrestTriggeredAbility extends TriggeredAbilityImpl { return true; // Player was targeted } Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent != null && this.getControllerId().equals(permanent.getControllerId())) { + if (permanent != null && this.isControlledBy(permanent.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/l/Leviathan.java b/Mage.Sets/src/mage/cards/l/Leviathan.java index c6bb0adc1f9..e963de31dc7 100644 --- a/Mage.Sets/src/mage/cards/l/Leviathan.java +++ b/Mage.Sets/src/mage/cards/l/Leviathan.java @@ -29,7 +29,7 @@ import mage.game.events.GameEvent; import mage.target.common.TargetControlledPermanent; -//import mage.abilities.decorator.ConditionalTriggeredAbility; +//import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; /** * diff --git a/Mage.Sets/src/mage/cards/l/LeylineOfTheMeek.java b/Mage.Sets/src/mage/cards/l/LeylineOfTheMeek.java index 56fc1e737b8..075873700e2 100644 --- a/Mage.Sets/src/mage/cards/l/LeylineOfTheMeek.java +++ b/Mage.Sets/src/mage/cards/l/LeylineOfTheMeek.java @@ -1,4 +1,3 @@ - package mage.cards.l; import java.util.UUID; @@ -10,29 +9,28 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.TokenPredicate; +import mage.filter.StaticFilters; /** * * @author emerald000 */ public final class LeylineOfTheMeek extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creature tokens"); - static { - filter.add(new TokenPredicate()); - } public LeylineOfTheMeek(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // If Leyline of the Meek is in your opening hand, you may begin the game with it on the battlefield. this.addAbility(LeylineAbility.getInstance()); - + // Creature tokens get +1/+1. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, false))); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostAllEffect( + 1, 1, Duration.WhileOnBattlefield, + StaticFilters.FILTER_CREATURE_TOKENS, false + ) + )); } public LeylineOfTheMeek(final LeylineOfTheMeek card) { diff --git a/Mage.Sets/src/mage/cards/l/LichsCaress.java b/Mage.Sets/src/mage/cards/l/LichsCaress.java new file mode 100644 index 00000000000..937ce0be839 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LichsCaress.java @@ -0,0 +1,34 @@ +package mage.cards.l; + +import java.util.UUID; +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.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class LichsCaress extends CardImpl { + + public LichsCaress(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}"); + + // Destroy target creature. You gain 3 life. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addEffect(new GainLifeEffect(3)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public LichsCaress(final LichsCaress card) { + super(card); + } + + @Override + public LichsCaress copy() { + return new LichsCaress(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/Lifeline.java b/Mage.Sets/src/mage/cards/l/Lifeline.java index 4f3d1a17472..e78a26f7086 100644 --- a/Mage.Sets/src/mage/cards/l/Lifeline.java +++ b/Mage.Sets/src/mage/cards/l/Lifeline.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; @@ -30,7 +30,7 @@ public final class Lifeline extends CardImpl { // Whenever a creature dies, if another creature is on the battlefield, return the first card to the battlefield under its owner's control at the beginning of the next end step. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new DiesCreatureTriggeredAbility( Zone.BATTLEFIELD, new LifelineEffect(), false, StaticFilters.FILTER_PERMANENT_CREATURE, true), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_PERMANENT_CREATURE, ComparisonType.MORE_THAN, 0, false), "Whenever a creature dies, if another creature is on the battlefield, return the first card to the battlefield under its owner's control at the beginning of the next end step."); diff --git a/Mage.Sets/src/mage/cards/l/LightOfSanction.java b/Mage.Sets/src/mage/cards/l/LightOfSanction.java index c9528142999..a0976975685 100644 --- a/Mage.Sets/src/mage/cards/l/LightOfSanction.java +++ b/Mage.Sets/src/mage/cards/l/LightOfSanction.java @@ -56,13 +56,13 @@ class LightOfSanctionEffect extends PreventionEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { MageObject damageSource = game.getObject(event.getSourceId()); if (damageSource instanceof Controllable) { - return ((Controllable) damageSource).getControllerId().equals(source.getControllerId()); + return ((Controllable) damageSource).isControlledBy(source.getControllerId()); } else if (damageSource instanceof Card) { - return ((Card) damageSource).getOwnerId().equals(source.getControllerId()); + return ((Card) damageSource).isOwnedBy(source.getControllerId()); } } } diff --git a/Mage.Sets/src/mage/cards/l/LightningMare.java b/Mage.Sets/src/mage/cards/l/LightningMare.java new file mode 100644 index 00000000000..557cd1daa89 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LightningMare.java @@ -0,0 +1,68 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.CantBeCounteredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class LightningMare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blue creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + } + + public LightningMare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{R}"); + + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.HORSE); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // This spell can't be countered. + this.addAbility(new CantBeCounteredAbility()); + + // Lightning Mare can't be blocked by blue creatures. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ) + )); + + // {1}{R}: Lightning Mare gets +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(1, 0, Duration.EndOfTurn), + new ManaCostsImpl("{1}{R}") + )); + } + + public LightningMare(final LightningMare card) { + super(card); + } + + @Override + public LightningMare copy() { + return new LightningMare(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java b/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java new file mode 100644 index 00000000000..9023347f94d --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java @@ -0,0 +1,109 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.constants.SuperType; +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.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class LilianaTheNecromancer extends CardImpl { + + public LilianaTheNecromancer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.LILIANA); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Target player loses 2 life. + Ability ability = new LoyaltyAbility(new LoseLifeTargetEffect(2), 1); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + + // −1: Return target creature card from your graveyard to your hand. + ability = new LoyaltyAbility(new ReturnToHandTargetEffect(), -1); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + this.addAbility(ability); + + // −7: Destroy up to two target creatures. Put up to two creature cards from graveyards onto the battlefield under your control. + ability = new LoyaltyAbility(new DestroyTargetEffect(), -7); + ability.addTarget(new TargetCreaturePermanent(0, 2)); + ability.addEffect(new LilianaTheNecromancerEffect()); + this.addAbility(ability); + } + + public LilianaTheNecromancer(final LilianaTheNecromancer card) { + super(card); + } + + @Override + public LilianaTheNecromancer copy() { + return new LilianaTheNecromancer(this); + } +} + +class LilianaTheNecromancerEffect extends OneShotEffect { + + private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards from graveyards"); + + public LilianaTheNecromancerEffect() { + super(Outcome.Benefit); + this.staticText = "Put up to two creature cards from graveyards onto the battlefield under your control"; + } + + public LilianaTheNecromancerEffect(final LilianaTheNecromancerEffect effect) { + super(effect); + } + + @Override + public LilianaTheNecromancerEffect copy() { + return new LilianaTheNecromancerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Target target = new TargetCardInGraveyard(0, 2, filter); + target.setNotTarget(true); + if (!player.choose(outcome, target, source.getSourceId(), game)) { + return false; + } + Cards cardsToMove = new CardsImpl(); + for (UUID targetId : target.getTargets()) { + Card card = game.getCard(targetId); + if (card != null) { + cardsToMove.add(card); + } + } + return player.moveCards(cardsToMove, Zone.BATTLEFIELD, source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java b/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java new file mode 100644 index 00000000000..6d569e10128 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java @@ -0,0 +1,145 @@ +package mage.cards.l; + +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class LilianaUntouchedByDeath extends CardImpl { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent(SubType.ZOMBIE, "Zombies you control"); + + public LilianaUntouchedByDeath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.LILIANA); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Put the top three cards of your library into your graveyard. If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life. + this.addAbility(new LoyaltyAbility(new LilianaUntouchedByDeathEffect(), 1)); + + // -2: Target creature gets -X/-X until end of turn, where X is the number of Zombies you control. + DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, -1); + Ability ability = new LoyaltyAbility( + new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn, true) + .setText("target creature gets -X/-X until end of turn, " + + "where X is the number of Zombies you control"), -2 + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // -3: You may cast Zombie cards from your graveyard this turn. + this.addAbility(new LoyaltyAbility(new LilianaUntouchedByDeathGraveyardEffect(), -3)); + } + + public LilianaUntouchedByDeath(final LilianaUntouchedByDeath card) { + super(card); + } + + @Override + public LilianaUntouchedByDeath copy() { + return new LilianaUntouchedByDeath(this); + } +} + +class LilianaUntouchedByDeathEffect extends OneShotEffect { + + public LilianaUntouchedByDeathEffect() { + super(Outcome.Benefit); + this.staticText = "put the top three cards of your library into your graveyard. " + + "If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life"; + } + + public LilianaUntouchedByDeathEffect(final LilianaUntouchedByDeathEffect effect) { + super(effect); + } + + @Override + public LilianaUntouchedByDeathEffect copy() { + return new LilianaUntouchedByDeathEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + boolean doEffect = false; + Set top3 = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, 3), source, game, Zone.LIBRARY); + for (Card card : top3) { + if (card != null && card.hasSubtype(SubType.ZOMBIE, game)) { + doEffect = true; + break; + } + } + if (doEffect) { + new LoseLifeOpponentsEffect(2).apply(game, source); + player.gainLife(2, game, source); + } + return true; + } +} + +class LilianaUntouchedByDeathGraveyardEffect extends AsThoughEffectImpl { + + public LilianaUntouchedByDeathGraveyardEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + staticText = "You may cast Zombie cards from your graveyard this turn"; + } + + public LilianaUntouchedByDeathGraveyardEffect(final LilianaUntouchedByDeathGraveyardEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public LilianaUntouchedByDeathGraveyardEffect copy() { + return new LilianaUntouchedByDeathGraveyardEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (affectedControllerId.equals(source.getControllerId())) { + Card card = game.getCard(objectId); + if (card != null + && card.hasSubtype(SubType.ZOMBIE, game) + && card.isOwnedBy(source.getControllerId()) + && game.getState().getZone(objectId) == Zone.GRAVEYARD) { + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/l/LilianasContract.java b/Mage.Sets/src/mage/cards/l/LilianasContract.java new file mode 100644 index 00000000000..68ca8092406 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LilianasContract.java @@ -0,0 +1,89 @@ +package mage.cards.l; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class LilianasContract extends CardImpl { + + public LilianasContract(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); + + // When Liliana's Contract enters the battlefield, you draw four cards and you lose 4 life. + Ability ability = new EntersBattlefieldTriggeredAbility( + new DrawCardSourceControllerEffect(4) + .setText("you draw four cards") + ); + ability.addEffect( + new LoseLifeSourceControllerEffect(4) + .setText("and you lose 4 life") + ); + this.addAbility(ability); + + // At the beginning of your upkeep, if you control four or more Demons with different names, you win the game. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility( + new WinGameSourceControllerEffect(), + TargetController.YOU, false + ), LilianasContractCondition.instance, + "At the beginning of your upkeep, " + + "if you control four or more Demons with different names, " + + "you win the game." + )); + } + + public LilianasContract(final LilianasContract card) { + super(card); + } + + @Override + public LilianasContract copy() { + return new LilianasContract(this); + } +} + +enum LilianasContractCondition implements Condition { + + instance; + + @Override + public boolean apply(Game game, Ability source) { + Set demonNames = new HashSet(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { + if (permanent == null + || !permanent.isControlledBy(source.getControllerId()) + || !permanent.hasSubtype(SubType.DEMON, game)) { + continue; + } + demonNames.add(permanent.getName()); + if (demonNames.size() > 3) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "you control four or more Demons with different names"; + } +} diff --git a/Mage.Sets/src/mage/cards/l/LilianasSpoils.java b/Mage.Sets/src/mage/cards/l/LilianasSpoils.java new file mode 100644 index 00000000000..9238ae90a55 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LilianasSpoils.java @@ -0,0 +1,53 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class LilianasSpoils extends CardImpl { + + private static final FilterCard filter = new FilterCard("a black card"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + public LilianasSpoils(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); + + // Target opponent discards a card. + this.getSpellAbility().addEffect(new DiscardTargetEffect(1)); + this.getSpellAbility().addTarget(new TargetOpponent()); + + // Look at the top five cards of your library. You may reveal a black card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect( + new StaticValue(5), false, new StaticValue(1), filter, + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false + ).setBackInRandomOrder(true).setText("Look at the top five cards of your library. " + + "You may reveal a black card from among them and put it into your hand. " + + "Put the rest on the bottom of your library in a random order.") + ); + } + + public LilianasSpoils(final LilianasSpoils card) { + super(card); + } + + @Override + public LilianasSpoils copy() { + return new LilianasSpoils(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java b/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java index c28203c2c1d..2079804bdce 100644 --- a/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java +++ b/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.condition.common.OpponentHasMoreLifeCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.FlyingAbility; @@ -35,12 +35,12 @@ public final class LinvalaThePreserver extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Linvala, the Preserver enters the battlefield, if an opponent has more life than you, you gain 5 life. - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5), false), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5), false), OpponentHasMoreLifeCondition.instance, "When {this} enters the battlefield, if an opponent has more life than you, you gain 5 life.")); // When Linvala enters the battlefield, if an opponent controls more creatures than you, create a 3/3 white Angel creature token with flying. - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new LinvalaAngelToken()), false), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new LinvalaAngelToken()), false), new OpponentControlsMoreCondition(new FilterCreaturePermanent()), "When {this} enters the battlefield, if an opponent controls more creatures than you, create a 3/3 white Angel creature token with flying.")); } diff --git a/Mage.Sets/src/mage/cards/l/LionsEyeDiamond.java b/Mage.Sets/src/mage/cards/l/LionsEyeDiamond.java index d90cc470085..69983349c42 100644 --- a/Mage.Sets/src/mage/cards/l/LionsEyeDiamond.java +++ b/Mage.Sets/src/mage/cards/l/LionsEyeDiamond.java @@ -42,8 +42,8 @@ public final class LionsEyeDiamond extends CardImpl { class LionsEyeDiamondAbility extends ActivatedManaAbilityImpl { public LionsEyeDiamondAbility() { - super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(3), new SacrificeSourceCost()); - this.addCost(new DiscardHandCost()); + super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(3), new DiscardHandCost()); + this.addCost(new SacrificeSourceCost()); this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 3, 0)); } diff --git a/Mage.Sets/src/mage/cards/l/LivingArtifact.java b/Mage.Sets/src/mage/cards/l/LivingArtifact.java index 9dda0d19d61..df0a4ce70ad 100644 --- a/Mage.Sets/src/mage/cards/l/LivingArtifact.java +++ b/Mage.Sets/src/mage/cards/l/LivingArtifact.java @@ -7,7 +7,7 @@ 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.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DoIfCostPaid; @@ -47,7 +47,8 @@ public final class LivingArtifact extends CardImpl { // Whenever you're dealt damage, put that many vitality counters on Living Artifact. this.addAbility(new LivingArtifactTriggeredAbility()); // At the beginning of your upkeep, you may remove a vitality counter from Living Artifact. If you do, you gain 1 life. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new GainLifeEffect(1), + //TODO make this a custom ability- it's really not intervening if because you should be able to add counters in response to this trigger + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new GainLifeEffect(1), new RemoveCountersSourceCost(CounterType.VITALITY.createInstance(1))), TargetController.YOU, false), new SourceHasCounterCondition(CounterType.VITALITY, 1), "At the beginning of your upkeep, you may remove a vitality counter from {this}. If you do, you gain 1 life")); } diff --git a/Mage.Sets/src/mage/cards/l/LlanowarScout.java b/Mage.Sets/src/mage/cards/l/LlanowarScout.java index 20b2ef33234..2c529a8ac69 100644 --- a/Mage.Sets/src/mage/cards/l/LlanowarScout.java +++ b/Mage.Sets/src/mage/cards/l/LlanowarScout.java @@ -29,7 +29,7 @@ public final class LlanowarScout extends CardImpl { // {T}: You may put a land card from your hand onto the battlefield. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_BASIC_LAND_A), new TapSourceCost())); + new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A), new TapSourceCost())); } public LlanowarScout(final LlanowarScout card) { diff --git a/Mage.Sets/src/mage/cards/l/LoafingGiant.java b/Mage.Sets/src/mage/cards/l/LoafingGiant.java new file mode 100644 index 00000000000..0bffafbc682 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoafingGiant.java @@ -0,0 +1,76 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.PreventCombatDamageBySourceEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByAllSourceEffect; +import mage.cards.Card; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author noahg + */ +public final class LoafingGiant extends CardImpl { + + public LoafingGiant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); + + this.subtype.add(SubType.GIANT); + this.power = new MageInt(4); + this.toughness = new MageInt(6); + + // Whenever Loafing Giant attacks or blocks, put the top card of your library into your graveyard. If that card is a land card, prevent all combat damage Loafing Giant would deal this turn. + this.addAbility(new AttacksOrBlocksTriggeredAbility(new LoafingGiantEffect(), false)); + } + + public LoafingGiant(final LoafingGiant card) { + super(card); + } + + @Override + public LoafingGiant copy() { + return new LoafingGiant(this); + } +} + +class LoafingGiantEffect extends OneShotEffect { + + public LoafingGiantEffect() { + super(Outcome.UnboostCreature); + this.staticText = "Put the top card of your library into your graveyard. If that card is a land card, prevent all combat damage {this} would deal this turn."; + } + + public LoafingGiantEffect(final LoafingGiantEffect effect) { + super(effect); + } + + @Override + public LoafingGiantEffect copy() { + return new LoafingGiantEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + Card card = player.getLibrary().getFromTop(game); + if (card != null) { + player.moveCards(card, Zone.GRAVEYARD, source, game); + if (card.isLand()) { + game.addEffect(new PreventCombatDamageBySourceEffect(Duration.EndOfTurn), source); + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/l/LoamingShaman.java b/Mage.Sets/src/mage/cards/l/LoamingShaman.java index d31cd699bf0..e9ed578b3f1 100644 --- a/Mage.Sets/src/mage/cards/l/LoamingShaman.java +++ b/Mage.Sets/src/mage/cards/l/LoamingShaman.java @@ -99,10 +99,10 @@ class LoamingShamanTargetCardsInGraveyard extends TargetCardInGraveyard { if (firstTarget != null) { Card card = game.getCard(firstTarget); if (card == null || targetCard == null - || !card.getOwnerId().equals(targetCard.getOwnerId())) { + || !card.isOwnedBy(targetCard.getOwnerId())) { return false; } - } else if (targetCard == null || !targetCard.getOwnerId().equals(targetPlayerId)) { + } else if (targetCard == null || !targetCard.isOwnedBy(targetPlayerId)) { return false; } return super.canTarget(id, source, game); diff --git a/Mage.Sets/src/mage/cards/l/LocketOfYesterdays.java b/Mage.Sets/src/mage/cards/l/LocketOfYesterdays.java index 8c649f6fcff..e987b48df8b 100644 --- a/Mage.Sets/src/mage/cards/l/LocketOfYesterdays.java +++ b/Mage.Sets/src/mage/cards/l/LocketOfYesterdays.java @@ -70,7 +70,7 @@ class LocketOfYesterdaysCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify.getControllerId().equals(source.getControllerId()) + if (abilityToModify.isControlledBy(source.getControllerId()) && (abilityToModify instanceof SpellAbility)) { return true; } diff --git a/Mage.Sets/src/mage/cards/l/LoneRider.java b/Mage.Sets/src/mage/cards/l/LoneRider.java index be4b2ad6745..dd364058d1f 100644 --- a/Mage.Sets/src/mage/cards/l/LoneRider.java +++ b/Mage.Sets/src/mage/cards/l/LoneRider.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.LifelinkAbility; @@ -47,7 +47,7 @@ public final class LoneRider extends CardImpl { // At the beginning of the end step, if you gained 3 or more life this turn, transform Lone Rider. this.addAbility(new TransformAbility()); TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new TransformSourceEffect(true)); - this.addAbility(new ConditionalTriggeredAbility(triggered, new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2), ruleText), new PlayerGainedLifeWatcher()); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2), ruleText), new PlayerGainedLifeWatcher()); } public LoneRider(final LoneRider card) { diff --git a/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java b/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java index 8832be2b6ae..53b08ece1dd 100644 --- a/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/cards/l/LoneWolfOfTheNatterknolls.java @@ -8,6 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; @@ -39,12 +40,12 @@ public final class LoneWolfOfTheNatterknolls extends CardImpl { this.addAbility(new ConditionalTriggeredAbility( new SpellCastOpponentTriggeredAbility(new DrawCardSourceControllerEffect(2), new FilterSpell("a spell"), true), MyTurnCondition.instance, - "Whenever an opponent casts a spell during your turn, draw two card." + "Whenever an opponent casts a spell during your turn, draw two cards." )); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Lone Wolf of the Natterknolls. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public LoneWolfOfTheNatterknolls(final LoneWolfOfTheNatterknolls card) { diff --git a/Mage.Sets/src/mage/cards/l/LordWindgrace.java b/Mage.Sets/src/mage/cards/l/LordWindgrace.java new file mode 100644 index 00000000000..3cbd21e70f2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LordWindgrace.java @@ -0,0 +1,112 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.CanBeYourCommanderAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.OneShotEffect; +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.TargetController; +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.TargetNonlandPermanent; + +/** + * + * @author TheElk801 + */ +public final class LordWindgrace extends CardImpl { + + private static final FilterLandCard filter = new FilterLandCard("land cards from your graveyard"); + + static { + filter.add(new OwnerPredicate(TargetController.YOU)); + } + + public LordWindgrace(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.WINDGRACE); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: Discard a card, then draw a card. If a land card is discarded this way, draw an additional card. + this.addAbility(new LoyaltyAbility(new LordWindgraceEffect(), 2)); + + // -3: Return up to two target land cards from your graveyard to the battlefield. + Ability ability = new LoyaltyAbility( + new ReturnFromGraveyardToBattlefieldTargetEffect(), -3 + ); + ability.addTarget(new TargetCardInASingleGraveyard(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. + ability = new LoyaltyAbility(new DestroyTargetEffect(), -11); + ability.addEffect( + new CreateTokenEffect(new CatWarriorToken(), 6) + .setText(", then create six 2/2 green Cat Warrior " + + "creature tokens with forestwalk") + ); + ability.addTarget(new TargetNonlandPermanent(0, 6, false)); + this.addAbility(ability); + + // Lord Windgrace can be your commander. + this.addAbility(CanBeYourCommanderAbility.getInstance()); + } + + public LordWindgrace(final LordWindgrace card) { + super(card); + } + + @Override + public LordWindgrace copy() { + return new LordWindgrace(this); + } +} + +class LordWindgraceEffect extends OneShotEffect { + + public LordWindgraceEffect() { + super(Outcome.Benefit); + this.staticText = "discard a card, then draw a card. " + + "If a land card is discarded this way, draw an additional card"; + } + + public LordWindgraceEffect(final LordWindgraceEffect effect) { + super(effect); + } + + @Override + public LordWindgraceEffect copy() { + return new LordWindgraceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.discardOne(false, source, game); + if (card == null || !card.isLand()) { + player.drawCards(1, game); + } else { + player.drawCards(2, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/l/LostLegacy.java b/Mage.Sets/src/mage/cards/l/LostLegacy.java index 6cb6d652549..a2eec689c1d 100644 --- a/Mage.Sets/src/mage/cards/l/LostLegacy.java +++ b/Mage.Sets/src/mage/cards/l/LostLegacy.java @@ -4,7 +4,7 @@ package mage.cards.l; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class LostLegacy extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}{B}"); // Name a nonartifact, nonland card. Search target player's graveyard, hand and library for any number of cards with that name and exile them. That player shuffles their library, then draws a card for each card exiled from hand this way. - this.getSpellAbility().addEffect((new NameACardEffect(NameACardEffect.TypeOfName.NON_ARTIFACT_AND_NON_LAND_NAME))); + this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_ARTIFACT_AND_NON_LAND_NAME))); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new LostLegacyEffect()); } @@ -52,7 +52,7 @@ class LostLegacyEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExi @Override public boolean apply(Game game, Ability source) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); if (targetPlayer != null && cardName != null && !cardName.isEmpty()) { FilterCard filter = new FilterCard(); diff --git a/Mage.Sets/src/mage/cards/l/LoyalApprentice.java b/Mage.Sets/src/mage/cards/l/LoyalApprentice.java new file mode 100644 index 00000000000..048afacdf9e --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoyalApprentice.java @@ -0,0 +1,95 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.common.CommanderInPlayCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.HasteAbility; +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.ThopterColorlessToken; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class LoyalApprentice extends CardImpl { + + public LoyalApprentice(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Lieutenant — At the beginning of combat on your turn, if you control your commander, create a 1/1 colorless Thopter artifact creature token with flying. That token gains haste until end of turn. + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfCombatTriggeredAbility( + new LoyalApprenticeEffect(), + TargetController.YOU, false + ), CommanderInPlayCondition.instance, + "Lieutenant — At the beginning of combat " + + "on your turn, create a 1/1 colorless Thopter " + + "artifact creature token with flying. " + + "That token gains haste until end of turn" + )); + } + + public LoyalApprentice(final LoyalApprentice card) { + super(card); + } + + @Override + public LoyalApprentice copy() { + return new LoyalApprentice(this); + } +} + +class LoyalApprenticeEffect extends OneShotEffect { + + public LoyalApprenticeEffect() { + super(Outcome.Benefit); + } + + public LoyalApprenticeEffect(final LoyalApprenticeEffect effect) { + super(effect); + } + + @Override + public LoyalApprenticeEffect copy() { + return new LoyalApprenticeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + CreateTokenEffect effect = new CreateTokenEffect(new ThopterColorlessToken()); + effect.apply(game, source); + effect.getLastAddedTokenIds().stream().map((tokenId) -> { + ContinuousEffect continuousEffect = new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ); + continuousEffect.setTargetPointer(new FixedTarget(tokenId, game)); + return continuousEffect; + }).forEachOrdered((continuousEffect) -> { + game.addEffect(continuousEffect, source); + }); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/l/LoyalDrake.java b/Mage.Sets/src/mage/cards/l/LoyalDrake.java new file mode 100644 index 00000000000..e2e27052ed1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoyalDrake.java @@ -0,0 +1,51 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.common.CommanderInPlayCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; + +/** + * + * @author TheElk801 + */ +public final class LoyalDrake extends CardImpl { + + public LoyalDrake(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.DRAKE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Lieutenant — At the beginning of combat on your turn, if you control your commander, draw a card. + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfCombatTriggeredAbility( + new DrawCardSourceControllerEffect(1), + TargetController.YOU, false + ), CommanderInPlayCondition.instance, + "Lieutenant — At the beginning of combat " + + "on your turn, if you control your commander, draw a card." + )); + } + + public LoyalDrake(final LoyalDrake card) { + super(card); + } + + @Override + public LoyalDrake copy() { + return new LoyalDrake(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LoyalGuardian.java b/Mage.Sets/src/mage/cards/l/LoyalGuardian.java new file mode 100644 index 00000000000..9b368b0bac7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoyalGuardian.java @@ -0,0 +1,56 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.common.CommanderInPlayCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class LoyalGuardian extends CardImpl { + + public LoyalGuardian(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.subtype.add(SubType.RHINO); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Lieutenant — At the beginning of combat on your turn, if you control your commander, put a +1/+1 counter on each creature you control. + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfCombatTriggeredAbility( + new AddCountersAllEffect( + CounterType.P1P1.createInstance(), + StaticFilters.FILTER_CONTROLLED_CREATURE + ), TargetController.YOU, false + ), CommanderInPlayCondition.instance, + "Lieutenant — At the beginning of combat " + + "on your turn, if you control your commander, " + + "put a +1/+1 counter on each creature you control." + )); + } + + public LoyalGuardian(final LoyalGuardian card) { + super(card); + } + + @Override + public LoyalGuardian copy() { + return new LoyalGuardian(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LoyalSubordinate.java b/Mage.Sets/src/mage/cards/l/LoyalSubordinate.java new file mode 100644 index 00000000000..fe87346014a --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoyalSubordinate.java @@ -0,0 +1,52 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.common.CommanderInPlayCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.constants.SubType; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; + +/** + * + * @author TheElk801 + */ +public final class LoyalSubordinate extends CardImpl { + + public LoyalSubordinate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Menace + this.addAbility(new MenaceAbility()); + + // Lieutenant — At the beginning of combat on your turn, if you control your commander, each opponent loses 3 life. + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfCombatTriggeredAbility( + new LoseLifeOpponentsEffect(3), + TargetController.YOU, false + ), CommanderInPlayCondition.instance, + "Lieutenant — At the beginning of combat " + + "on your turn, if you control your commander, " + + "each opponent loses 3 life." + )); + } + + public LoyalSubordinate(final LoyalSubordinate card) { + super(card); + } + + @Override + public LoyalSubordinate copy() { + return new LoyalSubordinate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LoyalUnicorn.java b/Mage.Sets/src/mage/cards/l/LoyalUnicorn.java new file mode 100644 index 00000000000..40b8aec51e1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoyalUnicorn.java @@ -0,0 +1,66 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.common.CommanderInPlayCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.PreventAllDamageToAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.constants.SubType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class LoyalUnicorn extends CardImpl { + + public LoyalUnicorn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.UNICORN); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Lieutenant — At the beginning of combat on your turn, if you control your commander, prevent all combat damage that would be dealt to creatures you control this turn. Other creatures you control gain vigilance until end of turn. + TriggeredAbility ability = new BeginningOfCombatTriggeredAbility( + new PreventAllDamageToAllEffect( + Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURES, + true + ), TargetController.YOU, false + ); + ability.addEffect(new GainAbilityAllEffect( + VigilanceAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURES, true + )); + this.addAbility(new ConditionalTriggeredAbility( + ability, CommanderInPlayCondition.instance, + "Lieutenant — At the beginning of combat " + + "on your turn, if you control your commander, " + + "prevent all combat damage that would be dealt " + + "to creatures you control this turn. " + + "Other creatures you control gain vigilance until end of turn." + )); + } + + public LoyalUnicorn(final LoyalUnicorn card) { + super(card); + } + + @Override + public LoyalUnicorn copy() { + return new LoyalUnicorn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java index 1dcfaf01d60..d6884df7a7d 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java +++ b/Mage.Sets/src/mage/cards/l/LudevicsTestSubject.java @@ -29,7 +29,7 @@ public final class LudevicsTestSubject extends CardImpl { public LudevicsTestSubject(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); - this.subtype.add(SubType.LIZARD); + this.subtype.add(SubType.LIZARD, SubType.EGG); this.power = new MageInt(0); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/l/LukeSkywalkerTheLastJedi.java b/Mage.Sets/src/mage/cards/l/LukeSkywalkerTheLastJedi.java new file mode 100644 index 00000000000..37f18bdf531 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LukeSkywalkerTheLastJedi.java @@ -0,0 +1,69 @@ +package mage.cards.l; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.command.emblems.LukeSkywalkerEmblem; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class LukeSkywalkerTheLastJedi extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("noncreature permanent"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + public LukeSkywalkerTheLastJedi(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{G}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.LUKE); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); + + // +1: Put two +1/+1 counters on up to one target creature. + Ability ability1 = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)), 2); + ability1.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability1); + + // -3: Put target noncreature permanent on top of its owner's library. + Ability ability2 = new LoyaltyAbility(new PutOnLibraryTargetEffect(true), -3); + ability2.addTarget(new TargetPermanent(filter)); + this.addAbility(ability2); + + // -6: You get an emblem with "Prevent all damage that would be dealt to you during combat." Exile Luke Skywalker, the Last Jedi. + Ability ability3 = new LoyaltyAbility(new GetEmblemEffect(new LukeSkywalkerEmblem()), -6); + ability3.addEffect(new ExileSourceEffect()); + this.addAbility(ability3); + } + + public LukeSkywalkerTheLastJedi(final LukeSkywalkerTheLastJedi card) { + super(card); + } + + @Override + public LukeSkywalkerTheLastJedi copy() { + return new LukeSkywalkerTheLastJedi(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LumengridDrake.java b/Mage.Sets/src/mage/cards/l/LumengridDrake.java index 6b32df10c53..884ac2cced3 100644 --- a/Mage.Sets/src/mage/cards/l/LumengridDrake.java +++ b/Mage.Sets/src/mage/cards/l/LumengridDrake.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MetalcraftCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -20,7 +20,7 @@ import mage.target.common.TargetCreaturePermanent; */ public final class LumengridDrake extends CardImpl { - private static final String ruleText = "Metalcraft - When {this} enters the battlefield, if you control three or more artifacts, return target creature to its owner's hand."; + private static final String ruleText = "Metalcraft — When {this} enters the battlefield, if you control three or more artifacts, return target creature to its owner's hand."; public LumengridDrake(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); @@ -34,7 +34,7 @@ public final class LumengridDrake extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Metalcraft — When Lumengrid Drake enters the battlefield, if you control three or more artifacts, return target creature to its owner's hand. - TriggeredAbility conditional = new ConditionalTriggeredAbility( + TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), MetalcraftCondition.instance, ruleText); conditional.addTarget(new TargetCreaturePermanent()); this.addAbility(conditional); diff --git a/Mage.Sets/src/mage/cards/l/LuminarchAscension.java b/Mage.Sets/src/mage/cards/l/LuminarchAscension.java index ebc9d328dae..b2710993d13 100644 --- a/Mage.Sets/src/mage/cards/l/LuminarchAscension.java +++ b/Mage.Sets/src/mage/cards/l/LuminarchAscension.java @@ -9,7 +9,7 @@ import mage.abilities.condition.Condition; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class LuminarchAscension extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); // At the beginning of each opponent's end step, if you didn't lose life this turn, you may put a quest counter on Luminarch Ascension. - this.addAbility(new ConditionalTriggeredAbility(new LuminarchAscensionTriggeredAbility(), YouLostNoLifeThisTurnCondition.instance, rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new LuminarchAscensionTriggeredAbility(), YouLostNoLifeThisTurnCondition.instance, rule)); // {1}{W}: Create a 4/4 white Angel creature token with flying. Activate this ability only if Luminarch Ascension has four or more quest counters on it. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new AngelToken()), new ManaCostsImpl("{1}{W}")); diff --git a/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java b/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java index d5df07c0b8a..ce678715e65 100644 --- a/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java +++ b/Mage.Sets/src/mage/cards/l/LuminatePrimordial.java @@ -88,7 +88,7 @@ class LuminatePrimordialEffect extends OneShotEffect { for (Target target: source.getTargets()) { if (target instanceof TargetCreaturePermanent) { Permanent targetCreature = game.getPermanent(target.getFirstTarget()); - if (targetCreature != null && !targetCreature.getControllerId().equals(source.getControllerId())) { + if (targetCreature != null && !targetCreature.isControlledBy(source.getControllerId())) { int amountLife = targetCreature.getPower().getValue(); Player controller = game.getPlayer(targetCreature.getControllerId()); targetCreature.moveToExile(null, null, source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/l/LureOfPrey.java b/Mage.Sets/src/mage/cards/l/LureOfPrey.java new file mode 100644 index 00000000000..c6b81a46c8e --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LureOfPrey.java @@ -0,0 +1,93 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; +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.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * + * @author TheElk801 + */ +public final class LureOfPrey extends CardImpl { + + private static final FilterCreatureCard filter = new FilterCreatureCard("a green creature card"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public LureOfPrey(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}{G}"); + + // Cast Lure of Prey only if an opponent cast a creature spell this turn. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new LureOfPreyRestrictionEffect())); + + // You may put a green creature card from your hand onto the battlefield. + this.getSpellAbility().addEffect(new PutCardFromHandOntoBattlefieldEffect(filter)); + } + + public LureOfPrey(final LureOfPrey card) { + super(card); + } + + @Override + public LureOfPrey copy() { + return new LureOfPrey(this); + } +} + +class LureOfPreyRestrictionEffect extends ContinuousRuleModifyingEffectImpl { + + public LureOfPreyRestrictionEffect() { + super(Duration.EndOfGame, Outcome.Detriment); + staticText = "Cast this spell only if an opponent cast a creature spell this turn"; + } + + public LureOfPreyRestrictionEffect(final LureOfPreyRestrictionEffect effect) { + super(effect); + } + + @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.getSourceId().equals(source.getSourceId())) { + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + if (watcher != null) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { + if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(playerId) != 0) { + return false; + } + } + } + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public LureOfPreyRestrictionEffect copy() { + return new LureOfPreyRestrictionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MadDog.java b/Mage.Sets/src/mage/cards/m/MadDog.java index 7b1a3c5769d..f9206d7ec02 100644 --- a/Mage.Sets/src/mage/cards/m/MadDog.java +++ b/Mage.Sets/src/mage/cards/m/MadDog.java @@ -9,7 +9,7 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class MadDog extends CardImpl { this.toughness = new MageInt(2); // At the beginning of your end step, if Mad Dog didn't attack or come under your control this turn, sacrifice it. - Ability ability = new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility(new SacrificeSourceEffect(), TargetController.YOU, false), MadDogCondition.instance, "At the beginning of your end step, if {this} didn't attack or come under your control this turn, sacrifice it"); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility(new SacrificeSourceEffect(), TargetController.YOU, false), MadDogCondition.instance, "At the beginning of your end step, if {this} didn't attack or come under your control this turn, sacrifice it"); ability.addWatcher(new AttackedThisTurnWatcher()); ability.addWatcher(new PermanentsEnteredBattlefieldWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/MadScienceFairProject.java b/Mage.Sets/src/mage/cards/m/MadScienceFairProject.java index 986645a92bc..98e77a9b71b 100644 --- a/Mage.Sets/src/mage/cards/m/MadScienceFairProject.java +++ b/Mage.Sets/src/mage/cards/m/MadScienceFairProject.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -25,7 +24,7 @@ public final class MadScienceFairProject extends CardImpl { public MadScienceFairProject(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - // {tap}: Roll a six-sided die. On a 3 or lower, target player adds {C}. Otherwise, that player adds one mana of any color he or she chooses. + // {T}: Roll a six-sided die. On a 3 or lower, target player adds {C}. Otherwise, that player adds one mana of any color he or she chooses. this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new MadScienceFairManaEffect(), new TapSourceCost())); } @@ -79,7 +78,6 @@ class MadScienceFairManaEffect extends ManaEffect { ChoiceColor choice = new ChoiceColor(); if (controller.choose(Outcome.PutManaInPool, choice, game)) { Mana chosen = choice.getMana(1); - checkToFirePossibleEvents(chosen, game, source); return chosen; } } diff --git a/Mage.Sets/src/mage/cards/m/MaelstromBlockade.java b/Mage.Sets/src/mage/cards/m/MaelstromBlockade.java new file mode 100644 index 00000000000..f846763df63 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MaelstromBlockade.java @@ -0,0 +1,34 @@ +package mage.cards.m; + +import java.util.UUID; + +import mage.abilities.effects.common.ExileTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetAttackingCreature; + +/** + * + * @author NinthWorld + */ +public final class MaelstromBlockade extends CardImpl { + + public MaelstromBlockade(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W/B}"); + + + // Exile target attacking creature. + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addTarget(new TargetAttackingCreature()); + } + + public MaelstromBlockade(final MaelstromBlockade card) { + super(card); + } + + @Override + public MaelstromBlockade copy() { + return new MaelstromBlockade(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MaelstromNexus.java b/Mage.Sets/src/mage/cards/m/MaelstromNexus.java index 73ed90b41ea..c88f8d523ce 100644 --- a/Mage.Sets/src/mage/cards/m/MaelstromNexus.java +++ b/Mage.Sets/src/mage/cards/m/MaelstromNexus.java @@ -67,7 +67,7 @@ class MaelstromNexusGainCascadeFirstSpellEffect extends ContinuousEffectImpl { if (controller != null) { for (StackObject stackObject : game.getStack()) { // only spells cast, so no copies of spells - if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; FirstSpellCastThisTurnWatcher watcher = (FirstSpellCastThisTurnWatcher) game.getState().getWatchers().get(FirstSpellCastThisTurnWatcher.class.getSimpleName()); if (watcher != null && spell.getId().equals(watcher.getIdOfFirstCastSpell(source.getControllerId()))) { diff --git a/Mage.Sets/src/mage/cards/m/MageSlayer.java b/Mage.Sets/src/mage/cards/m/MageSlayer.java index 46cf27870ea..537e414882c 100644 --- a/Mage.Sets/src/mage/cards/m/MageSlayer.java +++ b/Mage.Sets/src/mage/cards/m/MageSlayer.java @@ -47,7 +47,7 @@ class MageSlayerEffect extends OneShotEffect { public MageSlayerEffect() { super(Outcome.Damage); - staticText = "it deals damage equal to the player or planeswalker it’s attacking"; + staticText = "it deals damage equal to the player or planeswalker it's attacking"; } public MageSlayerEffect(final MageSlayerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java b/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java new file mode 100644 index 00000000000..49a0aba1f41 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java @@ -0,0 +1,199 @@ +package mage.cards.m; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.MageInt; +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.OneShotEffect; +import mage.cards.Card; +import mage.constants.SubType; +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.filter.FilterCard; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class MagusOfTheBalance extends CardImpl { + + public MagusOfTheBalance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {4}{W}, {T}, Sacrifice Magus of the Balance: Each player chooses a number of lands they control equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players discard cards and sacrifice creatures the same way. + Ability ability = new SimpleActivatedAbility( + new MagusOfTheBalanceEffect(), + new ManaCostsImpl("{4}{W}") + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public MagusOfTheBalance(final MagusOfTheBalance card) { + super(card); + } + + @Override + public MagusOfTheBalance copy() { + return new MagusOfTheBalance(this); + } +} + +class MagusOfTheBalanceEffect extends OneShotEffect { + + MagusOfTheBalanceEffect() { + super(Outcome.Sacrifice); + staticText = "each player chooses a number of lands they control " + + "equal to the number of lands controlled by the player " + + "who controls the fewest, then sacrifices the rest. " + + "Players discard cards and sacrifice creatures the same way"; + } + + MagusOfTheBalanceEffect(final MagusOfTheBalanceEffect effect) { + super(effect); + } + + @Override + public MagusOfTheBalanceEffect copy() { + return new MagusOfTheBalanceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + //Lands + int minLand = Integer.MAX_VALUE; + Cards landsToSacrifice = new CardsImpl(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int count = game.getBattlefield().countAll(new FilterControlledLandPermanent(), player.getId(), game); + if (count < minLand) { + minLand = count; + } + } + } + + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, new FilterControlledLandPermanent("lands to keep"), true); + if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledLandPermanent(), player.getId(), source.getSourceId(), game)) { + if (permanent != null && !target.getTargets().contains(permanent.getId())) { + landsToSacrifice.add(permanent); + } + } + } + } + } + + for (UUID cardId : landsToSacrifice) { + Permanent permanent = game.getPermanent(cardId); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + } + + //Creatures + int minCreature = Integer.MAX_VALUE; + Cards creaturesToSacrifice = new CardsImpl(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int count = game.getBattlefield().countAll(new FilterControlledCreaturePermanent(), player.getId(), game); + if (count < minCreature) { + minCreature = count; + } + } + } + + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, new FilterControlledCreaturePermanent("creatures to keep"), true); + if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), source.getSourceId(), game)) { + if (permanent != null && !target.getTargets().contains(permanent.getId())) { + creaturesToSacrifice.add(permanent); + } + } + } + } + } + + for (UUID cardId : creaturesToSacrifice) { + Permanent permanent = game.getPermanent(cardId); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + } + + //Cards in hand + int minCard = Integer.MAX_VALUE; + Map cardsToDiscard = new HashMap<>(2); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int count = player.getHand().size(); + if (count < minCard) { + minCard = count; + } + } + } + + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + Cards cards = new CardsImpl(); + TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard("cards to keep")); + if (target.choose(Outcome.Discard, player.getId(), source.getSourceId(), game)) { + for (Card card : player.getHand().getCards(game)) { + if (card != null && !target.getTargets().contains(card.getId())) { + cards.add(card); + } + } + cardsToDiscard.put(playerId, cards); + } + } + } + + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null && cardsToDiscard.get(playerId) != null) { + for (UUID cardId : cardsToDiscard.get(playerId)) { + Card card = game.getCard(cardId); + if (card != null) { + player.discard(card, source, game); + } + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java b/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java index e5e17cad40d..cc23294d283 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java @@ -9,7 +9,7 @@ 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.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class MagusOfTheScroll extends CardImpl { this.toughness = new MageInt(1); // {3}, {tap}: Name a card. Reveal a card at random from your hand. If it's the named card, Magus of the Scroll deals 2 damage to any target. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NameACardEffect(NameACardEffect.TypeOfName.ALL), new ManaCostsImpl("{3}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new ManaCostsImpl("{3}")); ability.addEffect(new MagusOfTheScrollEffect()); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); @@ -59,7 +59,7 @@ class MagusOfTheScrollEffect extends OneShotEffect { public MagusOfTheScrollEffect() { super(Outcome.Neutral); - staticText = ", then reveal a card at random from your hand. If it's the named card, {this} deals 2 damage to any target"; + staticText = ", then reveal a card at random from your hand. If that card has the chosen name, {this} deals 2 damage to any target"; } public MagusOfTheScrollEffect(final MagusOfTheScrollEffect effect) { @@ -70,7 +70,7 @@ class MagusOfTheScrollEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (sourceObject != null && you != null && cardName != null && !cardName.isEmpty()) { if (!you.getHand().isEmpty()) { Cards revealed = new CardsImpl(); diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheWill.java b/Mage.Sets/src/mage/cards/m/MagusOfTheWill.java index 604ffe0b417..e56c7ef98e5 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheWill.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheWill.java @@ -137,9 +137,9 @@ class MagusOfTheWillReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(source.getControllerId())) { + if (card != null && card.isOwnedBy(source.getControllerId())) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); - if (permanent == null || !(permanent instanceof PermanentToken)) { + if (!(permanent instanceof PermanentToken)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/m/Malfegor.java b/Mage.Sets/src/mage/cards/m/Malfegor.java index 31116dc7d7c..27e7f2fc1c9 100644 --- a/Mage.Sets/src/mage/cards/m/Malfegor.java +++ b/Mage.Sets/src/mage/cards/m/Malfegor.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -74,7 +73,7 @@ class MalfegorEffect extends OneShotEffect { return true; } new DiscardHandControllerEffect().apply(game, source); - return new SacrificeOpponentsEffect(sacrificeNumber, StaticFilters.FILTER_PERMANENT_CREATURE).apply(game, source); + return new SacrificeOpponentsEffect(sacrificeNumber, StaticFilters.FILTER_CONTROLLED_CREATURE).apply(game, source); } @Override diff --git a/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java b/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java index b7c5cccbfbc..56840b6b5b3 100644 --- a/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java +++ b/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java @@ -6,7 +6,7 @@ import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; @@ -38,8 +38,8 @@ public final class MaliciousAffliction extends CardImpl { public MaliciousAffliction(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}{B}"); - // Morbid - When you cast Malicious Affliction, if a creature died this turn, you may copy Malicious Affliction and may choose a new target for the copy. - Ability ability = new ConditionalTriggeredAbility( + // Morbid — When you cast Malicious Affliction, if a creature died this turn, you may copy Malicious Affliction and may choose a new target for the copy. + Ability ability = new ConditionalInterveningIfTriggeredAbility( new CastSourceTriggeredAbility(new CopySourceSpellEffect(), true), new LockedInCondition(MorbidCondition.instance), "Morbid — When you cast {this}, if a creature died this turn, you may copy {this} and may choose a new target for the copy"); @@ -81,7 +81,7 @@ class CopySourceSpellEffect extends OneShotEffect { Spell spell = game.getStack().getSpell(source.getSourceId()); if (spell != null) { StackObject stackObjectCopy = spell.createCopyOnStack(game, source, source.getControllerId(), true); - if (stackObjectCopy != null && stackObjectCopy instanceof Spell) { + if (stackObjectCopy instanceof Spell) { String activateMessage = ((Spell) stackObjectCopy).getActivatedMessage(game); if (activateMessage.startsWith(" casts ")) { activateMessage = activateMessage.substring(6); diff --git a/Mage.Sets/src/mage/cards/m/ManaBloom.java b/Mage.Sets/src/mage/cards/m/ManaBloom.java index 01c53a06ae2..fcc059f515f 100644 --- a/Mage.Sets/src/mage/cards/m/ManaBloom.java +++ b/Mage.Sets/src/mage/cards/m/ManaBloom.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; @@ -40,7 +40,7 @@ public final class ManaBloom extends CardImpl { // At the beginning of your upkeep, if Mana Bloom has no charge counters on it, return it to its owner's hand. TriggeredAbility triggeredAbility = new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(triggeredAbility, new SourceHasCounterCondition(CounterType.CHARGE, 0, 0), "At the beginning of your upkeep, if Mana Bloom has no charge counters on it, return it to its owner's hand.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggeredAbility, new SourceHasCounterCondition(CounterType.CHARGE, 0, 0), "At the beginning of your upkeep, if Mana Bloom has no charge counters on it, return it to its owner's hand.")); } diff --git a/Mage.Sets/src/mage/cards/m/ManaShort.java b/Mage.Sets/src/mage/cards/m/ManaShort.java index d91c911824e..f4d396e9196 100644 --- a/Mage.Sets/src/mage/cards/m/ManaShort.java +++ b/Mage.Sets/src/mage/cards/m/ManaShort.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -7,7 +6,7 @@ import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterLandPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; @@ -39,7 +38,7 @@ public final class ManaShort extends CardImpl { class ManaShortEffect extends TapAllTargetPlayerControlsEffect { public ManaShortEffect() { - super(new FilterLandPermanent()); + super(StaticFilters.FILTER_LANDS); staticText = "Tap all lands target player controls and that player loses all unspent mana"; } diff --git a/Mage.Sets/src/mage/cards/m/ManaVault.java b/Mage.Sets/src/mage/cards/m/ManaVault.java index efaab07fd19..334841b2b5d 100644 --- a/Mage.Sets/src/mage/cards/m/ManaVault.java +++ b/Mage.Sets/src/mage/cards/m/ManaVault.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; @@ -39,7 +39,7 @@ public final class ManaVault extends CardImpl { TargetController.YOU, false)); // At the beginning of your draw step, if Mana Vault is tapped, it deals 1 damage to you. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfDrawTriggeredAbility(Zone.BATTLEFIELD, new DamageControllerEffect(1), TargetController.YOU, false), SourceTappedCondition.instance, "At the beginning of your draw step, if {this} is tapped, it deals 1 damage to you.")); diff --git a/Mage.Sets/src/mage/cards/m/Manaplasm.java b/Mage.Sets/src/mage/cards/m/Manaplasm.java index d3fab12d96a..26e23737080 100644 --- a/Mage.Sets/src/mage/cards/m/Manaplasm.java +++ b/Mage.Sets/src/mage/cards/m/Manaplasm.java @@ -67,7 +67,7 @@ class ManaplasmAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getControllerId().equals(controllerId)) { + if (spell != null && spell.isControlledBy(controllerId)) { this.getEffects().remove(0); int x = spell.getConvertedManaCost(); this.addEffect(new BoostSourceEffect(x,x, Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/m/MangarasTome.java b/Mage.Sets/src/mage/cards/m/MangarasTome.java index 0d92198f566..c46179ffc40 100644 --- a/Mage.Sets/src/mage/cards/m/MangarasTome.java +++ b/Mage.Sets/src/mage/cards/m/MangarasTome.java @@ -123,6 +123,6 @@ class MangarasTomeReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/m/ManicScribe.java b/Mage.Sets/src/mage/cards/m/ManicScribe.java index ce55d1822d6..d97181341d2 100644 --- a/Mage.Sets/src/mage/cards/m/ManicScribe.java +++ b/Mage.Sets/src/mage/cards/m/ManicScribe.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect; import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveTargetEffect; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class ManicScribe extends CardImpl { // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // that player puts the top three cards of their library into their graveyard. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3), TargetController.OPPONENT, false, true), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/m/ManorGargoyle.java b/Mage.Sets/src/mage/cards/m/ManorGargoyle.java index 1b5ab352d04..848cf88b836 100644 --- a/Mage.Sets/src/mage/cards/m/ManorGargoyle.java +++ b/Mage.Sets/src/mage/cards/m/ManorGargoyle.java @@ -47,13 +47,13 @@ public final class ManorGargoyle extends CardImpl { 613.7. Within a layer or sublayer, determining which order effects are applied in is sometimes done using a dependency system. If a dependency exists, it will override the timestamp system. 613.7a An effect is said to “depend on” another if - (a) it’s applied in the same layer (and, if applicable, sublayer) as the other effect (see rules 613.1 and 613.3); + (a) it's applied in the same layer (and, if applicable, sublayer) as the other effect (see rules 613.1 and 613.3); (b) applying the other would change the text or the existence of the first effect, what it applies to, or what it does to any of the things it applies to; and (c) neither effect is from a characteristic-defining ability or both effects are from characteristic-defining abilities. Otherwise, the effect is considered to be independent of the other effect. 613.7b An effect dependent on one or more other effects waits to apply until just after all of those effects have been applied. - If multiple dependent effects would apply simultaneously in this way, they’re applied in timestamp order relative to each + If multiple dependent effects would apply simultaneously in this way, they're applied in timestamp order relative to each other. If several dependent effects form a dependency loop, then this rule is ignored and the effects in the dependency loop are applied in timestamp order. 613.7c After each effect is applied, the order of remaining effects is reevaluated and may change if an effect that has not yet diff --git a/Mage.Sets/src/mage/cards/m/MarangRiverProwler.java b/Mage.Sets/src/mage/cards/m/MarangRiverProwler.java index 1e7591a456a..e03922c936d 100644 --- a/Mage.Sets/src/mage/cards/m/MarangRiverProwler.java +++ b/Mage.Sets/src/mage/cards/m/MarangRiverProwler.java @@ -89,7 +89,7 @@ class MarangRiverProwlerCastEffect extends AsThoughEffectImpl { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(source.getSourceId()); if (card != null - && card.getOwnerId().equals(affectedControllerId) + && card.isOwnedBy(affectedControllerId) && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD && game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/m/MaraudersAxe.java b/Mage.Sets/src/mage/cards/m/MaraudersAxe.java new file mode 100644 index 00000000000..cafc791c90b --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MaraudersAxe.java @@ -0,0 +1,39 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class MaraudersAxe extends CardImpl { + + public MaraudersAxe(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature +2/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 0))); + + // Equip {2} + this.addAbility(new EquipAbility(2)); + } + + public MaraudersAxe(final MaraudersAxe card) { + super(card); + } + + @Override + public MaraudersAxe copy() { + return new MaraudersAxe(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MaraudingLooter.java b/Mage.Sets/src/mage/cards/m/MaraudingLooter.java index 4daa43e29db..97f12cf25a0 100644 --- a/Mage.Sets/src/mage/cards/m/MaraudingLooter.java +++ b/Mage.Sets/src/mage/cards/m/MaraudingLooter.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class MaraudingLooter extends CardImpl { this.toughness = new MageInt(3); // Raid - At the beginning of your end step, if you attacked with a creature this turn, you may draw a card. If you do, discard a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true), TargetController.YOU, false), RaidCondition.instance, "Raid — At the beginning of your end step, " diff --git a/Mage.Sets/src/mage/cards/m/MarblePriest.java b/Mage.Sets/src/mage/cards/m/MarblePriest.java new file mode 100644 index 00000000000..7cc77515bd5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MarblePriest.java @@ -0,0 +1,74 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.PreventAllDamageToSourceEffect; +import mage.abilities.effects.common.combat.MustBeBlockedByAllSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author TheElk801 + */ +public final class MarblePriest extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WALL, "Walls"); + + public MarblePriest(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // All Walls able to block Marble Priest do so. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new MustBeBlockedByAllSourceEffect( + Duration.WhileOnBattlefield, + filter + ) + )); + + // Prevent all combat damage that would be dealt to Marble Priest by Walls. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new MarblePriestPreventionEffect() + )); + } + + public MarblePriest(final MarblePriest card) { + super(card); + } + + @Override + public MarblePriest copy() { + return new MarblePriest(this); + } +} + +class MarblePriestPreventionEffect extends PreventAllDamageToSourceEffect { + + public MarblePriestPreventionEffect() { + super(Duration.WhileOnBattlefield); + staticText = "Prevent all combat damage that would be dealt to {this} by Walls"; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return super.applies(event, source, game) + && event.getFlag() + && game.getObject(event.getSourceId()).hasSubtype(SubType.WALL, game) + && event.getTargetId().equals(source.getSourceId()); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MarchOfTheDroids.java b/Mage.Sets/src/mage/cards/m/MarchOfTheDroids.java index 6a07b61fa9f..5e31a472b5b 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfTheDroids.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfTheDroids.java @@ -69,7 +69,7 @@ class MarchOfTheDroidsEffect extends OneShotEffect { if (controller != null) { Cards cardsToReturn = new CardsImpl(); for (Card card : controller.getGraveyard().getCards(game)) { - if (card.getOwnerId().equals(controller.getId()) && card.getCounters(game).getCount(CounterType.REPAIR) > 0) { + if (card.isOwnedBy(controller.getId()) && card.getCounters(game).getCount(CounterType.REPAIR) > 0) { int number = card.getCounters(game).getCount(CounterType.REPAIR); if (number > 0) { cardsToReturn.add(card); diff --git a/Mage.Sets/src/mage/cards/m/MarchesaTheBlackRose.java b/Mage.Sets/src/mage/cards/m/MarchesaTheBlackRose.java index 6617f13762c..1dc83d372b5 100644 --- a/Mage.Sets/src/mage/cards/m/MarchesaTheBlackRose.java +++ b/Mage.Sets/src/mage/cards/m/MarchesaTheBlackRose.java @@ -89,7 +89,7 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl { && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent != null - && permanent.getControllerId().equals(this.getControllerId()) + && permanent.isControlledBy(this.getControllerId()) && permanent.isCreature() && permanent.getCounters(game).getCount(CounterType.P1P1) > 0) { for (Effect effect : this.getEffects()) { diff --git a/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java b/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java index 72b98260c19..2be60fad5a5 100644 --- a/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java +++ b/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class MarduHeartPiercer extends CardImpl { this.toughness = new MageInt(3); // Raid - When Mardu Heart-Piercer enters the battlefield, if you attacked with a creature this turn, Mardu Heart-Piercer deals 2 damage to any target. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)), RaidCondition.instance, + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, {this} deals 2 damage to any target."); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability, new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/m/MarduHordechief.java b/Mage.Sets/src/mage/cards/m/MarduHordechief.java index 50c79dbdb94..7c01254d9f4 100644 --- a/Mage.Sets/src/mage/cards/m/MarduHordechief.java +++ b/Mage.Sets/src/mage/cards/m/MarduHordechief.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class MarduHordechief extends CardImpl { this.toughness = new MageInt(3); // Raid — When Mardu Hordechief enters the battlefield, if you attacked with a creature this turn, create a 1/1 white Warrior creature token - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorToken())), RaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorToken())), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, create a 1/1 white Warrior creature token."), new PlayerAttackedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java b/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java index 395a90175e1..bfbafab3142 100644 --- a/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java +++ b/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class MarduSkullhunter extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // Raid - When Mardu Skullhunter enters the battlefield, if you attacked with a creature this turn, target opponent discards a card. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)), RaidCondition.instance, + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, target opponent discards a card."); ability.addTarget(new TargetOpponent()); this.addAbility(ability, new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java b/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java index d654cea80fb..c5730481146 100644 --- a/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java +++ b/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.Mana; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class MarduWarshrieker extends CardImpl { this.toughness = new MageInt(3); // Raid - When Mardu Warshrieker enters the battlefield, if you attacked with a creature this turn, add {R}{W}{B}. - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new AddManaToManaPoolSourceControllerEffect(new Mana(1, 0, 0, 1, 1, 0, 0, 0))), RaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new AddManaToManaPoolSourceControllerEffect(new Mana(1, 0, 0, 1, 1, 0, 0, 0))), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, add {R}{W}{B}."), new PlayerAttackedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/m/MarkOfSakiko.java b/Mage.Sets/src/mage/cards/m/MarkOfSakiko.java index d72311ef87c..e0465716bdd 100644 --- a/Mage.Sets/src/mage/cards/m/MarkOfSakiko.java +++ b/Mage.Sets/src/mage/cards/m/MarkOfSakiko.java @@ -43,9 +43,9 @@ public final class MarkOfSakiko extends CardImpl { Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - // Enchanted creature has "Whenever this creature deals combat damage to a player, add that much {G}. Until end of turn, you don’t lose this mana as steps and phases end." + // Enchanted creature has "Whenever this creature deals combat damage to a player, add that much {G}. Until end of turn, you don't lose this mana as steps and phases end." Effect effect = new GainAbilityAttachedEffect(new MarkOfSakikoTriggeredAbility(), AttachmentType.AURA); - effect.setText("Enchanted creature has \"Whenever this creature deals combat damage to a player, add that much {G}. Until end of turn, you don’t lose this mana as steps and phases end.\""); + effect.setText("Enchanted creature has \"Whenever this creature deals combat damage to a player, add that much {G}. Until end of turn, you don't lose this mana as steps and phases end.\""); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } @@ -87,7 +87,7 @@ class MarkOfSakikoTriggeredAbility extends TriggeredAbilityImpl { this.getEffects().clear(); Effect effect = new AddManaToManaPoolTargetControllerEffect(Mana.GreenMana(event.getAmount()), "that player", true); effect.setTargetPointer(new FixedTarget(getControllerId())); - effect.setText("add that much {G}. Until end of turn, you don’t lose this mana as steps and phases end"); + effect.setText("add that much {G}. Until end of turn, you don't lose this mana as steps and phases end"); this.addEffect(effect); return true; } @@ -98,6 +98,6 @@ class MarkOfSakikoTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { return "Whenever this creature deals combat damage to a player, add that much {G}. " - + "Until end of turn, you don’t lose this mana as steps and phases end."; + + "Until end of turn, you don't lose this mana as steps and phases end."; } } diff --git a/Mage.Sets/src/mage/cards/m/MarketFestival.java b/Mage.Sets/src/mage/cards/m/MarketFestival.java index f6421137288..b6431fa7651 100644 --- a/Mage.Sets/src/mage/cards/m/MarketFestival.java +++ b/Mage.Sets/src/mage/cards/m/MarketFestival.java @@ -78,7 +78,7 @@ class MarketFestivalTriggeredAbility extends TriggeredManaAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent enchantment = game.getPermanent(this.getSourceId()); - return enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo()); + return enchantment != null && enchantment.isAttachedTo(event.getSourceId()); } @Override diff --git a/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java b/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java index ac98efd9fb9..39c3a3503da 100644 --- a/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java +++ b/Mage.Sets/src/mage/cards/m/MarshalsAnthem.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.continuous.BoostAllEffect; @@ -51,7 +51,8 @@ public final class MarshalsAnthem extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, false))); // 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. - Ability ability = new ConditionalTriggeredAbility( + //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."); diff --git a/Mage.Sets/src/mage/cards/m/MartyrsBond.java b/Mage.Sets/src/mage/cards/m/MartyrsBond.java index cebfff601bd..930d3670c18 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrsBond.java +++ b/Mage.Sets/src/mage/cards/m/MartyrsBond.java @@ -74,7 +74,7 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent.getControllerId().equals(this.getControllerId()) && !permanent.isLand()) { + if (permanent.isControlledBy(this.getControllerId()) && !permanent.isLand()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(permanent.getId())); } diff --git a/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java b/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java index ba482b84461..8a237ea8793 100644 --- a/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java +++ b/Mage.Sets/src/mage/cards/m/MarwynTheNurturer.java @@ -39,7 +39,7 @@ public final class MarwynTheNurturer extends CardImpl { // Whenever another Elf enters the battlefield under your control, put a +1/+1 counter on Marwyn, the Nurturer. this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter)); - // {T}: Add an amount of {G} equal to Marwyn’s power. + // {T}: Add an amount of {G} equal to Marwyn's power. this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), new SourcePermanentPowerCount(), "Add an amount of {G} equal to {this}'s power")); } diff --git a/Mage.Sets/src/mage/cards/m/MasakoTheHumorless.java b/Mage.Sets/src/mage/cards/m/MasakoTheHumorless.java index e4ef412e4c2..1ab1ddf3505 100644 --- a/Mage.Sets/src/mage/cards/m/MasakoTheHumorless.java +++ b/Mage.Sets/src/mage/cards/m/MasakoTheHumorless.java @@ -68,7 +68,7 @@ class BlockTappedEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java b/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java index 47baa6141a0..beeb2fc7838 100644 --- a/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java +++ b/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.DomainValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; @@ -28,7 +28,7 @@ public final class MaskOfIntolerance extends CardImpl { // At the beginning of each player's upkeep, if there are four or more basic land types among lands that player controls, Mask of Intolerance deals 3 damage to him or her. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new MaskOfIntoleranceCondition(), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new MaskOfIntoleranceCondition(), "At the beginning of each player's upkeep, if there are four or more basic land types among lands that player controls, {this} deals 3 damage to him or her.")); } diff --git a/Mage.Sets/src/mage/cards/m/Massacre.java b/Mage.Sets/src/mage/cards/m/Massacre.java index 4d67f3550b5..24af1a59d32 100644 --- a/Mage.Sets/src/mage/cards/m/Massacre.java +++ b/Mage.Sets/src/mage/cards/m/Massacre.java @@ -34,7 +34,7 @@ public final class Massacre extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}{B}"); - // If an opponent controls a Plains and you control a Swamp, you may cast Massacre without paying its mana cost. + // If an opponent controls a Plains and you control a Swamp, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Plains and you control a Swamp", new OpponentControlsPermanentCondition(filterPlains), new PermanentsOnTheBattlefieldCondition(filterSwamp)); diff --git a/Mage.Sets/src/mage/cards/m/MassacreWurm.java b/Mage.Sets/src/mage/cards/m/MassacreWurm.java index 86499f56004..48d3342c7a1 100644 --- a/Mage.Sets/src/mage/cards/m/MassacreWurm.java +++ b/Mage.Sets/src/mage/cards/m/MassacreWurm.java @@ -1,5 +1,3 @@ - - package mage.cards.m; import java.util.UUID; @@ -28,8 +26,8 @@ import mage.target.targetpointer.FixedTarget; */ public final class MassacreWurm extends CardImpl { - public MassacreWurm (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}{B}"); + public MassacreWurm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}"); this.subtype.add(SubType.WURM); this.power = new MageInt(6); @@ -38,7 +36,7 @@ public final class MassacreWurm extends CardImpl { this.addAbility(new MassacreWurmTriggeredAbility()); } - public MassacreWurm (final MassacreWurm card) { + public MassacreWurm(final MassacreWurm card) { super(card); } @@ -50,6 +48,7 @@ public final class MassacreWurm extends CardImpl { } class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl { + MassacreWurmTriggeredAbility() { super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(2)); } @@ -70,7 +69,7 @@ class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (((ZoneChangeEvent)event).isDiesEvent()) { + if (((ZoneChangeEvent) event).isDiesEvent()) { Permanent p = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); if (p != null && p.isCreature() && game.getOpponents(this.getControllerId()).contains(p.getControllerId())) { for (Effect effect : this.getEffects()) { @@ -84,6 +83,6 @@ class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a creature an opponent controls is put into a graveyard from the battlefield, " + super.getRule(); + return "Whenever a creature an opponent controls dies, " + super.getRule(); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MasterBiomancer.java b/Mage.Sets/src/mage/cards/m/MasterBiomancer.java index 7b1ca8c4a8a..79f1c605383 100644 --- a/Mage.Sets/src/mage/cards/m/MasterBiomancer.java +++ b/Mage.Sets/src/mage/cards/m/MasterBiomancer.java @@ -66,7 +66,7 @@ class MasterBiomancerEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - return creature != null && creature.getControllerId().equals(source.getControllerId()) + return creature != null && creature.isControlledBy(source.getControllerId()) && creature.isCreature() && !event.getTargetId().equals(source.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java b/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java index 03a269dc62f..00e6affcea9 100644 --- a/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java +++ b/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -11,8 +10,7 @@ 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; /** @@ -21,10 +19,14 @@ import mage.target.common.TargetCreaturePermanent; */ public final class MasterOfDiversion extends CardImpl { - private final UUID originalId; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(new DefendingPlayerControlsPredicate()); + } public MasterOfDiversion(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.SCOUT); @@ -33,27 +35,12 @@ public final class MasterOfDiversion extends CardImpl { // Whenever Master of Diversion attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); - } public MasterOfDiversion(final MasterOfDiversion 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/m/MasterWarcraft.java b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java index 52c6b7adeb5..a5861363c57 100644 --- a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java +++ b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java @@ -42,7 +42,7 @@ public final class MasterWarcraft extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R/W}{R/W}"); // Cast Master Warcraft only before attackers are declared. - this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeAttackersAreDeclaredCondition.instance, "Cast {this} only before attackers are declared")); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, BeforeAttackersAreDeclaredCondition.instance, "Cast this spell only before attackers are declared")); // You choose which creatures attack this turn. this.getSpellAbility().addEffect(new MasterWarcraftChooseAttackersEffect()); diff --git a/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java b/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java index 54ddce301a5..45ab9cb6320 100644 --- a/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java +++ b/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.AscendAbility; import mage.abilities.keyword.FlyingAbility; @@ -46,7 +46,7 @@ public final class MausoleumHarpy extends CardImpl { this.addAbility(new AscendAbility()); // Whenever another creature you control dies, if you have the city's blessing, put a +1/+1 counter on Mausoleum Harpy. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new DiesCreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, filter), CitysBlessingCondition.instance, "Whenever another creature you control dies, if you have the city's blessing, put a +1/+1 counter on {this}. ")); diff --git a/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java b/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java index d85d9d55468..a0b101ebcb4 100644 --- a/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java +++ b/Mage.Sets/src/mage/cards/m/MavrenFeinDuskApostle.java @@ -83,7 +83,7 @@ class MavrenFeinDuskApostleTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { for (UUID creatureId : game.getCombat().getAttackers()) { Permanent creature = game.getPermanent(creatureId); - if (creature != null && filter.match(creature, game) && creature.getControllerId().equals(controllerId)) { + if (creature != null && filter.match(creature, game) && creature.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java b/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java index 53b6eb0de2b..4800d7c2917 100644 --- a/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java +++ b/Mage.Sets/src/mage/cards/m/MayorOfAvabruck.java @@ -10,7 +10,7 @@ import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; @@ -55,7 +55,7 @@ public final class MayorOfAvabruck extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Mayor of Avabruck. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public MayorOfAvabruck(final MayorOfAvabruck card) { diff --git a/Mage.Sets/src/mage/cards/m/MazesEnd.java b/Mage.Sets/src/mage/cards/m/MazesEnd.java index 1a002578e61..d76dbd72717 100644 --- a/Mage.Sets/src/mage/cards/m/MazesEnd.java +++ b/Mage.Sets/src/mage/cards/m/MazesEnd.java @@ -49,7 +49,7 @@ public final class MazesEnd extends CardImpl { // {T}: Add 1. this.addAbility(new ColorlessManaAbility()); - // 3, {T}, Return Maze's End to its owner’s hand: Search your library for a Gate card, put it onto the battlefield, then shuffle your library. If you control ten or more Gates with different names, you win the game. + // 3, {T}, Return Maze's End to its owner's hand: Search your library for a Gate card, put it onto the battlefield, then shuffle your library. If you control ten or more Gates with different names, you win the game. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filterCard)), new GenericManaCost(3)); ability.addEffect(new MazesEndEffect()); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/m/MeanderingTowershell.java b/Mage.Sets/src/mage/cards/m/MeanderingTowershell.java index 5cc9b3b3571..b4725877aaf 100644 --- a/Mage.Sets/src/mage/cards/m/MeanderingTowershell.java +++ b/Mage.Sets/src/mage/cards/m/MeanderingTowershell.java @@ -22,19 +22,19 @@ import mage.players.Player; /** * As Meandering Towershell returns to the battlefield because of the delayed - * triggered ability, you choose which opponent or opposing planeswalker it’s - * attacking. It doesn’t have to attack the same opponent or opposing + * triggered ability, you choose which opponent or opposing planeswalker it's + * attacking. It doesn't have to attack the same opponent or opposing * planeswalker that it was when it was exiled. * - * If Meandering Towershell enters the battlefield attacking, it wasn’t declared + * If Meandering Towershell enters the battlefield attacking, it wasn't declared * as an attacking creature that turn. Abilities that trigger when a creature - * attacks, including its own triggered ability, won’t trigger. + * attacks, including its own triggered ability, won't trigger. * * On the turn Meandering Towershell attacks and is exiled, raid abilities will * see it as a creature that attacked. Conversely, on the turn Meandering * Towershell enters the battlefield attacking, raid abilities will not. * - * If you attack with a Meandering Towershell that you don’t own, you’ll control + * If you attack with a Meandering Towershell that you don't own, you'll control * it when it returns to the battlefield. * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/m/MeddlingMage.java b/Mage.Sets/src/mage/cards/m/MeddlingMage.java index b7b7105730b..c2afa5dce53 100644 --- a/Mage.Sets/src/mage/cards/m/MeddlingMage.java +++ b/Mage.Sets/src/mage/cards/m/MeddlingMage.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -8,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -27,7 +26,7 @@ import mage.game.events.GameEvent.EventType; public final class MeddlingMage extends CardImpl { public MeddlingMage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -35,7 +34,7 @@ public final class MeddlingMage extends CardImpl { this.toughness = new MageInt(2); // As Meddling Mage enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); //The named card can't be cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MeddlingMageReplacementEffect())); @@ -55,7 +54,7 @@ class MeddlingMageReplacementEffect extends ContinuousRuleModifyingEffectImpl { public MeddlingMageReplacementEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "The named card can't be cast"; + staticText = "Spells with the chosen name can't be cast"; } public MeddlingMageReplacementEffect(final MeddlingMageReplacementEffect effect) { @@ -76,7 +75,7 @@ class MeddlingMageReplacementEffect 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 a card with that name (" + mageObject.getLogName() + " in play)."; + return "You can't cast a spell with that name (" + mageObject.getLogName() + " in play)."; } return null; } @@ -90,7 +89,7 @@ class MeddlingMageReplacementEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); // fixes issue #1072 - return object != null && !object.isCopy() && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY)); + return object != null && !object.isCopy() && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY)); } } diff --git a/Mage.Sets/src/mage/cards/m/Melee.java b/Mage.Sets/src/mage/cards/m/Melee.java index 9b6d0ce7856..3031c15e649 100644 --- a/Mage.Sets/src/mage/cards/m/Melee.java +++ b/Mage.Sets/src/mage/cards/m/Melee.java @@ -41,7 +41,7 @@ public final class Melee extends CardImpl { Condition condition = new CompoundCondition(BeforeBlockersAreDeclaredCondition.instance, new IsPhaseCondition(TurnPhase.COMBAT), MyTurnCondition.instance); - this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, condition, "Cast {this} only during your turn and only during combat before blockers are declared")); + this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, condition, "Cast this spell only during your turn and only during combat before blockers are declared")); // You choose which creatures block this combat and how those creatures block. // (only the last resolved Melee spell's blocking effect applies) diff --git a/Mage.Sets/src/mage/cards/m/MelekIzzetParagon.java b/Mage.Sets/src/mage/cards/m/MelekIzzetParagon.java index a407ae32946..8d6dd6cd670 100644 --- a/Mage.Sets/src/mage/cards/m/MelekIzzetParagon.java +++ b/Mage.Sets/src/mage/cards/m/MelekIzzetParagon.java @@ -93,7 +93,7 @@ class MelekIzzetParagonTriggeredAbility extends TriggeredAbilityImpl { if (event.getZone() == Zone.LIBRARY) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null - && spell.getOwnerId().equals(super.getControllerId()) + && spell.isOwnedBy(super.getControllerId()) && (spell.isInstant() || spell.isSorcery())) { for (Effect effect : this.getEffects()) { diff --git a/Mage.Sets/src/mage/cards/m/MeletisCharlatan.java b/Mage.Sets/src/mage/cards/m/MeletisCharlatan.java index fe3d216e277..32170f2ac65 100644 --- a/Mage.Sets/src/mage/cards/m/MeletisCharlatan.java +++ b/Mage.Sets/src/mage/cards/m/MeletisCharlatan.java @@ -39,7 +39,7 @@ public final class MeletisCharlatan extends CardImpl { // {2}{U}, {T}: The controller of target instant or sorcery spell copies it. That player may choose new targets for the copy. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MeletisCharlatanCopyTargetSpellEffect(), new ManaCostsImpl("{2}{U}")); ability.addCost(new TapSourceCost()); - Target target = new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL); + Target target = new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java b/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java index d83881a5f5e..d3d868a2e25 100644 --- a/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java +++ b/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java @@ -121,7 +121,7 @@ class MeliraSylvokOutcastEffect2 extends ReplacementEffectImpl { if (perm == null) { perm = game.getPermanentEntering(event.getTargetId()); } - if (perm != null && perm.isCreature() && perm.getControllerId().equals(source.getControllerId())) { + if (perm != null && perm.isCreature() && perm.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/m/Memoricide.java b/Mage.Sets/src/mage/cards/m/Memoricide.java index fc4d0e8e40c..c38672412f9 100644 --- a/Mage.Sets/src/mage/cards/m/Memoricide.java +++ b/Mage.Sets/src/mage/cards/m/Memoricide.java @@ -1,10 +1,9 @@ - package mage.cards.m; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -19,11 +18,11 @@ import mage.target.TargetPlayer; public final class Memoricide extends CardImpl { public Memoricide(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); // Name a nonland card. Search target player's graveyard, hand, and library for any number of cards with // that name and exile them. Then that player shuffles their library - this.getSpellAbility().addEffect((new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new MemoricideEffect()); } @@ -51,7 +50,7 @@ class MemoricideEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExi @Override public boolean apply(Game game, Ability source) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); return super.applySearchAndExile(game, source, cardName, targetPointer.getFirst(game, source)); } @@ -62,6 +61,6 @@ class MemoricideEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExi @Override public String getText(Mode mode) { - return "Name a nonland card. " + super.getText(mode); + return "Search target player's graveyard, hand, and library for any number of cards with that name and exile them. Then that player shuffles their library"; } } diff --git a/Mage.Sets/src/mage/cards/m/MemoryCrystal.java b/Mage.Sets/src/mage/cards/m/MemoryCrystal.java index 961c67224f3..2da9818be48 100644 --- a/Mage.Sets/src/mage/cards/m/MemoryCrystal.java +++ b/Mage.Sets/src/mage/cards/m/MemoryCrystal.java @@ -74,7 +74,7 @@ class MemoryCrystalSpellsCostReductionEffect extends CostModificationEffectImpl @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { if (BuybackCondition.instance.apply(game, abilityToModify)) { diff --git a/Mage.Sets/src/mage/cards/m/MercilessPredator.java b/Mage.Sets/src/mage/cards/m/MercilessPredator.java index 718162e0cf5..e1a5597fe29 100644 --- a/Mage.Sets/src/mage/cards/m/MercilessPredator.java +++ b/Mage.Sets/src/mage/cards/m/MercilessPredator.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class MercilessPredator extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Merciless Predator. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public MercilessPredator(final MercilessPredator card) { diff --git a/Mage.Sets/src/mage/cards/m/MercurialGeists.java b/Mage.Sets/src/mage/cards/m/MercurialGeists.java index e80e43ced28..4842ee08274 100644 --- a/Mage.Sets/src/mage/cards/m/MercurialGeists.java +++ b/Mage.Sets/src/mage/cards/m/MercurialGeists.java @@ -29,7 +29,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_INSTANT_OR_SORCERY_SPELL, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false)); } public MercurialGeists(final MercurialGeists card) { diff --git a/Mage.Sets/src/mage/cards/m/MercurialPretender.java b/Mage.Sets/src/mage/cards/m/MercurialPretender.java index 12650ac73f7..250feb98cbc 100644 --- a/Mage.Sets/src/mage/cards/m/MercurialPretender.java +++ b/Mage.Sets/src/mage/cards/m/MercurialPretender.java @@ -23,7 +23,7 @@ import mage.util.functions.AbilityApplier; */ public final class MercurialPretender extends CardImpl { - private static final String effectText = "as a copy of any creature you control except it gains \"{2}{U}{U}: Return this creature to its owner's hand.\""; + private static final String effectText = "as a copy of any creature you control, except it has \"{2}{U}{U}: Return this creature to its owner's hand.\""; public MercurialPretender(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); @@ -33,8 +33,8 @@ public final class MercurialPretender extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - // You may have Mercurial Pretender enter the battlefield as a copy of any creature you control - // except it gains "{2}{U}{U}: Return this creature to its owner's hand." + // You may have Mercurial Pretender enter the battlefield as a copy of any creature you control, + // except it has "{2}{U}{U}: Return this creature to its owner's hand." Effect effect = new CopyPermanentEffect(new FilterControlledCreaturePermanent(), new AbilityApplier(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl("{2}{U}{U}")))); effect.setText(effectText); diff --git a/Mage.Sets/src/mage/cards/m/MetallicMimic.java b/Mage.Sets/src/mage/cards/m/MetallicMimic.java index 28105b9f4d6..9dfcca6887d 100644 --- a/Mage.Sets/src/mage/cards/m/MetallicMimic.java +++ b/Mage.Sets/src/mage/cards/m/MetallicMimic.java @@ -4,6 +4,7 @@ package mage.cards.m; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.effects.common.continuous.AddChosenSubtypeEffect; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; @@ -32,10 +33,11 @@ public final class MetallicMimic extends CardImpl { this.toughness = new MageInt(1); // As Metallic Mimic enters the battlefield, choose a creature type. - AsEntersBattlefieldAbility ability = new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature), null, EnterEventType.SELF); + AsEntersBattlefieldAbility ability = new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature)); // Metallic Mimic is the chosen type in addition to its other types. ability.addEffect(new EnterAttributeAddChosenSubtypeEffect()); this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AddChosenSubtypeEffect())); // Each other creature you control of the chosen type enters the battlefield with an additional +1/+1 counter on it. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MetallicMimicReplacementEffect())); @@ -75,7 +77,7 @@ class MetallicMimicReplacementEffect extends ReplacementEffectImpl { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent enteringCreature = ((EntersTheBattlefieldEvent) event).getTarget(); if (enteringCreature != null && sourcePermanent != null - && enteringCreature.getControllerId().equals(source.getControllerId()) + && enteringCreature.isControlledBy(source.getControllerId()) && enteringCreature.isCreature() && !event.getTargetId().equals(source.getSourceId())) { SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java b/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java new file mode 100644 index 00000000000..07c2c8a20a6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MetamorphicAlteration.java @@ -0,0 +1,155 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.keyword.EnchantAbility; +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.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author noahg + */ +public final class MetamorphicAlteration extends CardImpl { + + public MetamorphicAlteration(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); + + // As Metamorphic Alteration enters the battlefield, choose a creature. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACreature())); + + // Enchanted creature is a copy of the chosen creature. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MetamorphicAlterationEffect())); + } + + public MetamorphicAlteration(final MetamorphicAlteration card) { + super(card); + } + + @Override + public MetamorphicAlteration copy() { + return new MetamorphicAlteration(this); + } +} + +class ChooseACreature extends OneShotEffect { + + public static String INFO_KEY = "CHOSEN_CREATURE"; + + public ChooseACreature() { + super(Outcome.Copy); + staticText = "choose a creature"; + } + + public ChooseACreature(final ChooseACreature effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getPermanentEntering(source.getSourceId()); + if (sourceObject == null) { + sourceObject = game.getObject(source.getSourceId()); + } + if (controller != null && sourceObject != null) { + Target target = new TargetCreaturePermanent(); + target.setNotTarget(true); + if (target.canChoose(source.getSourceId(), controller.getId(), game)) { + controller.choose(Outcome.Copy, target, source.getSourceId(), game); + Permanent chosenPermanent = game.getPermanent(target.getFirstTarget()); + if (chosenPermanent != null) { + game.getState().setValue(source.getSourceId().toString() + INFO_KEY, chosenPermanent.copy()); + } + } + return true; + } + return false; + } + + @Override + public ChooseACreature copy() { + return new ChooseACreature(this); + } +} + +class MetamorphicAlterationEffect extends ContinuousEffectImpl { + + public MetamorphicAlterationEffect() { + super(Duration.WhileOnBattlefield, Layer.CopyEffects_1, SubLayer.NA, Outcome.Copy); + this.staticText = "Enchanted creature is a copy of the chosen creature."; + } + + public MetamorphicAlterationEffect(MetamorphicAlterationEffect effect) { + super(effect); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + //TODO this is stupid and there's got to be a better way, but it works and people probably want to practice full M19 before Prerelease. + Permanent enchantment = game.getPermanent(source.getSourceId()); + Permanent copied = (Permanent) game.getState().getValue(source.getSourceId().toString() + ChooseACreature.INFO_KEY); + if (enchantment != null && copied != null) { + Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); + if (permanent != null && layer == Layer.CopyEffects_1) { + permanent.setName(copied.getName()); + permanent.getManaCost().clear(); + permanent.getManaCost().addAll(copied.getManaCost()); + permanent.setExpansionSetCode(copied.getExpansionSetCode()); + permanent.getSuperType().clear(); + for (SuperType t : copied.getSuperType()) { + permanent.addSuperType(t); + } + permanent.getCardType().clear(); + for (CardType t : copied.getCardType()) { + permanent.addCardType(t); + } + permanent.getSubtype(game).retainAll(SubType.getLandTypes(false)); + for (SubType t : copied.getSubtype(game)) { + permanent.getSubtype(game).add(t); + } + permanent.getColor(game).setColor(copied.getColor(game)); + permanent.removeAllAbilities(source.getSourceId(), game); + for (Ability ability : copied.getAbilities()) { + permanent.addAbility(ability, source.getSourceId(), game); + } + permanent.getPower().setValue(copied.getPower().getValue()); + permanent.getToughness().setValue(copied.getToughness().getValue()); + return true; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public MetamorphicAlterationEffect copy() { + return new MetamorphicAlterationEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MeteorGolem.java b/Mage.Sets/src/mage/cards/m/MeteorGolem.java new file mode 100644 index 00000000000..7ddbb6af77f --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MeteorGolem.java @@ -0,0 +1,50 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class MeteorGolem extends CardImpl { + + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent an opponent controls"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public MeteorGolem(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Meteor Golem enters the battlefield, destroy target nonland permanent an opponent controls. + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public MeteorGolem(final MeteorGolem card) { + super(card); + } + + @Override + public MeteorGolem copy() { + return new MeteorGolem(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/Metrognome.java b/Mage.Sets/src/mage/cards/m/Metrognome.java index 733eeb3ae51..daded0f3631 100644 --- a/Mage.Sets/src/mage/cards/m/Metrognome.java +++ b/Mage.Sets/src/mage/cards/m/Metrognome.java @@ -3,7 +3,7 @@ package mage.cards.m; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.DiscardedByOpponentTriggerAbility; +import mage.abilities.common.DiscardedByOpponentTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -24,7 +24,7 @@ public final class Metrognome extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // When a spell or ability an opponent controls causes you to discard Metrognome, create four 1/1 colorless Gnome artifact creature tokens. - this.addAbility(new DiscardedByOpponentTriggerAbility(new CreateTokenEffect(new GnomeToken(), 4))); + this.addAbility(new DiscardedByOpponentTriggeredAbility(new CreateTokenEffect(new GnomeToken(), 4))); // {4}, {tap}: Create a 1/1 colorless Gnome artifact creature token. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new GnomeToken()), new ManaCostsImpl("{4}")); diff --git a/Mage.Sets/src/mage/cards/m/MidnightOil.java b/Mage.Sets/src/mage/cards/m/MidnightOil.java index 3dd316efc81..954d3408969 100644 --- a/Mage.Sets/src/mage/cards/m/MidnightOil.java +++ b/Mage.Sets/src/mage/cards/m/MidnightOil.java @@ -87,10 +87,8 @@ class MidnightOilTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getControllerId().equals(event.getPlayerId())) { - return true; - } - return false; + return isControlledBy(event.getPlayerId()); + } @Override diff --git a/Mage.Sets/src/mage/cards/m/MightMakesRight.java b/Mage.Sets/src/mage/cards/m/MightMakesRight.java index cc8c4333da3..3054b42de96 100644 --- a/Mage.Sets/src/mage/cards/m/MightMakesRight.java +++ b/Mage.Sets/src/mage/cards/m/MightMakesRight.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -47,7 +47,7 @@ public final class MightMakesRight extends CardImpl { gainControlAbility.addEffect(new UntapTargetEffect()); gainControlAbility.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); gainControlAbility.addTarget(new TargetCreaturePermanent(filter)); - Ability conditionalAbility = new ConditionalTriggeredAbility(gainControlAbility, ControlsEachCreatureWithGreatestPowerCondition.instance, ruleText); + Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(gainControlAbility, ControlsEachCreatureWithGreatestPowerCondition.instance, ruleText); this.addAbility(conditionalAbility); } @@ -82,7 +82,7 @@ enum ControlsEachCreatureWithGreatestPowerCondition implements Condition { result = true; } if (power == maxPower) { - result &= permanent.getControllerId().equals(source.getControllerId()); + result &= permanent.isControlledBy(source.getControllerId()); } } return result; diff --git a/Mage.Sets/src/mage/cards/m/MilitiaBugler.java b/Mage.Sets/src/mage/cards/m/MilitiaBugler.java new file mode 100644 index 00000000000..dc13cdc4cfb --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MilitiaBugler.java @@ -0,0 +1,54 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.constants.SubType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author TheElk801 + */ +public final class MilitiaBugler extends CardImpl { + + private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with power 2 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public MilitiaBugler(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()); + + // When Militia Bugler enters the battlefield, look at the top four cards of your library. You may reveal a creature card with power 2 or less from among them and put it into your hand. 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, false + ), false)); + } + + public MilitiaBugler(final MilitiaBugler card) { + super(card); + } + + @Override + public MilitiaBugler copy() { + return new MilitiaBugler(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MindbladeRender.java b/Mage.Sets/src/mage/cards/m/MindbladeRender.java index ab7e20d8796..f17a4d593cb 100644 --- a/Mage.Sets/src/mage/cards/m/MindbladeRender.java +++ b/Mage.Sets/src/mage/cards/m/MindbladeRender.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -12,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; @@ -48,13 +48,13 @@ class MindbladeRenderTriggeredAbility extends TriggeredAbilityImpl { private boolean usedForCombatDamageStep; - MindbladeRenderTriggeredAbility() { + public MindbladeRenderTriggeredAbility() { super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1)); this.addEffect(new LoseLifeSourceControllerEffect(1)); this.usedForCombatDamageStep = false; } - MindbladeRenderTriggeredAbility(final MindbladeRenderTriggeredAbility effect) { + public MindbladeRenderTriggeredAbility(final MindbladeRenderTriggeredAbility effect) { super(effect); this.usedForCombatDamageStep = effect.usedForCombatDamageStep; } @@ -71,6 +71,13 @@ class MindbladeRenderTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_POST) { + usedForCombatDamageStep = false; + return false; + } + if (event.getType() != GameEvent.EventType.DAMAGED_PLAYER) { + return false; + } Player controller = game.getPlayer(getControllerId()); if (controller == null) { return false; @@ -79,17 +86,13 @@ class MindbladeRenderTriggeredAbility extends TriggeredAbilityImpl { if (damager == null) { return false; } - if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER - && event.getFlag() + if (((DamagedPlayerEvent) event).isCombatDamage() && controller.hasOpponent(event.getTargetId(), game) && damager.hasSubtype(SubType.WARRIOR, game) && !usedForCombatDamageStep) { usedForCombatDamageStep = true; return true; } - if (event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_POST) { - usedForCombatDamageStep = false; - } return false; } diff --git a/Mage.Sets/src/mage/cards/m/Mindswipe.java b/Mage.Sets/src/mage/cards/m/Mindswipe.java index cda1df94a9f..fbfa217fd31 100644 --- a/Mage.Sets/src/mage/cards/m/Mindswipe.java +++ b/Mage.Sets/src/mage/cards/m/Mindswipe.java @@ -70,7 +70,7 @@ class MindswipeEffect extends OneShotEffect { if (object == null) { object = game.getLastKnownInformation(getTargetPointer().getFirst(game, source), Zone.STACK); } - if (object != null && object instanceof Spell) { + if (object instanceof Spell) { Spell spell = (Spell) object; Player spellController = game.getPlayer(spell.getControllerId()); if (spellController != null) { diff --git a/Mage.Sets/src/mage/cards/m/MindwrackDemon.java b/Mage.Sets/src/mage/cards/m/MindwrackDemon.java index d5816fef2ad..1bcd1ff2388 100644 --- a/Mage.Sets/src/mage/cards/m/MindwrackDemon.java +++ b/Mage.Sets/src/mage/cards/m/MindwrackDemon.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect; import mage.abilities.keyword.FlyingAbility; @@ -41,7 +41,7 @@ public final class MindwrackDemon extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(4))); // At the beginning of your upkeep, if you don't have 4 or more card types in your graveyard, you lose 4 life. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new LoseLifeSourceControllerEffect(4), TargetController.YOU, false), new InvertCondition(DeliriumCondition.instance), "Delirium — At the beginning of your upkeep, you lose 4 life unless there are four or more card types among cards in your graveyard."); diff --git a/Mage.Sets/src/mage/cards/m/MineMineMine.java b/Mage.Sets/src/mage/cards/m/MineMineMine.java index 51f7444aaa2..b5c54f0dad2 100644 --- a/Mage.Sets/src/mage/cards/m/MineMineMine.java +++ b/Mage.Sets/src/mage/cards/m/MineMineMine.java @@ -63,7 +63,7 @@ class MineMineMineDrawEffect extends OneShotEffect { MineMineMineDrawEffect() { super(Outcome.DrawCard); - this.staticText = "each player puts his or her library into his or her hand"; + this.staticText = "each player puts their library into their hand"; } MineMineMineDrawEffect(final MineMineMineDrawEffect effect) { diff --git a/Mage.Sets/src/mage/cards/m/MinionReflector.java b/Mage.Sets/src/mage/cards/m/MinionReflector.java index e792a5f431b..a4226643089 100644 --- a/Mage.Sets/src/mage/cards/m/MinionReflector.java +++ b/Mage.Sets/src/mage/cards/m/MinionReflector.java @@ -48,8 +48,8 @@ public final class MinionReflector extends CardImpl { "entered the battlefield?"), filter, false, SetTargetPointer.PERMANENT, "Whenever a nontoken creature enters the battlefield under your control, " + - "you may pay 2. If you do, create a token that's a copy of that creature. " + - "That token has haste and \"At the beginning of the end step, sacrifice this " + + "you may pay 2. If you do, create a token that's a copy of that creature, " + + "except it has haste and \"At the beginning of the end step, sacrifice this " + "permanent.\""); this.addAbility(ability); } @@ -69,7 +69,7 @@ class MinionReflectorEffect extends OneShotEffect { public MinionReflectorEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "create a token that's a copy of that creature. That token has haste and \"At the beginning of the end step, sacrifice this permanent."; + this.staticText = "create a token that's a copy of that creature, except it has haste and \"At the beginning of the end step, sacrifice this permanent."; } public MinionReflectorEffect(final MinionReflectorEffect effect) { diff --git a/Mage.Sets/src/mage/cards/m/Mirari.java b/Mage.Sets/src/mage/cards/m/Mirari.java index bdace8ebf8e..0c0b0fe580f 100644 --- a/Mage.Sets/src/mage/cards/m/Mirari.java +++ b/Mage.Sets/src/mage/cards/m/Mirari.java @@ -92,7 +92,7 @@ class MirariTriggeredAbility extends TriggeredAbilityImpl { private boolean isControlledInstantOrSorcery(Spell spell) { return spell != null - && (spell.getControllerId().equals(this.getControllerId())) + && (spell.isControlledBy(this.getControllerId())) && (spell.isInstant() || spell.isSorcery()); } diff --git a/Mage.Sets/src/mage/cards/m/MirranMettle.java b/Mage.Sets/src/mage/cards/m/MirranMettle.java index d8f0751f0c7..50b66bd8e03 100644 --- a/Mage.Sets/src/mage/cards/m/MirranMettle.java +++ b/Mage.Sets/src/mage/cards/m/MirranMettle.java @@ -18,7 +18,7 @@ import mage.target.common.TargetCreaturePermanent; */ public final class MirranMettle extends CardImpl { - private static final String effectText = "Metalcraft - That creature gets +4/+4 until end of turn instead if you control three or more artifacts."; + private static final String effectText = "Metalcraft — That creature gets +4/+4 until end of turn instead if you control three or more artifacts."; public MirranMettle(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}"); diff --git a/Mage.Sets/src/mage/cards/m/MirrorGolem.java b/Mage.Sets/src/mage/cards/m/MirrorGolem.java new file mode 100644 index 00000000000..96aa5fb00e7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MirrorGolem.java @@ -0,0 +1,138 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.Card; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.util.CardUtil; + +/** + * + * @author noahg + */ +public final class MirrorGolem extends CardImpl { + + public MirrorGolem(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Imprint - When Mirror Golem enters the battlefield, you may exile target card from a graveyard. + Ability ability = new EntersBattlefieldTriggeredAbility(new MirrorGolemImprintEffect(), true, "Imprint — "); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + + // Mirror Golem has protection from each of the exiled card's card types. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MirrorGolemEffect())); + } + + public MirrorGolem(final MirrorGolem card) { + super(card); + } + + @Override + public MirrorGolem copy() { + return new MirrorGolem(this); + } +} + +class MirrorGolemImprintEffect extends OneShotEffect { + + MirrorGolemImprintEffect() { + super(Outcome.Exile); + this.staticText = "you may exile target card from a graveyard"; + } + + MirrorGolemImprintEffect(final MirrorGolemImprintEffect effect) { + super(effect); + } + + @Override + public MirrorGolemImprintEffect copy() { + return new MirrorGolemImprintEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card != null) { + controller.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), source.getSourceObject(game).getIdName()); + if (sourcePermanent != null) { + sourcePermanent.imprint(this.getTargetPointer().getFirst(game, source), game); + } + } + return true; + } + return false; + } +} + +class MirrorGolemEffect extends ContinuousEffectImpl { + + public MirrorGolemEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.addDependedToType(DependencyType.AddingAbility); + staticText = "{this} has protection from each of the exiled card's card types."; + } + + public MirrorGolemEffect(final MirrorGolemEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourceObject = game.getPermanent(source.getSourceId()); + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId())); + + if (sourceObject == null || sourceObject.getImprinted() == null) { + return false; + } + + for (UUID imprinted : sourceObject.getImprinted()){ + if (imprinted != null && exileZone.contains(imprinted)){ + Card card = game.getCard(imprinted); + if (card != null) { + for (CardType cardType : card.getCardType()){ + FilterCard filterCard; + if (cardType.equals(CardType.SORCERY)){ + filterCard = new FilterCard("sorceries"); + } else if (cardType.equals(CardType.TRIBAL)){ + filterCard = new FilterCard("tribal"); + } else { + filterCard = new FilterCard(cardType.toString()+"s"); + } + filterCard.add(new CardTypePredicate(cardType)); + sourceObject.addAbility(new ProtectionAbility(filterCard)); + } + } + } + } + return true; + } + + @Override + public MirrorGolemEffect copy() { + return new MirrorGolemEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MirrorImage.java b/Mage.Sets/src/mage/cards/m/MirrorImage.java new file mode 100644 index 00000000000..ffed21f69f4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MirrorImage.java @@ -0,0 +1,43 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.common.CopyPermanentEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class MirrorImage extends CardImpl { + + public MirrorImage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.SHAPESHIFTER); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // You may have Mirror Image enter the battlefield as a copy of any creature you control. + this.addAbility(new EntersBattlefieldAbility( + new CopyPermanentEffect(StaticFilters.FILTER_CONTROLLED_CREATURE) + .setText("you may have {this} enter the battlefield " + + "as a copy of any creature you control"), + true + )); + } + + public MirrorImage(final MirrorImage card) { + super(card); + } + + @Override + public MirrorImage copy() { + return new MirrorImage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MirrorMatch.java b/Mage.Sets/src/mage/cards/m/MirrorMatch.java index f3bfc7ae932..895f00a1caa 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorMatch.java +++ b/Mage.Sets/src/mage/cards/m/MirrorMatch.java @@ -70,7 +70,7 @@ class MirrorMatchEffect extends OneShotEffect { for (UUID attackerId : game.getCombat().getAttackers()) { Permanent attacker = game.getPermanent(attackerId); if (attacker != null - && source.getControllerId().equals(game.getCombat().getDefendingPlayerId(attackerId, game))) { + && source.isControlledBy(game.getCombat().getDefendingPlayerId(attackerId, game))) { CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, false); effect.setTargetPointer(new FixedTarget(attacker, game)); effect.apply(game, source); diff --git a/Mage.Sets/src/mage/cards/m/MirrorOfFate.java b/Mage.Sets/src/mage/cards/m/MirrorOfFate.java index f66350bffed..bc8bd0e12fd 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorOfFate.java +++ b/Mage.Sets/src/mage/cards/m/MirrorOfFate.java @@ -134,7 +134,7 @@ class MirrorOfFateTarget extends TargetCardInExile { @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); - if (card != null && card.getOwnerId().equals(source.getControllerId()) + if (card != null && card.isOwnedBy(source.getControllerId()) && game.getState().getZone(card.getId()) == Zone.EXILED) { for (ExileZone exile : game.getExile().getExileZones()) { if (exile != null && exile.contains(id)) { diff --git a/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java b/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java index 165770358e9..737385b8fef 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java +++ b/Mage.Sets/src/mage/cards/m/MirrorOfTheForebears.java @@ -38,7 +38,7 @@ public final class MirrorOfTheForebears extends CardImpl { // 1: Until end of turn, Mirror of the Forebears becomes a copy of target creature you control of the chosen type, except it's an artifact in addition to its other types. FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorOfTheForebearsCopyEffect(), new ManaCostsImpl("{1}")); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java b/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java index bfa62f4de33..f2a91224b48 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java +++ b/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -49,7 +49,7 @@ public final class MirrorSigilSergeant extends CardImpl { Effect effect = new CreateTokenCopySourceEffect(); effect.setText("you may create a token that's a copy of {this}"); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, true); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); } diff --git a/Mage.Sets/src/mage/cards/m/MirrorwingDragon.java b/Mage.Sets/src/mage/cards/m/MirrorwingDragon.java index d91e782b5b3..73e4af0c51d 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorwingDragon.java +++ b/Mage.Sets/src/mage/cards/m/MirrorwingDragon.java @@ -153,7 +153,7 @@ class MirrorwingDragonCopySpellEffect extends CopySpellForEachItCouldTargetEffec @Override protected boolean okUUIDToCopyFor(UUID potentialTarget, Game game, Ability source, Spell spell) { Permanent permanent = game.getPermanent(potentialTarget); - if (permanent == null || !permanent.getControllerId().equals(spell.getControllerId())) { + if (permanent == null || !permanent.isControlledBy(spell.getControllerId())) { return false; } return true; diff --git a/Mage.Sets/src/mage/cards/m/MischievousQuanar.java b/Mage.Sets/src/mage/cards/m/MischievousQuanar.java index bc36aec1725..3d93d88581f 100644 --- a/Mage.Sets/src/mage/cards/m/MischievousQuanar.java +++ b/Mage.Sets/src/mage/cards/m/MischievousQuanar.java @@ -44,7 +44,7 @@ public final class MischievousQuanar extends CardImpl { Effect effect2 = new CopyTargetSpellEffect(); effect2.setText("copy target instant or sorcery spell. You may choose new targets for that copy"); Ability ability = new TurnedFaceUpSourceTriggeredAbility(effect2); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MisersCage.java b/Mage.Sets/src/mage/cards/m/MisersCage.java index 828d7987085..9a344eee5dd 100644 --- a/Mage.Sets/src/mage/cards/m/MisersCage.java +++ b/Mage.Sets/src/mage/cards/m/MisersCage.java @@ -78,6 +78,6 @@ class MisersCageTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "at the beginning of each opponent’s upkeep, if that player has five or more cards in hand, {this} deals 2 damage to that player"; + return "at the beginning of each opponent's upkeep, if that player has five or more cards in hand, {this} deals 2 damage to that player"; } } diff --git a/Mage.Sets/src/mage/cards/m/MistCloakedHerald.java b/Mage.Sets/src/mage/cards/m/MistCloakedHerald.java index f7bd25a9567..3dbd7d79dcb 100644 --- a/Mage.Sets/src/mage/cards/m/MistCloakedHerald.java +++ b/Mage.Sets/src/mage/cards/m/MistCloakedHerald.java @@ -22,7 +22,7 @@ public final class MistCloakedHerald extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // Mist-Cloaked Herald can’t be blocked. + // Mist-Cloaked Herald can't be blocked. this.addAbility(new CantBeBlockedSourceAbility()); } diff --git a/Mage.Sets/src/mage/cards/m/MistOfStagnation.java b/Mage.Sets/src/mage/cards/m/MistOfStagnation.java index 962cf65d1ab..bd9fbcf5adf 100644 --- a/Mage.Sets/src/mage/cards/m/MistOfStagnation.java +++ b/Mage.Sets/src/mage/cards/m/MistOfStagnation.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -15,6 +14,7 @@ import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -30,7 +30,7 @@ public final class MistOfStagnation extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}"); // Permanents don't untap during their controllers' untap steps. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepAllEffect(Duration.WhileOnBattlefield, TargetController.ANY, new FilterPermanent("permanents")))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepAllEffect(Duration.WhileOnBattlefield, TargetController.ANY, StaticFilters.FILTER_PERMANENT))); // At the beginning of each player's upkeep, that player chooses a permanent for each card in their graveyard, then untaps those permanents. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MistOfStagnationEffect(), TargetController.ANY, false)); diff --git a/Mage.Sets/src/mage/cards/m/Mistcaller.java b/Mage.Sets/src/mage/cards/m/Mistcaller.java new file mode 100644 index 00000000000..88f7d3952ed --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Mistcaller.java @@ -0,0 +1,112 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.watchers.common.CreatureWasCastWatcher; + +/** + * + * @author TheElk801 + */ +public final class Mistcaller extends CardImpl { + + public Mistcaller(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Sacrifice Mistcaller: Until end of turn, if a nontoken creature would enter the battlefield and it wasn't cast, exile it instead. + this.addAbility(new SimpleActivatedAbility( + new ContainmentPriestReplacementEffect(), + new SacrificeSourceCost() + ), new CreatureWasCastWatcher()); + } + + public Mistcaller(final Mistcaller card) { + super(card); + } + + @Override + public Mistcaller copy() { + return new Mistcaller(this); + } +} + +class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { + + public ContainmentPriestReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Exile); + staticText = "until end of turn, if a nontoken creature would enter the battlefield and it wasn't cast, exile it instead"; + } + + public ContainmentPriestReplacementEffect(final ContainmentPriestReplacementEffect effect) { + super(effect); + } + + @Override + public ContainmentPriestReplacementEffect copy() { + return new ContainmentPriestReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = game.getCard(event.getTargetId()); + if (card != null) { + controller.moveCardsToExile(card, source, game, true, null, null); + } + return true; + + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; // Token create the create Token event + } + + @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.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; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MisthollowGriffin.java b/Mage.Sets/src/mage/cards/m/MisthollowGriffin.java index cc59223b768..decac80309c 100644 --- a/Mage.Sets/src/mage/cards/m/MisthollowGriffin.java +++ b/Mage.Sets/src/mage/cards/m/MisthollowGriffin.java @@ -72,7 +72,7 @@ class MisthollowGriffinPlayEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(source.getSourceId()); - if (card != null && card.getOwnerId().equals(affectedControllerId) + if (card != null && card.isOwnedBy(affectedControllerId) && game.getState().getZone(source.getSourceId()) == Zone.EXILED) { return true; } diff --git a/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java b/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java index 149bef4fc2e..298c2f4d8d9 100644 --- a/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java +++ b/Mage.Sets/src/mage/cards/m/MizziumTransreliquat.java @@ -31,7 +31,7 @@ public final class MizziumTransreliquat extends CardImpl { ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); - // {1}{U}{R}: Mizzium Transreliquat becomes a copy of target artifact and gains this ability. + // {1}{U}{R}: Mizzium Transreliquat becomes a copy of target artifact, except it has this ability. ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MizziumTransreliquatCopyAndGainAbilityEffect(), new ManaCostsImpl("{1}{U}{R}")); ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); @@ -79,7 +79,7 @@ class MizziumTransreliquatCopyAndGainAbilityEffect extends OneShotEffect { public MizziumTransreliquatCopyAndGainAbilityEffect() { super(Outcome.Benefit); - this.staticText = "{this} becomes a copy of target artifact and gains this ability"; + this.staticText = "{this} becomes a copy of target artifact, except it has this ability"; } public MizziumTransreliquatCopyAndGainAbilityEffect(final MizziumTransreliquatCopyAndGainAbilityEffect effect) { diff --git a/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java b/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java index c5de6457ea4..4a598ae096b 100644 --- a/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java +++ b/Mage.Sets/src/mage/cards/m/MizzixOfTheIzmagnus.java @@ -107,7 +107,7 @@ class MizzixOfTheIzmagnusCostReductionEffect extends CostModificationEffectImpl @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (abilityToModify instanceof SpellAbility && abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify instanceof SpellAbility && abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { return StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(spell, source.getSourceId(), source.getControllerId(), game); diff --git a/Mage.Sets/src/mage/cards/m/MoggInfestation.java b/Mage.Sets/src/mage/cards/m/MoggInfestation.java index be7b4dc9a4c..e0a05836ef8 100644 --- a/Mage.Sets/src/mage/cards/m/MoggInfestation.java +++ b/Mage.Sets/src/mage/cards/m/MoggInfestation.java @@ -65,7 +65,7 @@ class MoggInfestationEffect extends OneShotEffect { if (controller != null && getTargetPointer().getFirst(game, source) != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, getTargetPointer().getFirst(game, source), game)) { if (permanent.destroy(source.getSourceId(), game, false)) { - if (game.getState().getZone(permanent.getId()).equals(Zone.GRAVEYARD)) { // If a commander is replaced to command zone, the creature does not die + if (game.getState().getZone(permanent.getId()) == Zone.GRAVEYARD) { // If a commander is replaced to command zone, the creature does not die Effect effect = new CreateTokenTargetEffect(new GoblinToken(), 2); effect.setTargetPointer(getTargetPointer()); effect.apply(game, source); diff --git a/Mage.Sets/src/mage/cards/m/MoggSalvage.java b/Mage.Sets/src/mage/cards/m/MoggSalvage.java index fed1f36fef6..d45d5d2af70 100644 --- a/Mage.Sets/src/mage/cards/m/MoggSalvage.java +++ b/Mage.Sets/src/mage/cards/m/MoggSalvage.java @@ -33,7 +33,7 @@ public final class MoggSalvage extends CardImpl { public MoggSalvage(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}"); - // If an opponent controls an Island and you control a Mountain, you may cast Mogg Salvage without paying its mana cost. + // If an opponent controls an Island and you control a Mountain, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls an Island and you control a Mountain", new OpponentControlsPermanentCondition(filterIsland), new PermanentsOnTheBattlefieldCondition(filterMountain)); diff --git a/Mage.Sets/src/mage/cards/m/MoldShambler.java b/Mage.Sets/src/mage/cards/m/MoldShambler.java index 10ff8369321..5c8bd2a2b07 100644 --- a/Mage.Sets/src/mage/cards/m/MoldShambler.java +++ b/Mage.Sets/src/mage/cards/m/MoldShambler.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -45,7 +45,7 @@ public final class MoldShambler extends CardImpl { EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); Target target = new TargetPermanent(filter); ability.addTarget(target); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target noncreature permanent.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target noncreature permanent.")); } public MoldShambler(final MoldShambler card) { diff --git a/Mage.Sets/src/mage/cards/m/MoltenFirebird.java b/Mage.Sets/src/mage/cards/m/MoltenFirebird.java new file mode 100644 index 00000000000..81001ce6abc --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MoltenFirebird.java @@ -0,0 +1,52 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.*; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author noahg + */ +public final class MoltenFirebird extends CardImpl { + + public MoltenFirebird(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); + + this.subtype.add(SubType.PHOENIX); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Molten Firebird dies, return it to the battlefield under its owner’s control at the beginning of the next end step and you skip your next draw step. + Ability ability = new DiesTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect()))); + ability.addEffect(new SkipNextDrawStepControllerEffect()); + this.addAbility(ability); + + // {4}{R}: Exile Molten Firebird. + this.addAbility(new SimpleActivatedAbility(new ExileSourceEffect(), new ManaCostsImpl("{4}{R}"))); + } + + public MoltenFirebird(final MoltenFirebird card) { + super(card); + } + + @Override + public MoltenFirebird copy() { + return new MoltenFirebird(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MoltenInfluence.java b/Mage.Sets/src/mage/cards/m/MoltenInfluence.java index 6433587b100..d7188dba64c 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenInfluence.java +++ b/Mage.Sets/src/mage/cards/m/MoltenInfluence.java @@ -24,7 +24,7 @@ public final class MoltenInfluence extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); // Counter target instant or sorcery spell unless its controller has Molten Influence deal 4 damage to him or her. - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.getSpellAbility().addEffect(new MoltenInfluenceEffect()); } diff --git a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java index 0757e2fbd19..bd9f8b6e8de 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java +++ b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java @@ -29,7 +29,7 @@ public final class MoltenPsyche extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}{R}"); // Each player shuffles the cards from their hand into their library, then draws that many cards. - // Metalcraft - If you control three or more artifacts, Molten Psyche deals damage to each opponent equal to the number of cards that player has drawn this turn. + // Metalcraft — If you control three or more artifacts, Molten Psyche deals damage to each opponent equal to the number of cards that player has drawn this turn. this.getSpellAbility().addEffect(new MoltenPsycheEffect()); this.getSpellAbility().addWatcher(new MoltenPsycheWatcher()); } diff --git a/Mage.Sets/src/mage/cards/m/MonasterySiege.java b/Mage.Sets/src/mage/cards/m/MonasterySiege.java index 089a1583846..162abdd40c7 100644 --- a/Mage.Sets/src/mage/cards/m/MonasterySiege.java +++ b/Mage.Sets/src/mage/cards/m/MonasterySiege.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.SpellAbility; @@ -15,17 +14,14 @@ import mage.abilities.effects.common.DrawDiscardControllerEffect; 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.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; import mage.util.CardUtil; +import java.util.UUID; + /** * * @author emerald000 @@ -90,7 +86,7 @@ class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl { return true; } Permanent permanent = game.getPermanent(targetUUID); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/m/MondronenShaman.java b/Mage.Sets/src/mage/cards/m/MondronenShaman.java index 1af6653b463..aadaae2d692 100644 --- a/Mage.Sets/src/mage/cards/m/MondronenShaman.java +++ b/Mage.Sets/src/mage/cards/m/MondronenShaman.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class MondronenShaman extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Mondronen Shaman. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/m/MoonEatingDog.java b/Mage.Sets/src/mage/cards/m/MoonEatingDog.java new file mode 100644 index 00000000000..1467030f595 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MoonEatingDog.java @@ -0,0 +1,59 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +/** + * + * @author TheElk801 + */ +public final class MoonEatingDog extends CardImpl { + + private static final FilterControlledPlaneswalkerPermanent filter + = new FilterControlledPlaneswalkerPermanent( + SubType.YANLING, + "a Yanling planeswalker" + ); + + public MoonEatingDog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.HOUND); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // As long as you control a Yanling planeswalker, Moon-Eating Dog has flying. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + FlyingAbility.getInstance(), + Duration.WhileOnBattlefield + ), + new PermanentsOnTheBattlefieldCondition(filter), + "As long as you control a Yanling planeswalker, {this} has flying." + ) + )); + } + + public MoonEatingDog(final MoonEatingDog card) { + super(card); + } + + @Override + public MoonEatingDog copy() { + return new MoonEatingDog(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java b/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java index 3d35815cff8..8ec19df1393 100644 --- a/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java +++ b/Mage.Sets/src/mage/cards/m/MoonriseIntruder.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.TransformAbility; @@ -38,7 +38,7 @@ public final class MoonriseIntruder extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Moonrise Intruder. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public MoonriseIntruder(final MoonriseIntruder card) { diff --git a/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java b/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java index 442c6432aab..e2cf3555330 100644 --- a/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java +++ b/Mage.Sets/src/mage/cards/m/MoonscarredWerewolf.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.abilities.keyword.VigilanceAbility; @@ -43,7 +43,7 @@ public final class MoonscarredWerewolf extends CardImpl { this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(2), new TapSourceCost())); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Moonscarred Werewolf. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/m/MordantDragon.java b/Mage.Sets/src/mage/cards/m/MordantDragon.java index a53bf5a8f5e..3960e387e61 100644 --- a/Mage.Sets/src/mage/cards/m/MordantDragon.java +++ b/Mage.Sets/src/mage/cards/m/MordantDragon.java @@ -1,13 +1,14 @@ - package mage.cards.m; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -16,8 +17,11 @@ import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -26,7 +30,7 @@ import mage.target.common.TargetCreaturePermanent; public final class MordantDragon extends CardImpl { public MordantDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(5); @@ -39,7 +43,7 @@ public final class MordantDragon extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}"))); // Whenever Mordant Dragon deals combat damage to a player, you may have it deal that much damage to target creature that player controls. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new MordantDragonEffect(), true, true)); + this.addAbility(new MordantDragonTriggeredAbility()); } public MordantDragon(final MordantDragon card) { @@ -52,6 +56,53 @@ public final class MordantDragon extends CardImpl { } } +class MordantDragonTriggeredAbility extends TriggeredAbilityImpl { + + public MordantDragonTriggeredAbility() { + super(Zone.BATTLEFIELD, new MordantDragonEffect(), true); + } + + public MordantDragonTriggeredAbility(final MordantDragonTriggeredAbility ability) { + super(ability); + } + + @Override + public MordantDragonTriggeredAbility copy() { + return new MordantDragonTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; + Player opponent = game.getPlayer(event.getPlayerId()); + if (!damageEvent.isCombatDamage() + || !event.getSourceId().equals(this.getSourceId()) + || opponent == null) { + return false; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + opponent.getLogName() + " controls"); + filter.add(new ControllerIdPredicate(opponent.getId())); + this.getTargets().clear(); + this.addTarget(new TargetCreaturePermanent(filter)); + for (Effect effect : this.getAllEffects()) { + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + effect.setValue("damage", event.getAmount()); + } + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may have it deal that much damage to target creature that player controls"; + } +} + class MordantDragonEffect extends OneShotEffect { public MordantDragonEffect() { @@ -65,23 +116,7 @@ class MordantDragonEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if (player != null) { - int amount = (Integer) getValue("damage"); - if (amount > 0) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + player.getLogName() + " controls"); - filter.add(new ControllerIdPredicate(player.getId())); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - if (target.canChoose(source.getControllerId(), game) && target.choose(Outcome.Damage, source.getControllerId(), source.getSourceId(), game)) { - UUID creature = target.getFirstTarget(); - if (creature != null) { - game.getPermanent(creature).damage(amount, source.getSourceId(), game, false, true); - return true; - } - } - } - } - return false; + return new DamageTargetEffect((Integer) getValue("damage")).apply(game, source); } @Override diff --git a/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java b/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java index d78243f0f15..f3d68ccc2c9 100644 --- a/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java +++ b/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ import mage.target.common.TargetCreaturePermanent; */ public final class MorkrutBanshee extends CardImpl { - private static final String staticText = "Morbid - When {this} enters the battlefield, if a creature died this turn, target creature gets -4/-4 until end of turn."; + private static final String staticText = "Morbid — When {this} enters the battlefield, if a creature died this turn, target creature gets -4/-4 until end of turn."; public MorkrutBanshee(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); @@ -30,9 +30,9 @@ public final class MorkrutBanshee extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - // Morbid - When Morkut Banshee enters the battlefield, if a creature died this turn, target creature gets -4/-4 until end of turn. + // Morbid — When Morkut Banshee enters the battlefield, if a creature died this turn, target creature gets -4/-4 until end of turn. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-4, -4, Duration.EndOfTurn)); - TriggeredAbility ability = new ConditionalTriggeredAbility(triggeredAbility, MorbidCondition.instance, staticText); + TriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, MorbidCondition.instance, staticText); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MortalCombat.java b/Mage.Sets/src/mage/cards/m/MortalCombat.java index d055dffa601..4869fd235d9 100644 --- a/Mage.Sets/src/mage/cards/m/MortalCombat.java +++ b/Mage.Sets/src/mage/cards/m/MortalCombat.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class MortalCombat extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}"); // At the beginning of your upkeep, if twenty or more creature cards are in your graveyard, you win the game. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false), new TwentyGraveyardCreatureCondition(), "At the beginning of your upkeep, if twenty or more creature cards are in your graveyard, you win the game.")); diff --git a/Mage.Sets/src/mage/cards/m/MournersShield.java b/Mage.Sets/src/mage/cards/m/MournersShield.java new file mode 100644 index 00000000000..889e6e77369 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MournersShield.java @@ -0,0 +1,170 @@ +package mage.cards.m; + +import java.util.UUID; + +import mage.MageObject; +import mage.MageObjectReference; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +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; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterObject; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.ColorlessPredicate; +import mage.filter.predicate.mageobject.SharesColorPredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetSource; +import mage.target.common.TargetCardInGraveyard; +import mage.util.CardUtil; + +/** + * + * @author noahg + */ +public final class MournersShield extends CardImpl { + + public MournersShield(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + + // Imprint - When Mourner's Shield enters the battlefield, you may exile target card from a graveyard. + Ability ability = new EntersBattlefieldTriggeredAbility(new MournersShieldImprintEffect(), true, "Imprint — "); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + + // {2}, {tap}: Prevent all damage that would be dealt this turn by a source of your choice that shares a color with the exiled card. + Ability preventAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MournersShieldEffect(), new GenericManaCost(2)); + preventAbility.addCost(new TapSourceCost()); + this.addAbility(preventAbility); + } + + public MournersShield(final MournersShield card) { + super(card); + } + + @Override + public MournersShield copy() { + return new MournersShield(this); + } +} + +class MournersShieldImprintEffect extends OneShotEffect { + + MournersShieldImprintEffect() { + super(Outcome.Exile); + this.staticText = "you may exile target card from a graveyard"; + } + + MournersShieldImprintEffect(final MournersShieldImprintEffect effect) { + super(effect); + } + + @Override + public MournersShieldImprintEffect copy() { + return new MournersShieldImprintEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card != null) { + controller.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), source.getSourceObject(game).getIdName()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent != null) { + sourcePermanent.imprint(this.getTargetPointer().getFirst(game, source), game); + } + } + return true; + } + return false; + } +} + +class MournersShieldEffect extends PreventionEffectImpl { + + private TargetSource target; + private MageObjectReference mageObjectReference; + private boolean noneExiled; + + public MournersShieldEffect() { + super(Duration.EndOfTurn); + noneExiled = false; + this.staticText = "Prevent all damage that would be dealt this turn by a source of your choice that shares a color with the exiled card."; + } + + public MournersShieldEffect(final MournersShieldEffect effect) { + super(effect); + if (effect.target != null) { + this.target = effect.target.copy(); + } else { + this.target = null; + } + this.mageObjectReference = effect.mageObjectReference; + this.noneExiled = effect.noneExiled; + } + + @Override + public MournersShieldEffect copy() { + return new MournersShieldEffect(this); + } + + @Override + public void init(Ability source, Game game) { + ObjectColor colorsAmongImprinted = new ObjectColor(); + Permanent sourceObject = game.getPermanent(source.getSourceId()); + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId())); + if (sourceObject == null || sourceObject.getImprinted() == null) { + noneExiled = true; + return; + } + for (UUID imprinted : sourceObject.getImprinted()){ + if (imprinted != null && exileZone.contains(imprinted)){ + Card card = game.getCard(imprinted); + if (card != null) { + colorsAmongImprinted = colorsAmongImprinted.union(card.getColor(game)); + } + } + } + FilterObject filterObject = new FilterObject("a source of your choice that shares a color with the exiled card"); + filterObject.add(new SharesColorPredicate(colorsAmongImprinted)); + this.target = new TargetSource(filterObject); + this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + if (target.getFirstTarget() != null) { + mageObjectReference = new MageObjectReference(target.getFirstTarget(), game); + } else { + mageObjectReference = null; + } + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (noneExiled || mageObjectReference == null){ + return false; + } + if (super.applies(event, source, game)) { + MageObject mageObject = game.getObject(event.getSourceId()); + return mageObjectReference.refersTo(mageObject, game); + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/Mournwillow.java b/Mage.Sets/src/mage/cards/m/Mournwillow.java index 0889969a697..5a1fe7ec50f 100644 --- a/Mage.Sets/src/mage/cards/m/Mournwillow.java +++ b/Mage.Sets/src/mage/cards/m/Mournwillow.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.RestrictionEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class Mournwillow extends CardImpl { // Delirium — When Mournwillow enters the battlefield, if there are four or more card types among cards in your graveyard, // creatures with power 2 or less can't block this turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new MournwillowEffect(), false), DeliriumCondition.instance, "Delirium — When {this} enters the battlefield, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/m/MouseDroid.java b/Mage.Sets/src/mage/cards/m/MouseDroid.java new file mode 100644 index 00000000000..1d911de6687 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MouseDroid.java @@ -0,0 +1,41 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.RepairAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author NinthWorld + */ +public final class MouseDroid extends CardImpl { + + public MouseDroid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.DROID); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // When Mouse Droid dies, draw a card. + this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1))); + + // Repair 3 + this.addAbility(new RepairAbility(3)); + } + + public MouseDroid(final MouseDroid card) { + super(card); + } + + @Override + public MouseDroid copy() { + return new MouseDroid(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MudTrooper.java b/Mage.Sets/src/mage/cards/m/MudTrooper.java new file mode 100644 index 00000000000..0fc2f6d128f --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MudTrooper.java @@ -0,0 +1,59 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ColorlessManaCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.constants.Duration; +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.mageobject.SubtypePredicate; + +/** + * + * @author NinthWorld + */ +public final class MudTrooper extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Trooper creatures you control"); + + static { + filter.add(new SubtypePredicate(SubType.TROOPER)); + } + + public MudTrooper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Trooper creatures you control have "2: This creature gets +1/+1 until end of turn." + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new BoostSourceEffect(1, 1, Duration.EndOfTurn) + .setText("This creature gets +1/+1 until end of turn"), + new GenericManaCost(2)); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new GainAbilityControlledEffect(ability, Duration.WhileOnBattlefield, filter, false))); + } + + public MudTrooper(final MudTrooper card) { + super(card); + } + + @Override + public MudTrooper copy() { + return new MudTrooper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java b/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java index 45df40b95bf..f80bf2ab4d4 100644 --- a/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java +++ b/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java @@ -84,8 +84,8 @@ class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (source.getControllerId().equals(affectedControllerId) - && source.getControllerId().equals(game.getOwnerId(objectId)) // only from your graveyard + if (source.isControlledBy(affectedControllerId) + && 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()); @@ -115,7 +115,7 @@ class MuldrothaTheGravetideWatcher extends Watcher { final HashMap> sourcePlayedPermanentTypes = new HashMap<>(); // source that played permanent types from graveyard // final HashMap> playerPlayedPermanentTypes = new HashMap<>(); // player that played permanent types from graveyard // 4/27/2018 If multiple effects allow you to play a card from your graveyard, such as those of Gisa and Geralf and Karador, - // Ghost Chieftain, you must announce which permission you’re using as you begin to play the card. + // Ghost Chieftain, you must announce which permission you're using as you begin to play the card. // 4/27/2018: If you play a card from your graveyard and then have a new Muldrotha come under your control in the same turn, // you may play another card of that type from your graveyard that turn. private Zone fromZone; @@ -139,13 +139,13 @@ class MuldrothaTheGravetideWatcher extends Watcher { if (event.getType() == GameEvent.EventType.PLAY_LAND) { fromZone = game.getState().getZone(event.getTargetId()); // Remember the Zone the land came from } - if (event.getType() == GameEvent.EventType.LAND_PLAYED && fromZone.equals(Zone.GRAVEYARD)) { + if (event.getType() == GameEvent.EventType.LAND_PLAYED && fromZone == Zone.GRAVEYARD) { addPermanentTypes(event, game.getPermanentOrLKIBattlefield(event.getTargetId()), game); } if (event.getType() == GameEvent.EventType.SPELL_CAST) { Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell.getFromZone().equals(Zone.GRAVEYARD)) { + if (spell.getFromZone() == Zone.GRAVEYARD) { addPermanentTypes(event, spell, game); } } diff --git a/Mage.Sets/src/mage/cards/m/MuseVessel.java b/Mage.Sets/src/mage/cards/m/MuseVessel.java new file mode 100644 index 00000000000..8744823ebc6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MuseVessel.java @@ -0,0 +1,185 @@ +package mage.cards.m; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import mage.MageObject; +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.AsThoughEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInExile; +import mage.target.common.TargetCardInHand; +import mage.util.CardUtil; + +/** + * + * @author noahg + */ +public final class MuseVessel extends CardImpl { + + public MuseVessel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + + // {3}, {tap}: Target player exiles a card from their hand. Activate this ability only any time you could cast a sorcery. + ActivateAsSorceryActivatedAbility tapAbility = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new MuseVesselExileEffect(), new TapSourceCost()); + tapAbility.addCost(new ManaCostsImpl("{3}")); + tapAbility.addTarget(new TargetPlayer()); + this.addAbility(tapAbility); + + // {1}: Choose a card exiled with Muse Vessel. You may play that card this turn. + SimpleActivatedAbility playAbility = new SimpleActivatedAbility(new MuseVesselMayPlayExiledEffect(), new ManaCostsImpl("{1}")); + playAbility.addTarget(new TargetCardInMuseVesselExile()); + this.addAbility(playAbility); + } + + public MuseVessel(final MuseVessel card) { + super(card); + } + + @Override + public MuseVessel copy() { + return new MuseVessel(this); + } +} + +class MuseVesselExileEffect extends OneShotEffect { + + public MuseVesselExileEffect() { + super(Outcome.Exile); + staticText = "target player exiles a card from their hand"; + } + + public MuseVesselExileEffect(final MuseVesselExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject == null) { + return false; + } + if (player == null) { + return false; + } + TargetCardInHand target = new TargetCardInHand(); + if (target.canChoose(source.getSourceId(), player.getId(), game) + && target.chooseTarget(Outcome.Exile, player.getId(), source, game)) { + UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + return player.moveCardsToExile(new CardsImpl(target.getTargets()).getCards(game), source, game, true, exileId, sourceObject.getIdName()); + } + return false; + } + + @Override + public MuseVesselExileEffect copy() { + return new MuseVesselExileEffect(this); + } + +} + +class MuseVesselMayPlayExiledEffect extends AsThoughEffectImpl { + + public MuseVesselMayPlayExiledEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + this.staticText = "Choose a card exiled with {this}. You may play that card this turn"; + } + + public MuseVesselMayPlayExiledEffect(final MuseVesselMayPlayExiledEffect effect) { + super(effect); + } + + @Override + public MuseVesselMayPlayExiledEffect copy() { + return new MuseVesselMayPlayExiledEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return affectedControllerId.equals(source.getControllerId()) + && getTargetPointer().getTargets(game, source).contains(objectId); + } + +} + +class TargetCardInMuseVesselExile extends TargetCardInExile { + + public TargetCardInMuseVesselExile() { + super(1, 1, new FilterCard("card exiled with Muse Vessel"), null); + } + + public TargetCardInMuseVesselExile(final TargetCardInMuseVesselExile target) { + super(target); + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + Card sourceCard = game.getCard(sourceId); + if (sourceCard != null) { + UUID exileId = CardUtil.getCardExileZoneId(game, sourceId); + ExileZone exile = game.getExile().getExileZone(exileId); + if (exile != null && !exile.isEmpty()) { + possibleTargets.addAll(exile); + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + Card sourceCard = game.getCard(sourceId); + if (sourceCard != null) { + UUID exileId = CardUtil.getCardExileZoneId(game, sourceId); + ExileZone exile = game.getExile().getExileZone(exileId); + if (exile != null && !exile.isEmpty()) { + return true; + } + } + return false; + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + Card card = game.getCard(id); + if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { + ExileZone exile = null; + Card sourceCard = game.getCard(source.getSourceId()); + if (sourceCard != null) { + UUID exileId = CardUtil.getCardExileZoneId(game, source); + exile = game.getExile().getExileZone(exileId); + } + if (exile != null && exile.contains(id)) { + return filter.match(card, source.getControllerId(), game); + } + } + return false; + } + + @Override + public TargetCardInMuseVesselExile copy() { + return new TargetCardInMuseVesselExile(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MycoidShepherd.java b/Mage.Sets/src/mage/cards/m/MycoidShepherd.java index 2e00d71e7ec..ae18362969c 100644 --- a/Mage.Sets/src/mage/cards/m/MycoidShepherd.java +++ b/Mage.Sets/src/mage/cards/m/MycoidShepherd.java @@ -75,7 +75,7 @@ class MycoidShepherdTriggeredAbility extends TriggeredAbilityImpl { } if (super.getSourceId().equals(event.getTargetId()) || permanent.getPower().getValue() > 4 - && permanent.getControllerId().equals(controllerId)) { + && permanent.isControlledBy(controllerId)) { Zone after = game.getState().getZone(event.getTargetId()); return after != null && Zone.GRAVEYARD.match(after); } diff --git a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java index 6e5a5022796..8349c70f48a 100644 --- a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java +++ b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java @@ -96,7 +96,7 @@ class MyrBattlesphereTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} attacks, you may tap X untapped Myr you control. If you do, {this} gets +X/+0 until end of turn and deals X damage to the player or planeswalker it’s attacking."; + return "Whenever {this} attacks, you may tap X untapped Myr you control. If you do, {this} gets +X/+0 until end of turn and deals X damage to the player or planeswalker it's attacking."; } } @@ -111,7 +111,7 @@ class MyrBattlesphereEffect extends OneShotEffect { public MyrBattlesphereEffect() { super(Outcome.Damage); - staticText = "you may tap X untapped Myr you control. If you do, {this} gets +X/+0 until end of turn and deals X damage to the player or planeswalker it’s attacking."; + staticText = "you may tap X untapped Myr you control. If you do, {this} gets +X/+0 until end of turn and deals X damage to the player or planeswalker it's attacking."; } public MyrBattlesphereEffect(final MyrBattlesphereEffect effect) { diff --git a/Mage.Sets/src/mage/cards/m/MyrServitor.java b/Mage.Sets/src/mage/cards/m/MyrServitor.java index 070ef591750..d63f1db4250 100644 --- a/Mage.Sets/src/mage/cards/m/MyrServitor.java +++ b/Mage.Sets/src/mage/cards/m/MyrServitor.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class MyrServitor extends CardImpl { this.toughness = new MageInt(1); // At the beginning of your upkeep, if Myr Servitor is on the battlefield, each player returns all cards named Myr Servitor from their graveyard to the battlefield. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new MyrServitorReturnEffect(), TargetController.YOU, false), SourceOnBattlefieldCondition.instance, "At the beginning of your upkeep, if {this} is on the battlefield, each player returns all cards named Myr Servitor from their graveyard to the battlefield" diff --git a/Mage.Sets/src/mage/cards/m/MysticArchaeologist.java b/Mage.Sets/src/mage/cards/m/MysticArchaeologist.java new file mode 100644 index 00000000000..21e85f2a2b9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MysticArchaeologist.java @@ -0,0 +1,44 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +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.Zone; + +/** + * + * @author TheElk801 + */ +public final class MysticArchaeologist extends CardImpl { + + public MysticArchaeologist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {3}{U}{U}: Draw two cards. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(2), + new ManaCostsImpl("{3}{U}{U}") + )); + } + + public MysticArchaeologist(final MysticArchaeologist card) { + super(card); + } + + @Override + public MysticArchaeologist copy() { + return new MysticArchaeologist(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MysticBarrier.java b/Mage.Sets/src/mage/cards/m/MysticBarrier.java index fe315e44081..a3f34a5f7c2 100644 --- a/Mage.Sets/src/mage/cards/m/MysticBarrier.java +++ b/Mage.Sets/src/mage/cards/m/MysticBarrier.java @@ -1,32 +1,24 @@ - package mage.cards.m; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.ChooseModeEffect; +import mage.abilities.meta.OrTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.choices.Choice; -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.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.players.PlayerList; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MysticBarrier extends CardImpl { @@ -38,7 +30,10 @@ public final class MysticBarrier extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); // When Mystic Barrier enters the battlefield or at the beginning of your upkeep, choose left or right. - this.addAbility(new MysticBarrierTriggeredAbility()); + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new ChooseModeEffect("Choose a direction to allow attacking in.", + ALLOW_ATTACKING_LEFT, ALLOW_ATTACKING_RIGHT), + new EntersBattlefieldTriggeredAbility(null, false), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false))); // Each player may attack only the opponent seated nearest him or her in the last chosen direction and planeswalkers controlled by that player. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MysticBarrierReplacementEffect())); @@ -54,77 +49,6 @@ public final class MysticBarrier extends CardImpl { } } -class MysticBarrierTriggeredAbility extends TriggeredAbilityImpl { - - public MysticBarrierTriggeredAbility() { - super(Zone.BATTLEFIELD, new MysticBarrierChooseEffect(), false); - } - - public MysticBarrierTriggeredAbility(final MysticBarrierTriggeredAbility ability) { - super(ability); - } - - @Override - public MysticBarrierTriggeredAbility copy() { - return new MysticBarrierTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.ENTERS_THE_BATTLEFIELD || event.getType() == EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - return event.getTargetId().equals(this.getSourceId()); - } else { - return event.getPlayerId().equals(this.getControllerId()); - } - } - - @Override - public String getRule() { - return "When {this} enters the battlefield or at the beginning of your upkeep, " + super.getRule(); - } -} - -class MysticBarrierChooseEffect extends OneShotEffect { - - static final String[] SET_VALUES = new String[]{MysticBarrier.ALLOW_ATTACKING_LEFT, MysticBarrier.ALLOW_ATTACKING_RIGHT}; - static final Set CHOICES = new HashSet<>(Arrays.asList(SET_VALUES)); - - public MysticBarrierChooseEffect() { - super(Outcome.Benefit); - this.staticText = "choose left or right"; - } - - public MysticBarrierChooseEffect(final MysticBarrierChooseEffect effect) { - super(effect); - } - - @Override - public MysticBarrierChooseEffect copy() { - return new MysticBarrierChooseEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Choice directionChoice = new ChoiceImpl(true); - directionChoice.setChoices(CHOICES); - directionChoice.setMessage("Direction each player may only attack to"); - directionChoice.isRequired(); - if (!controller.choose(outcome, directionChoice, game)) { - game.getState().setValue("attack_direction_" + source.getSourceId(), directionChoice.getChoice()); - return true; - } - } - return false; - } -} - class MysticBarrierReplacementEffect extends ReplacementEffectImpl { MysticBarrierReplacementEffect() { @@ -152,7 +76,7 @@ class MysticBarrierReplacementEffect extends ReplacementEffectImpl { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { if (game.getState().getPlayersInRange(controller.getId(), game).contains(event.getPlayerId())) { - String allowedDirection = (String) game.getState().getValue(new StringBuilder("attack_direction_").append(source.getSourceId()).toString()); + String allowedDirection = (String) game.getState().getValue(source.getSourceId() + "_modeChoice"); if (allowedDirection != null) { Player defender = game.getPlayer(event.getTargetId()); if (defender == null) { diff --git a/Mage.Sets/src/mage/cards/m/MythUnbound.java b/Mage.Sets/src/mage/cards/m/MythUnbound.java new file mode 100644 index 00000000000..28924a6075f --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MythUnbound.java @@ -0,0 +1,113 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.ZoneChangeAllTriggeredAbility; +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.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.other.OwnerPredicate; +import mage.filter.predicate.permanent.CommanderPredicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author TheElk801 + */ +public final class MythUnbound extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(new CommanderPredicate()); + filter.add(new OwnerPredicate(TargetController.YOU)); + } + + public MythUnbound(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + + // Your commander costs {1} less to cast for each time it's been cast from the command zone this game. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new MythUnboundCostReductionEffect() + )); + + // Whenever your commander is put into the command zone from anywhere, draw a card. + this.addAbility(new ZoneChangeAllTriggeredAbility( + Zone.BATTLEFIELD, Zone.ALL, Zone.COMMAND, + new DrawCardSourceControllerEffect(1), filter, + "Whenever your commander is put into " + + "the command zone from anywhere, ", false + )); + } + + public MythUnbound(final MythUnbound card) { + super(card); + } + + @Override + public MythUnbound copy() { + return new MythUnbound(this); + } +} + +class MythUnboundCostReductionEffect extends CostModificationEffectImpl { + + MythUnboundCostReductionEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "your commander costs {1} less to cast for each time " + + "it's been cast from the command zone this game"; + } + + MythUnboundCostReductionEffect(MythUnboundCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + Ability spellAbility = (SpellAbility) abilityToModify; + if (spellAbility != null) { + Integer amount = (Integer) game.getState().getValue(abilityToModify.getControllerId() + "_castCount"); + if (amount != null && amount > 0) { + CardUtil.reduceCost(spellAbility, amount); + return true; + } + } + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + if (abilityToModify instanceof SpellAbility) { + if (abilityToModify.isControlledBy(source.getControllerId())) { + Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); + if (spell != null) { + return player.getCommandersIds().contains(spell.getId()); + } + } + } + return false; + } + + @Override + public MythUnboundCostReductionEffect copy() { + return new MythUnboundCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java b/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java index 3a7b63ae636..be2690ceb58 100644 --- a/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java +++ b/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java @@ -74,7 +74,7 @@ class NabanDeanOfIterationEffect extends ReplacementEffectImpl { if (event instanceof NumberOfTriggersEvent) { NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; // Only triggers of the controller of Naban - if (source.getControllerId().equals(event.getPlayerId())) { + if (source.isControlledBy(event.getPlayerId())) { GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); // Only EtB triggers if (sourceEvent != null diff --git a/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java b/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java index 71148b1167a..d39e57e989d 100644 --- a/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java +++ b/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java @@ -35,7 +35,7 @@ import mage.game.permanent.token.WarriorToken; */ public final class NajeelaTheBladeBlossom extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WARRIOR, "a Warrior"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WARRIOR, "Warrior"); public NajeelaTheBladeBlossom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); diff --git a/Mage.Sets/src/mage/cards/n/NantukoShaman.java b/Mage.Sets/src/mage/cards/n/NantukoShaman.java index 5937fe9fca6..b17eaccb4bd 100644 --- a/Mage.Sets/src/mage/cards/n/NantukoShaman.java +++ b/Mage.Sets/src/mage/cards/n/NantukoShaman.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.SuspendAbility; import mage.cards.CardImpl; @@ -38,7 +38,7 @@ public final class NantukoShaman extends CardImpl { this.toughness = new MageInt(2); // When Nantuko Shaman enters the battlefield, if you control no tapped lands, draw a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0), "When {this} enters the battlefield, if you control no tapped lands, draw a card"); diff --git a/Mage.Sets/src/mage/cards/n/NaturesWill.java b/Mage.Sets/src/mage/cards/n/NaturesWill.java index 2aec1b05d60..4c771bf5fee 100644 --- a/Mage.Sets/src/mage/cards/n/NaturesWill.java +++ b/Mage.Sets/src/mage/cards/n/NaturesWill.java @@ -1,20 +1,18 @@ package mage.cards.n; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect; +import mage.abilities.effects.common.UntapAllEffect; 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.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterLandPermanent; /** * @@ -26,7 +24,11 @@ public final class NaturesWill extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}"); // Whenever one or more creatures you control deal combat damage to a player, tap all lands that player controls and untap all lands you control. - this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(new NaturesWillEffect())); + Effect tapAllEffect = new TapAllTargetPlayerControlsEffect(new FilterLandPermanent()); + tapAllEffect.setText("tap all lands that player controls"); + Ability ability = new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone.BATTLEFIELD, tapAllEffect, true); + ability.addEffect(new UntapAllEffect(new FilterControlledLandPermanent())); + addAbility(ability); } public NaturesWill(final NaturesWill card) { @@ -38,37 +40,3 @@ public final class NaturesWill extends CardImpl { return new NaturesWill(this); } } - -class NaturesWillEffect extends OneShotEffect { - - public NaturesWillEffect() { - super(Outcome.Benefit); - this.staticText = "tap all lands that player controls and untap all lands you control"; - } - - public NaturesWillEffect(final NaturesWillEffect effect) { - super(effect); - } - - @Override - public NaturesWillEffect copy() { - return new NaturesWillEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Set damagedPlayers = (HashSet) this.getValue("damagedPlayers"); - if (damagedPlayers != null) { - List lands = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source.getSourceId(), game); - for (Permanent land : lands) { - if (damagedPlayers.contains(land.getControllerId())) { - land.tap(game); - } else if (land.getControllerId().equals(source.getControllerId())) { - land.untap(game); - } - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/n/NavigatorsCompass.java b/Mage.Sets/src/mage/cards/n/NavigatorsCompass.java index a5c21620e9b..e8e964b4548 100644 --- a/Mage.Sets/src/mage/cards/n/NavigatorsCompass.java +++ b/Mage.Sets/src/mage/cards/n/NavigatorsCompass.java @@ -25,7 +25,7 @@ public final class NavigatorsCompass extends CardImpl { public NavigatorsCompass(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); - // When Navigator’s Compass enters the battlefield, you gain 3 life. + // When Navigator's Compass enters the battlefield, you gain 3 life. Ability etbAbility = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)); this.addAbility(etbAbility); // {tap}: Until end of turn, target land you control becomes the basic land type of your choice in addition to its other types. diff --git a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java index c12ff398c74..d7ce59cf37d 100644 --- a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java +++ b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -24,7 +24,7 @@ public final class NavigatorsRuin extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // Raid - At the beginning of your end step, if you attacked with a creature this turm, target opponent puts the top four cards of their library into their graveyard. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), TargetController.YOU, false), RaidCondition.instance, "Raid — At the beginning of your end step, if you attacked with a creature this turn, target opponent puts the top four cards of their library into their graveyard."); diff --git a/Mage.Sets/src/mage/cards/n/NearDeathExperience.java b/Mage.Sets/src/mage/cards/n/NearDeathExperience.java index ffda771b809..d4563d5d298 100644 --- a/Mage.Sets/src/mage/cards/n/NearDeathExperience.java +++ b/Mage.Sets/src/mage/cards/n/NearDeathExperience.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -26,7 +26,7 @@ public final class NearDeathExperience extends CardImpl { // At the beginning of your upkeep, if you have exactly 1 life, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new OneLifeCondition(), "At the beginning of your upkeep, if you have exactly 1 life, you win the game.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new OneLifeCondition(), "At the beginning of your upkeep, if you have exactly 1 life, you win the game.")); } public NearDeathExperience(final NearDeathExperience card) { diff --git a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java index 9973b8d6fd5..6a9271a242a 100644 --- a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java +++ b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java @@ -1,4 +1,3 @@ - package mage.cards.n; import java.util.UUID; @@ -6,16 +5,14 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.*; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SuperType; import mage.constants.Zone; @@ -38,7 +35,7 @@ public final class Nebuchadnezzar extends CardImpl { this.toughness = new MageInt(3); // {X}, {T}: Choose a card name. Target opponent reveals X cards at random from their hand. Then that player discards all cards with that name revealed this way. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new NameACardEffect(NameACardEffect.TypeOfName.ALL), new ManaCostsImpl("{X}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new ManaCostsImpl("{X}"), MyTurnCondition.instance); ability.addCost(new TapSourceCost()); ability.addEffect(new NebuchadnezzarEffect()); ability.addTarget(new TargetOpponent()); @@ -70,7 +67,7 @@ class NebuchadnezzarEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); MageObject sourceObject = game.getObject(source.getSourceId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (opponent != null && sourceObject != null && !cardName.isEmpty()) { int costX = source.getManaCostsToPay().getX(); if (costX > 0 && !opponent.getHand().isEmpty()) { diff --git a/Mage.Sets/src/mage/cards/n/NeckBreaker.java b/Mage.Sets/src/mage/cards/n/NeckBreaker.java index eda3130e3de..e47c72f19c0 100644 --- a/Mage.Sets/src/mage/cards/n/NeckBreaker.java +++ b/Mage.Sets/src/mage/cards/n/NeckBreaker.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -50,7 +50,7 @@ public final class NeckBreaker extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Neck Breaker. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public NeckBreaker(final NeckBreaker card) { diff --git a/Mage.Sets/src/mage/cards/n/NecraSanctuary.java b/Mage.Sets/src/mage/cards/n/NecraSanctuary.java index f18f891f83c..444249762d4 100644 --- a/Mage.Sets/src/mage/cards/n/NecraSanctuary.java +++ b/Mage.Sets/src/mage/cards/n/NecraSanctuary.java @@ -4,7 +4,7 @@ package mage.cards.n; import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryTriggeredAbility; +import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +21,7 @@ public final class NecraSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); // At the beginning of your upkeep, if you control a green or white permanent, target player loses 1 life. If you control a green permanent and a white permanent, that player loses 3 life instead. - Ability ability = new SanctuaryTriggeredAbility( + Ability ability = new SanctuaryInterveningIfTriggeredAbility( new LoseLifeTargetEffect(1), new LoseLifeTargetEffect(3), ObjectColor.GREEN, ObjectColor.WHITE, "At the beginning of your upkeep, if you control a green or white permanent, " + "target player loses 1 life. If you control a green permanent and a white permanent, that player loses 3 life instead." diff --git a/Mage.Sets/src/mage/cards/n/Necrologia.java b/Mage.Sets/src/mage/cards/n/Necrologia.java index fbd8bfe218c..1d35c3bebab 100644 --- a/Mage.Sets/src/mage/cards/n/Necrologia.java +++ b/Mage.Sets/src/mage/cards/n/Necrologia.java @@ -23,7 +23,7 @@ public final class Necrologia extends CardImpl { // Cast Necrologia only during your end step. this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.END_TURN, MyTurnCondition.instance, - "Cast {this} only during your end step")); + "Cast this spell only during your end step")); // As an additional cost to cast to Necrologia, pay X life. this.getSpellAbility().addCost(new PayVariableLifeCost(true)); diff --git a/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java b/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java index 7ec8e35d058..168c633cb71 100644 --- a/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java +++ b/Mage.Sets/src/mage/cards/n/NecromancersMagemark.java @@ -113,7 +113,7 @@ class NecromancersMagemarkEffect extends ReplacementEffectImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { for (UUID attachmentId : permanent.getAttachments()) { Permanent attachment = game.getPermanentOrLKIBattlefield(attachmentId); if (attachment != null && attachment.hasSubtype(SubType.AURA, game)) { diff --git a/Mage.Sets/src/mage/cards/n/Necromancy.java b/Mage.Sets/src/mage/cards/n/Necromancy.java index c217d6d1056..fe12c03723a 100644 --- a/Mage.Sets/src/mage/cards/n/Necromancy.java +++ b/Mage.Sets/src/mage/cards/n/Necromancy.java @@ -9,7 +9,7 @@ import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.common.SacrificeIfCastAtInstantTimeTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashSourceEffect; @@ -45,7 +45,7 @@ public final class Necromancy extends CardImpl { // When Necromancy enters the battlefield, if it's on the battlefield, it becomes an Aura with "enchant creature put onto the battlefield with Necromancy." // Put target creature card from a graveyard onto the battlefield under your control and attach Necromancy to it. // When Necromancy leaves the battlefield, that creature's controller sacrifices it. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new NecromancyReAttachEffect(), false), SourceOnBattlefieldCondition.instance, "When {this} enters the battlefield, if it's on the battlefield, it becomes an Aura with \"enchant creature put onto the battlefield with {this}.\" Put target creature card from a graveyard onto the battlefield under your control and attach {this} to it."); diff --git a/Mage.Sets/src/mage/cards/n/NecropolisRegent.java b/Mage.Sets/src/mage/cards/n/NecropolisRegent.java index d7a628de3d4..5e53ec1011b 100644 --- a/Mage.Sets/src/mage/cards/n/NecropolisRegent.java +++ b/Mage.Sets/src/mage/cards/n/NecropolisRegent.java @@ -76,7 +76,7 @@ class NecropolisRegentTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { this.getEffects().clear(); Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(event.getAmount())); effect.setTargetPointer(new FixedTarget(creature.getId())); diff --git a/Mage.Sets/src/mage/cards/n/Necropotence.java b/Mage.Sets/src/mage/cards/n/Necropotence.java index 8a7372a4b2b..3c1cc4bf289 100644 --- a/Mage.Sets/src/mage/cards/n/Necropotence.java +++ b/Mage.Sets/src/mage/cards/n/Necropotence.java @@ -79,7 +79,7 @@ class NecropotenceTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getControllerId().equals(event.getPlayerId())) { + if (isControlledBy(event.getPlayerId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getTargetId())); return true; } diff --git a/Mage.Sets/src/mage/cards/n/NessianDemolok.java b/Mage.Sets/src/mage/cards/n/NessianDemolok.java index 2f093a48b95..2ecd67ab9a7 100644 --- a/Mage.Sets/src/mage/cards/n/NessianDemolok.java +++ b/Mage.Sets/src/mage/cards/n/NessianDemolok.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class NessianDemolok extends CardImpl { // When Nessian Demolok enters the battlefield, if tribute wasn't paid, destroy target noncreature permanent. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetPermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, destroy target noncreature permanent.")); } diff --git a/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java b/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java index f4ee1ac8563..3cb5b250f23 100644 --- a/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java +++ b/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -40,7 +40,7 @@ public final class NessianWildsRavager extends CardImpl { // When Nessian Wilds Ravager enters the battlefield, if tribute wasn't paid, you may have Nessian Wilds Ravager fight another target creature. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect(), true); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, you may have {this} fight another target creature.")); } diff --git a/Mage.Sets/src/mage/cards/n/NestOfScarabs.java b/Mage.Sets/src/mage/cards/n/NestOfScarabs.java index c5d031e6373..2086264318a 100644 --- a/Mage.Sets/src/mage/cards/n/NestOfScarabs.java +++ b/Mage.Sets/src/mage/cards/n/NestOfScarabs.java @@ -56,7 +56,7 @@ class NestOfScarabsTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - boolean weAreDoingIt = getControllerId().equals(game.getControllerId(event.getSourceId())); + boolean weAreDoingIt = isControlledBy(game.getControllerId(event.getSourceId())); boolean isM1M1Counters = event.getData().equals(CounterType.M1M1.getName()); if (weAreDoingIt && isM1M1Counters && event.getAmount() > 0) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); diff --git a/Mage.Sets/src/mage/cards/n/NestingDragon.java b/Mage.Sets/src/mage/cards/n/NestingDragon.java new file mode 100644 index 00000000000..9f50c82d243 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NestingDragon.java @@ -0,0 +1,44 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.LandfallAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.NestingDragonToken; + +/** + * + * @author TheElk801 + */ +public final class NestingDragon extends CardImpl { + + public NestingDragon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Landfall — Whenever a land enters the battlefield under your control, create a 0/2 red Dragon Egg creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'" + this.addAbility(new LandfallAbility( + new CreateTokenEffect(new NestingDragonToken()), false + )); + } + + public NestingDragon(final NestingDragon card) { + super(card); + } + + @Override + public NestingDragon copy() { + return new NestingDragon(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NetherSpirit.java b/Mage.Sets/src/mage/cards/n/NetherSpirit.java index f6e60bc88aa..392754dc55e 100644 --- a/Mage.Sets/src/mage/cards/n/NetherSpirit.java +++ b/Mage.Sets/src/mage/cards/n/NetherSpirit.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class NetherSpirit extends CardImpl { // At the beginning of your upkeep, if Nether Spirit is the only creature card in your graveyard, you may return Nether Spirit to the battlefield. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), TargetController.YOU, true); - this.addAbility(new ConditionalTriggeredAbility(ability, new NetherSpiritCondition(), "At the beginning of your upkeep, if {this} is the only creature card in your graveyard, you may return {this} to the battlefield.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new NetherSpiritCondition(), "At the beginning of your upkeep, if {this} is the only creature card in your graveyard, you may return {this} to the battlefield.")); } public NetherSpirit(final NetherSpirit card) { diff --git a/Mage.Sets/src/mage/cards/n/NetherTraitor.java b/Mage.Sets/src/mage/cards/n/NetherTraitor.java index e790731580e..269030fc48e 100644 --- a/Mage.Sets/src/mage/cards/n/NetherTraitor.java +++ b/Mage.Sets/src/mage/cards/n/NetherTraitor.java @@ -75,13 +75,13 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; for (Zone z : Zone.values()) { - if (game.getShortLivingLKI(sourceId, z) && !z.equals(Zone.GRAVEYARD)) { + if (game.getShortLivingLKI(sourceId, z) && z != Zone.GRAVEYARD) { return false; } } if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { if (zEvent.getTarget() != null && - zEvent.getTarget().getOwnerId().equals(this.getControllerId()) && + zEvent.getTarget().isOwnedBy(this.getControllerId()) && zEvent.getTarget().isCreature()&& !zEvent.getTarget().getId().equals(this.getSourceId())) { return true; diff --git a/Mage.Sets/src/mage/cards/n/NettlingCurse.java b/Mage.Sets/src/mage/cards/n/NettlingCurse.java new file mode 100644 index 00000000000..18456d6a31b --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NettlingCurse.java @@ -0,0 +1,54 @@ +package mage.cards.n; + +import java.util.UUID; + +import mage.abilities.common.AttacksOrBlocksEnchantedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.LoseLifeControllerAttachedEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.combat.AttacksIfAbleAttachedEffect; +import mage.constants.*; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; + +/** + * + * @author noahg + */ +public final class NettlingCurse extends CardImpl { + + public NettlingCurse(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + + 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); + + // Whenever enchanted creature attacks or blocks, its controller loses 3 life. + this.addAbility(new AttacksOrBlocksEnchantedTriggeredAbility(Zone.BATTLEFIELD, new LoseLifeControllerAttachedEffect(3))); + + // {1}{R}: Enchanted creature attacks this turn if able. + this.addAbility(new SimpleActivatedAbility(new AttacksIfAbleAttachedEffect(Duration.EndOfTurn, AttachmentType.AURA).setText("Enchanted creature attacks this turn if able."), new ManaCostsImpl("{1}{R}"))); + } + + public NettlingCurse(final NettlingCurse card) { + super(card); + } + + @Override + public NettlingCurse copy() { + return new NettlingCurse(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java b/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java new file mode 100644 index 00000000000..886d089c0b3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java @@ -0,0 +1,71 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.AddCardTypeTargetEffect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.abilities.effects.common.continuous.LoseArtifactTypeTargetEffect; +import mage.abilities.effects.common.continuous.LoseCreatureTypeSourceEffect; +import mage.constants.Duration; +import mage.constants.SubType; +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.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetArtifactPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author noahg + */ +public final class NeurokTransmuter extends CardImpl { + + final static FilterCreaturePermanent filter = new FilterCreaturePermanent("artifact creature"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + + public NeurokTransmuter(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(2); + this.toughness = new MageInt(2); + + // {U}: Target creature becomes an artifact in addition to its other types until end of turn. + Ability becomeArtifactAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCardTypeTargetEffect(Duration.EndOfTurn, CardType.ARTIFACT), new ManaCostsImpl("{U}")); + becomeArtifactAbility.addTarget(new TargetCreaturePermanent()); + this.addAbility(becomeArtifactAbility); + // {U}: Until end of turn, target artifact creature becomes blue and isn't an artifact. + Effect blueEffect = new BecomesColorTargetEffect(ObjectColor.BLUE, Duration.EndOfTurn); + blueEffect.setText("Until end of turn, target artifact creature becomes blue and "); + Ability becomeBlueAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, blueEffect, new ManaCostsImpl("{U}")); + becomeBlueAbility.addTarget(new TargetCreaturePermanent(filter)); + Effect loseArtifactEffect = new LoseArtifactTypeTargetEffect(Duration.EndOfTurn); + loseArtifactEffect.setText("isn't an artifact"); + becomeBlueAbility.addEffect(loseArtifactEffect); + this.addAbility(becomeBlueAbility); + } + + public NeurokTransmuter(final NeurokTransmuter card) { + super(card); + } + + @Override + public NeurokTransmuter copy() { + return new NeurokTransmuter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/Nevermore.java b/Mage.Sets/src/mage/cards/n/Nevermore.java index 1fbd5332fcd..755bf786cd2 100644 --- a/Mage.Sets/src/mage/cards/n/Nevermore.java +++ b/Mage.Sets/src/mage/cards/n/Nevermore.java @@ -1,4 +1,3 @@ - package mage.cards.n; import java.util.UUID; @@ -7,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -25,10 +24,10 @@ import mage.game.events.GameEvent.EventType; public final class Nevermore extends CardImpl { public Nevermore(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}"); // As Nevermore enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); // The named card can't be cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NevermoreEffect2())); @@ -50,7 +49,7 @@ class NevermoreEffect2 extends ContinuousRuleModifyingEffectImpl { public NevermoreEffect2() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "The named card can't be cast"; + staticText = "Spells with the chosen name can't be cast"; } public NevermoreEffect2(final NevermoreEffect2 effect) { @@ -71,7 +70,7 @@ class NevermoreEffect2 extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.CAST_SPELL) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/n/NexusOfFate.java b/Mage.Sets/src/mage/cards/n/NexusOfFate.java new file mode 100644 index 00000000000..58e9e0af285 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NexusOfFate.java @@ -0,0 +1,35 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility; +import mage.abilities.effects.common.RevealAndShuffleIntoLibrarySourceEffect; +import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class NexusOfFate extends CardImpl { + + public NexusOfFate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{U}{U}"); + + // Take an extra turn after this one. + this.getSpellAbility().addEffect(new AddExtraTurnControllerEffect()); + + // If Nexus of Fate would be put into a graveyard from anywhere, reveal Nexus of Fate and shuffle it into its owner's library instead. + this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new RevealAndShuffleIntoLibrarySourceEffect())); + } + + public NexusOfFate(final NexusOfFate card) { + super(card); + } + + @Override + public NexusOfFate copy() { + return new NexusOfFate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java b/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java index fe436eca297..aafd4aeadf1 100644 --- a/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java +++ b/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java @@ -43,7 +43,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_INSTANT_OR_SORCERY_SPELL, false); + Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), StaticFilters.FILTER_SPELL_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/NicolBolasPlaneswalker.java b/Mage.Sets/src/mage/cards/n/NicolBolasPlaneswalker.java index 609163006be..ba43fe13c59 100644 --- a/Mage.Sets/src/mage/cards/n/NicolBolasPlaneswalker.java +++ b/Mage.Sets/src/mage/cards/n/NicolBolasPlaneswalker.java @@ -53,7 +53,7 @@ public final class NicolBolasPlaneswalker extends CardImpl { ability = new LoyaltyAbility(new DamageTargetEffect(7), -9); ability.addTarget(new TargetPlayerOrPlaneswalker()); ability.addEffect(new DiscardTargetEffect(7) - .setText("That player or that planeswalker’s controller discards seven cards") + .setText("That player or that planeswalker's controller discards seven cards") ); ability.addEffect(new SacrificeEffect(new FilterPermanent(), 7, "then") .setText("then sacrifices seven permanents") diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java b/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java new file mode 100644 index 00000000000..825c0d5c41c --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NicolBolasTheArisen.java @@ -0,0 +1,110 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +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.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCreatureOrPlaneswalker; + +/** + * + * @author TheElk801 + */ +public final class NicolBolasTheArisen extends CardImpl { + + private static final FilterCard filter = new FilterCard("creature or planeswalker card from a graveyard"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.PLANESWALKER) + )); + } + + public NicolBolasTheArisen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.BOLAS); + + this.color.setBlue(true); + this.color.setBlack(true); + this.color.setRed(true); + this.nightCard = true; + this.transformable = true; + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(7)); + + // +2: Draw two cards. + this.addAbility(new LoyaltyAbility(new DrawCardSourceControllerEffect(2), 2)); + + // −3: Nicol Bolas, the Arisen deals 10 damage to target creature or planeswalker. + Ability ability = new LoyaltyAbility(new DamageTargetEffect(10), -3); + ability.addTarget(new TargetCreatureOrPlaneswalker()); + this.addAbility(ability); + + // −4: Put target creature or planeswalker card from a graveyard onto the battlefield under your control. + ability = new LoyaltyAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), -4); + ability.addTarget(new TargetCardInGraveyard(filter)); + this.addAbility(ability); + + // −12: Exile all but the bottom card of target player's library. + ability = new LoyaltyAbility(new NicolBolasTheArisenEffect(), -12); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public NicolBolasTheArisen(final NicolBolasTheArisen card) { + super(card); + } + + @Override + public NicolBolasTheArisen copy() { + return new NicolBolasTheArisen(this); + } +} + +class NicolBolasTheArisenEffect extends OneShotEffect { + + public NicolBolasTheArisenEffect() { + super(Outcome.Benefit); + this.staticText = "Exile all but the bottom card of target player's library."; + } + + public NicolBolasTheArisenEffect(final NicolBolasTheArisenEffect effect) { + super(effect); + } + + @Override + public NicolBolasTheArisenEffect copy() { + return new NicolBolasTheArisenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (targetPlayer == null || controller == null) { + return false; + } + return controller.moveCards(targetPlayer.getLibrary().getTopCards(game, targetPlayer.getLibrary().size() - 1), Zone.EXILED, source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java b/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java new file mode 100644 index 00000000000..b6c5f0efd2e --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NicolBolasTheRavager.java @@ -0,0 +1,63 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Gender; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.ExileAndReturnTransformedSourceEffect; +import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class NicolBolasTheRavager extends CardImpl { + + public NicolBolasTheRavager(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + this.transformable = true; + this.secondSideCardClazz = NicolBolasTheArisen.class; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Nicol Bolas, the Ravager enters the battlefield, each opponent discards a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect(new StaticValue(1), false, TargetController.OPPONENT))); + + // {4}{U}{B}{R}: Exile Nicol Bolas, the Ravager, then return him to the battlefield transformed under his owner's control. Activate this ability only any time you could cast a sorcerry. + this.addAbility(new TransformAbility()); + this.addAbility(new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, + new ExileAndReturnTransformedSourceEffect(Gender.MALE), + new ManaCostsImpl("{4}{U}{B}{R}") + )); + } + + public NicolBolasTheRavager(final NicolBolasTheRavager card) { + super(card); + } + + @Override + public NicolBolasTheRavager copy() { + return new NicolBolasTheRavager(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NightIncarnate.java b/Mage.Sets/src/mage/cards/n/NightIncarnate.java new file mode 100644 index 00000000000..e4cac134219 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NightIncarnate.java @@ -0,0 +1,49 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.constants.SubType; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.EvokeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; + +/** + * + * @author TheElk801 + */ +public final class NightIncarnate extends CardImpl { + + public NightIncarnate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // When Night Incarnate leaves the battlefield, all creatures get -3/-3 until end of turn. + this.addAbility(new LeavesBattlefieldTriggeredAbility( + new BoostAllEffect(-3, -3, Duration.EndOfTurn), false + )); + + // Evoke {3}{B} + this.addAbility(new EvokeAbility(this, "{3}{B}")); + + } + + public NightIncarnate(final NightIncarnate card) { + super(card); + } + + @Override + public NightIncarnate copy() { + return new NightIncarnate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/Nightcreep.java b/Mage.Sets/src/mage/cards/n/Nightcreep.java new file mode 100644 index 00000000000..13e51cd7b0a --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/Nightcreep.java @@ -0,0 +1,100 @@ +package mage.cards.n; + +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +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.target.targetpointer.FixedTargets; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class Nightcreep extends CardImpl { + + public Nightcreep(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); + + + // Until end of turn, all creatures become black and all lands become Swamps. + this.getSpellAbility().addEffect(new NightcreepCreatureEffect()); + this.getSpellAbility().addEffect(new NightcreepLandEffect()); + } + + public Nightcreep(final Nightcreep card) { + super(card); + } + + @Override + public Nightcreep copy() { + return new Nightcreep(this); + } +} + +class NightcreepLandEffect extends BecomesBasicLandTargetEffect { + + public NightcreepLandEffect() { + super(Duration.EndOfTurn, SubType.SWAMP); + this.staticText = ""; + } + + public NightcreepLandEffect(NightcreepLandEffect effect) { + super(effect); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + List targets = new ArrayList<>(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source.getSourceId(), game)); + 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); + } +} + +class NightcreepCreatureEffect extends BecomesColorTargetEffect { + + public NightcreepCreatureEffect() { + super(ObjectColor.BLACK, Duration.EndOfTurn); + this.staticText = "Until end of turn, all creatures become black and all lands become Swamps"; + } + + public NightcreepCreatureEffect(NightcreepCreatureEffect effect) { + super(effect); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + List targets = new ArrayList<>(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)); + 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); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NightfallPredator.java b/Mage.Sets/src/mage/cards/n/NightfallPredator.java index a2d8dd9a1d8..f93f9232ad9 100644 --- a/Mage.Sets/src/mage/cards/n/NightfallPredator.java +++ b/Mage.Sets/src/mage/cards/n/NightfallPredator.java @@ -10,7 +10,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -50,7 +50,7 @@ public final class NightfallPredator extends CardImpl { this.addAbility(activatedAbility); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Nightfall Predator. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public NightfallPredator(final NightfallPredator card) { diff --git a/Mage.Sets/src/mage/cards/n/NightmaresThirst.java b/Mage.Sets/src/mage/cards/n/NightmaresThirst.java new file mode 100644 index 00000000000..9af916beeae --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NightmaresThirst.java @@ -0,0 +1,43 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.dynamicvalue.common.ControllerGotLifeCount; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.PlayerGainedLifeWatcher; + +/** + * + * @author TheElk801 + */ +public final class NightmaresThirst extends CardImpl { + + public NightmaresThirst(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); + + // You gain 1 life. Target creature gets -X/-X until end of turn, where X is the amount of life you gained this turn. + this.getSpellAbility().addEffect(new GainLifeEffect(1)); + DynamicValue xValue = new MultipliedValue(ControllerGotLifeCount.getInstance(), -1); + this.getSpellAbility().addEffect(new BoostTargetEffect( + xValue, xValue, Duration.EndOfTurn, true + ).setText("Target creature gets -X/-X until end of turn, where X is the amount of life you gained this turn.")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addWatcher(new PlayerGainedLifeWatcher()); + } + + public NightmaresThirst(final NightmaresThirst card) { + super(card); + } + + @Override + public NightmaresThirst copy() { + return new NightmaresThirst(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java b/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java index d288bad4016..e04904264a2 100644 --- a/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -48,12 +48,12 @@ public final class NightscapeBattlemage extends CardImpl { // When Nightscape Battlemage enters the battlefield, if it was kicked with its {2}{U} kicker, return up to two target nonblack creatures to their owners' hands. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); ability.addTarget(new TargetCreaturePermanent(0, 2, filter, false)); - this.addAbility(new ConditionalTriggeredAbility(ability, new KickedCostCondition("{2}{U}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{2}{U}"), "When {this} enters the battlefield, if it was kicked with its {2}{U} kicker, return up to two target nonblack creatures to their owners' hands.")); // When Nightscape Battlemage enters the battlefield, if it was kicked with its {2}{R} kicker, destroy target land. ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetLandPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, new KickedCostCondition("{2}{R}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{2}{R}"), "When {this} enters the battlefield, if it was kicked with its {2}{R} kicker, destroy target land.")); } diff --git a/Mage.Sets/src/mage/cards/n/Nihilith.java b/Mage.Sets/src/mage/cards/n/Nihilith.java index 73cfcc2508a..de40e72459d 100644 --- a/Mage.Sets/src/mage/cards/n/Nihilith.java +++ b/Mage.Sets/src/mage/cards/n/Nihilith.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility; import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FearAbility; import mage.abilities.keyword.SuspendAbility; @@ -39,7 +39,7 @@ public final class Nihilith extends CardImpl { this.addAbility(new SuspendAbility(7, new ManaCostsImpl("{1}{B}"), this, false)); // Whenever a card is put into an opponent's graveyard from anywhere, if Nihilith is suspended, you may remove a time counter from Nihilith. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new PutCardIntoGraveFromAnywhereAllTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), true, new FilterCard(), TargetController.OPPONENT, SetTargetPointer.NONE), SuspendedCondition.instance, diff --git a/Mage.Sets/src/mage/cards/n/NimDeathmantle.java b/Mage.Sets/src/mage/cards/n/NimDeathmantle.java index 6ccaafd97b1..895ef5405cf 100644 --- a/Mage.Sets/src/mage/cards/n/NimDeathmantle.java +++ b/Mage.Sets/src/mage/cards/n/NimDeathmantle.java @@ -91,7 +91,7 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; Permanent permanent = zEvent.getTarget(); if (permanent != null - && permanent.getOwnerId().equals(this.controllerId) + && permanent.isOwnedBy(this.controllerId) && zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.BATTLEFIELD && !(permanent instanceof PermanentToken) diff --git a/Mage.Sets/src/mage/cards/n/NimbusChampion.java b/Mage.Sets/src/mage/cards/n/NimbusChampion.java index 3392d7de1a2..0c656d95bbf 100644 --- a/Mage.Sets/src/mage/cards/n/NimbusChampion.java +++ b/Mage.Sets/src/mage/cards/n/NimbusChampion.java @@ -60,7 +60,7 @@ class NimbusChampionEffect extends OneShotEffect { super(Outcome.Benefit); this.staticText = "return target creature to its owner's hand if " + "that creature's power is less than or equal to " - + "the number of Warriors your team control."; + + "the number of Warriors your team controls"; } NimbusChampionEffect(final NimbusChampionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/n/NineTailWhiteFox.java b/Mage.Sets/src/mage/cards/n/NineTailWhiteFox.java new file mode 100644 index 00000000000..08fadbb07c2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NineTailWhiteFox.java @@ -0,0 +1,38 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class NineTailWhiteFox extends CardImpl { + + public NineTailWhiteFox(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.FOX); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Nine-Tail White Fox deals combat damage to a player, draw a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); + } + + public NineTailWhiteFox(final NineTailWhiteFox card) { + super(card); + } + + @Override + public NineTailWhiteFox copy() { + return new NineTailWhiteFox(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java index 34c9c6718b2..4b4fd3b1a4c 100644 --- a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java +++ b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java @@ -7,7 +7,7 @@ import mage.abilities.Gender; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAndReturnTransformedSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.TransformAbility; @@ -51,7 +51,7 @@ public final class NissaVastwoodSeer extends CardImpl { // Whenever a land enters the battlefield under your control, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldControlledTriggeredAbility(new ExileAndReturnTransformedSourceEffect(Gender.FEMALE), new FilterLandPermanent()), new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), ComparisonType.MORE_THAN, 6, true), "Whenever a land enters the battlefield under your control, if you control seven or more lands, exile {this}, then return her to the battlefield transformed under her owner's control.")); diff --git a/Mage.Sets/src/mage/cards/n/NivixAerieOfTheFiremind.java b/Mage.Sets/src/mage/cards/n/NivixAerieOfTheFiremind.java index 38aa79dcba5..f9bbf4d741e 100644 --- a/Mage.Sets/src/mage/cards/n/NivixAerieOfTheFiremind.java +++ b/Mage.Sets/src/mage/cards/n/NivixAerieOfTheFiremind.java @@ -112,7 +112,7 @@ class NivixAerieOfTheFiremindCanCastEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(this.getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/n/NivixCyclops.java b/Mage.Sets/src/mage/cards/n/NivixCyclops.java index 7850c215494..7b7f9890381 100644 --- a/Mage.Sets/src/mage/cards/n/NivixCyclops.java +++ b/Mage.Sets/src/mage/cards/n/NivixCyclops.java @@ -1,4 +1,3 @@ - package mage.cards.n; import java.util.UUID; @@ -15,9 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.FilterSpell; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -27,16 +24,8 @@ import mage.game.permanent.Permanent; */ public final class NivixCyclops extends CardImpl { - private static final FilterSpell filter = new FilterSpell("an instant or sorcery spell"); - - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY))); - } - public NivixCyclops(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); this.subtype.add(SubType.CYCLOPS); this.power = new MageInt(1); @@ -46,7 +35,11 @@ public final class NivixCyclops extends CardImpl { this.addAbility(DefenderAbility.getInstance()); // Whenever you cast an instant or sorcery spell, Nivix Cyclops gets +3/+0 until end of turn and can attack this turn as though it didn't have defender. - Ability ability = new SpellCastControllerTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), filter, false); + Ability ability = new SpellCastControllerTriggeredAbility( + new BoostSourceEffect(3, 0, Duration.EndOfTurn), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false + ); ability.addEffect(new AsThoughNoDefenderEffect()); this.addAbility(ability); @@ -59,14 +52,14 @@ public final class NivixCyclops extends CardImpl { @Override public NivixCyclops copy() { return new NivixCyclops(this); - } + } } class AsThoughNoDefenderEffect extends AsThoughEffectImpl { public AsThoughNoDefenderEffect() { super(AsThoughEffectType.ATTACK, Duration.EndOfTurn, Outcome.Benefit); - staticText ="and it can attack as though it didn't have defender"; + staticText = "and it can attack as though it didn't have defender"; } public AsThoughNoDefenderEffect(final AsThoughNoDefenderEffect effect) { @@ -93,5 +86,3 @@ class AsThoughNoDefenderEffect extends AsThoughEffectImpl { return false; } } - - diff --git a/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java b/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java index dcf415c54ec..063f4958cbd 100644 --- a/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java +++ b/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java @@ -67,7 +67,7 @@ class NoRestForTheWickedEffect extends OneShotEffect { if (c != null) { if (game.getState().getZone(cardId) == Zone.GRAVEYARD && c.isCreature() - && c.getOwnerId().equals(source.getControllerId())) { + && c.isOwnedBy(source.getControllerId())) { cardsToHand.add(c); } } diff --git a/Mage.Sets/src/mage/cards/n/NoblePurpose.java b/Mage.Sets/src/mage/cards/n/NoblePurpose.java index e2df397cd8d..6fce1fb36ff 100644 --- a/Mage.Sets/src/mage/cards/n/NoblePurpose.java +++ b/Mage.Sets/src/mage/cards/n/NoblePurpose.java @@ -66,7 +66,7 @@ class NoblePurposeTriggeredAbility extends TriggeredAbilityImpl { if (damageEvent.isCombatDamage()) { Permanent permanent = game.getPermanent(event.getSourceId()); if (permanent != null && permanent.isCreature() - && permanent.getControllerId().equals(this.getControllerId())) { + && permanent.isControlledBy(this.getControllerId())) { this.getEffects().clear(); this.getEffects().add(new GainLifeEffect(damageEvent.getAmount())); return true; diff --git a/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java b/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java index f9c10694952..c117f727616 100644 --- a/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java +++ b/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; @@ -47,12 +47,12 @@ public final class NoggleHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Noggle Hedge-Mage enters the battlefield, if you control two or more Islands, you may tap two target permanents. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule); ability.addTarget(new TargetPermanent(2, new FilterPermanent())); this.addAbility(ability); // When Noggle Hedge-Mage enters the battlefield, if you control two or more Mountains, you may have Noggle Hedge-Mage deal 2 damage to target player. - Ability ability2 = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); + Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); ability2.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java b/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java index 5c0ab9a662f..740bd42953c 100644 --- a/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java +++ b/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java @@ -94,7 +94,7 @@ class TargetStackObjectTargetingControlledPermanent extends TargetObject { for (Target target : objectTargets) { for (UUID targetId : target.getTargets()) { Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); - if (targetedPermanent != null && targetedPermanent.getControllerId().equals(sourceControllerId)) { + if (targetedPermanent != null && targetedPermanent.isControlledBy(sourceControllerId)) { return true; } } @@ -121,7 +121,7 @@ class TargetStackObjectTargetingControlledPermanent extends TargetObject { for (Target target : objectTargets) { for (UUID targetId : target.getTargets()) { Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); - if (targetedPermanent != null && targetedPermanent.getControllerId().equals(sourceControllerId)) { + if (targetedPermanent != null && targetedPermanent.isControlledBy(sourceControllerId)) { possibleTargets.add(stackObject.getId()); } } diff --git a/Mage.Sets/src/mage/cards/n/NotionThief.java b/Mage.Sets/src/mage/cards/n/NotionThief.java index 1d790f30eb7..9ff6a3977a7 100644 --- a/Mage.Sets/src/mage/cards/n/NotionThief.java +++ b/Mage.Sets/src/mage/cards/n/NotionThief.java @@ -89,7 +89,7 @@ class NotionThiefReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { - if (game.getActivePlayerId().equals(event.getPlayerId()) && game.getStep().getType() == PhaseStep.DRAW) { + if (game.isActivePlayer(event.getPlayerId()) && game.getStep().getType() == PhaseStep.DRAW) { CardsDrawnDuringDrawStepWatcher watcher = (CardsDrawnDuringDrawStepWatcher) game.getState().getWatchers().get(CardsDrawnDuringDrawStepWatcher.class.getSimpleName()); if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/n/NoviceKnight.java b/Mage.Sets/src/mage/cards/n/NoviceKnight.java new file mode 100644 index 00000000000..1a40f02fc3f --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NoviceKnight.java @@ -0,0 +1,93 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.constants.SubType; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class NoviceKnight extends CardImpl { + + public NoviceKnight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // As long as Novice Knight is enchanted or equipped, it can attack as though it didn't have defender. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, new NoviceKnightEffect() + )); + } + + public NoviceKnight(final NoviceKnight card) { + super(card); + } + + @Override + public NoviceKnight copy() { + return new NoviceKnight(this); + } +} + +class NoviceKnightEffect extends AsThoughEffectImpl { + + public NoviceKnightEffect() { + super(AsThoughEffectType.ATTACK, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "As long as {this} is enchanted or equipped, " + + "it can attack as though it didn't have defender."; + } + + public NoviceKnightEffect(final NoviceKnightEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public NoviceKnightEffect copy() { + return new NoviceKnightEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (!objectId.equals(source.getSourceId())) { + return false; + } + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null) { + for (UUID uuid : permanent.getAttachments()) { + Permanent attached = game.getBattlefield().getPermanent(uuid); + if (attached != null + && (attached.hasSubtype(SubType.EQUIPMENT, game) + || attached.hasSubtype(SubType.AURA, game))) { + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/n/NykthosShrineToNyx.java b/Mage.Sets/src/mage/cards/n/NykthosShrineToNyx.java index 74a5e024287..6b08d876413 100644 --- a/Mage.Sets/src/mage/cards/n/NykthosShrineToNyx.java +++ b/Mage.Sets/src/mage/cards/n/NykthosShrineToNyx.java @@ -1,4 +1,3 @@ - package mage.cards.n; import java.util.ArrayList; @@ -67,11 +66,11 @@ class NykthosShrineToNyxManaAbility extends ActivatedManaAbilityImpl { @Override public List getNetMana(Game game) { - netMana.clear(); + ArrayList netManaCopy = new ArrayList<>(); if (game != null) { - netMana.addAll(((ManaEffect) this.getEffects().get(0)).getNetMana(game, this)); + netManaCopy.addAll(((ManaEffect) this.getEffects().get(0)).getNetMana(game, this)); } - return netMana; + return netManaCopy; } } @@ -107,7 +106,10 @@ class NykthosDynamicManaEffect extends ManaEffect { public List getNetMana(Game game, Ability source) { List netMana = new ArrayList<>(); for (String colorChoice : ChoiceColor.getBaseColors()) { - netMana.add(computeMana(colorChoice, game, source)); + Mana mana = computeMana(colorChoice, game, source); + if (mana.count() > 0) { + netMana.add(mana); + } } return netMana; } diff --git a/Mage.Sets/src/mage/cards/n/NyleasColossus.java b/Mage.Sets/src/mage/cards/n/NyleasColossus.java new file mode 100644 index 00000000000..4f0f7caf7ec --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NyleasColossus.java @@ -0,0 +1,75 @@ +package mage.cards.n; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.abilityword.ConstellationAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class NyleasColossus extends CardImpl { + + public NyleasColossus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{6}{G}"); + + this.subtype.add(SubType.GIANT); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Constellation — Whenever Nylea's Colossus or another enchantment enters the battlefield under your control, double target creature's power and toughness until end of turn. + Ability ability = new ConstellationAbility(new NyleasColossusEffect(), false); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public NyleasColossus(final NyleasColossus card) { + super(card); + } + + @Override + public NyleasColossus copy() { + return new NyleasColossus(this); + } +} + +class NyleasColossusEffect extends OneShotEffect { + + public NyleasColossusEffect() { + super(Outcome.BoostCreature); + this.staticText = "double target creature's power and toughness until end of turn"; + } + + public NyleasColossusEffect(final NyleasColossusEffect effect) { + super(effect); + } + + @Override + public NyleasColossusEffect copy() { + return new NyleasColossusEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + int power = permanent.getPower().getValue(); + int toughness = permanent.getToughness().getValue(); + game.addEffect(new BoostTargetEffect(power, toughness, Duration.EndOfTurn), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/n/Nyxathid.java b/Mage.Sets/src/mage/cards/n/Nyxathid.java index 98af32988d3..c38c097e221 100644 --- a/Mage.Sets/src/mage/cards/n/Nyxathid.java +++ b/Mage.Sets/src/mage/cards/n/Nyxathid.java @@ -74,7 +74,7 @@ class CardsInChosenPlayerHandCount implements DynamicValue { @Override public String getMessage() { - return "cards in chosen opponents hand"; + return "card in chosen opponents hand"; } @Override diff --git a/Mage.Sets/src/mage/cards/o/OathOfChandra.java b/Mage.Sets/src/mage/cards/o/OathOfChandra.java index b5ec01bbeec..4610ca8f5c8 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfChandra.java +++ b/Mage.Sets/src/mage/cards/o/OathOfChandra.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamagePlayersEffect; @@ -47,7 +47,7 @@ public final class OathOfChandra extends CardImpl { ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); // At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, Oath of Chandra deals 2 damage to each opponent. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT), TargetController.ANY, false), OathOfChandraCondition.instance, "At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, {this} deals 2 damage to each opponent."), new OathOfChandraWatcher()); diff --git a/Mage.Sets/src/mage/cards/o/OathOfGideon.java b/Mage.Sets/src/mage/cards/o/OathOfGideon.java index dbc04025c0d..255862c77ed 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfGideon.java +++ b/Mage.Sets/src/mage/cards/o/OathOfGideon.java @@ -63,7 +63,7 @@ class OathOfGideonReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - return creature != null && creature.getControllerId().equals(source.getControllerId()) + return creature != null && creature.isControlledBy(source.getControllerId()) && creature.isPlaneswalker() && !event.getTargetId().equals(source.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/o/OathOfLiliana.java b/Mage.Sets/src/mage/cards/o/OathOfLiliana.java index b9c83646ca2..5e45a1e6bef 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfLiliana.java +++ b/Mage.Sets/src/mage/cards/o/OathOfLiliana.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.SacrificeOpponentsEffect; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class OathOfLiliana extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeOpponentsEffect(new FilterControlledCreaturePermanent("a creature")), false)); // At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, create a 2/2 black Zombie creature token. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new CreateTokenEffect(new ZombieToken()), TargetController.ANY, false), OathOfLilianaCondition.instance, "At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, " diff --git a/Mage.Sets/src/mage/cards/o/OathOfNissa.java b/Mage.Sets/src/mage/cards/o/OathOfNissa.java index ce7ead3c278..514e75cb565 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfNissa.java +++ b/Mage.Sets/src/mage/cards/o/OathOfNissa.java @@ -128,7 +128,7 @@ class OathOfNissaSpendAnyManaEffect extends AsThoughEffectImpl implements AsThou @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (source.getControllerId().equals(affectedControllerId)) { + if (source.isControlledBy(affectedControllerId)) { MageObject mageObject = game.getObject(objectId); if (mageObject != null) { if (mageObject.isPlaneswalker()) { diff --git a/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java b/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java index d758ecf8281..c73958f38d0 100644 --- a/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java +++ b/Mage.Sets/src/mage/cards/o/OathkeeperTakenosDaisho.java @@ -8,7 +8,7 @@ import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlAttachedEffect; @@ -41,7 +41,7 @@ public final class OathkeeperTakenosDaisho extends CardImpl { // Equipped creature gets +3/+1. 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 ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new DiesAttachedTriggeredAbility(new ReturnToBattlefieldUnderYourControlAttachedEffect(),"equipped creature", false), new OathkeeperEquippedMatchesFilterCondition(filter), "")); diff --git a/Mage.Sets/src/mage/cards/o/OathswornVampire.java b/Mage.Sets/src/mage/cards/o/OathswornVampire.java index a1caad56ea6..8fc5b428128 100644 --- a/Mage.Sets/src/mage/cards/o/OathswornVampire.java +++ b/Mage.Sets/src/mage/cards/o/OathswornVampire.java @@ -80,7 +80,7 @@ class OathswornVampirePlayEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(source.getSourceId()) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(source.getSourceId()) && source.isControlledBy(affectedControllerId)) { Card card = game.getCard(source.getSourceId()); if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { return condition.apply(game, source); diff --git a/Mage.Sets/src/mage/cards/o/OblivionSower.java b/Mage.Sets/src/mage/cards/o/OblivionSower.java index 87df2ef4d37..8742de4f54a 100644 --- a/Mage.Sets/src/mage/cards/o/OblivionSower.java +++ b/Mage.Sets/src/mage/cards/o/OblivionSower.java @@ -73,8 +73,8 @@ class OblivionSowerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { /* - 8/25/2015: Oblivion Sower’s ability allows you to put any land cards the player owns from exile onto the battlefield, regardless of how those cards were exiled. - 8/25/2015: Cards that are face down in exile have no characteristics. Such cards can’t be put onto the battlefield with Oblivion Sower’s ability. + 8/25/2015: Oblivion Sower's ability allows you to put any land cards the player owns from exile onto the battlefield, regardless of how those cards were exiled. + 8/25/2015: Cards that are face down in exile have no characteristics. Such cards can't be put onto the battlefield with Oblivion Sower's ability. */ Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); diff --git a/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java b/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java index 673d0c3c631..2edac2bd3e6 100644 --- a/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java +++ b/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class ObsessiveSkinner extends CardImpl { // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // put a +1/+1 counter on target creature. - ability = new ConditionalTriggeredAbility( + ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), TargetController.OPPONENT, false), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/o/Occupation.java b/Mage.Sets/src/mage/cards/o/Occupation.java new file mode 100644 index 00000000000..52e7aeae9d8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/Occupation.java @@ -0,0 +1,193 @@ +package mage.cards.o; + +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.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.RestrictionEffect; +import mage.abilities.effects.common.combat.CantAttackBlockTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.turn.Step; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Occupation extends CardImpl { + + public Occupation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{B}"); + + + // Creatures your opponents control enter the battlefield tapped. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new OccupationTapEffect())); + + // {W}{B}: Target creature can't attack or block this turn, and its activated abilities can't be activated until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new OccupationOneShotEffect("Target creature can't attack or block this turn, and its activated abilities can't be activated until end of turn"), + new ManaCostsImpl("{W}{B}")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public Occupation(final Occupation card) { + super(card); + } + + @Override + public Occupation copy() { + return new Occupation(this); + } +} + +class OccupationTapEffect extends ReplacementEffectImpl { + + OccupationTapEffect() { + super(Duration.WhileOnBattlefield, Outcome.Tap); + staticText = "Creatures your opponents control enter the battlefield tapped"; + } + + OccupationTapEffect(final OccupationTapEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent target = ((EntersTheBattlefieldEvent) event).getTarget(); + if (target != null) { + target.setTapped(true); + } + return false; + } + + @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) { + if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); + if (permanent != null && permanent.isCreature()) { + return true; + } + } + return false; + } + + @Override + public OccupationTapEffect copy() { + return new OccupationTapEffect(this); + } +} + +class OccupationOneShotEffect extends OneShotEffect { + + public OccupationOneShotEffect() { + super(Outcome.LoseAbility); + } + + public OccupationOneShotEffect(String ruleText) { + super(Outcome.LoseAbility); + staticText = ruleText; + } + + public OccupationOneShotEffect(final OccupationOneShotEffect effect) { + super(effect); + } + + @Override + public OccupationOneShotEffect copy() { + return new OccupationOneShotEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + OccupationRestrictionEffect effect = new OccupationRestrictionEffect(); + game.addEffect(effect, source); + return true; + } +} + +class OccupationRestrictionEffect extends RestrictionEffect { + + public OccupationRestrictionEffect() { + super(Duration.Custom); + staticText = ""; + } + + public OccupationRestrictionEffect(final OccupationRestrictionEffect effect) { + super(effect); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.addInfo("Can't attack or block and its activated abilities can't be activated." + getId(), "", game); + } + } + } + + @Override + public boolean isInactive(Ability source, Game game) { + if (game.getPhase().getStep().getType() == PhaseStep.UNTAP + && game.getStep().getStepPart() == Step.StepPart.PRE) { + if (game.isActivePlayer(source.getControllerId()) + || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.addInfo("Can't attack or block and its activated abilities can't be activated." + getId(), "", game); + } + } + return true; + } + } + return false; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (this.targetPointer.getTargets(game, source).contains(permanent.getId())) { + return true; + } + return false; + } + + @Override + public boolean canAttack(Game game) { + return false; + } + + @Override + public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { + return false; + } + + @Override + public boolean canUseActivatedAbilities(Permanent permanent, Ability source, Game game) { + return false; + } + + @Override + public OccupationRestrictionEffect copy() { + return new OccupationRestrictionEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/o/OctopusUmbra.java b/Mage.Sets/src/mage/cards/o/OctopusUmbra.java new file mode 100644 index 00000000000..148586f6fc1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OctopusUmbra.java @@ -0,0 +1,76 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessEnchantedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TotemArmorAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author TheElk801 + */ +public final class OctopusUmbra extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power 8 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 9)); + } + + public OctopusUmbra(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{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); + + // Enchanted creature has base power and toughness 8/8 and has "Whenever this creature attacks, you may tap target creature with power 8 or less." + Ability abilityToAdd = new AttacksTriggeredAbility(new TapTargetEffect(), true); + abilityToAdd.addTarget(new TargetCreaturePermanent(filter)); + ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new SetPowerToughnessEnchantedEffect(8, 8) + ); + ability.addEffect(new GainAbilityAttachedEffect( + abilityToAdd, AttachmentType.AURA + ).setText("and has \"Whenever this creature attacks, " + + "you may tap target creature with power 8 or less.\"")); + this.addAbility(ability); + + // Totem armor + this.addAbility(new TotemArmorAbility()); + + } + + public OctopusUmbra(final OctopusUmbra card) { + super(card); + } + + @Override + public OctopusUmbra copy() { + return new OctopusUmbra(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OddsEnds.java b/Mage.Sets/src/mage/cards/o/OddsEnds.java index 2c208ba31db..e83b5f5258e 100644 --- a/Mage.Sets/src/mage/cards/o/OddsEnds.java +++ b/Mage.Sets/src/mage/cards/o/OddsEnds.java @@ -26,7 +26,7 @@ public final class OddsEnds extends SplitCard { // Odds // Flip a coin. If it comes up heads, counter target instant or sorcery spell. If it comes up tails, copy that spell and you may choose new targets for the copy. getLeftHalfCard().getSpellAbility().addEffect(new OddsEffect()); - getLeftHalfCard().getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + getLeftHalfCard().getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); // Ends // Target player sacrifices two attacking creatures. diff --git a/Mage.Sets/src/mage/cards/o/OgreSavant.java b/Mage.Sets/src/mage/cards/o/OgreSavant.java index 611d644509e..3b7cafa2ac4 100644 --- a/Mage.Sets/src/mage/cards/o/OgreSavant.java +++ b/Mage.Sets/src/mage/cards/o/OgreSavant.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,9 +29,10 @@ public final class OgreSavant extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); + //When Ogre Savant enters the battlefield, if {U} was spent to cast Ogre Savant, return target creature to its owner’s hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(),false); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.U), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.U), "if {U} was spent to cast {this}, return target creature to its owner's hand."), new ManaSpentToCastWatcher()); } diff --git a/Mage.Sets/src/mage/cards/o/OmnathLocusOfMana.java b/Mage.Sets/src/mage/cards/o/OmnathLocusOfMana.java index aa3ff8341bb..1f73f13cb9b 100644 --- a/Mage.Sets/src/mage/cards/o/OmnathLocusOfMana.java +++ b/Mage.Sets/src/mage/cards/o/OmnathLocusOfMana.java @@ -52,7 +52,7 @@ class OmnathRuleEffect extends ContinuousEffectImpl { public OmnathRuleEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "You don’t lose unspent green mana as steps and phases end"; + staticText = "You don't lose unspent green mana as steps and phases end"; } public OmnathRuleEffect(final OmnathRuleEffect effect) { diff --git a/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java b/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java index 467c6d2724d..a5e986680f4 100644 --- a/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java +++ b/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java @@ -55,7 +55,7 @@ class OnceMoreWithFeelingEffect extends OneShotEffect { public OnceMoreWithFeelingEffect() { super(Outcome.Detriment); - staticText = "Exile all permanents and all cards from all graveyards. Each player shuffles his or her hand into his or her library"; + staticText = "Exile all permanents and all cards from all graveyards. Each player shuffles their hand into their library"; } public OnceMoreWithFeelingEffect(final OnceMoreWithFeelingEffect effect) { diff --git a/Mage.Sets/src/mage/cards/o/OneOfThePack.java b/Mage.Sets/src/mage/cards/o/OneOfThePack.java index 6280e6c952c..ff9464e0387 100644 --- a/Mage.Sets/src/mage/cards/o/OneOfThePack.java +++ b/Mage.Sets/src/mage/cards/o/OneOfThePack.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class OneOfThePack extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform One of the Pack. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public OneOfThePack(final OneOfThePack card) { diff --git a/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java b/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java new file mode 100644 index 00000000000..953963221ee --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java @@ -0,0 +1,34 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.HighestConvertedManaCostValue; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class OneWithTheMachine extends CardImpl { + + public OneWithTheMachine(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}"); + + // Draw cards equal to the highest converted mana cost among artifacts you control. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect( + new HighestConvertedManaCostValue(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT) + ).setText("Draw cards equal to the highest converted mana cost among artifacts you control")); + } + + public OneWithTheMachine(final OneWithTheMachine card) { + super(card); + } + + @Override + public OneWithTheMachine copy() { + return new OneWithTheMachine(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OonasBlackguard.java b/Mage.Sets/src/mage/cards/o/OonasBlackguard.java index 452995f26ab..f4e3abb70a1 100644 --- a/Mage.Sets/src/mage/cards/o/OonasBlackguard.java +++ b/Mage.Sets/src/mage/cards/o/OonasBlackguard.java @@ -74,7 +74,7 @@ class OonasBlackguardReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - if (creature != null && creature.getControllerId().equals(source.getControllerId()) + if (creature != null && creature.isControlledBy(source.getControllerId()) && creature.isCreature() && creature.hasSubtype(SubType.ROGUE, game) && !event.getTargetId().equals(source.getSourceId())) { @@ -127,7 +127,7 @@ class OonasBlackguardTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(getControllerId()) && creature.getCounters(game).getCount(CounterType.P1P1) > 0) { + if (creature != null && creature.isControlledBy(getControllerId()) && creature.getCounters(game).getCount(CounterType.P1P1) > 0) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage.Sets/src/mage/cards/o/OpalArchangel.java b/Mage.Sets/src/mage/cards/o/OpalArchangel.java index bca276e9289..d01b6c79500 100644 --- a/Mage.Sets/src/mage/cards/o/OpalArchangel.java +++ b/Mage.Sets/src/mage/cards/o/OpalArchangel.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; @@ -17,7 +17,6 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureSpell; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -34,7 +33,7 @@ public final class OpalArchangel extends CardImpl { // When an opponent casts a creature spell, if Opal Archangel is an enchantment, Opal Archangel becomes a 5/5 Angel creature with flying and vigilance. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalArchangelToken(), "", Duration.WhileOnBattlefield, true, false), new FilterCreatureSpell(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 5/5 Angel creature with flying and vigilance.")); } diff --git a/Mage.Sets/src/mage/cards/o/OpalCaryatid.java b/Mage.Sets/src/mage/cards/o/OpalCaryatid.java index 71c09b12977..41e8f0a1f80 100644 --- a/Mage.Sets/src/mage/cards/o/OpalCaryatid.java +++ b/Mage.Sets/src/mage/cards/o/OpalCaryatid.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class OpalCaryatid extends CardImpl { // When an opponent casts a creature spell, if Opal Caryatid is an enchantment, Opal Caryatid becomes a 2/2 Soldier creature. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalCaryatidSoldierToken(), "", Duration.WhileOnBattlefield, true, false), new FilterCreatureSpell(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 2/2 Soldier creature.")); } diff --git a/Mage.Sets/src/mage/cards/o/OpalChampion.java b/Mage.Sets/src/mage/cards/o/OpalChampion.java index cd38ed0e7c7..ad80f47b587 100644 --- a/Mage.Sets/src/mage/cards/o/OpalChampion.java +++ b/Mage.Sets/src/mage/cards/o/OpalChampion.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; @@ -16,7 +16,6 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureSpell; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -33,7 +32,7 @@ public final class OpalChampion extends CardImpl { // When an opponent casts a creature spell, if Opal Champion is an enchantment, Opal Champion becomes a 3/3 Knight creature with first strike. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalChampionKnight(), "", Duration.WhileOnBattlefield, true, false), new FilterCreatureSpell(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 3/3 Knight creature with first strike.")); } diff --git a/Mage.Sets/src/mage/cards/o/OpalGargoyle.java b/Mage.Sets/src/mage/cards/o/OpalGargoyle.java index eb7d2c42337..7af1f098b0d 100644 --- a/Mage.Sets/src/mage/cards/o/OpalGargoyle.java +++ b/Mage.Sets/src/mage/cards/o/OpalGargoyle.java @@ -5,7 +5,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -16,7 +16,6 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureSpell; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -33,7 +32,7 @@ public final class OpalGargoyle extends CardImpl { // When an opponent casts a creature spell, if Opal Gargoyle is an enchantment, Opal Gargoyle becomes a 2/2 Gargoyle creature with flying. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalGargoyleToken(), "", Duration.WhileOnBattlefield, true, false), new FilterCreatureSpell(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 2/2 Gargoyle creature with flying.")); } diff --git a/Mage.Sets/src/mage/cards/o/OpalGuardian.java b/Mage.Sets/src/mage/cards/o/OpalGuardian.java index 258002501a4..2ef3d5f02f7 100644 --- a/Mage.Sets/src/mage/cards/o/OpalGuardian.java +++ b/Mage.Sets/src/mage/cards/o/OpalGuardian.java @@ -6,7 +6,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ProtectionAbility; @@ -18,7 +18,6 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureSpell; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import java.util.UUID; @@ -35,7 +34,7 @@ public final class OpalGuardian extends CardImpl { // When an opponent casts a creature spell, if Opal Guardian is an enchantment, Opal Guardian becomes a 3/4 Gargoyle creature with flying and protection from red. TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalGuardianGargoyle(), "", Duration.WhileOnBattlefield, true, false), new FilterCreatureSpell(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 3/4 Gargoyle creature with flying and protection from red.")); } diff --git a/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java b/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java index f3c7b6d9fa3..4a41c8e08d7 100644 --- a/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java +++ b/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java @@ -6,7 +6,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class OpalLakeGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Opal Lake Gatekeepers enters the battlefield, if you control two or more Gates, you may draw a card. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), "When Opal Lake Gatekeepers enters the battlefield, if you control two or more Gates, you may draw a card.")); diff --git a/Mage.Sets/src/mage/cards/o/OpenTheGraves.java b/Mage.Sets/src/mage/cards/o/OpenTheGraves.java new file mode 100644 index 00000000000..b76f2b1047a --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OpenTheGraves.java @@ -0,0 +1,47 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.ZombieToken; + +/** + * + * @author TheElk801 + */ +public final class OpenTheGraves extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(new TokenPredicate())); + } + + public OpenTheGraves(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); + + // Whenever a nontoken creature you control dies, create a 2/2 black Zombie creature token. + this.addAbility(new DiesCreatureTriggeredAbility( + new CreateTokenEffect(new ZombieToken()), + false, filter + )); + } + + public OpenTheGraves(final OpenTheGraves card) { + super(card); + } + + @Override + public OpenTheGraves copy() { + return new OpenTheGraves(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/Ophiomancer.java b/Mage.Sets/src/mage/cards/o/Ophiomancer.java index 2984ff3dcd1..3bcde4f46d3 100644 --- a/Mage.Sets/src/mage/cards/o/Ophiomancer.java +++ b/Mage.Sets/src/mage/cards/o/Ophiomancer.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,7 +28,7 @@ public final class Ophiomancer extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each upkeep, if you control no Snakes, create a 1/1 black Snake creature token with deathtouch. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new OphiomancerSnakeToken()), TargetController.ANY, false, false), new PermanentsOnTheBattlefieldCondition(new FilterCreaturePermanent(SubType.SNAKE, "no Snakes"), ComparisonType.EQUAL_TO, 0), "At the beginning of each upkeep, if you control no Snakes, create a 1/1 black Snake creature token with deathtouch.")); diff --git a/Mage.Sets/src/mage/cards/o/OracleEnVec.java b/Mage.Sets/src/mage/cards/o/OracleEnVec.java index 4770125d3fc..118fd61524d 100644 --- a/Mage.Sets/src/mage/cards/o/OracleEnVec.java +++ b/Mage.Sets/src/mage/cards/o/OracleEnVec.java @@ -139,7 +139,7 @@ class OracleEnVecMustAttackRequirementEffect extends RequirementEffect { public boolean isInactive(Ability source, Game game) { return startingTurn != game.getTurnNum() && (game.getPhase().getType() == TurnPhase.END - && game.getActivePlayerId().equals(this.getTargetPointer().getFirst(game, source))); + && game.isActivePlayer(this.getTargetPointer().getFirst(game, source))); } @Override @@ -177,7 +177,7 @@ class OracleEnVecCantAttackRestrictionEffect extends RestrictionEffect { public boolean isInactive(Ability source, Game game) { return startingTurn != game.getTurnNum() && (game.getPhase().getType() == TurnPhase.END - && game.getActivePlayerId().equals(this.getTargetPointer().getFirst(game, source))); + && game.isActivePlayer(this.getTargetPointer().getFirst(game, source))); } @Override @@ -207,7 +207,7 @@ class OracleEnVecDelayedTriggeredAbility extends DelayedTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return startingTurn != game.getTurnNum() && game.getActivePlayerId().equals(event.getPlayerId()); + return startingTurn != game.getTurnNum() && game.isActivePlayer(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/o/OracleOfBones.java b/Mage.Sets/src/mage/cards/o/OracleOfBones.java index 80208b1d8c6..d54fec1de78 100644 --- a/Mage.Sets/src/mage/cards/o/OracleOfBones.java +++ b/Mage.Sets/src/mage/cards/o/OracleOfBones.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TributeAbility; @@ -45,7 +45,7 @@ public final class OracleOfBones extends CardImpl { this.addAbility(new TributeAbility(2)); // When Oracle of Bones enters the battlefield, if tribute wasn't paid, you may cast an instant or sorcery card from your hand without paying its mana cost. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new OracleOfBonesCastEffect(), false); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, you may cast an instant or sorcery card from your hand without paying its mana cost.")); } diff --git a/Mage.Sets/src/mage/cards/o/OranRiefHydra.java b/Mage.Sets/src/mage/cards/o/OranRiefHydra.java index ff793ae4f9e..fab442f4267 100644 --- a/Mage.Sets/src/mage/cards/o/OranRiefHydra.java +++ b/Mage.Sets/src/mage/cards/o/OranRiefHydra.java @@ -78,7 +78,7 @@ class OranRiefHydraTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isLand() - && permanent.getControllerId().equals(getControllerId())) { + && permanent.isControlledBy(getControllerId())) { Permanent sourcePermanent = game.getPermanent(getSourceId()); if (sourcePermanent != null) { for (Effect effect : getEffects()) { diff --git a/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java b/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java index f2b158cd949..833b811865a 100644 --- a/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java +++ b/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -46,7 +46,7 @@ public final class OranRiefRecluse extends CardImpl { // When Oran-Rief Recluse enters the battlefield, if it was kicked, destroy target creature with flying. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target creature with flying.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target creature with flying.")); } public OranRiefRecluse(final OranRiefRecluse card) { diff --git a/Mage.Sets/src/mage/cards/o/OrcishLumberjack.java b/Mage.Sets/src/mage/cards/o/OrcishLumberjack.java index fe0f317c572..7dbd242d0b2 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishLumberjack.java +++ b/Mage.Sets/src/mage/cards/o/OrcishLumberjack.java @@ -1,4 +1,3 @@ - package mage.cards.o; import java.util.ArrayList; @@ -65,7 +64,7 @@ public final class OrcishLumberjack extends CardImpl { class OrcishLumberjackManaEffect extends ManaEffect { - private List netMana = new ArrayList(); + private List netMana = new ArrayList<>(); public OrcishLumberjackManaEffect() { super(); diff --git a/Mage.Sets/src/mage/cards/o/OrcishMine.java b/Mage.Sets/src/mage/cards/o/OrcishMine.java new file mode 100644 index 00000000000..747e86604ea --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OrcishMine.java @@ -0,0 +1,103 @@ +package mage.cards.o; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageAttachedControllerEffect; +import mage.abilities.effects.common.DestroyAttachedToEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.meta.OrTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetLandPermanent; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class OrcishMine extends CardImpl { + + public OrcishMine(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}"); + + this.subtype.add(SubType.AURA); + + // Enchant land + TargetPermanent auraTarget = new TargetLandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.DestroyPermanent)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Orcish Mine enters the battlefield with three ore counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.ORE.createInstance(3)), "with three ore counters on it")); + + // At the beginning of your upkeep or whenever enchanted land becomes tapped, remove an ore counter from Orcish Mine. + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new RemoveCounterSourceEffect(CounterType.ORE.createInstance()), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false), + new BecomesTappedAttachedTriggeredAbility(null, "enchanted land"))); + + // When the last ore counter is removed from Orcish Mine, destroy enchanted land and Orcish Mine deals 2 damage to that land's controller. + this.addAbility(new OrcishMineAbility()); + } + + public OrcishMine(final OrcishMine card) { + super(card); + } + + @Override + public OrcishMine copy() { + return new OrcishMine(this); + } +} + +class OrcishMineAbility extends TriggeredAbilityImpl { + + public OrcishMineAbility() { + super(Zone.BATTLEFIELD, new DestroyAttachedToEffect("enchanted land")); + this.addEffect(new DamageAttachedControllerEffect(2)); + } + + public OrcishMineAbility(final OrcishMineAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COUNTER_REMOVED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getData().equals("ore") && event.getTargetId().equals(this.getSourceId())) { + Permanent p = game.getPermanent(this.getSourceId()); + if (p != null) { + return p.getCounters(game).getCount(CounterType.ORE) == 0; + } + } + return false; + } + + @Override + public OrcishMineAbility copy() { + return new OrcishMineAbility(this); + } + + @Override + public String getRule() { + return "When the last ore counter is removed from {this}, destroy enchanted land and {this} deals 2 damage to that land's controller."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java b/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java index e88e00e95c3..eb366f17fe2 100644 --- a/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java +++ b/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java @@ -70,7 +70,7 @@ class OrderOfSuccessionEffect extends OneShotEffect { if (controller != null) { Map playerCreature = new HashMap<>(2); Choice choice = new ChoiceLeftOrRight(); - if (controller.choose(Outcome.Neutral, choice, game)) { + if (!controller.choose(Outcome.Neutral, choice, game)) { return false; } boolean left = choice.getChoice().equals("Left"); diff --git a/Mage.Sets/src/mage/cards/o/OrnateKanzashi.java b/Mage.Sets/src/mage/cards/o/OrnateKanzashi.java index cde70b63df7..163714d47e0 100644 --- a/Mage.Sets/src/mage/cards/o/OrnateKanzashi.java +++ b/Mage.Sets/src/mage/cards/o/OrnateKanzashi.java @@ -113,7 +113,7 @@ class OrnateKanzashiCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/o/Ornitharch.java b/Mage.Sets/src/mage/cards/o/Ornitharch.java index edee0495a92..674177dab3c 100644 --- a/Mage.Sets/src/mage/cards/o/Ornitharch.java +++ b/Mage.Sets/src/mage/cards/o/Ornitharch.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TributeAbility; @@ -35,7 +35,7 @@ public final class Ornitharch extends CardImpl { this.addAbility(new TributeAbility(2)); // When Ornitharch enters the battlefield, if tribute wasn't paid, create two 1/1 white Bird creature tokens with flying. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken(), 2), false); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, create two 1/1 white Bird creature tokens with flying.")); } diff --git a/Mage.Sets/src/mage/cards/o/OrzhovCharm.java b/Mage.Sets/src/mage/cards/o/OrzhovCharm.java index f15c6adda17..bf6486b1cb5 100644 --- a/Mage.Sets/src/mage/cards/o/OrzhovCharm.java +++ b/Mage.Sets/src/mage/cards/o/OrzhovCharm.java @@ -92,12 +92,12 @@ class OrzhovCharmReturnToHandEffect extends OneShotEffect { attachments.addAll(target.getAttachments()); for (UUID attachmentId : attachments) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getControllerId().equals(source.getControllerId()) + if (attachment != null && attachment.isControlledBy(source.getControllerId()) && attachment.hasSubtype(SubType.AURA, game)) { attachment.moveToZone(Zone.HAND, source.getSourceId(), game, false); } } - if (target.getControllerId().equals(source.getControllerId())) { + if (target.isControlledBy(source.getControllerId())) { target.moveToZone(Zone.HAND, source.getSourceId(), game, false); } return true; diff --git a/Mage.Sets/src/mage/cards/o/OsaiVultures.java b/Mage.Sets/src/mage/cards/o/OsaiVultures.java index 40c192a16ca..77c550a5b9d 100644 --- a/Mage.Sets/src/mage/cards/o/OsaiVultures.java +++ b/Mage.Sets/src/mage/cards/o/OsaiVultures.java @@ -7,7 +7,7 @@ import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.MorbidCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -35,7 +35,7 @@ public final class OsaiVultures extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // At the beginning of each end step, if a creature died this turn, put a carrion counter on Osai Vultures. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new AddCountersSourceEffect(CounterType.CARRION.createInstance()), TargetController.ANY, false), MorbidCondition.instance, "At the beginning of each end step, if a creature died this turn, put a carrion counter on {this}.")); // Remove two carrion counters from Osai Vultures: Osai Vultures gets +1/+1 until end of turn. diff --git a/Mage.Sets/src/mage/cards/o/OupheVandals.java b/Mage.Sets/src/mage/cards/o/OupheVandals.java index a33b6944e55..d4847067598 100644 --- a/Mage.Sets/src/mage/cards/o/OupheVandals.java +++ b/Mage.Sets/src/mage/cards/o/OupheVandals.java @@ -18,10 +18,12 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterStackObject; import mage.filter.predicate.Predicate; +import mage.filter.predicate.ability.ArtifactSourcePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; +import mage.target.common.TargetActivatedAbility; import mage.target.common.TargetActivatedOrTriggeredAbility; /** @@ -47,7 +49,7 @@ public final class OupheVandals extends CardImpl { // {G}, Sacrifice Ouphe Vandals: Counter target activated ability from an artifact source and destroy that artifact if it's on the battlefield. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OupheVandalsEffect(), new ManaCostsImpl<>("{G}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetActivatedOrTriggeredAbility(filter)); + ability.addTarget(new TargetActivatedAbility(filter)); this.addAbility(ability); } @@ -61,25 +63,6 @@ public final class OupheVandals extends CardImpl { } } -class ArtifactSourcePredicate implements Predicate { - - public ArtifactSourcePredicate() { - } - - @Override - public boolean apply(Ability input, Game game) { - if (input instanceof StackAbility) { - return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED; - } - return false; - } - - @Override - public String toString() { - return "Source(Artifact)"; - } -} - class OupheVandalsEffect extends OneShotEffect { public OupheVandalsEffect() { diff --git a/Mage.Sets/src/mage/cards/o/Oust.java b/Mage.Sets/src/mage/cards/o/Oust.java index 23c82474624..9500d98b4dd 100644 --- a/Mage.Sets/src/mage/cards/o/Oust.java +++ b/Mage.Sets/src/mage/cards/o/Oust.java @@ -1,4 +1,3 @@ - package mage.cards.o; import java.util.UUID; @@ -62,7 +61,7 @@ class OustEffect extends OneShotEffect { if (owner == null || controller == null) { return false; } - owner.getLibrary().putCardToTopXPos(permanent, 2, game); + owner.putCardOnTopXOfLibrary(permanent, game, source, 2); controller.gainLife(3, game, source); } return true; diff --git a/Mage.Sets/src/mage/cards/o/OuterRimGang.java b/Mage.Sets/src/mage/cards/o/OuterRimGang.java new file mode 100644 index 00000000000..ea112908e2d --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OuterRimGang.java @@ -0,0 +1,49 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.CounterPredicate; + +/** + * + * @author NinthWorld + */ +public final class OuterRimGang extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each creature with a bounty counter on it"); + + static { + filter.add(new CounterPredicate(CounterType.BOUNTY)); + } + + public OuterRimGang(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.subtype.add(SubType.HUNTER); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // When Outer Rim Gang enters the battlefield, each creature with a bounty counter on it gets -2/-2 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new BoostAllEffect(-2, -2, Duration.EndOfTurn, filter, false))); + } + + public OuterRimGang(final OuterRimGang card) { + super(card); + } + + @Override + public OuterRimGang copy() { + return new OuterRimGang(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java b/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java index 6ecf75e4dfd..98ea2f4b723 100644 --- a/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java +++ b/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java @@ -12,6 +12,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.target.common.TargetCreaturePermanent; /** @@ -30,8 +32,14 @@ public final class OuterRimSlaver extends CardImpl { // When Outer Rim Slaver enters the battlefield, you may put a bounty counter on target creature. If you do, another target creature fights that creature Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), true); ability.addEffect(new FightTargetsEffect("another target creature fights that creature")); - ability.addTarget(new TargetCreaturePermanent()); - ability.addTarget(new TargetCreaturePermanent()); + TargetCreaturePermanent target = new TargetCreaturePermanent(); + target.setTargetTag(1); + ability.addTarget(target); + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new AnotherTargetPredicate(2)); + TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); + target2.setTargetTag(2); + ability.addTarget(target2); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OutpostSiege.java b/Mage.Sets/src/mage/cards/o/OutpostSiege.java index dc028a94dbf..2fabfdbc093 100644 --- a/Mage.Sets/src/mage/cards/o/OutpostSiege.java +++ b/Mage.Sets/src/mage/cards/o/OutpostSiege.java @@ -133,7 +133,7 @@ class CastFromNonHandZoneTargetEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { if (getTargetPointer().getTargets(game, source).contains(objectId) - && source.getControllerId().equals(affectedControllerId)) { + && source.isControlledBy(affectedControllerId)) { Card card = game.getCard(objectId); if (card != null) { return true; diff --git a/Mage.Sets/src/mage/cards/o/Overgrowth.java b/Mage.Sets/src/mage/cards/o/Overgrowth.java index 27718d28c09..39d17416692 100644 --- a/Mage.Sets/src/mage/cards/o/Overgrowth.java +++ b/Mage.Sets/src/mage/cards/o/Overgrowth.java @@ -77,7 +77,7 @@ class OvergrowthTriggeredAbility extends TriggeredManaAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent enchantment = game.getPermanent(this.getSourceId()); - if (enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo())) { + if (enchantment != null && enchantment.isAttachedTo(event.getSourceId())) { Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); if (enchanted != null) { getEffects().get(0).setTargetPointer(new FixedTarget(enchanted.getControllerId())); diff --git a/Mage.Sets/src/mage/cards/o/Overmaster.java b/Mage.Sets/src/mage/cards/o/Overmaster.java index 366ddf52cd6..b5c7fdb07b7 100644 --- a/Mage.Sets/src/mage/cards/o/Overmaster.java +++ b/Mage.Sets/src/mage/cards/o/Overmaster.java @@ -28,7 +28,7 @@ public final class Overmaster extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}"); - // The next instant or sorcery spell you cast this turn can't be countered by spells or abilities. + // The next instant or sorcery spell you cast this turn can't be countered. this.getSpellAbility().addEffect(new OvermasterEffect()); this.getSpellAbility().addWatcher(new OvermasterWatcher()); @@ -52,7 +52,7 @@ class OvermasterEffect extends ContinuousRuleModifyingEffectImpl { OvermasterEffect() { super(Duration.EndOfTurn, Outcome.Benefit); - staticText = "The next instant or sorcery spell you cast this turn can't be countered by spells or abilities"; + staticText = "The next instant or sorcery spell you cast this turn can't be countered"; } OvermasterEffect(final OvermasterEffect effect) { diff --git a/Mage.Sets/src/mage/cards/o/Overrun.java b/Mage.Sets/src/mage/cards/o/Overrun.java index 17da42d6f7d..c89aac5dcca 100644 --- a/Mage.Sets/src/mage/cards/o/Overrun.java +++ b/Mage.Sets/src/mage/cards/o/Overrun.java @@ -1,5 +1,3 @@ - - package mage.cards.o; import java.util.UUID; @@ -11,7 +9,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; /** * @@ -20,14 +18,17 @@ import mage.filter.common.FilterCreaturePermanent; public final class Overrun extends CardImpl { public Overrun(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}{G}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}{G}{G}"); // Creatures you control get +3/+3 and gain trample until end of turn. Effect effect = new BoostControlledEffect(3, 3, Duration.EndOfTurn); effect.setText("Creatures you control get +3/+3"); this.getSpellAbility().addEffect(effect); - effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterCreaturePermanent()); + effect = new GainAbilityControlledEffect( + TrampleAbility.getInstance(), + Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + ); effect.setText("and gain trample until end of turn"); this.getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/o/OversoldCemetery.java b/Mage.Sets/src/mage/cards/o/OversoldCemetery.java index ee4f321b182..5c4825f137a 100644 --- a/Mage.Sets/src/mage/cards/o/OversoldCemetery.java +++ b/Mage.Sets/src/mage/cards/o/OversoldCemetery.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInControllerGraveCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class OversoldCemetery extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToHandTargetEffect(), TargetController.YOU, true); ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard())); CardsInControllerGraveCondition condition = new CardsInControllerGraveCondition(4, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD); - this.addAbility(new ConditionalTriggeredAbility(ability, condition, "At the beginning of your upkeep, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, "At the beginning of your upkeep, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand.")); } public OversoldCemetery(final OversoldCemetery card) { diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmingDenial.java b/Mage.Sets/src/mage/cards/o/OverwhelmingDenial.java index 610b106b430..f6e0864349b 100644 --- a/Mage.Sets/src/mage/cards/o/OverwhelmingDenial.java +++ b/Mage.Sets/src/mage/cards/o/OverwhelmingDenial.java @@ -25,7 +25,7 @@ public final class OverwhelmingDenial extends CardImpl { // Overwhelming Denial can't be countered by spell or abilities. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, effect); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java b/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java index 4ed9f24c3d3..b22a6b76e31 100644 --- a/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java +++ b/Mage.Sets/src/mage/cards/p/PadeemConsulOfInnovation.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.ControlsPermanentGreatestCMCCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HexproofAbility; @@ -35,7 +35,7 @@ public final class PadeemConsulOfInnovation extends CardImpl { new GainAbilityControlledEffect(HexproofAbility.getInstance(), Duration.WhileOnBattlefield, new FilterArtifactPermanent(), false))); // At the beginning of your upkeep, if you control the artifact with the highest converted mana cost or tied for the highest converted mana cost, draw a card. - Ability ability = new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false), + Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false), new ControlsPermanentGreatestCMCCondition(new FilterArtifactPermanent()), "At the beginning of your upkeep, if you control the artifact with the highest converted mana cost or tied for the highest converted mana cost, draw a card."); diff --git a/Mage.Sets/src/mage/cards/p/PalaceSiege.java b/Mage.Sets/src/mage/cards/p/PalaceSiege.java index 7e39368e178..97624a9c482 100644 --- a/Mage.Sets/src/mage/cards/p/PalaceSiege.java +++ b/Mage.Sets/src/mage/cards/p/PalaceSiege.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; @@ -19,6 +18,8 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreatureCard; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java b/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java index c6c0b36d281..3b21dd98e74 100644 --- a/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java +++ b/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.condition.common.LiveLostLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.SourcePermanentToughnessValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -32,7 +32,7 @@ public final class PaladinOfAtonement extends CardImpl { this.toughness = new MageInt(1); // At the beginning of each upkeep, if you lost life last turn, put a +1/+1 counter on Paladin of Atonement. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.ANY, false), LiveLostLastTurnCondition.instance, "At the beginning of each upkeep, if you lost life last turn, put a +1/+1 counter on {this}")); diff --git a/Mage.Sets/src/mage/cards/p/PalisadeGiant.java b/Mage.Sets/src/mage/cards/p/PalisadeGiant.java index 5f3a83ca376..10a8ffde346 100644 --- a/Mage.Sets/src/mage/cards/p/PalisadeGiant.java +++ b/Mage.Sets/src/mage/cards/p/PalisadeGiant.java @@ -98,7 +98,7 @@ class PalisadeGiantReplacementEffect extends ReplacementEffectImpl { Permanent targetPermanent = game.getPermanent(event.getTargetId()); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (targetPermanent != null && - targetPermanent.getControllerId().equals(source.getControllerId()) && + targetPermanent.isControlledBy(source.getControllerId()) && !targetPermanent.getName().equals(sourcePermanent.getName())) { // no redirection from or to other Palisade Giants return true; } diff --git a/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java b/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java new file mode 100644 index 00000000000..0ce811c3ee0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PalladiaMorsTheRuiner.java @@ -0,0 +1,129 @@ +package mage.cards.p; + +import java.util.HashSet; +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.condition.Condition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +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.SubType; +import mage.constants.SuperType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; + +/** + * + * @author TheElk801 + */ +public final class PalladiaMorsTheRuiner extends CardImpl { + + public PalladiaMorsTheRuiner(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Palladia-Mors, the Ruiner has hexproof if it hasn't dealt damage yet. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilitySourceEffect(HexproofAbility.getInstance()), + PalladiaMorsTheRuinerCondition.instance, + "{this} has hexproof if it hasn't dealt damage yet" + ) + ), new PalladiaMorsTheRuinerWatcher()); + } + + public PalladiaMorsTheRuiner(final PalladiaMorsTheRuiner card) { + super(card); + } + + @Override + public PalladiaMorsTheRuiner copy() { + return new PalladiaMorsTheRuiner(this); + } +} + +enum PalladiaMorsTheRuinerCondition implements Condition { + + instance; + + @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()); + return permanent != null && !watcher.getDamagers().contains(new MageObjectReference(permanent, game)); + } + + @Override + public String toString() { + return "{this} hasn't dealt damage yet"; + } + +} + +class PalladiaMorsTheRuinerWatcher extends Watcher { + + private final Set damagers = new HashSet(); + + public PalladiaMorsTheRuinerWatcher() { + super(PalladiaMorsTheRuinerWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public PalladiaMorsTheRuinerWatcher(final PalladiaMorsTheRuinerWatcher watcher) { + super(watcher); + damagers.addAll(watcher.damagers); + } + + @Override + public PalladiaMorsTheRuinerWatcher copy() { + return new PalladiaMorsTheRuinerWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + switch (event.getType()) { + case DAMAGED_CREATURE: + case DAMAGED_PLAYER: + case DAMAGED_PLANESWALKER: + break; + default: + return; + } + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent != null) { + damagers.add(new MageObjectReference(permanent, game)); + } + } + + public Set getDamagers() { + return damagers; + } +} diff --git a/Mage.Sets/src/mage/cards/p/Panharmonicon.java b/Mage.Sets/src/mage/cards/p/Panharmonicon.java index ea7bedb1874..35ee17e6e70 100644 --- a/Mage.Sets/src/mage/cards/p/Panharmonicon.java +++ b/Mage.Sets/src/mage/cards/p/Panharmonicon.java @@ -66,7 +66,7 @@ class PanharmoniconEffect extends ReplacementEffectImpl { if (event instanceof NumberOfTriggersEvent) { NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; // Only triggers of the controller of Panharmonicon - if (source.getControllerId().equals(event.getPlayerId())) { + if (source.isControlledBy(event.getPlayerId())) { GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); // Only EtB triggers if (sourceEvent != null diff --git a/Mage.Sets/src/mage/cards/p/ParadoxHaze.java b/Mage.Sets/src/mage/cards/p/ParadoxHaze.java index 38b926a89fb..eb98a98e32b 100644 --- a/Mage.Sets/src/mage/cards/p/ParadoxHaze.java +++ b/Mage.Sets/src/mage/cards/p/ParadoxHaze.java @@ -79,7 +79,7 @@ class ParadoxHazeTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(getSourceId()); if (permanent != null) { Player player = game.getPlayer(permanent.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId())) { + if (player != null && game.isActivePlayer(player.getId())) { FirstTimeStepWatcher watcher = (FirstTimeStepWatcher) game.getState().getWatchers().get(EventType.UPKEEP_STEP_POST.toString() + FirstTimeStepWatcher.class.getSimpleName()); if (watcher != null && !watcher.conditionMet()) { this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); diff --git a/Mage.Sets/src/mage/cards/p/ParallelThoughts.java b/Mage.Sets/src/mage/cards/p/ParallelThoughts.java index cf23ec4d588..16858edec0a 100644 --- a/Mage.Sets/src/mage/cards/p/ParallelThoughts.java +++ b/Mage.Sets/src/mage/cards/p/ParallelThoughts.java @@ -150,6 +150,6 @@ class ParallelThoughtsReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/p/PardicDragon.java b/Mage.Sets/src/mage/cards/p/PardicDragon.java index 03002ad2fb5..992255a6fa9 100644 --- a/Mage.Sets/src/mage/cards/p/PardicDragon.java +++ b/Mage.Sets/src/mage/cards/p/PardicDragon.java @@ -9,7 +9,7 @@ import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.mana.ColoredManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -43,7 +43,7 @@ public final class PardicDragon extends CardImpl { // Suspend 2-{R}{R} this.addAbility(new SuspendAbility(2, new ManaCostsImpl("{R}{R}"), this, true)); // Whenever an opponent casts a spell, if Pardic Dragon is suspended, that player may put a time counter on Pardic Dragon. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new SpellCastOpponentTriggeredAbility(Zone.EXILED, new PardicDragonEffect(), StaticFilters.FILTER_SPELL, false, SetTargetPointer.PLAYER), SuspendedCondition.instance, "Whenever an opponent casts a spell, if {this} is suspended, that player may put a time counter on {this}." diff --git a/Mage.Sets/src/mage/cards/p/PathOfAncestry.java b/Mage.Sets/src/mage/cards/p/PathOfAncestry.java index 3b4289d2876..9e490d07baf 100644 --- a/Mage.Sets/src/mage/cards/p/PathOfAncestry.java +++ b/Mage.Sets/src/mage/cards/p/PathOfAncestry.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.Iterator; @@ -75,7 +74,7 @@ class PathOfAncestryTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(getSourceId())) { + if (getSourceId().equals(event.getSourceId())) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId()); if (sourcePermanent != null) { boolean found = false; diff --git a/Mage.Sets/src/mage/cards/p/PathOfMettle.java b/Mage.Sets/src/mage/cards/p/PathOfMettle.java index 274b6023e5b..10ec5e2d641 100644 --- a/Mage.Sets/src/mage/cards/p/PathOfMettle.java +++ b/Mage.Sets/src/mage/cards/p/PathOfMettle.java @@ -101,7 +101,7 @@ class PathOfMettleTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { int attackerCount = 0; if (game.getCombat() != null) { - if (getControllerId().equals(game.getCombat().getAttackingPlayerId())) { + if (isControlledBy(game.getCombat().getAttackingPlayerId())) { for (UUID attacker : game.getCombat().getAttackers()) { if (filter.match(game.getPermanent(attacker), game)) { attackerCount++; diff --git a/Mage.Sets/src/mage/cards/p/PatientRebuilding.java b/Mage.Sets/src/mage/cards/p/PatientRebuilding.java new file mode 100644 index 00000000000..a884bf96150 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PatientRebuilding.java @@ -0,0 +1,85 @@ +package mage.cards.p; + +import java.util.Set; +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.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class PatientRebuilding extends CardImpl { + + public PatientRebuilding(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}"); + + // At the beginning of your upkeep, target opponent puts the top three cards of their library into their graveyard, then you draw a card for each land card put into that graveyard this way. + Ability ability = new BeginningOfUpkeepTriggeredAbility( + new PatientRebuildingEffect(), + TargetController.YOU, + false + ); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public PatientRebuilding(final PatientRebuilding card) { + super(card); + } + + @Override + public PatientRebuilding copy() { + return new PatientRebuilding(this); + } +} + +class PatientRebuildingEffect extends OneShotEffect { + + public PatientRebuildingEffect() { + super(Outcome.DrawCard); + this.staticText = "target opponent puts the top three cards of their library into their graveyard, " + + "then you draw a card for each land card put into that graveyard this way"; + } + + public PatientRebuildingEffect(final PatientRebuildingEffect effect) { + super(effect); + } + + @Override + public PatientRebuildingEffect copy() { + return new PatientRebuildingEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null || player == null) { + return false; + } + int numberOfLandCards = 0; + Set movedCards = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, 3), source, game, Zone.LIBRARY); + for (Card card : movedCards) { + if (card.isLand()) { + numberOfLandCards++; + } + } + if (numberOfLandCards > 0) { + return controller.drawCards(numberOfLandCards, game) > 0; + } + return true; + } + +} diff --git a/Mage.Sets/src/mage/cards/p/PatriciansScorn.java b/Mage.Sets/src/mage/cards/p/PatriciansScorn.java index b8a7048837d..0aed2b41deb 100644 --- a/Mage.Sets/src/mage/cards/p/PatriciansScorn.java +++ b/Mage.Sets/src/mage/cards/p/PatriciansScorn.java @@ -31,7 +31,7 @@ public final class PatriciansScorn extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{W}"); - // If you've cast another white spell this turn, you may cast Patrician's Scorn without paying its mana cost. + // If you've cast another white spell this turn, you may cast this spell without paying its mana cost. this.addAbility(new AlternativeCostSourceAbility(new CastWhiteSpellThisTurnCondition()), new PatriciansScornWatcher()); // Destroy all enchantments. this.getSpellAbility().addEffect(new DestroyAllEffect(StaticFilters.FILTER_ENCHANTMENT_PERMANENT)); @@ -87,7 +87,7 @@ class PatriciansScornWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (condition == true) { //no need to check - condition has already occured + if (condition) { //no need to check - condition has already occured return; } if (event.getType() == EventType.SPELL_CAST && controllerId.equals(event.getPlayerId())) { diff --git a/Mage.Sets/src/mage/cards/p/PatronOfTheNezumi.java b/Mage.Sets/src/mage/cards/p/PatronOfTheNezumi.java index 8ef958b5261..65dd8a1f14f 100644 --- a/Mage.Sets/src/mage/cards/p/PatronOfTheNezumi.java +++ b/Mage.Sets/src/mage/cards/p/PatronOfTheNezumi.java @@ -74,7 +74,7 @@ class PatronOfTheNezumiTriggeredAbility extends TriggeredAbilityImpl { if (zEvent.isDiesEvent()) { Permanent permanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId()); if (permanent != null && game.getOpponents(controllerId).contains(permanent.getOwnerId())) { - this.getEffects().get(0).setTargetPointer(new FixedTarget(zEvent.getPlayerId())); + this.getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getOwnerId())); return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PaupersCage.java b/Mage.Sets/src/mage/cards/p/PaupersCage.java index d0c92d16659..961a57eecbd 100644 --- a/Mage.Sets/src/mage/cards/p/PaupersCage.java +++ b/Mage.Sets/src/mage/cards/p/PaupersCage.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +27,7 @@ public final class PaupersCage extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), TargetController.OPPONENT, false, true); CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 3); - this.addAbility(new ConditionalTriggeredAbility(ability, condition, "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 2 damage to him or her.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 2 damage to him or her.")); } public PaupersCage(final PaupersCage card) { diff --git a/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java b/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java index e270d7f1d98..0ef7b2de1c2 100644 --- a/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java +++ b/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java @@ -74,7 +74,7 @@ class PawnOfUlamogTriggeredAbility extends TriggeredAbilityImpl { Permanent permanent = (Permanent) card; ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD - && permanent.getControllerId().equals(this.controllerId) + && permanent.isControlledBy(this.controllerId) && (targetId.equals(this.getSourceId()) || (permanent.isCreature() && !targetId.equals(this.getSourceId()) diff --git a/Mage.Sets/src/mage/cards/p/PedanticLearning.java b/Mage.Sets/src/mage/cards/p/PedanticLearning.java index a11782b0cc0..b72a54652c1 100644 --- a/Mage.Sets/src/mage/cards/p/PedanticLearning.java +++ b/Mage.Sets/src/mage/cards/p/PedanticLearning.java @@ -63,7 +63,7 @@ class PedanticLearningTriggeredAbility extends TriggeredAbilityImpl { UUID cardOwnerId = card.getOwnerId(); Set cardType = card.getCardType(); if (cardOwnerId != null - && card.getOwnerId().equals(getControllerId()) + && card.isOwnedBy(getControllerId()) && cardType != null && card.isLand()) { return true; diff --git a/Mage.Sets/src/mage/cards/p/PerimeterCaptain.java b/Mage.Sets/src/mage/cards/p/PerimeterCaptain.java index f46eaf61a67..5034a47c860 100644 --- a/Mage.Sets/src/mage/cards/p/PerimeterCaptain.java +++ b/Mage.Sets/src/mage/cards/p/PerimeterCaptain.java @@ -67,7 +67,7 @@ class PerimeterCaptainTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent creature = game.getPermanent(event.getSourceId()); if (creature != null) { - if (creature.getControllerId().equals(this.getControllerId()) && creature.getAbilities().contains(DefenderAbility.getInstance())) { + if (creature.isControlledBy(this.getControllerId()) && creature.getAbilities().contains(DefenderAbility.getInstance())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java b/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java index f6f62c3deb9..2a0cdb373b8 100644 --- a/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java +++ b/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java @@ -68,7 +68,7 @@ class PersonalSanctuaryEffect extends PreventionEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER) { - if (event.getTargetId().equals(source.getControllerId()) && game.getActivePlayerId().equals(source.getControllerId())) + if (event.getTargetId().equals(source.getControllerId()) && game.isActivePlayer(source.getControllerId())) return super.applies(event, source, game); } return false; diff --git a/Mage.Sets/src/mage/cards/p/Pestilence.java b/Mage.Sets/src/mage/cards/p/Pestilence.java index e584a3e20eb..1b9d417a3a7 100644 --- a/Mage.Sets/src/mage/cards/p/Pestilence.java +++ b/Mage.Sets/src/mage/cards/p/Pestilence.java @@ -7,7 +7,7 @@ import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CreatureCountCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -30,7 +30,7 @@ public final class Pestilence extends CardImpl { // At the beginning of the end step, if no creatures are on the battlefield, sacrifice Pestilence. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); // {B}: Pestilence deals 1 damage to each creature and each player. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageEverythingEffect(1), new ManaCostsImpl("{B}"))); diff --git a/Mage.Sets/src/mage/cards/p/PestilenceRats.java b/Mage.Sets/src/mage/cards/p/PestilenceRats.java index f40a6abd1db..bbf9acf52d9 100644 --- a/Mage.Sets/src/mage/cards/p/PestilenceRats.java +++ b/Mage.Sets/src/mage/cards/p/PestilenceRats.java @@ -12,7 +12,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.AnotherCardPredicate; import mage.filter.predicate.mageobject.SubtypePredicate; @@ -22,7 +22,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate; */ public final class PestilenceRats extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other Rats on the battlefield"); + private static final FilterPermanent filter = new FilterPermanent("other Rats on the battlefield"); static{ filter.add(new SubtypePredicate(SubType.RAT)); filter.add(new AnotherCardPredicate()); diff --git a/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java b/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java index 32ba55f44c1..e1bc4cafc83 100644 --- a/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java +++ b/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java @@ -8,7 +8,7 @@ import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LoseGameSourceControllerEffect; import mage.abilities.effects.common.LoseGameTargetPlayerEffect; @@ -35,7 +35,7 @@ public final class PhageTheUntouchable extends CardImpl { this.toughness = new MageInt(4); // When Phage the Untouchable enters the battlefield, if you didn't cast it from your hand, you lose the game. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false), new InvertCondition(CastFromHandSourceCondition.instance), "When {this} enters the battlefield, if you didn't cast it from your hand, you lose the game" diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java index 383d66b2380..003ff68f888 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalImage.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalImage.java @@ -26,7 +26,7 @@ import java.util.UUID; */ 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 gains \"When this creature becomes the target of a spell or ability, sacrifice it.\""; + 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() { @Override @@ -62,7 +62,7 @@ public final class PhantasmalImage extends CardImpl { // You may have Phantasmal Image enter the battlefield as a copy of any creature // on the battlefield, except it's an Illusion in addition to its other types and - // it gains "When this creature becomes the target of a spell or ability, sacrifice it." + // it has "When this creature becomes the target of a spell or ability, sacrifice it." Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, phantasmalImageApplier); effect.setText(effectText); this.addAbility(new EntersBattlefieldAbility(effect, true)); diff --git a/Mage.Sets/src/mage/cards/p/PharagaxGiant.java b/Mage.Sets/src/mage/cards/p/PharagaxGiant.java index 08a362cff76..c90976a6ea3 100644 --- a/Mage.Sets/src/mage/cards/p/PharagaxGiant.java +++ b/Mage.Sets/src/mage/cards/p/PharagaxGiant.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -32,7 +32,7 @@ public final class PharagaxGiant extends CardImpl { this.addAbility(new TributeAbility(2)); // When Pharagax Giant enters the battlefield, if tribute wasn't paid, Pharagax Giant deals 5 damage to each opponent. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(5, TargetController.OPPONENT), false); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, {this} deals 5 damage to each opponent.")); } diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java b/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java index 592fc1b0913..a0880af364a 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -33,7 +33,7 @@ public final class PhyrexianRevoker extends CardImpl { this.toughness = new MageInt(1); // As Phyrexian Revoker enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); // Activated abilities of sources with the chosen name can't be activated. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PhyrexianRevokerEffect2())); @@ -84,7 +84,7 @@ class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.ACTIVATE_ABILITY) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PillarTombsOfAku.java b/Mage.Sets/src/mage/cards/p/PillarTombsOfAku.java new file mode 100644 index 00000000000..acaef90f970 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PillarTombsOfAku.java @@ -0,0 +1,82 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class PillarTombsOfAku extends CardImpl { + + public PillarTombsOfAku(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); + + this.addSuperType(SuperType.WORLD); + + // At the beginning of each player's upkeep, that player may sacrifice a creature. If that player doesn't, he or she loses 5 life and you sacrifice Pillar Tombs of Aku. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new PillarTombsOfAkuEffect(), + TargetController.ANY, + false + )); + } + + public PillarTombsOfAku(final PillarTombsOfAku card) { + super(card); + } + + @Override + public PillarTombsOfAku copy() { + return new PillarTombsOfAku(this); + } +} + +class PillarTombsOfAkuEffect extends OneShotEffect { + + public PillarTombsOfAkuEffect() { + super(Outcome.Benefit); + this.staticText = "that player may sacrifice a creature. If that " + + "player doesn’t, they lose 5 life and you sacrifice {this}"; + } + + public PillarTombsOfAkuEffect(final PillarTombsOfAkuEffect effect) { + super(effect); + } + + @Override + public PillarTombsOfAkuEffect copy() { + return new PillarTombsOfAkuEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player activePlayer = game.getPlayer(game.getActivePlayerId()); + if (activePlayer == null) { + return false; + } + if (activePlayer.chooseUse(Outcome.Sacrifice, "Sacrifice a creature?", source, game)) { + Cost cost = new SacrificeTargetCost(new TargetControlledCreaturePermanent()); + if (cost.canPay(source, source.getSourceId(), activePlayer.getId(), game) + && cost.pay(source, game, source.getSourceId(), activePlayer.getId(), true)) { + return true; + } + } + activePlayer.loseLife(5, game, false); + return new SacrificeSourceEffect().apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PirsWhim.java b/Mage.Sets/src/mage/cards/p/PirsWhim.java index cba003412b6..09ea5499bbb 100644 --- a/Mage.Sets/src/mage/cards/p/PirsWhim.java +++ b/Mage.Sets/src/mage/cards/p/PirsWhim.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.UUID; @@ -63,7 +62,7 @@ class PirsWhimEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); ChooseFriendsAndFoes choice = new ChooseFriendsAndFoes(); if (!choice.chooseFriendOrFoe(controller, source, game)) { return false; diff --git a/Mage.Sets/src/mage/cards/p/PitKeeper.java b/Mage.Sets/src/mage/cards/p/PitKeeper.java index d758888bc52..ce51141cf77 100644 --- a/Mage.Sets/src/mage/cards/p/PitKeeper.java +++ b/Mage.Sets/src/mage/cards/p/PitKeeper.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -35,7 +35,7 @@ public final class PitKeeper extends CardImpl { // When Pit Keeper enters the battlefield, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); triggeredAbility.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new CreatureCardsInControllerGraveCondition(4), "When {this} enters the battlefield, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand.")); diff --git a/Mage.Sets/src/mage/cards/p/PithingNeedle.java b/Mage.Sets/src/mage/cards/p/PithingNeedle.java index e9b4196bb12..402cfba00d8 100644 --- a/Mage.Sets/src/mage/cards/p/PithingNeedle.java +++ b/Mage.Sets/src/mage/cards/p/PithingNeedle.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -25,7 +25,7 @@ public final class PithingNeedle extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // As Pithing Needle enters the battlefield, name a card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL))); // Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PithingNeedleEffect())); @@ -74,7 +74,7 @@ class PithingNeedleEffect extends ContinuousRuleModifyingEffectImpl { if (ability.isPresent() && object != null) { if (game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range && ability.get().getAbilityType() != AbilityType.MANA - && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PlagueMare.java b/Mage.Sets/src/mage/cards/p/PlagueMare.java new file mode 100644 index 00000000000..277b9d4113a --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PlagueMare.java @@ -0,0 +1,61 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.effects.common.continuous.BoostOpponentsEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class PlagueMare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("white creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + } + + public PlagueMare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); + + this.subtype.add(SubType.NIGHTMARE); + this.subtype.add(SubType.HORSE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Plague Mare can't be blocked by white creatures. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ) + )); + + // When Plague Mare enters the battlefield, creatures your opponents control get -1/-1 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new BoostOpponentsEffect(-1, -1, Duration.EndOfTurn) + )); + } + + public PlagueMare(final PlagueMare card) { + super(card); + } + + @Override + public PlagueMare copy() { + return new PlagueMare(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PlanarCollapse.java b/Mage.Sets/src/mage/cards/p/PlanarCollapse.java index fadfd1060aa..f627cf2be7e 100644 --- a/Mage.Sets/src/mage/cards/p/PlanarCollapse.java +++ b/Mage.Sets/src/mage/cards/p/PlanarCollapse.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -29,7 +29,7 @@ public final class PlanarCollapse extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU, false); ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE, true)); PlanarCollapseCondition contition = new PlanarCollapseCondition(); - this.addAbility(new ConditionalTriggeredAbility(ability, contition, "At the beginning of your upkeep, if there are four or more creatures on the battlefield, sacrifice {this} and destroy all creatures. They can't be regenerated")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, contition, "At the beginning of your upkeep, if there are four or more creatures on the battlefield, sacrifice {this} and destroy all creatures. They can't be regenerated")); } diff --git a/Mage.Sets/src/mage/cards/p/PlatedPegasus.java b/Mage.Sets/src/mage/cards/p/PlatedPegasus.java new file mode 100644 index 00000000000..ab53c9aab37 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PlatedPegasus.java @@ -0,0 +1,83 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.PreventionEffectImpl; +import mage.constants.Duration; +import mage.constants.SubType; +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.Zone; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; + +/** + * + * @author noahg + */ +public final class PlatedPegasus extends CardImpl { + + public PlatedPegasus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.PEGASUS); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // If a spell would deal damage to a permanent or player, prevent 1 damage that spell would deal to that permanent or player. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlatedPegasusEffect())); + } + + public PlatedPegasus(final PlatedPegasus card) { + super(card); + } + + @Override + public PlatedPegasus copy() { + return new PlatedPegasus(this); + } +} + +class PlatedPegasusEffect extends PreventionEffectImpl { + + public PlatedPegasusEffect() { + super(Duration.WhileOnBattlefield, 1, false, false); + staticText = "If a spell would deal damage to a permanent or player, prevent 1 damage that spell would deal to that permanent or player."; + } + + public PlatedPegasusEffect(PlatedPegasusEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); + if (stackObject == null) { + stackObject = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK); + } + if (stackObject instanceof Spell) { + return super.applies(event, source, game); + } + return false; + } + + @Override + public PlatedPegasusEffect copy() { + return new PlatedPegasusEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PledgeOfLoyalty.java b/Mage.Sets/src/mage/cards/p/PledgeOfLoyalty.java new file mode 100644 index 00000000000..f2292eb1349 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PledgeOfLoyalty.java @@ -0,0 +1,134 @@ +package mage.cards.p; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import mage.MageObject; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.constants.*; +import mage.filter.Filter; +import mage.filter.FilterCard; +import mage.filter.FilterObject; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.PlayerList; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; + +/** + * + * @author noahg + */ +public final class PledgeOfLoyalty extends CardImpl { + + public PledgeOfLoyalty(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{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 protection from the colors of permanents you control. This effect doesn't remove Pledge of Loyalty. + ProtectionAbility gainedAbility = new PledgeOfLoyaltyProtectionAbility(); + gainedAbility.setAuraIdNotToBeRemoved(this.getId()); + Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA); + effect.setText("Enchanted creature has protection from the colors of permanents you control. This effect doesn't remove {this}."); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public PledgeOfLoyalty(final PledgeOfLoyalty card) { + super(card); + } + + @Override + public PledgeOfLoyalty copy() { + return new PledgeOfLoyalty(this); + } + + class PledgeOfLoyaltyProtectionAbility extends ProtectionAbility { + + public PledgeOfLoyaltyProtectionAbility() { + super(new FilterCard()); + } + + public PledgeOfLoyaltyProtectionAbility(final PledgeOfLoyaltyProtectionAbility ability) { + super(ability); + } + + @Override + public PledgeOfLoyaltyProtectionAbility copy() { + return new PledgeOfLoyaltyProtectionAbility(this); + } + + + @Override + public boolean canTarget(MageObject source, Game game) { + ObjectColor color = new ObjectColor(); + for (Permanent permanent: game.getBattlefield().getAllActivePermanents(controllerId)) { + ObjectColor permanentColor = permanent.getColor(game); + if (permanentColor.isColorless()) { + continue; + } + if (permanentColor.isBlack()) { + color.setBlack(true); + } + if (permanentColor.isBlue()) { + color.setBlue(true); + } + if (permanentColor.isGreen()) { + color.setGreen(true); + } + if (permanentColor.isRed()) { + color.setRed(true); + } + if (permanentColor.isWhite()) { + color.setWhite(true); + } + } + + List> colorPredicates = new ArrayList<>(); + if (color.isBlack()) { + colorPredicates.add(new ColorPredicate(ObjectColor.BLACK)); + } + if (color.isBlue()) { + colorPredicates.add(new ColorPredicate(ObjectColor.BLUE)); + } + if (color.isGreen()) { + colorPredicates.add(new ColorPredicate(ObjectColor.GREEN)); + } + if (color.isRed()) { + colorPredicates.add(new ColorPredicate(ObjectColor.RED)); + } + if (color.isWhite()) { + colorPredicates.add(new ColorPredicate(ObjectColor.WHITE)); + } + Filter protectionFilter = new FilterObject("the colors of permanents you control"); + protectionFilter.add(Predicates.or(colorPredicates)); + this.filter = protectionFilter; + return super.canTarget(source, game); + } + + @Override + public String getRule() { + return "{this} has protection from the colors of permanents you control."; + } + } +} diff --git a/Mage.Sets/src/mage/cards/p/PoeDameron.java b/Mage.Sets/src/mage/cards/p/PoeDameron.java new file mode 100644 index 00000000000..f0e7d9c6a8a --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PoeDameron.java @@ -0,0 +1,54 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; + +/** + * + * @author NinthWorld + */ +public final class PoeDameron extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("{this} or another nontoken creature you control"); + private static final FilterCreaturePermanent filterStarship = new FilterCreaturePermanent("starship creatures you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(new TokenPredicate())); + filterStarship.add(new ControllerPredicate(TargetController.YOU)); + filterStarship.add(new SubtypePredicate(SubType.STARSHIP)); + } + + public PoeDameron(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever Poe Dameron or another nontoken creature enters the battlefield under your control, starship creatures you control get +1/+1 until end of turn. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.EndOfTurn, filterStarship, false), filter, false)); + } + + public PoeDameron(final PoeDameron card) { + super(card); + } + + @Override + public PoeDameron copy() { + return new PoeDameron(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PoisonTipArcher.java b/Mage.Sets/src/mage/cards/p/PoisonTipArcher.java new file mode 100644 index 00000000000..4adc94c77bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PoisonTipArcher.java @@ -0,0 +1,48 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.constants.SubType; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class PoisonTipArcher extends CardImpl { + + public PoisonTipArcher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.ARCHER); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Whenever another creature dies, each opponent loses 1 life. + this.addAbility(new DiesCreatureTriggeredAbility( + new LoseLifeOpponentsEffect(1), false, true + )); + } + + public PoisonTipArcher(final PoisonTipArcher card) { + super(card); + } + + @Override + public PoisonTipArcher copy() { + return new PoisonTipArcher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PolisCrusher.java b/Mage.Sets/src/mage/cards/p/PolisCrusher.java index eff3cf8d3dc..22c4d9118b7 100644 --- a/Mage.Sets/src/mage/cards/p/PolisCrusher.java +++ b/Mage.Sets/src/mage/cards/p/PolisCrusher.java @@ -1,13 +1,9 @@ - package mage.cards.p; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.MonstrousCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.MonstrosityAbility; import mage.abilities.keyword.ProtectionAbility; @@ -16,16 +12,16 @@ 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.FilterPermanent; -import mage.filter.common.FilterEnchantmentPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; -import mage.target.Target; import mage.target.TargetPermanent; -import mage.target.targetpointer.FirstTargetPointer; /** * @@ -39,10 +35,8 @@ public final class PolisCrusher extends CardImpl { filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); } - private final UUID originalId; - public PolisCrusher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); this.subtype.add(SubType.CYCLOPS); this.power = new MageInt(4); @@ -50,42 +44,19 @@ public final class PolisCrusher extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); + // protection from enchantments this.addAbility(new ProtectionAbility(filter)); + // {4}{R}{G}: Monstrosity 3. this.addAbility(new MonstrosityAbility("{4}{R}{G}", 3)); + // Whenever Polis Crusher deals combat damage to a player, if Polis Crusher is monstrous, destroy target enchantment that player controls. - Ability ability = new ConditionalTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility(new DestroyTargetEffect(), false, true), - MonstrousCondition.instance, - "Whenever {this} deals combat damage to a player, if {this} is monstrous, destroy target enchantment that player controls."); - originalId = ability.getOriginalId(); - this.addAbility(ability); + this.addAbility(new PolisCrusherTriggeredAbility()); } public PolisCrusher(final PolisCrusher card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - for (Effect effect : ability.getEffects()) { - if (effect instanceof DestroyTargetEffect) { - Player attackedPlayer = game.getPlayer(effect.getTargetPointer().getFirst(game, ability)); - if (attackedPlayer != null) { - ability.getTargets().clear(); - FilterPermanent filterEnchantment = new FilterEnchantmentPermanent("enchantment attacked player controls"); - filterEnchantment.add(new ControllerIdPredicate(attackedPlayer.getId())); - Target target = new TargetPermanent(filterEnchantment); - ability.addTarget(target); - effect.setTargetPointer(new FirstTargetPointer()); - break; - } - } - } - } } @Override @@ -93,3 +64,51 @@ public final class PolisCrusher extends CardImpl { return new PolisCrusher(this); } } + +class PolisCrusherTriggeredAbility extends TriggeredAbilityImpl { + + public PolisCrusherTriggeredAbility() { + super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true); + } + + public PolisCrusherTriggeredAbility(final PolisCrusherTriggeredAbility ability) { + super(ability); + } + + @Override + public PolisCrusherTriggeredAbility copy() { + return new PolisCrusherTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + return MonstrousCondition.instance.apply(game, this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getSourceId().equals(this.sourceId) && ((DamagedPlayerEvent) event).isCombatDamage()) { + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + FilterPermanent filter = new FilterPermanent("an enchantment controlled by " + player.getLogName()); + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + filter.add(new ControllerIdPredicate(event.getTargetId())); + 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," + + " if {this} is monstrous, destroy target enchantment that player controls"; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PollenRemedy.java b/Mage.Sets/src/mage/cards/p/PollenRemedy.java index 2d7d42b2711..65d52569733 100644 --- a/Mage.Sets/src/mage/cards/p/PollenRemedy.java +++ b/Mage.Sets/src/mage/cards/p/PollenRemedy.java @@ -35,7 +35,7 @@ public final class PollenRemedy extends CardImpl { // 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)); - effect.setText("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 this spell was kicked, prevent the next 6 damage this way instead."); + 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(); } diff --git a/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java b/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java index 5f95be2611a..6f6b1ca6b6b 100644 --- a/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java +++ b/Mage.Sets/src/mage/cards/p/PolukranosWorldEater.java @@ -25,20 +25,20 @@ import mage.target.common.TargetCreaturePermanentAmount; /** * - * * The value of X in Polukranos’s last ability is equal to the value chosen + * * The value of X in Polukranos's last ability is equal to the value chosen * 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 + * (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. + * * 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. * - * * As Polukranos’s triggered ability resolves, Polukranos deals damage first, then + * * 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. * diff --git a/Mage.Sets/src/mage/cards/p/Polyraptor.java b/Mage.Sets/src/mage/cards/p/Polyraptor.java index e88958d2b1a..98d4e06a3b7 100644 --- a/Mage.Sets/src/mage/cards/p/Polyraptor.java +++ b/Mage.Sets/src/mage/cards/p/Polyraptor.java @@ -26,7 +26,7 @@ public final class Polyraptor extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(5); - // Enrage - Whenever Polyraptor is dealt damage, create a token that’s a copy of Polyraptor. + // Enrage - Whenever Polyraptor is dealt damage, create a token that's a copy of Polyraptor. Ability ability = new DealtDamageToSourceTriggeredAbility( Zone.BATTLEFIELD, new CreateTokenCopySourceEffect(), diff --git a/Mage.Sets/src/mage/cards/p/PorgNest.java b/Mage.Sets/src/mage/cards/p/PorgNest.java new file mode 100644 index 00000000000..d5c03946523 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PorgNest.java @@ -0,0 +1,44 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.constants.SubType; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.permanent.token.PorgToken; + +/** + * + * @author NinthWorld + */ +public final class PorgNest extends CardImpl { + + public PorgNest(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.BIRD); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // At the beginning of your upkeep, create a 0/1 green Bird creature token named Porg with "{G}: Monstrosity 1." + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new PorgToken()), TargetController.YOU, false)); + } + + public PorgNest(final PorgNest card) { + super(card); + } + + @Override + public PorgNest copy() { + return new PorgNest(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PortalMage.java b/Mage.Sets/src/mage/cards/p/PortalMage.java index 8a162d3d56b..69e75544b12 100644 --- a/Mage.Sets/src/mage/cards/p/PortalMage.java +++ b/Mage.Sets/src/mage/cards/p/PortalMage.java @@ -1,9 +1,6 @@ package mage.cards.p; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -14,9 +11,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.PhaseStep; +import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterAttackingCreature; import mage.game.Game; @@ -26,6 +23,10 @@ import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetDefender; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + /** * * @author LevelX2 diff --git a/Mage.Sets/src/mage/cards/p/Portcullis.java b/Mage.Sets/src/mage/cards/p/Portcullis.java index 319e341c8cd..c238942678d 100644 --- a/Mage.Sets/src/mage/cards/p/Portcullis.java +++ b/Mage.Sets/src/mage/cards/p/Portcullis.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.UUID; @@ -7,7 +6,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect; @@ -32,14 +31,13 @@ public final class Portcullis extends CardImpl { private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature"); public Portcullis(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature. String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature"; TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(), filter, false, SetTargetPointer.PERMANENT, rule); - MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2); - this.addAbility(new ConditionalTriggeredAbility(ability, condition, rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule)); // Return that card to the battlefield under its owner's control when Portcullis leaves the battlefield. Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false); @@ -91,14 +89,18 @@ class PortcullisExileEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); Permanent creature = game.getPermanent(targetPointer.getFirst(game, source)); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + } if (permanent != null && creature != null) { Player controller = game.getPlayer(creature.getControllerId()); Zone currentZone = game.getState().getZone(creature.getId()); if (currentZone == Zone.BATTLEFIELD) { controller.moveCardsToExile(creature, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName()); + return true; } } return false; diff --git a/Mage.Sets/src/mage/cards/p/PouncingWurm.java b/Mage.Sets/src/mage/cards/p/PouncingWurm.java index 25b6d07f201..df36219167f 100644 --- a/Mage.Sets/src/mage/cards/p/PouncingWurm.java +++ b/Mage.Sets/src/mage/cards/p/PouncingWurm.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.HasteAbility; @@ -34,7 +34,7 @@ public final class PouncingWurm extends CardImpl { // Kicker {2}{G} this.addAbility(new KickerAbility("{2}{G}")); // If Pouncing Wurm was kicked, it enters the battlefield with three +1/+1 counters on it and with haste. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3))), KickedCondition.instance,"If Pouncing Wurm was kicked, it enters the battlefield with three +1/+1 counters on it and with haste."); ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield)); diff --git a/Mage.Sets/src/mage/cards/p/PowerSink.java b/Mage.Sets/src/mage/cards/p/PowerSink.java index 49105eebbb3..a8e51d8e470 100644 --- a/Mage.Sets/src/mage/cards/p/PowerSink.java +++ b/Mage.Sets/src/mage/cards/p/PowerSink.java @@ -29,7 +29,7 @@ public final class PowerSink extends CardImpl { public PowerSink(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); - // Counter target spell unless its controller pays {X}. If that player doesn’t, they tap all lands with mana abilities they control and lose all unspent mana. + // Counter target spell unless its controller pays {X}. If that player doesn't, they tap all lands with mana abilities they control and lose all unspent mana. this.getSpellAbility().addEffect(new PowerSinkCounterUnlessPaysEffect()); this.getSpellAbility().addTarget(new TargetSpell()); } @@ -48,7 +48,7 @@ class PowerSinkCounterUnlessPaysEffect extends OneShotEffect { public PowerSinkCounterUnlessPaysEffect() { super(Outcome.Detriment); - this.staticText = "Counter target spell unless its controller pays {X}. If that player doesn’t, they tap all lands with mana abilities they control and lose all unspent mana"; + this.staticText = "Counter target spell unless its controller pays {X}. If that player doesn't, they tap all lands with mana abilities they control and lose all unspent mana"; } public PowerSinkCounterUnlessPaysEffect(final PowerSinkCounterUnlessPaysEffect effect) { diff --git a/Mage.Sets/src/mage/cards/p/Pox.java b/Mage.Sets/src/mage/cards/p/Pox.java index 3437720153f..f1c96ba39f2 100644 --- a/Mage.Sets/src/mage/cards/p/Pox.java +++ b/Mage.Sets/src/mage/cards/p/Pox.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.UUID; @@ -24,8 +23,7 @@ import mage.target.common.TargetControlledPermanent; public final class Pox extends CardImpl { public Pox(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}{B}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}{B}{B}"); // Each player loses a third of their life, then discards a third of the cards in their hand, then sacrifices a third of the creatures he or she controls, then sacrifices a third of the lands he or she controls. Round up each time. this.getSpellAbility().addEffect(new PoxEffect()); @@ -42,21 +40,25 @@ public final class Pox extends CardImpl { } class PoxEffect extends OneShotEffect { - + PoxEffect() { super(Outcome.Detriment); - this.staticText = "Each player loses a third of their life, then discards a third of the cards in their hand, then sacrifices a third of the creatures he or she controls, then sacrifices a third of the lands he or she controls. Round up each time."; + this.staticText = "Each player loses a third of their life, " + + "then discards a third of the cards in their hand, " + + "then sacrifices a third of the creatures they control, " + + "then sacrifices a third of the lands they control. " + + "Round up each time."; } - + PoxEffect(final PoxEffect effect) { super(effect); } - + @Override public PoxEffect copy() { return new PoxEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/p/PraetorianTrooper.java b/Mage.Sets/src/mage/cards/p/PraetorianTrooper.java new file mode 100644 index 00000000000..0c9bd16aa15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PraetorianTrooper.java @@ -0,0 +1,49 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.constants.Duration; +import mage.constants.SubType; +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.mageobject.SubtypePredicate; + +/** + * + * @author NinthWorld + */ +public final class PraetorianTrooper extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Trooper creatures"); + + static { + filter.add(new SubtypePredicate(SubType.TROOPER)); + } + + public PraetorianTrooper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Trooper creatures you control have double strike. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter, false))); + } + + public PraetorianTrooper(final PraetorianTrooper card) { + super(card); + } + + @Override + public PraetorianTrooper copy() { + return new PraetorianTrooper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java b/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java index f0989f29591..8ed229abe34 100644 --- a/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java +++ b/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java @@ -66,7 +66,7 @@ class PrecipiceOfMortisEffect extends ReplacementEffectImpl { if (event instanceof NumberOfTriggersEvent) { NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; // Only triggers of the controller of Precipice of Mortis - if (source.getControllerId().equals(event.getPlayerId())) { + if (source.isControlledBy(event.getPlayerId())) { GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); // enters triggers if (sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) { diff --git a/Mage.Sets/src/mage/cards/p/PredatorsHowl.java b/Mage.Sets/src/mage/cards/p/PredatorsHowl.java index 38f2d633786..b0ebabf2149 100644 --- a/Mage.Sets/src/mage/cards/p/PredatorsHowl.java +++ b/Mage.Sets/src/mage/cards/p/PredatorsHowl.java @@ -21,7 +21,7 @@ public final class PredatorsHowl extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{G}"); // Create a 2/2 green Wolf creature token. - // Morbid - Create three 2/2 green Wolf creature tokens instead if a creature died this turn. + // Morbid — Create three 2/2 green Wolf creature tokens instead if a creature died this turn. Effect effect = new ConditionalOneShotEffect( new CreateTokenEffect(new WolfToken(), 3), new CreateTokenEffect(new WolfToken(), 1), diff --git a/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java b/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java index 551d5a692cc..fe202bc1e04 100644 --- a/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java +++ b/Mage.Sets/src/mage/cards/p/PredatoryAdvantage.java @@ -76,7 +76,7 @@ class CastCreatureWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.SPELL_CAST - && game.getActivePlayerId().equals(event.getPlayerId()) + && game.isActivePlayer(event.getPlayerId()) && game.getOpponents(controllerId).contains(event.getPlayerId())) { Spell spell = (Spell) game.getObject(event.getTargetId()); if (spell.isCreature()) { diff --git a/Mage.Sets/src/mage/cards/p/PredatoryFocus.java b/Mage.Sets/src/mage/cards/p/PredatoryFocus.java new file mode 100644 index 00000000000..807f5249596 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PredatoryFocus.java @@ -0,0 +1,81 @@ +package mage.cards.p; + +import java.util.UUID; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffect; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author noahg + */ +public final class PredatoryFocus extends CardImpl { + + public PredatoryFocus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); + + + // You may have creatures you control assign their combat damage this turn as though they weren't blocked. + this.getSpellAbility().addEffect(new PredatoryFocusEffect()); + } + + public PredatoryFocus(final PredatoryFocus card) { + super(card); + } + + @Override + public PredatoryFocus copy() { + return new PredatoryFocus(this); + } +} + +class PredatoryFocusEffect extends AsThoughEffectImpl { + + private boolean choseUse; + + public PredatoryFocusEffect() { + super(AsThoughEffectType.DAMAGE_NOT_BLOCKED, Duration.EndOfTurn, Outcome.Damage); + this.staticText = "You may have creatures you control assign their combat damage this turn as though they weren't blocked."; + } + + public PredatoryFocusEffect(PredatoryFocusEffect effect) { + super(effect); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + Player controller = game.getPlayer(source.getControllerId()); + String sourceName = source.getSourceObject(game).getLogName(); + choseUse = controller.chooseUse(Outcome.Damage, "Have creatures you control deal combat damage this turn" + + " as though they weren't blocked?", source, game); + game.informPlayers(choseUse ? controller.getName()+" chose to use "+sourceName+"'s effect" : + controller.getName()+" chose not to use "+sourceName+"'s effect."); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + return choseUse && affectedControllerId.equals(source.getControllerId()); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public PredatoryFocusEffect copy() { + return new PredatoryFocusEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/Predict.java b/Mage.Sets/src/mage/cards/p/Predict.java index e29d6935864..193ae9b8c0f 100644 --- a/Mage.Sets/src/mage/cards/p/Predict.java +++ b/Mage.Sets/src/mage/cards/p/Predict.java @@ -1,10 +1,9 @@ - package mage.cards.p; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -22,11 +21,10 @@ import mage.target.TargetPlayer; public final class Predict extends CardImpl { public Predict(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Name a card, then target player puts the top card of their library into their graveyard. If that card is the named card, you draw two cards. Otherwise, you draw a card. - this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); this.getSpellAbility().addEffect(new PredictEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); } @@ -46,9 +44,9 @@ class PredictEffect extends OneShotEffect { public PredictEffect() { super(Outcome.DrawCard); this.staticText = ", then target player puts the top card of their library into their graveyard. " - + "If that card is the named card, you draw two cards. Otherwise, you draw a card."; + + "If that card has the chosen name, you draw two cards. Otherwise, you draw a card."; } - + public PredictEffect(final PredictEffect effect) { super(effect); } @@ -57,25 +55,25 @@ class PredictEffect extends OneShotEffect { public PredictEffect copy() { return new PredictEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(source.getFirstTarget()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); - if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) { - int amount = 1; + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); + if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) { + int amount = 1; Card card = targetPlayer.getLibrary().getFromTop(game); if (card != null) { controller.moveCards(card, Zone.GRAVEYARD, source, game); if (card.getName().equals(cardName)) { amount = 2; } - } - controller.drawCards(amount, game); + } + controller.drawCards(amount, game); return true; } return false; } - + } diff --git a/Mage.Sets/src/mage/cards/p/PreeminentCaptain.java b/Mage.Sets/src/mage/cards/p/PreeminentCaptain.java index 05d5ae902e5..552d957cb2b 100644 --- a/Mage.Sets/src/mage/cards/p/PreeminentCaptain.java +++ b/Mage.Sets/src/mage/cards/p/PreeminentCaptain.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.UUID; @@ -72,12 +71,13 @@ class PreeminentCaptainEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); TargetCardInHand target = new TargetCardInHand(filter); - if (target.canChoose(controller.getId(), game) && target.choose(getOutcome(), controller.getId(), source.getSourceId(), game)) { + if (target.canChoose(controller.getId(), game) + && target.choose(getOutcome(), controller.getId(), source.getSourceId(), game)) { if (!target.getTargets().isEmpty()) { UUID cardId = target.getFirstTarget(); Card card = controller.getHand().get(cardId, game); if (card != null) { - if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { + if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null)) { Permanent permanent = game.getPermanent(card.getId()); if (permanent != null) { game.getCombat().addAttackingCreature(permanent.getId(), game); diff --git a/Mage.Sets/src/mage/cards/p/PrematureBurial.java b/Mage.Sets/src/mage/cards/p/PrematureBurial.java new file mode 100644 index 00000000000..9f35bb58888 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PrematureBurial.java @@ -0,0 +1,143 @@ +package mage.cards.p; + +import mage.MageObject; +import mage.MageObjectReference; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.WatcherScope; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.Watcher; + +import java.util.*; + +/** + * + * @author noahg + */ +public final class PrematureBurial extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature that entered the battlefield since your last turn ended"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public PrematureBurial(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); + + + // Destroy target nonblack creature that entered the battlefield since your last turn ended. + this.getSpellAbility().addEffect(new DestroyTargetEffect().setText("Destroy target nonblack creature that entered the battlefield since your last turn ended.")); + this.getSpellAbility().addTarget(new ETBSinceYourLastTurnTarget(filter)); + this.getSpellAbility().addWatcher(new ETBSinceYourLastTurnWatcher()); + } + + public PrematureBurial(final PrematureBurial card) { + super(card); + } + + @Override + public PrematureBurial copy() { + return new PrematureBurial(this); + } +} + +class ETBSinceYourLastTurnTarget extends TargetCreaturePermanent { + + public ETBSinceYourLastTurnTarget(FilterCreaturePermanent filter) { + super(filter); + this.targetName = "nonblack creature that entered the battlefield since your last turn ended"; + } + + public ETBSinceYourLastTurnTarget(ETBSinceYourLastTurnTarget target){ + super(target); + } + + @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()); + if (watcher != null){ + if (watcher.enteredSinceLastTurn(controllerId, new MageObjectReference(id, game))){ + System.out.println(game.getPermanent(id).getIdName()+" entered since the last turn."); + return super.canTarget(controllerId, id, source, game); + } + } + return false; + } + + @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()); + 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))) { + return true; + } + } + } + return false; + } + + @Override + public ETBSinceYourLastTurnTarget copy() { + return new ETBSinceYourLastTurnTarget(this); + } +} + +class ETBSinceYourLastTurnWatcher extends Watcher { + + private final Map> playerToETBMap; + + public ETBSinceYourLastTurnWatcher() { + super(ETBSinceYourLastTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + this.playerToETBMap = new HashMap<>(); + } + + public ETBSinceYourLastTurnWatcher(ETBSinceYourLastTurnWatcher watcher) { + super(watcher); + this.playerToETBMap = new HashMap<>(); + for (UUID player : watcher.playerToETBMap.keySet()){ + this.playerToETBMap.put(player, new HashSet<>(watcher.playerToETBMap.get(player))); + } + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.END_TURN_STEP_POST){ + System.out.println("End of turn for "+game.getPlayer(event.getPlayerId()).getName()); + playerToETBMap.put(event.getPlayerId(), new HashSet<>()); + } else if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD){ + Permanent etbPermanent = game.getPermanent(event.getTargetId()); + if (etbPermanent != null){ + System.out.println("nonnull permanent entered: "+etbPermanent.getIdName()); + for (UUID player : game.getPlayerList()){ + if (!playerToETBMap.containsKey(player)){ + playerToETBMap.put(player, new HashSet<>()); + } + playerToETBMap.get(player).add(new MageObjectReference(etbPermanent.getBasicMageObject(game), game)); + } + } + } + } + + public boolean enteredSinceLastTurn(UUID player, MageObjectReference mor){ + return playerToETBMap.get(player).contains(mor); + } + + @Override + public ETBSinceYourLastTurnWatcher copy() { + return new ETBSinceYourLastTurnWatcher(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PrescientChimera.java b/Mage.Sets/src/mage/cards/p/PrescientChimera.java index 03d44324385..124a222a486 100644 --- a/Mage.Sets/src/mage/cards/p/PrescientChimera.java +++ b/Mage.Sets/src/mage/cards/p/PrescientChimera.java @@ -28,7 +28,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_INSTANT_OR_SORCERY_SPELL, false)); + this.addAbility(new SpellCastControllerTriggeredAbility(new ScryEffect(1), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false)); } public PrescientChimera(final PrescientChimera card) { diff --git a/Mage.Sets/src/mage/cards/p/PriceOfGlory.java b/Mage.Sets/src/mage/cards/p/PriceOfGlory.java index cfe602387f3..c34c287cd4f 100644 --- a/Mage.Sets/src/mage/cards/p/PriceOfGlory.java +++ b/Mage.Sets/src/mage/cards/p/PriceOfGlory.java @@ -69,7 +69,7 @@ class PriceOfGloryAbility extends TriggeredAbilityImpl { } if (permanent.isLand() && player.getInRange().contains(permanent.getControllerId()) - && !permanent.getControllerId().equals(game.getActivePlayerId())) { // intervening if clause + && !permanent.isControlledBy(game.getActivePlayerId())) { // intervening if clause getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId())); return true; } @@ -103,7 +103,7 @@ class PriceOfGloryEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { Permanent land = game.getPermanentOrLKIBattlefield(this.targetPointer.getFirst(game, source)); - if (land != null && !land.getControllerId().equals(game.getActivePlayerId())) { // intervening if clause has to be checked again + if (land != null && !land.isControlledBy(game.getActivePlayerId())) { // intervening if clause has to be checked again land.destroy(source.getSourceId(), game, false); } return true; diff --git a/Mage.Sets/src/mage/cards/p/PrimitiveEtchings.java b/Mage.Sets/src/mage/cards/p/PrimitiveEtchings.java index addf6310f54..630ceaa9e1a 100644 --- a/Mage.Sets/src/mage/cards/p/PrimitiveEtchings.java +++ b/Mage.Sets/src/mage/cards/p/PrimitiveEtchings.java @@ -65,7 +65,7 @@ class PrimitiveEtchingsAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(this.getControllerId())) { - if (game.getActivePlayerId().equals(this.getControllerId()) && this.lastTriggeredTurn != game.getTurnNum()) { + if (game.isActivePlayer(this.getControllerId()) && this.lastTriggeredTurn != game.getTurnNum()) { Card card = game.getCard(event.getTargetId()); Player controller = game.getPlayer(this.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(this.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/p/PrimordialMist.java b/Mage.Sets/src/mage/cards/p/PrimordialMist.java new file mode 100644 index 00000000000..ee917e9486e --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PrimordialMist.java @@ -0,0 +1,146 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.keyword.ManifestEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.other.FaceDownPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author spjspj + */ +public final class PrimordialMist extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("face down permanent"); + + static { + filter.add(new FaceDownPredicate()); + } + + public PrimordialMist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); + + // At the beginning of your end step, you may manifest the top card of your library. + this.addAbility(new BeginningOfEndStepTriggeredAbility(new ManifestEffect(1), TargetController.YOU, true)); + + // Exile a face-down permanent you control face-up: You may play that card this turn + TargetPermanent target = new TargetPermanent(filter); + target.setNotTarget(true); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new PrimordialMistCastFromExileEffect(), + new PrimordialMistCost(target)); + this.addAbility(ability); + } + + public PrimordialMist(final PrimordialMist card) { + super(card); + } + + @Override + public PrimordialMist copy() { + return new PrimordialMist(this); + } +} + +class PrimordialMistCost extends CostImpl { + + TargetPermanent target; + + public PrimordialMistCost(TargetPermanent target) { + this.target = target; + this.text = "Exile a face-down permanent you control face-up"; + } + + public PrimordialMistCost(final PrimordialMistCost cost) { + super(cost); + this.target = cost.target.copy(); + } + + @Override + public PrimordialMistCost copy() { + return new PrimordialMistCost(this); + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + return target.canChoose(controllerId, game); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + if (target.choose(Outcome.Exile, controllerId, sourceId, game)) { + Card card = game.getCard(sourceId); + if (card != null) { + Permanent sourcePermanent = game.getPermanent(sourceId); + if (sourcePermanent != null) { + Permanent targetPermanent = game.getPermanent(target.getFirstTarget()); + Card targetCard = game.getCard(target.getFirstTarget()); + if (targetPermanent != null && targetCard != null) { + String exileName = sourcePermanent.getIdName() + " "; + controller.moveCardsToExile(targetPermanent, ability, game, true, sourceId, exileName); + targetPermanent.setFaceDown(false, game); + ContinuousEffect effect = new PrimordialMistCastFromExileEffect(); + effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); + game.addEffect(effect, ability); + this.setPaid(); + } + } + } + this.setPaid(); + return true; + } + } + return false; + } +} + +class PrimordialMistCastFromExileEffect extends AsThoughEffectImpl { + + public PrimordialMistCastFromExileEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + staticText = "Exile a face-down permanent you control face-up. You may play the card from exile"; + } + + public PrimordialMistCastFromExileEffect(final PrimordialMistCastFromExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public PrimordialMistCastFromExileEffect copy() { + return new PrimordialMistCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return source.isControlledBy(affectedControllerId) + && (game.getCard(getTargetPointer().getFirst(game, source)) != null); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java b/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java index 3bc2bd9159b..77d939f26f8 100644 --- a/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java +++ b/Mage.Sets/src/mage/cards/p/PrizedAmalgam.java @@ -77,18 +77,18 @@ class PrizedAmalgamTriggerdAbility extends EntersBattlefieldAllTriggeredAbility @Override public boolean checkTrigger(GameEvent event, Game game) { /** - * 4/8/2016 Prized Amalgam’s ability triggers only if it’s in your + * 4/8/2016 Prized Amalgam's ability triggers only if it's in your * graveyard immediately after a creature enters the battlefield from * your graveyard or you cast a creature from your graveyard. A Prized - * Amalgam that’s already on the battlefield won’t be returned at the - * beginning of the next end step if it’s put into your graveyard later. + * Amalgam that's already on the battlefield won't be returned at the + * beginning of the next end step if it's put into your graveyard later. */ boolean result = false; if (super.checkTrigger(event, game)) { EntersTheBattlefieldEvent entersEvent = (EntersTheBattlefieldEvent) event; if (entersEvent.getFromZone() == Zone.GRAVEYARD) { result = true; - } else if (entersEvent.getFromZone() == Zone.STACK && entersEvent.getTarget().getControllerId().equals(getControllerId())) { + } else if (entersEvent.getFromZone() == Zone.STACK && entersEvent.getTarget().isControlledBy(getControllerId())) { CastFromGraveyardWatcher watcher = (CastFromGraveyardWatcher) game.getState().getWatchers().get(CastFromGraveyardWatcher.class.getSimpleName()); if (watcher != null) { int zcc = game.getState().getZoneChangeCounter(event.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/p/ProdigiousGrowth.java b/Mage.Sets/src/mage/cards/p/ProdigiousGrowth.java new file mode 100644 index 00000000000..057ac9f647c --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/ProdigiousGrowth.java @@ -0,0 +1,61 @@ +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.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class ProdigiousGrowth extends CardImpl { + + public ProdigiousGrowth(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); + + 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 gets +7/+7 and has trample. + ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostEnchantedEffect(7, 7, Duration.WhileOnBattlefield) + ); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), + AttachmentType.AURA + ) + .setText("and has trample")); + this.addAbility(ability); + } + + public ProdigiousGrowth(final ProdigiousGrowth card) { + super(card); + } + + @Override + public ProdigiousGrowth copy() { + return new ProdigiousGrowth(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java index b3a181e230c..156ae583dc9 100644 --- a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java +++ b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.effects.common.CopyPermanentEffect; @@ -40,19 +40,19 @@ public final class ProgenitorMimic extends CardImpl { this.toughness = new MageInt(0); // You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield - // except it gains "At the beginning of your upkeep, if this creature isn't a token, + // except it has "At the beginning of your upkeep, if this creature isn't a token, // create a token that's a copy of this creature." Effect effect = new CreateTokenCopySourceEffect(); effect.setText("create a token that's a copy of this creature"); AbilityApplier applier = new AbilityApplier( - new ConditionalTriggeredAbility( + new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, false), new SourceMatchesFilterCondition(filter), "At the beginning of your upkeep, if this creature isn't a token, create a token that's a copy of this creature.") ); effect = new CopyPermanentEffect(applier); - effect.setText("as a copy of any creature on the battlefield except it gains \"At the beginning of your upkeep, if this creature isn't a token, create a token that's a copy of this creature.\""); + effect.setText("as a copy of any creature on the battlefield except it has \"At the beginning of your upkeep, if this creature isn't a token, create a token that's a copy of this creature.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); } diff --git a/Mage.Sets/src/mage/cards/p/ProperBurial.java b/Mage.Sets/src/mage/cards/p/ProperBurial.java index 1c178d59036..53b6feb9d28 100644 --- a/Mage.Sets/src/mage/cards/p/ProperBurial.java +++ b/Mage.Sets/src/mage/cards/p/ProperBurial.java @@ -63,7 +63,7 @@ class ProperBurialTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { + if (permanent.isControlledBy(this.getControllerId()) && permanent.isCreature()) { this.getEffects().clear(); this.addEffect(new GainLifeEffect(permanent.getToughness().getValue())); return true; diff --git a/Mage.Sets/src/mage/cards/p/Prophecy.java b/Mage.Sets/src/mage/cards/p/Prophecy.java new file mode 100644 index 00000000000..e8c1e6260f5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/Prophecy.java @@ -0,0 +1,89 @@ +package mage.cards.p; + +import java.util.UUID; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.Card; +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.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author noahg + */ +public final class Prophecy extends CardImpl { + + public Prophecy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}"); + + + // Reveal the top card of target opponent's library. If it's a land, you gain 1 life. Then that player shuffles their library. + this.getSpellAbility().addEffect(new ProphecyEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + + // Draw a card at the beginning of the next turn's upkeep. + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false)); + } + + public Prophecy(final Prophecy card) { + super(card); + } + + @Override + public Prophecy copy() { + return new Prophecy(this); + } +} + +class ProphecyEffect extends OneShotEffect { + + public ProphecyEffect() { + super(Outcome.GainLife); + this.staticText = "Reveal the top card of target opponent's library. If it's a land, you gain 1 life. Then that player shuffles their library"; + } + + public ProphecyEffect(final ProphecyEffect effect) { + super(effect); + } + + @Override + public ProphecyEffect copy() { + return new ProphecyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject == null || targetPlayer == null || controller == null) { + return false; + } + if (targetPlayer.getLibrary().hasCards()) { + CardsImpl cards = new CardsImpl(); + Card card = targetPlayer.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + cards.add(card); + targetPlayer.revealCards(sourceObject.getIdName(), cards, game); + if (card.isLand()) { + controller.gainLife(1, game, source.getSourceId()); + } + targetPlayer.shuffleLibrary(source, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PropheticFlamespeaker.java b/Mage.Sets/src/mage/cards/p/PropheticFlamespeaker.java index e4a257ed00e..2309a098cd9 100644 --- a/Mage.Sets/src/mage/cards/p/PropheticFlamespeaker.java +++ b/Mage.Sets/src/mage/cards/p/PropheticFlamespeaker.java @@ -113,7 +113,7 @@ class PropheticFlamespeakerCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/p/ProwlingPangolin.java b/Mage.Sets/src/mage/cards/p/ProwlingPangolin.java index 933ef29e446..a6c373ffd12 100644 --- a/Mage.Sets/src/mage/cards/p/ProwlingPangolin.java +++ b/Mage.Sets/src/mage/cards/p/ProwlingPangolin.java @@ -27,7 +27,7 @@ public final class ProwlingPangolin extends CardImpl { public ProwlingPangolin(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); - this.subtype.add(SubType.BEAST); + this.subtype.add(SubType.BEAST, SubType.PANGOLIN); this.power = new MageInt(6); this.toughness = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/p/PsychicBattle.java b/Mage.Sets/src/mage/cards/p/PsychicBattle.java index 65673a95833..f4f3eb91b9a 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicBattle.java +++ b/Mage.Sets/src/mage/cards/p/PsychicBattle.java @@ -88,7 +88,7 @@ class PsychicBattleEffect extends OneShotEffect { public PsychicBattleEffect() { super(Outcome.Benefit); - this.staticText = "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"; + this.staticText = "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"; } public PsychicBattleEffect(final PsychicBattleEffect effect) { diff --git a/Mage.Sets/src/mage/cards/p/PsychicCorrosion.java b/Mage.Sets/src/mage/cards/p/PsychicCorrosion.java new file mode 100644 index 00000000000..50e5f46cf35 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PsychicCorrosion.java @@ -0,0 +1,36 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.abilities.common.DrawCardControllerTriggeredAbility; +import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; + +/** + * + * @author TheElk801 + */ +public final class PsychicCorrosion extends CardImpl { + + public PsychicCorrosion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // Whenever you draw a card, each opponent puts the top two cards of their library into their graveyard. + this.addAbility(new DrawCardControllerTriggeredAbility( + new PutTopCardOfLibraryIntoGraveEachPlayerEffect( + 2, TargetController.OPPONENT + ), false + )); + } + + public PsychicCorrosion(final PsychicCorrosion card) { + super(card); + } + + @Override + public PsychicCorrosion copy() { + return new PsychicCorrosion(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PsychicSymbiont.java b/Mage.Sets/src/mage/cards/p/PsychicSymbiont.java new file mode 100644 index 00000000000..e5933fa387c --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PsychicSymbiont.java @@ -0,0 +1,48 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class PsychicSymbiont extends CardImpl { + + public PsychicSymbiont(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{B}"); + + this.subtype.add(SubType.NIGHTMARE); + this.subtype.add(SubType.HORROR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Psychic Symbiont enters the battlefield, target opponent discards a card and you draw a card. + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)); + ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and you draw a card")); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public PsychicSymbiont(final PsychicSymbiont card) { + super(card); + } + + @Override + public PsychicSymbiont copy() { + return new PsychicSymbiont(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PulseOfMurasa.java b/Mage.Sets/src/mage/cards/p/PulseOfMurasa.java index e6858924a84..f1f541e9932 100644 --- a/Mage.Sets/src/mage/cards/p/PulseOfMurasa.java +++ b/Mage.Sets/src/mage/cards/p/PulseOfMurasa.java @@ -18,7 +18,7 @@ import mage.target.common.TargetCardInGraveyard; */ public final class PulseOfMurasa extends CardImpl { - private static final FilterCard FILTER = new FilterCard("creature or land card in a graveyard"); + private static final FilterCard FILTER = new FilterCard("creature or land card from a graveyard"); static { FILTER.add(Predicates.or( diff --git a/Mage.Sets/src/mage/cards/p/PureIntentions.java b/Mage.Sets/src/mage/cards/p/PureIntentions.java index 9ef3d452264..df8ff3752bb 100644 --- a/Mage.Sets/src/mage/cards/p/PureIntentions.java +++ b/Mage.Sets/src/mage/cards/p/PureIntentions.java @@ -71,7 +71,7 @@ class PureIntentionsAllTriggeredAbility extends DelayedTriggeredAbility { if (stackObject != null && game.getOpponents(this.getControllerId()).contains(stackObject.getControllerId())) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(getControllerId())) { + if (card != null && card.isOwnedBy(getControllerId())) { for (Effect effect : getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); } diff --git a/Mage.Sets/src/mage/cards/p/PuresteelPaladin.java b/Mage.Sets/src/mage/cards/p/PuresteelPaladin.java index 395ea6b16e8..19252b5c053 100644 --- a/Mage.Sets/src/mage/cards/p/PuresteelPaladin.java +++ b/Mage.Sets/src/mage/cards/p/PuresteelPaladin.java @@ -39,11 +39,11 @@ public final class PuresteelPaladin extends CardImpl { // Whenever an Equipment enters the battlefield under your control, you may draw a card. this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, true)); - // Metalcraft - Equipment you control have equip {0} as long as you control three or more artifacts + // Metalcraft — Equipment you control have equip {0} as long as you control three or more artifacts this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( new GainAbilityControlledEffect(new EquipAbility(Outcome.AddAbility, new GenericManaCost(0)), Duration.WhileOnBattlefield, filter), MetalcraftCondition.instance, - "Metalcraft - Equipment you control have equip {0} as long as you control three or more artifacts"))); + "Metalcraft — Equipment you control have equip {0} as long as you control three or more artifacts"))); } public PuresteelPaladin(final PuresteelPaladin card) { diff --git a/Mage.Sets/src/mage/cards/p/Purgatory.java b/Mage.Sets/src/mage/cards/p/Purgatory.java index 15fdd00b4be..7fdb5917e89 100644 --- a/Mage.Sets/src/mage/cards/p/Purgatory.java +++ b/Mage.Sets/src/mage/cards/p/Purgatory.java @@ -94,7 +94,7 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl { && zEvent.getFromZone() == Zone.BATTLEFIELD && !(permanent instanceof PermanentToken) && permanent.isCreature() - && permanent.getOwnerId().equals(controller.getId())) { + && permanent.isOwnedBy(controller.getId())) { this.getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId())); return true; @@ -129,7 +129,7 @@ class PurgatoryExileEffect extends OneShotEffect { MageObject sourceObject = source.getSourceObject(game); Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); if (sourceController != null && exileId != null && sourceObject != null && card != null) { - if (game.getState().getZone(card.getId()).equals(Zone.GRAVEYARD)) { + if (game.getState().getZone(card.getId()) == Zone.GRAVEYARD) { sourceController.moveCardsToExile(card, source, game, true, exileId, sourceObject.getIdName()); } return true; diff --git a/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java b/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java new file mode 100644 index 00000000000..43dbbc267b0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java @@ -0,0 +1,37 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class PurpleCrystalCrab extends CardImpl { + + public PurpleCrystalCrab(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.CRAB); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Purple-Crystal Crab dies, draw card. + this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); + } + + public PurpleCrystalCrab(final PurpleCrystalCrab card) { + super(card); + } + + @Override + public PurpleCrystalCrab copy() { + return new PurpleCrystalCrab(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/Pyrohemia.java b/Mage.Sets/src/mage/cards/p/Pyrohemia.java index 0cb68a49bad..e0305312256 100644 --- a/Mage.Sets/src/mage/cards/p/Pyrohemia.java +++ b/Mage.Sets/src/mage/cards/p/Pyrohemia.java @@ -7,7 +7,7 @@ import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CreatureCountCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -30,7 +30,7 @@ public final class Pyrohemia extends CardImpl { // At the beginning of the end step, if no creatures are on the battlefield, sacrifice Pyrohemia. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); // {R}: Pyrohemia deals 1 damage to each creature and each player. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageEverythingEffect(1), new ManaCostsImpl("{R}"))); diff --git a/Mage.Sets/src/mage/cards/p/PyromancerAscension.java b/Mage.Sets/src/mage/cards/p/PyromancerAscension.java index 8cb391cd509..c4831f5dd24 100644 --- a/Mage.Sets/src/mage/cards/p/PyromancerAscension.java +++ b/Mage.Sets/src/mage/cards/p/PyromancerAscension.java @@ -88,7 +88,7 @@ class PyromancerAscensionQuestTriggeredAbility extends TriggeredAbilityImpl { private boolean isControlledInstantOrSorcery(Spell spell) { return spell != null && - (spell.getControllerId().equals(this.getControllerId())) && + (spell.isControlledBy(this.getControllerId())) && (spell.isInstant() || spell.isSorcery()); } @@ -135,7 +135,7 @@ class PyromancerAscensionCopyTriggeredAbility extends TriggeredAbilityImpl { private boolean isControlledInstantOrSorcery(Spell spell) { return spell != null && - (spell.getControllerId().equals(this.getControllerId())) && + (spell.isControlledBy(this.getControllerId())) && (spell.isInstant() || spell.isSorcery()); } diff --git a/Mage.Sets/src/mage/cards/p/PyromancersGauntlet.java b/Mage.Sets/src/mage/cards/p/PyromancersGauntlet.java index 77c12981a06..8c6055dc4bb 100644 --- a/Mage.Sets/src/mage/cards/p/PyromancersGauntlet.java +++ b/Mage.Sets/src/mage/cards/p/PyromancersGauntlet.java @@ -63,7 +63,7 @@ class PyromancersGauntletReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object instanceof Spell) { - if (((Spell) object).getControllerId().equals(source.getControllerId()) + if (((Spell) object).isControlledBy(source.getControllerId()) && (object.isInstant() || object.isSorcery())){ return true; diff --git a/Mage.Sets/src/mage/cards/p/PyromancersSwath.java b/Mage.Sets/src/mage/cards/p/PyromancersSwath.java index 79fac231a10..9bcae7d269b 100644 --- a/Mage.Sets/src/mage/cards/p/PyromancersSwath.java +++ b/Mage.Sets/src/mage/cards/p/PyromancersSwath.java @@ -67,7 +67,7 @@ class PyromancersSwathReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getControllerId().equals(game.getControllerId(event.getSourceId()))) { + if (source.isControlledBy(game.getControllerId(event.getSourceId()))) { MageObject object = game.getObject(event.getSourceId()); return object != null && (object.isInstant() || object.isSorcery()); } diff --git a/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java b/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java index c4739d42e48..134df294229 100644 --- a/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java +++ b/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java @@ -81,7 +81,7 @@ class QasaliAmbusherAbility extends ActivatedAbilityImpl { if (!game.getBattlefield().getActivePermanents(filterPlains, this.getControllerId(), this.getSourceId(), game).isEmpty() && !game.getBattlefield().getActivePermanents(filterForest, this.getControllerId(), this.getSourceId(), game).isEmpty()) { for (CombatGroup group : game.getCombat().getGroups()) { - if (getControllerId().equals(group.getDefenderId())) { + if (isControlledBy(group.getDefenderId())) { return super.canActivate(playerId, game); } } diff --git a/Mage.Sets/src/mage/cards/q/QasaliSlingers.java b/Mage.Sets/src/mage/cards/q/QasaliSlingers.java index 7d9b09aac1a..a68dd907373 100644 --- a/Mage.Sets/src/mage/cards/q/QasaliSlingers.java +++ b/Mage.Sets/src/mage/cards/q/QasaliSlingers.java @@ -76,7 +76,7 @@ class QasaliSlingersTriggeredAbility extends TriggeredAbilityImpl { if (permanent.getId().equals(this.getSourceId())) { return true; } - if (permanent.hasSubtype(SubType.CAT, game) && permanent.getControllerId().equals(this.getControllerId())) { + if (permanent.hasSubtype(SubType.CAT, game) && permanent.isControlledBy(this.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/q/QilinsBlessing.java b/Mage.Sets/src/mage/cards/q/QilinsBlessing.java new file mode 100644 index 00000000000..c9b7fc5f15b --- /dev/null +++ b/Mage.Sets/src/mage/cards/q/QilinsBlessing.java @@ -0,0 +1,33 @@ +package mage.cards.q; + +import java.util.UUID; +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.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class QilinsBlessing extends CardImpl { + + public QilinsBlessing(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()); + } + + public QilinsBlessing(final QilinsBlessing card) { + super(card); + } + + @Override + public QilinsBlessing copy() { + return new QilinsBlessing(this); + } +} diff --git a/Mage.Sets/src/mage/cards/q/Quagnoth.java b/Mage.Sets/src/mage/cards/q/Quagnoth.java index d8134503fb3..a6b90c6005a 100644 --- a/Mage.Sets/src/mage/cards/q/Quagnoth.java +++ b/Mage.Sets/src/mage/cards/q/Quagnoth.java @@ -3,7 +3,7 @@ package mage.cards.q; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.DiscardedByOpponentTriggerAbility; +import mage.abilities.common.DiscardedByOpponentTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.keyword.ShroudAbility; import mage.abilities.keyword.SplitSecondAbility; @@ -31,7 +31,7 @@ public final class Quagnoth extends CardImpl { this.addAbility(ShroudAbility.getInstance()); // When a spell or ability an opponent controls causes you to discard Quagnoth, return it to your hand. - this.addAbility(new DiscardedByOpponentTriggerAbility(new ReturnToHandSourceEffect())); + this.addAbility(new DiscardedByOpponentTriggeredAbility(new ReturnToHandSourceEffect())); } public Quagnoth(final Quagnoth card) { diff --git a/Mage.Sets/src/mage/cards/q/Quash.java b/Mage.Sets/src/mage/cards/q/Quash.java index 75cc2788706..74ddf3633eb 100644 --- a/Mage.Sets/src/mage/cards/q/Quash.java +++ b/Mage.Sets/src/mage/cards/q/Quash.java @@ -21,7 +21,7 @@ public final class Quash extends CardImpl { // Counter target instant or sorcery spell. // Search its controller's graveyard, hand, and library for all cards with the same name as that spell and exile them. Then that player shuffles their library. - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.getSpellAbility().addEffect(new CounterTargetAndSearchGraveyardHandLibraryEffect()); } diff --git a/Mage.Sets/src/mage/cards/q/QueenMarchesa.java b/Mage.Sets/src/mage/cards/q/QueenMarchesa.java index 7c02c754d5f..6b38efbc83f 100644 --- a/Mage.Sets/src/mage/cards/q/QueenMarchesa.java +++ b/Mage.Sets/src/mage/cards/q/QueenMarchesa.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.DeathtouchAbility; @@ -44,7 +44,7 @@ public final class QueenMarchesa extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect(), false)); // At the beginning of your upkeep, if an opponent is the monarch, create a 1/1 black Assassin creature token with deathtouch and haste. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new QueenMarchesaAssassinToken()), TargetController.YOU, false), OpponentIsMonarchCondition.instance, "At the beginning of your upkeep, if an opponent is the monarch, create a 1/1 black Assassin creature token with deathtouch and haste.")); diff --git a/Mage.Sets/src/mage/cards/q/QuenchableFire.java b/Mage.Sets/src/mage/cards/q/QuenchableFire.java index f28a75909fe..53b8aa25412 100644 --- a/Mage.Sets/src/mage/cards/q/QuenchableFire.java +++ b/Mage.Sets/src/mage/cards/q/QuenchableFire.java @@ -11,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.PhaseStep; import mage.target.TargetPlayer; +import mage.target.common.TargetPlayerOrPlaneswalker; /** * @@ -22,12 +23,12 @@ public final class QuenchableFire extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}"); // Quenchable Fire deals 3 damage to target player. - this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); this.getSpellAbility().addEffect(new DamageTargetEffect(3)); - // It deals an additional 3 damage to that player at the beginning of your next upkeep step unless he or she pays {U} before that step. + // It deals an additional 3 damage to that player or planeswalker at the beginning of your next upkeep step unless that player or that planeswalker’s controller pays {U} before that step. this.getSpellAbility().addEffect(new UnlessPaysDelayedEffect(new ManaCostsImpl("{U}"), - new DamageTargetEffect(3, true, "that player"), PhaseStep.UPKEEP, false, - "It deals an additional 3 damage to that player at the beginning of your next upkeep step unless he or she pays {U} before that step.")); + new DamageTargetEffect(3, true, "that player or that planeswalker's controller"), PhaseStep.UPKEEP, false, + "It deals an additional 3 damage to that player or planeswalker at the beginning of your next upkeep step unless that player or that planeswalker’s controller pays {U} before that step.")); } public QuenchableFire(final QuenchableFire card) { diff --git a/Mage.Sets/src/mage/cards/q/QuestForPureFlame.java b/Mage.Sets/src/mage/cards/q/QuestForPureFlame.java index ab997678880..abd0c7e33f3 100644 --- a/Mage.Sets/src/mage/cards/q/QuestForPureFlame.java +++ b/Mage.Sets/src/mage/cards/q/QuestForPureFlame.java @@ -72,7 +72,7 @@ class QuestForPureFlameTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(getControllerId()).contains(event.getTargetId())) { - return getControllerId().equals(game.getControllerId(event.getSourceId())); + return isControlledBy(game.getControllerId(event.getSourceId())); } return false; } @@ -108,7 +108,7 @@ class QuestForPureFlameEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(game.getControllerId(event.getSourceId())); + return source.isControlledBy(game.getControllerId(event.getSourceId())); } @Override diff --git a/Mage.Sets/src/mage/cards/q/Quicken.java b/Mage.Sets/src/mage/cards/q/Quicken.java index 07ff6c72b9a..e34973989e3 100644 --- a/Mage.Sets/src/mage/cards/q/Quicken.java +++ b/Mage.Sets/src/mage/cards/q/Quicken.java @@ -86,7 +86,7 @@ class QuickenAsThoughEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { if (quickenWatcher.isQuickenSpellActive(affectedControllerId, source.getSourceId(), zoneChangeCounter)) { Card card = game.getCard(sourceId); - if (card != null && card.isSorcery() && source.getControllerId().equals(affectedControllerId)) { + if (card != null && card.isSorcery() && source.isControlledBy(affectedControllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java b/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java index c5e28fa0503..e925ecda970 100644 --- a/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java +++ b/Mage.Sets/src/mage/cards/q/QuicksilverGargantuan.java @@ -28,7 +28,7 @@ public final class QuicksilverGargantuan extends CardImpl { this.toughness = new MageInt(7); Ability ability = new EntersBattlefieldAbility(new CopyPermanentEffect(new QuicksilverGargantuanApplyToPermanent()), - "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's still 7/7"); + "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's 7/7"); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RadiantDestiny.java b/Mage.Sets/src/mage/cards/r/RadiantDestiny.java index f8e3a2473eb..f008dc39c4c 100644 --- a/Mage.Sets/src/mage/cards/r/RadiantDestiny.java +++ b/Mage.Sets/src/mage/cards/r/RadiantDestiny.java @@ -45,12 +45,12 @@ public final class RadiantDestiny extends CardImpl { // As Radiant Destiny enters the battlefield, choose a creature type. this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); - // Creatures you control of the chosen type get +1/+1. As long as you have the city’s blessing, they also have vigilance. + // Creatures you control of the chosen type get +1/+1. As long as you have the city's blessing, they also have vigilance. Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllOfChosenSubtypeEffect(1, 1, Duration.WhileOnBattlefield, filter, true)); ContinuousEffect effect = new ConditionalContinuousEffect( new GainAbilityAllOfChosenSubtypeEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, FILTER_PERMANENT_CREATURES_CONTROLLED), CitysBlessingCondition.instance, - "As long as you have the city’s blessing, they also have vigilance."); + "As long as you have the city's blessing, they also have vigilance."); ability.addEffect(effect); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RafiqOfTheMany.java b/Mage.Sets/src/mage/cards/r/RafiqOfTheMany.java index c8384d9c944..904e443aa4a 100644 --- a/Mage.Sets/src/mage/cards/r/RafiqOfTheMany.java +++ b/Mage.Sets/src/mage/cards/r/RafiqOfTheMany.java @@ -77,7 +77,7 @@ class RafiqOfTheManyAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId) ) { + if (game.isActivePlayer(this.controllerId) ) { if (game.getCombat().attacksAlone()) { for (Effect effect: this.getEffects()) { effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); diff --git a/Mage.Sets/src/mage/cards/r/RagingRiver.java b/Mage.Sets/src/mage/cards/r/RagingRiver.java index 6f065dd5131..1d5eba39f43 100644 --- a/Mage.Sets/src/mage/cards/r/RagingRiver.java +++ b/Mage.Sets/src/mage/cards/r/RagingRiver.java @@ -128,11 +128,11 @@ class RagingRiverEffect extends OneShotEffect { } else { List leftLog = left.stream() .filter(permanent -> permanent.getControllerId() != null) - .filter(permanent -> permanent.getControllerId().equals(defender.getId())) + .filter(permanent -> permanent.isControlledBy(defender.getId())) .collect(Collectors.toList()); List rightLog = right.stream() .filter(permanent -> permanent.getControllerId() != null) - .filter(permanent -> permanent.getControllerId().equals(defender.getId())) + .filter(permanent -> permanent.isControlledBy(defender.getId())) .collect(Collectors.toList()); diff --git a/Mage.Sets/src/mage/cards/r/RaidBombardment.java b/Mage.Sets/src/mage/cards/r/RaidBombardment.java index 74a95d90a3a..25f1a4d7a1d 100644 --- a/Mage.Sets/src/mage/cards/r/RaidBombardment.java +++ b/Mage.Sets/src/mage/cards/r/RaidBombardment.java @@ -59,7 +59,7 @@ class RaidBombardmentTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.isActivePlayer(this.controllerId)) { Permanent attacker = game.getPermanent(event.getSourceId()); if (attacker != null) { if (attacker.getPower().getValue() <= 2) { diff --git a/Mage.Sets/src/mage/cards/r/RaidersSpoils.java b/Mage.Sets/src/mage/cards/r/RaidersSpoils.java index dc20f31e86d..ed92d70e999 100644 --- a/Mage.Sets/src/mage/cards/r/RaidersSpoils.java +++ b/Mage.Sets/src/mage/cards/r/RaidersSpoils.java @@ -70,7 +70,7 @@ class RaidersSpoilsTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent permanent = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && permanent != null && permanent.hasSubtype(SubType.WARRIOR, game) && permanent.getControllerId().equals(controllerId)) { + if (damageEvent.isCombatDamage() && permanent != null && permanent.hasSubtype(SubType.WARRIOR, game) && permanent.isControlledBy(controllerId)) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/r/RaidersWake.java b/Mage.Sets/src/mage/cards/r/RaidersWake.java index d183ddeb648..3fafbd93f9f 100644 --- a/Mage.Sets/src/mage/cards/r/RaidersWake.java +++ b/Mage.Sets/src/mage/cards/r/RaidersWake.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.DiscardsACardOpponentTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; @@ -30,7 +30,7 @@ public final class RaidersWake extends CardImpl { this.addAbility(new DiscardsACardOpponentTriggeredAbility(new LoseLifeTargetEffect(2), false, SetTargetPointer.PLAYER)); // Raid — At the beginning of your end step, if you attacked with a creature this turn, target opponent discards a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new DiscardTargetEffect(1), TargetController.YOU, false), RaidCondition.instance, "Raid — At the beginning of your end step, if you attacked with a creature this turn, target opponent discards a card."); ability.addTarget(new TargetOpponent()); diff --git a/Mage.Sets/src/mage/cards/r/RainOfGore.java b/Mage.Sets/src/mage/cards/r/RainOfGore.java index e14e6fbfb37..9deeecbaf74 100644 --- a/Mage.Sets/src/mage/cards/r/RainOfGore.java +++ b/Mage.Sets/src/mage/cards/r/RainOfGore.java @@ -77,7 +77,7 @@ class RainOfGoreEffect extends ReplacementEffectImpl { if (!game.getStack().isEmpty()) { StackObject stackObject = game.getStack().getFirst(); if (stackObject != null) { - return stackObject.getControllerId().equals(event.getPlayerId()); + return stackObject.isControlledBy(event.getPlayerId()); } } return false; diff --git a/Mage.Sets/src/mage/cards/r/RakaSanctuary.java b/Mage.Sets/src/mage/cards/r/RakaSanctuary.java index 45a2ff888fd..279ef34daef 100644 --- a/Mage.Sets/src/mage/cards/r/RakaSanctuary.java +++ b/Mage.Sets/src/mage/cards/r/RakaSanctuary.java @@ -4,7 +4,7 @@ package mage.cards.r; import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryTriggeredAbility; +import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,7 +21,7 @@ public final class RakaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // At the beginning of your upkeep, if you control a white or blue permanent, Raka Sanctuary deals 1 damage to target creature. If you control a white permanent and a blue permanent, Raka Sanctuary deals 3 damage to that creature instead. - Ability ability = new SanctuaryTriggeredAbility( + Ability ability = new SanctuaryInterveningIfTriggeredAbility( new DamageTargetEffect(1), new DamageTargetEffect(3), ObjectColor.WHITE, ObjectColor.BLUE, "At the beginning of your upkeep, if you control a white or blue permanent, Raka Sanctuary deals 1 damage to target creature. " + "If you control a white permanent and a blue permanent, Raka Sanctuary deals 3 damage to that creature instead." diff --git a/Mage.Sets/src/mage/cards/r/RakdosAugermage.java b/Mage.Sets/src/mage/cards/r/RakdosAugermage.java new file mode 100644 index 00000000000..422d4c32918 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RakdosAugermage.java @@ -0,0 +1,94 @@ +package mage.cards.r; + +import mage.MageInt; +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.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +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); + this.toughness = new MageInt(2); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // {tap}: Reveal your hand and discard a card of target opponent’s choice. Then that player reveals their hand and discards a card of your choice. Activate this ability only any time you could cast a sorcery. + ActivateAsSorceryActivatedAbility ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new RakdosAugermageEffect(), new TapSourceCost()); + ability.addEffect(new DiscardCardYouChooseTargetEffect()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public RakdosAugermage(final RakdosAugermage card) { + super(card); + } + + @Override + public RakdosAugermage copy() { + return new RakdosAugermage(this); + } +} + +class RakdosAugermageEffect extends OneShotEffect { + + public RakdosAugermageEffect() { + super(Outcome.Discard); + staticText = "reveal your hand and discard a card of target opponent’s choice"; + } + + public RakdosAugermageEffect(final RakdosAugermageEffect effect) { + super(effect); + } + + @Override + 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); + 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 false; + } + + @Override + public RakdosAugermageEffect copy() { + return new RakdosAugermageEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java b/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java index 18074ed07df..31d5b44e3d4 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java +++ b/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java @@ -120,7 +120,7 @@ class RakdosLordOfRiotsCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { return spell.isCreature(); diff --git a/Mage.Sets/src/mage/cards/r/RakdosRiteknife.java b/Mage.Sets/src/mage/cards/r/RakdosRiteknife.java new file mode 100644 index 00000000000..5af3ca5d8db --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RakdosRiteknife.java @@ -0,0 +1,103 @@ +package mage.cards.r; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeEffect; +import mage.abilities.effects.common.SacrificeOpponentsEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledCreaturePermanent; + +import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; + +/** + * + * @author noahg + */ +public final class RakdosRiteknife extends CardImpl { + + public RakdosRiteknife(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature gets +1/+0 for each blood counter on Rakdos Riteknife and has "{T}, Sacrifice a creature: Put a blood counter on Rakdos Riteknife." + SimpleStaticAbility staticAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new CountersSourceCount(CounterType.BLOOD), new StaticValue(0)).setText("Equipped creature gets +1/+0 for each blood counter on {this}")); + SimpleActivatedAbility grantedAbility = new SimpleActivatedAbility(new RakdosRiteKnifeEffect(this.getId()), new TapSourceCost()); + grantedAbility.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); + staticAbility.addEffect(new GainAbilityAttachedEffect(grantedAbility, AttachmentType.EQUIPMENT).setText("and has \"{T}, Sacrifice a creature: Put a blood counter on {this}.\"")); + this.addAbility(staticAbility); + + // {B}{R}, Sacrifice Rakdos Riteknife: Target player sacrifices a permanent for each blood counter on Rakdos Riteknife. + SimpleActivatedAbility activatedAbility = new SimpleActivatedAbility( + new SacrificeEffect(StaticFilters.FILTER_PERMANENT, new CountersSourceCount(CounterType.BLOOD), "Target player") + .setText("target player sacrifices a permanent for each blood counter on {this}"), new ManaCostsImpl("{R}{B}")); + activatedAbility.addCost(new SacrificeSourceCost()); + activatedAbility.addTarget(new TargetPlayer()); + this.addAbility(activatedAbility); + + // Equip {2} + this.addAbility(new EquipAbility(2)); + } + + public RakdosRiteknife(final RakdosRiteknife card) { + super(card); + } + + @Override + public RakdosRiteknife copy() { + return new RakdosRiteknife(this); + } +} + +class RakdosRiteKnifeEffect extends OneShotEffect { + + private UUID effectGivingEquipmentId; + + public RakdosRiteKnifeEffect(UUID effectGivingEquipmentId) { + super(Outcome.Benefit); + this.effectGivingEquipmentId = effectGivingEquipmentId; + staticText = "Put a blood counter on Rakdos Riteknife"; + } + + public RakdosRiteKnifeEffect(final RakdosRiteKnifeEffect effect) { + super(effect); + this.effectGivingEquipmentId = effect.effectGivingEquipmentId; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent equipment = game.getPermanent(this.effectGivingEquipmentId); + if (equipment != null) { + equipment.addCounters(CounterType.BLOOD.createInstance(), source, game); + } + return true; + } + + @Override + public RakdosRiteKnifeEffect copy() { + return new RakdosRiteKnifeEffect(this); + } + + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RakdossReturn.java b/Mage.Sets/src/mage/cards/r/RakdossReturn.java index 394de5f8e48..5d9276caf36 100644 --- a/Mage.Sets/src/mage/cards/r/RakdossReturn.java +++ b/Mage.Sets/src/mage/cards/r/RakdossReturn.java @@ -15,6 +15,7 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponent; +import mage.target.common.TargetOpponentOrPlaneswalker; import mage.target.targetpointer.FixedTarget; /** @@ -26,10 +27,10 @@ public final class RakdossReturn extends CardImpl { public RakdossReturn(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{R}"); - // Rakdos's Return deals X damage to target opponent. That player discards X cards. + // 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 RakdossReturnEffect()); - this.getSpellAbility().addTarget(new TargetOpponent()); + this.getSpellAbility().addTarget(new TargetOpponentOrPlaneswalker()); } public RakdossReturn(final RakdossReturn card) { @@ -46,7 +47,7 @@ class RakdossReturnEffect extends OneShotEffect { RakdossReturnEffect() { super(Outcome.Benefit); - this.staticText = "That player or that planeswalker’s controller discards X cards."; + this.staticText = "That player or that planeswalker's controller discards X cards."; } RakdossReturnEffect(final RakdossReturnEffect effect) { diff --git a/Mage.Sets/src/mage/cards/r/RakishHeir.java b/Mage.Sets/src/mage/cards/r/RakishHeir.java index 4234f39dc99..37de821632b 100644 --- a/Mage.Sets/src/mage/cards/r/RakishHeir.java +++ b/Mage.Sets/src/mage/cards/r/RakishHeir.java @@ -71,7 +71,7 @@ class RakishHeirTriggeredAbility extends TriggeredAbilityImpl { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent permanent = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage() && permanent != null - && permanent.hasSubtype(SubType.VAMPIRE, game) && permanent.getControllerId().equals(controllerId)) { + && permanent.hasSubtype(SubType.VAMPIRE, game) && permanent.isControlledBy(controllerId)) { this.getEffects().clear(); AddCountersTargetEffect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setTargetPointer(new FixedTarget(permanent.getId())); diff --git a/Mage.Sets/src/mage/cards/r/RakshasaVizier.java b/Mage.Sets/src/mage/cards/r/RakshasaVizier.java index 6e306889927..955fc762581 100644 --- a/Mage.Sets/src/mage/cards/r/RakshasaVizier.java +++ b/Mage.Sets/src/mage/cards/r/RakshasaVizier.java @@ -67,7 +67,7 @@ class RakshasaVizierTriggeredAbility extends TriggeredAbilityImpl { if (zEvent.getFromZone() == Zone.GRAVEYARD && zEvent.getToZone() == Zone.EXILED) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(getControllerId())) { + if (card != null && card.isOwnedBy(getControllerId())) { return true; } diff --git a/Mage.Sets/src/mage/cards/r/RallyTheTroops.java b/Mage.Sets/src/mage/cards/r/RallyTheTroops.java index 0d636ff1c4a..34c8f2beaf4 100644 --- a/Mage.Sets/src/mage/cards/r/RallyTheTroops.java +++ b/Mage.Sets/src/mage/cards/r/RallyTheTroops.java @@ -26,7 +26,7 @@ public final class RallyTheTroops extends CardImpl { // Cast Rally the Troops only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java b/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java index 5b055cafe61..8820712bdb8 100644 --- a/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java +++ b/Mage.Sets/src/mage/cards/r/RampagingWerewolf.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class RampagingWerewolf extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Rampaging Werewolf. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/r/RangeTrooper.java b/Mage.Sets/src/mage/cards/r/RangeTrooper.java new file mode 100644 index 00000000000..6dfb18ef5e5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RangeTrooper.java @@ -0,0 +1,92 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author NinthWorld + */ +public final class RangeTrooper extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Trooper creatures you control"); + + static { + filter.add(new SubtypePredicate(SubType.TROOPER)); + } + + public RangeTrooper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Trooper creatures you control have "When this creature enters that battlefield, you may exile target creature. Return that creature to the battlefield at the beginning of the next end step." + Ability ability = new EntersBattlefieldTriggeredAbility(new RangeTrooperEffect(), true, true); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new GainAbilityControlledEffect(ability, Duration.WhileOnBattlefield, filter, false))); + } + + public RangeTrooper(final RangeTrooper card) { + super(card); + } + + @Override + public RangeTrooper copy() { + return new RangeTrooper(this); + } +} + +class RangeTrooperEffect extends OneShotEffect { + + public RangeTrooperEffect() { + super(Outcome.Detriment); + staticText = "When this creature enters the battlefield, you may exile target creature. Return that creature to the battlefield at the beginning of the next end step"; + } + + public RangeTrooperEffect(final RangeTrooperEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (permanent != null && sourceObject != null) { + if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game)) { + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); + return true; + } + } + return false; + } + + @Override + public RangeTrooperEffect copy() { + return new RangeTrooperEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java index c22f6e0af6c..36a1b7cc433 100644 --- a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java +++ b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java @@ -13,7 +13,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.PreventDamageToSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.SimpleManaAbility; @@ -54,7 +54,7 @@ public final class RasputinDreamweaver extends CardImpl { // At the beginning of your upkeep, if Rasputin started the turn untapped, put a dream counter on it. this.addAbility( - new ConditionalTriggeredAbility( + new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.DREAM.createInstance()), TargetController.YOU, false), RasputinDreamweaverStartedUntappedCondition.instance, "At the beginning of your upkeep, if {this} started the turn untapped, put a dream counter on it."), diff --git a/Mage.Sets/src/mage/cards/r/Rathtar.java b/Mage.Sets/src/mage/cards/r/Rathtar.java new file mode 100644 index 00000000000..379cb23c4f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Rathtar.java @@ -0,0 +1,49 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.effects.common.combat.BlocksIfAbleTargetEffect; +import mage.abilities.keyword.MonstrosityAbility; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Rathtar extends CardImpl { + + public Rathtar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // {5}{G}{G}: Monstrosity 2. + this.addAbility(new MonstrosityAbility("{5}{G}{G}", 2)); + + // When Rathtar becomes monstrous, any number of target creatures must block it this turn if able. + Ability ability = new BecomesMonstrousSourceTriggeredAbility( + new BlocksIfAbleTargetEffect(Duration.EndOfTurn).setText("any number of target creatures must block it this turn if able")); + ability.addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); + this.addAbility(ability); + } + + public Rathtar(final Rathtar card) { + super(card); + } + + @Override + public Rathtar copy() { + return new Rathtar(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java index 505f07ec9bd..c64031eef9a 100644 --- a/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java +++ b/Mage.Sets/src/mage/cards/r/RavagerOfTheFells.java @@ -11,7 +11,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -59,7 +59,7 @@ public final class RavagerOfTheFells extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ravager of the Fells. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE @@ -114,7 +114,7 @@ class RavagerOfTheFellsAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever this creature transforms into {this}, " + "it deals 2 damage to target opponent or planeswalker " - + "and 2 damage to up to one target creature that player or that planeswalker’s controller controls."; + + "and 2 damage to up to one target creature that player or that planeswalker's controller controls."; } } @@ -164,7 +164,7 @@ class RavagerOfTheFellsTarget extends TargetPermanent { } UUID firstTarget = player.getId(); Permanent permanent = game.getPermanent(id); - if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + if (firstTarget != null && permanent != null && permanent.isControlledBy(firstTarget)) { return super.canTarget(id, source, game); } return false; @@ -191,7 +191,7 @@ class RavagerOfTheFellsTarget extends TargetPermanent { if (player != null) { for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.getControllerId().equals(player.getId())) { + if (permanent != null && permanent.isControlledBy(player.getId())) { possibleTargets.add(targetId); } } diff --git a/Mage.Sets/src/mage/cards/r/RavenousHarpy.java b/Mage.Sets/src/mage/cards/r/RavenousHarpy.java new file mode 100644 index 00000000000..1e0184f7cd3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RavenousHarpy.java @@ -0,0 +1,56 @@ +package mage.cards.r; + +import java.util.UUID; +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.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class RavenousHarpy extends CardImpl { + + public RavenousHarpy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.HARPY); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {1}, Sacrifice another creature: Put a +1/+1 counter on Ravenous Harpy. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + new GenericManaCost(1) + ); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent( + StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE + ))); + this.addAbility(ability); + } + + public RavenousHarpy(final RavenousHarpy card) { + super(card); + } + + @Override + public RavenousHarpy copy() { + return new RavenousHarpy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RavenousSlime.java b/Mage.Sets/src/mage/cards/r/RavenousSlime.java new file mode 100644 index 00000000000..f68af5571d9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RavenousSlime.java @@ -0,0 +1,141 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleEvasionAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +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.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class RavenousSlime 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 RavenousSlime(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.OOZE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Ravenous Slime can't be blocked by creatures with power 2 or less. + this.addAbility(new SimpleEvasionAbility( + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ) + )); + + // If a creature an opponent controls would die, instead exile it and put a number of +1/+1 counters equal to that creature's power on Ravenous Slime. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new RavenousSlimeEffect() + )); + } + + public RavenousSlime(final RavenousSlime card) { + super(card); + } + + @Override + public RavenousSlime copy() { + return new RavenousSlime(this); + } +} + +class RavenousSlimeEffect extends ReplacementEffectImpl { + + public RavenousSlimeEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If a creature an opponent controls would die, " + + "instead exile it and put a number of +1/+1 counters " + + "equal to that creature's power on {this}"; + } + + public RavenousSlimeEffect(final RavenousSlimeEffect effect) { + super(effect); + } + + @Override + public RavenousSlimeEffect copy() { + return new RavenousSlimeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourceCreature = game.getPermanent(source.getSourceId()); + if (controller == null || sourceCreature == null) { + return false; + } + if (((ZoneChangeEvent) event).getFromZone() != Zone.BATTLEFIELD) { + return false; + } + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (permanent == null) { + return false; + } + int power = permanent.getPower().getValue(); + controller.moveCards(permanent, Zone.EXILED, source, game); + return new AddCountersSourceEffect( + CounterType.P1P1.createInstance(power) + ).apply(game, source); + } + + @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; + if (zEvent.getToZone() != Zone.GRAVEYARD) { + return false; + } + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (permanent == null + || !game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) { + return false; + } + if (zEvent.getTarget() != null) { // if it comes from permanent, check if it was a creature on the battlefield + if (zEvent.getTarget().isCreature()) { + return true; + } + } else if (permanent.isCreature()) { + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RayneAcademyChancellor.java b/Mage.Sets/src/mage/cards/r/RayneAcademyChancellor.java index 341f7f277d1..b20a2e3d949 100644 --- a/Mage.Sets/src/mage/cards/r/RayneAcademyChancellor.java +++ b/Mage.Sets/src/mage/cards/r/RayneAcademyChancellor.java @@ -77,7 +77,7 @@ class RayneAcademyChancellorTriggeredAbility extends TriggeredAbilityImpl { return true; } Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent != null && this.getControllerId().equals(permanent.getControllerId())) { + if (permanent != null && this.isControlledBy(permanent.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/r/RazorfieldRhino.java b/Mage.Sets/src/mage/cards/r/RazorfieldRhino.java index bf23b4fca7a..28b09384e2a 100644 --- a/Mage.Sets/src/mage/cards/r/RazorfieldRhino.java +++ b/Mage.Sets/src/mage/cards/r/RazorfieldRhino.java @@ -28,7 +28,7 @@ public final class RazorfieldRhino extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); ContinuousEffect effect1 = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, "Metalcraft - Razorfield Rhino gets +2/+2 as long as you control three or more artifacts"))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, "Metalcraft — Razorfield Rhino gets +2/+2 as long as you control three or more artifacts"))); } public RazorfieldRhino (final RazorfieldRhino card) { diff --git a/Mage.Sets/src/mage/cards/r/RealityScramble.java b/Mage.Sets/src/mage/cards/r/RealityScramble.java new file mode 100644 index 00000000000..f3f8096971e --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RealityScramble.java @@ -0,0 +1,111 @@ +package mage.cards.r; + +import java.util.EnumSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.RetraceAbility; +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.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.other.OwnerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class RealityScramble extends CardImpl { + + private static final FilterPermanent filter + = new FilterPermanent("permanent you own"); + + static { + filter.add(new OwnerPredicate(TargetController.YOU)); + } + + public RealityScramble(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{R}"); + + // Put target permanent you own on the bottom of your library. Reveal cards from the top of your library until you reveal a card that shares a card type with that permanent. Put that card onto the battlefield and the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new RealityScrambleEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + + // Retrace + this.addAbility(new RetraceAbility(this)); + } + + public RealityScramble(final RealityScramble card) { + super(card); + } + + @Override + public RealityScramble copy() { + return new RealityScramble(this); + } +} + +class RealityScrambleEffect extends OneShotEffect { + + public RealityScrambleEffect() { + super(Outcome.Benefit); + this.staticText = "Put target permanent you own " + + "on the bottom of your library. Reveal cards from " + + "the top of your library until you reveal a card " + + "that shares a card type with that permanent. " + + "Put that card onto the battlefield and the rest " + + "on the bottom of your library in a random order."; + } + + public RealityScrambleEffect(final RealityScrambleEffect effect) { + super(effect); + } + + @Override + public RealityScrambleEffect copy() { + return new RealityScrambleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (permanent == null || controller == null) { + return false; + } + Set types = EnumSet.noneOf(CardType.class); + types.addAll(permanent.getCardType()); + controller.putCardsOnBottomOfLibrary( + new CardsImpl(permanent), game, source, false + ); + Cards toReveal = new CardsImpl(); + Card cardToPlay = null; + for (Card card : controller.getLibrary().getCards(game)) { + toReveal.add(card); + for (CardType type : types) { + if (card.getCardType().contains(type)) { + cardToPlay = card; + break; + } + } + } + controller.revealCards(source, toReveal, game); + if (cardToPlay != null) { + controller.moveCards(cardToPlay, Zone.BATTLEFIELD, source, game); + toReveal.remove(cardToPlay); + } + controller.putCardsOnBottomOfLibrary(toReveal, game, source, false); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RealitySmasher.java b/Mage.Sets/src/mage/cards/r/RealitySmasher.java index 8d559180e5e..706af59e41f 100644 --- a/Mage.Sets/src/mage/cards/r/RealitySmasher.java +++ b/Mage.Sets/src/mage/cards/r/RealitySmasher.java @@ -73,7 +73,7 @@ class RealitySmasherTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (spell == null || !(spell instanceof Spell)) { + if (!(spell instanceof Spell)) { return false; } else { if (event.getTargetId().equals(this.getSourceId()) diff --git a/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java b/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java index c9f2aa56786..c9a9bf3f10d 100644 --- a/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java +++ b/Mage.Sets/src/mage/cards/r/ReaperFromTheAbyss.java @@ -87,6 +87,6 @@ class ReaperFromTheAbyssAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Morbid - At the beginning of each end step, if a creature died this turn, destroy target non-demon creature."; + return "Morbid — At the beginning of each end step, if a creature died this turn, destroy target non-demon creature."; } } diff --git a/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java b/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java index c822ffb01d3..0e83f3b7fcd 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java +++ b/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SurgedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; @@ -47,7 +47,7 @@ public final class RecklessBushwhacker extends CardImpl { // When Reckless Bushwhacker enters the battlefield, if its surge cost was paid, other creatures you control get +1/+0 and gain haste until end of turn. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostControlledEffect(1, 0, Duration.EndOfTurn, true), false); ability.addEffect(new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.EndOfTurn, FILTER, true)); - this.addAbility(new ConditionalTriggeredAbility(ability, SurgedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, SurgedCondition.instance, "When {this} enters the battlefield, if its surge cost was paid, other creatures you control get +1/+0 and gain haste until end of turn.")); } diff --git a/Mage.Sets/src/mage/cards/r/RecklessPangolin.java b/Mage.Sets/src/mage/cards/r/RecklessPangolin.java new file mode 100644 index 00000000000..0db27835e91 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RecklessPangolin.java @@ -0,0 +1,38 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; + +/** + * + * @author TheElk801 + */ +public final class RecklessPangolin extends CardImpl { + + public RecklessPangolin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.PANGOLIN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Reckless Pangolin attacks, it gets +1/+1 until end of turn. + this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false)); + } + + public RecklessPangolin(final RecklessPangolin card) { + super(card); + } + + @Override + public RecklessPangolin copy() { + return new RecklessPangolin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RecklessRage.java b/Mage.Sets/src/mage/cards/r/RecklessRage.java index 1de5107091c..b39f5a9aed0 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessRage.java +++ b/Mage.Sets/src/mage/cards/r/RecklessRage.java @@ -20,8 +20,8 @@ public final class RecklessRage extends CardImpl { public RecklessRage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); - // Reckless Rage deals 4 damage to target creature you don’t control and 2 damage to target creature you control. - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don’t control"); + // Reckless Rage deals 4 damage to target creature you don't control and 2 damage to target creature you control. + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control"); filter.add(new ControllerPredicate(TargetController.NOT_YOU)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addEffect(new DamageTargetEffect(4).setUseOnlyTargetPointer(true)); diff --git a/Mage.Sets/src/mage/cards/r/RecklessWaif.java b/Mage.Sets/src/mage/cards/r/RecklessWaif.java index e471eebc414..04e5cca06c5 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessWaif.java +++ b/Mage.Sets/src/mage/cards/r/RecklessWaif.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class RecklessWaif extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Reckless Waif. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public RecklessWaif(final RecklessWaif card) { diff --git a/Mage.Sets/src/mage/cards/r/ReclusiveWight.java b/Mage.Sets/src/mage/cards/r/ReclusiveWight.java index 82bf120cbe7..01995437b14 100644 --- a/Mage.Sets/src/mage/cards/r/ReclusiveWight.java +++ b/Mage.Sets/src/mage/cards/r/ReclusiveWight.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class ReclusiveWight extends CardImpl { this.toughness = new MageInt(4); // At the beginning of your upkeep, if you control another nonland permanent, sacrifice Reclusive Wight. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect(), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filter), "At the beginning of your upkeep, if you control another nonland permanent, sacrifice {this}." diff --git a/Mage.Sets/src/mage/cards/r/RecurringNightmare.java b/Mage.Sets/src/mage/cards/r/RecurringNightmare.java index f7cbaa78ac6..2c6b3a90b70 100644 --- a/Mage.Sets/src/mage/cards/r/RecurringNightmare.java +++ b/Mage.Sets/src/mage/cards/r/RecurringNightmare.java @@ -1,6 +1,6 @@ - package mage.cards.r; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.costs.common.ReturnToHandFromBattlefieldSourceCost; @@ -10,28 +10,26 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreatureCard; +import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetControlledPermanent; -import java.util.UUID; - /** * * @author jeffwadsworth */ public final class RecurringNightmare extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard("creature card"); - private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("creature"); - public RecurringNightmare(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); // Sacrifice a creature, Return Recurring Nightmare to its owner's hand: Return target creature card from your graveyard to the battlefield. Activate this ability only any time you could cast a sorcery. - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new SacrificeTargetCost(new TargetControlledPermanent(filter2))); - ability.addTarget(new TargetCardInYourGraveyard(filter)); + Ability ability = new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, + new ReturnFromGraveyardToBattlefieldTargetEffect(), + new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE)) + ); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE)); ability.addCost(new ReturnToHandFromBattlefieldSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RefractionTrap.java b/Mage.Sets/src/mage/cards/r/RefractionTrap.java index a058cff52dc..84d3bc36722 100644 --- a/Mage.Sets/src/mage/cards/r/RefractionTrap.java +++ b/Mage.Sets/src/mage/cards/r/RefractionTrap.java @@ -158,7 +158,7 @@ class RefractionTrapPreventDamageEffect extends PreventionEffectImpl { // check permanent first Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - if (permanent.getControllerId().equals(source.getControllerId())) { + if (permanent.isControlledBy(source.getControllerId())) { // it's your permanent return true; } diff --git a/Mage.Sets/src/mage/cards/r/RefreshingRain.java b/Mage.Sets/src/mage/cards/r/RefreshingRain.java index 57fb9afe340..038c187b5af 100644 --- a/Mage.Sets/src/mage/cards/r/RefreshingRain.java +++ b/Mage.Sets/src/mage/cards/r/RefreshingRain.java @@ -33,7 +33,7 @@ public final class RefreshingRain extends CardImpl { public RefreshingRain(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{G}"); - // If an opponent controls a Swamp and you control a Forest, you may cast Refreshing Rain without paying its mana cost. + // If an opponent controls a Swamp and you control a Forest, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Swamp and you control a Forest", new OpponentControlsPermanentCondition(filterSwamp), new PermanentsOnTheBattlefieldCondition(filterForest)); diff --git a/Mage.Sets/src/mage/cards/r/RegalBehemoth.java b/Mage.Sets/src/mage/cards/r/RegalBehemoth.java index 2ef608b4954..07e8352ad17 100644 --- a/Mage.Sets/src/mage/cards/r/RegalBehemoth.java +++ b/Mage.Sets/src/mage/cards/r/RegalBehemoth.java @@ -80,7 +80,7 @@ class RegalBehemothTriggeredManaAbility extends TriggeredManaAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getControllerId().equals(game.getMonarchId())) { + if (isControlledBy(game.getMonarchId())) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); if (permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) { ManaEvent mEvent = (ManaEvent) event; diff --git a/Mage.Sets/src/mage/cards/r/RegalBloodlord.java b/Mage.Sets/src/mage/cards/r/RegalBloodlord.java new file mode 100644 index 00000000000..5f12d0ffc6b --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RegalBloodlord.java @@ -0,0 +1,57 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.common.YouGainedLifeCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +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.TargetController; +import mage.game.permanent.token.BatToken; +import mage.watchers.common.PlayerGainedLifeWatcher; + +/** + * + * @author TheElk801 + */ +public final class RegalBloodlord extends CardImpl { + + public RegalBloodlord(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of each end step, if you gained life this turn, create a 1/1 black Bat creature token with flying. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfEndStepTriggeredAbility( + new CreateTokenEffect(new BatToken()), + TargetController.ANY, false + ), + new YouGainedLifeCondition(ComparisonType.MORE_THAN, 0), + "At the beginning of each end step, " + + "if you gained life this turn, " + + "create a 1/1 black Bat creature token with flying." + ), new PlayerGainedLifeWatcher()); + } + + public RegalBloodlord(final RegalBloodlord card) { + super(card); + } + + @Override + public RegalBloodlord copy() { + return new RegalBloodlord(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java b/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java index 591bd73cbef..12dd708519e 100644 --- a/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java +++ b/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.constants.SubType; import mage.constants.SuperType; @@ -43,7 +43,7 @@ public final class RegnaTheRedeemer extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of each end step, if your team gained life this turn, create two 1/1 white Warrior creature tokens. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility( new CreateTokenEffect(new WarriorToken(), 2), TargetController.ANY, diff --git a/Mage.Sets/src/mage/cards/r/Reiterate.java b/Mage.Sets/src/mage/cards/r/Reiterate.java index 7f32c919dcd..c6ea6417f4b 100644 --- a/Mage.Sets/src/mage/cards/r/Reiterate.java +++ b/Mage.Sets/src/mage/cards/r/Reiterate.java @@ -23,7 +23,7 @@ public final class Reiterate extends CardImpl { this.addAbility(new BuybackAbility("{3}")); // Copy target instant or sorcery spell. You may choose new targets for the copy. - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.getSpellAbility().addEffect(new CopyTargetSpellEffect()); } diff --git a/Mage.Sets/src/mage/cards/r/ReiverDemon.java b/Mage.Sets/src/mage/cards/r/ReiverDemon.java index 3f10b6aeede..fa048d0f34e 100644 --- a/Mage.Sets/src/mage/cards/r/ReiverDemon.java +++ b/Mage.Sets/src/mage/cards/r/ReiverDemon.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class ReiverDemon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Reiver Demon enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter, true), false), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated."), diff --git a/Mage.Sets/src/mage/cards/r/RekindledFlame.java b/Mage.Sets/src/mage/cards/r/RekindledFlame.java index 4a0c0d8bf7b..b294ef6821a 100644 --- a/Mage.Sets/src/mage/cards/r/RekindledFlame.java +++ b/Mage.Sets/src/mage/cards/r/RekindledFlame.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class RekindledFlame extends CardImpl { this.getSpellAbility().addTarget(new TargetAnyTarget()); // At the beginning of your upkeep, if an opponent has no cards in hand, you may return Rekindled Flame from your graveyard to your hand. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), TargetController.YOU, true ), diff --git a/Mage.Sets/src/mage/cards/r/RelicBind.java b/Mage.Sets/src/mage/cards/r/RelicBind.java index 0aa55f1b2ef..3068f732e7c 100644 --- a/Mage.Sets/src/mage/cards/r/RelicBind.java +++ b/Mage.Sets/src/mage/cards/r/RelicBind.java @@ -19,6 +19,7 @@ import mage.filter.common.FilterArtifactPermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.TargetPermanent; import mage.target.TargetPlayer; +import mage.target.common.TargetPlayerOrPlaneswalker; /** * @@ -44,9 +45,9 @@ public final class RelicBind extends CardImpl { this.addAbility(ability); // Whenever enchanted artifact becomes tapped, choose one - // — Relic Bind deals 1 damage to target player. + // — Relic Bind deals 1 damage to target player or planeswalker. Ability ability2 = new BecomesTappedAttachedTriggeredAbility(new DamageTargetEffect(1), "enchanted artifact"); - ability2.addTarget(new TargetPlayer()); + ability2.addTarget(new TargetPlayerOrPlaneswalker()); // — Target player gains 1 life. Mode mode = new Mode(); mode.getEffects().add(new GainLifeTargetEffect(1)); diff --git a/Mage.Sets/src/mage/cards/r/RemorsefulCleric.java b/Mage.Sets/src/mage/cards/r/RemorsefulCleric.java new file mode 100644 index 00000000000..225f6ef9802 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RemorsefulCleric.java @@ -0,0 +1,48 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.common.ExileGraveyardAllTargetPlayerEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author TheElk801 + */ +public final class RemorsefulCleric extends CardImpl { + + public RemorsefulCleric(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.SPIRIT); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Sacrifice Contrite Cleric: Exile all cards in target player's graveyard. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileGraveyardAllTargetPlayerEffect(), new SacrificeSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public RemorsefulCleric(final RemorsefulCleric card) { + super(card); + } + + @Override + public RemorsefulCleric copy() { + return new RemorsefulCleric(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/Remove.java b/Mage.Sets/src/mage/cards/r/Remove.java index 6d18d96f598..be84decdf2e 100644 --- a/Mage.Sets/src/mage/cards/r/Remove.java +++ b/Mage.Sets/src/mage/cards/r/Remove.java @@ -26,7 +26,7 @@ public final class Remove extends CardImpl { // Cast Remove only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RemoveEnchantments.java b/Mage.Sets/src/mage/cards/r/RemoveEnchantments.java index 9c6d6165cfa..6828490c7f7 100644 --- a/Mage.Sets/src/mage/cards/r/RemoveEnchantments.java +++ b/Mage.Sets/src/mage/cards/r/RemoveEnchantments.java @@ -86,7 +86,7 @@ class AttachedToOpponentControlledAttackingCreaturePredicate implements ObjectPl if (permanent != null) { if (permanent.isCreature()) { if (permanent.isAttacking()) { - if (!permanent.getControllerId().equals(input.getPlayerId()) && + if (!permanent.isControlledBy(input.getPlayerId()) && game.getPlayer(input.getPlayerId()).hasOpponent(permanent.getControllerId(), game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/r/RendingVolley.java b/Mage.Sets/src/mage/cards/r/RendingVolley.java index 5ade6362ed2..ad1f36d05b8 100644 --- a/Mage.Sets/src/mage/cards/r/RendingVolley.java +++ b/Mage.Sets/src/mage/cards/r/RendingVolley.java @@ -34,9 +34,9 @@ public final class RendingVolley extends CardImpl { public RendingVolley(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}"); - // Rending Volley can't be countered by spells or abilities. + // Rending Volley can't be countered. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK,effect); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java b/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java index f137b6278f6..a6c2585ab44 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeDoppelganger.java @@ -72,7 +72,7 @@ class RenegadeDoppelgangerTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (!event.getTargetId().equals(this.getSourceId())) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.isCreature() && permanent.getControllerId().equals(this.getControllerId())) { + if (permanent != null && permanent.isCreature() && permanent.isControlledBy(this.getControllerId())) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(permanent.getId())); } diff --git a/Mage.Sets/src/mage/cards/r/RenegadeRallier.java b/Mage.Sets/src/mage/cards/r/RenegadeRallier.java index da05e35ea03..6c412dfcdb4 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeRallier.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeRallier.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -41,7 +41,7 @@ public final class RenegadeRallier extends CardImpl { // Revolt — When Renegade Rallier enters the battlefield, if a permanent you controlled left the battlefield this turn, // return target permanent card with converted mana cost 2 or less from your graveyard to your battlefield. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new ReturnFromGraveyardToBattlefieldTargetEffect(), false), RevoltCondition.instance, "Revolt — When {this} enters the battlefield, if a permanent you controlled left" + " the battlefield this turn, return target permanent card with converted mana cost 2 or less from your graveyard to your battlefield."); diff --git a/Mage.Sets/src/mage/cards/r/Reparations.java b/Mage.Sets/src/mage/cards/r/Reparations.java index 249f94a636f..e909ec6339f 100644 --- a/Mage.Sets/src/mage/cards/r/Reparations.java +++ b/Mage.Sets/src/mage/cards/r/Reparations.java @@ -74,7 +74,7 @@ class ReparationsTriggeredAbility extends TriggeredAbilityImpl { } if (targetPermanent != null && targetPermanent.isCreature() - && targetPermanent.getControllerId().equals(controllerId)) { + && targetPermanent.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/r/Reroute.java b/Mage.Sets/src/mage/cards/r/Reroute.java index a9154c8da34..609112ba64a 100644 --- a/Mage.Sets/src/mage/cards/r/Reroute.java +++ b/Mage.Sets/src/mage/cards/r/Reroute.java @@ -8,6 +8,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterAbility; +import mage.filter.FilterStackObject; import mage.filter.predicate.mageobject.NumberOfTargetsPredicate; import mage.target.common.TargetActivatedAbility; @@ -17,7 +18,7 @@ import mage.target.common.TargetActivatedAbility; */ public final class Reroute extends CardImpl { - private static final FilterAbility filter = new FilterAbility("activated ability with a single target"); + private static final FilterStackObject filter = new FilterStackObject("activated ability with a single target"); static { filter.add(new NumberOfTargetsPredicate(1)); diff --git a/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java b/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java index 96d91f8212f..4c975ab58c8 100644 --- a/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java +++ b/Mage.Sets/src/mage/cards/r/RescueFromTheUnderworld.java @@ -31,19 +31,19 @@ import mage.target.common.TargetControlledCreaturePermanent; /** * - * Once you announce you’re casting Rescue from the Underworld, no player may + * Once you announce you're casting Rescue from the Underworld, no player may * attempt to stop you from casting the spell by removing the creature you want * to sacrifice. * * If you sacrifice a creature token to cast Rescue from the Underworld, it - * won’t return to the battlefield, although the target creature card will. + * won't return to the battlefield, although the target creature card will. * * If either the sacrificed creature or the target creature card leaves the * graveyard before the delayed triggered ability resolves during your next - * upkeep, it won’t return. + * upkeep, it won't return. * * However, if the sacrificed creature is put into another public zone instead - * of the graveyard, perhaps because it’s your commander or because of another + * of the graveyard, perhaps because it's your commander or because of another * replacement effect, it will return to the battlefield from the zone it went * to. * @@ -212,7 +212,7 @@ class RescueFromTheUnderworldReturnEffect extends OneShotEffect { } } // However, if the sacrificed creature is put into another public zone instead of the graveyard, - // perhaps because it’s your commander or because of another replacement effect, it will return + // perhaps because it's your commander or because of another replacement effect, it will return // to the battlefield from the zone it went to. if (source.getTargets().get(1) != null) { for (UUID targetId : source.getTargets().get(1).getTargets()) { diff --git a/Mage.Sets/src/mage/cards/r/Reset.java b/Mage.Sets/src/mage/cards/r/Reset.java index 75eb88fa6de..67c6762340f 100644 --- a/Mage.Sets/src/mage/cards/r/Reset.java +++ b/Mage.Sets/src/mage/cards/r/Reset.java @@ -22,7 +22,7 @@ public final class Reset extends CardImpl { // Cast Reset only during an opponent's turn after their upkeep step. this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, new CompoundCondition(OnOpponentsTurnCondition.instance, AfterUpkeepStepCondtion.instance), - "Cast {this} only during an opponent's turn after their upkeep step")); + "Cast this spell only during an opponent's turn after their upkeep step")); // Untap all lands you control. this.getSpellAbility().addEffect(new UntapAllLandsControllerEffect()); diff --git a/Mage.Sets/src/mage/cards/r/Resistance.java b/Mage.Sets/src/mage/cards/r/Resistance.java new file mode 100644 index 00000000000..b7586d9c95b --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Resistance.java @@ -0,0 +1,60 @@ +package mage.cards.r; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect; +import mage.abilities.effects.common.combat.BlocksIfAbleTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.AttacksThisTurnMarkerAbility; +import mage.abilities.keyword.BlocksThisTurnMarkerAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Resistance extends CardImpl { + + public Resistance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}{W}"); + + + // Whenever a creature enters the battlefield under your control, Resistance deals 1 damage to each opponent. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DamagePlayersEffect(1, TargetController.OPPONENT), StaticFilters.FILTER_PERMANENT_CREATURE, false)); + + // {R}{W}: Target creature gains haste until end of turn and must attack or block this turn if able. + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn) + .setText("Target creature gains haste until end of turn"), + new ManaCostsImpl("{R}{W}")); + ability.addEffect(new AttacksIfAbleTargetEffect(Duration.EndOfTurn).setText("and must attack")); + //ability.addEffect(new GainAbilityTargetEffect(AttacksThisTurnMarkerAbility.getInstance(), Duration.EndOfTurn, "").setText("")); + ability.addEffect(new BlocksIfAbleTargetEffect(Duration.EndOfTurn).setText("or block this turn if able")); + //ability.addEffect(new GainAbilityTargetEffect(BlocksThisTurnMarkerAbility.getInstance(), Duration.EndOfTurn, "").setText("")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public Resistance(final Resistance card) { + super(card); + } + + @Override + public Resistance copy() { + return new Resistance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/ResistanceBomber.java b/Mage.Sets/src/mage/cards/r/ResistanceBomber.java new file mode 100644 index 00000000000..bcfbc62cf50 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/ResistanceBomber.java @@ -0,0 +1,60 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.common.SourceAttackingCondition; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class ResistanceBomber extends CardImpl { + + public ResistanceBomber(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // Resistance Bomber enters the battlefield with a charge counter on it. + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.CHARGE.createInstance()) + .setText("with a charge counter on it"))); + + // Remove a charge counter from Resistance Bomber: Resistance Bomber deals 5 damage to target creature. Activate this ability only if Resistance Bomber is attacking. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + new DamageTargetEffect(5), + new RemoveCountersSourceCost(CounterType.CHARGE.createInstance()), + SourceAttackingCondition.instance); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public ResistanceBomber(final ResistanceBomber card) { + super(card); + } + + @Override + public ResistanceBomber copy() { + return new ResistanceBomber(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/ResplendentAngel.java b/Mage.Sets/src/mage/cards/r/ResplendentAngel.java new file mode 100644 index 00000000000..ef40284b699 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/ResplendentAngel.java @@ -0,0 +1,73 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.YouGainedLifeCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.permanent.token.AngelToken2; +import mage.watchers.common.PlayerGainedLifeWatcher; + +/** + * + * @author TheElk801 + */ +public final class ResplendentAngel extends CardImpl { + + public ResplendentAngel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of each end step, if you gained 5 or more life this turn, create a 4/4 white Angel creature token with flying and vigilance. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + Zone.BATTLEFIELD, + new CreateTokenEffect(new AngelToken2()), + TargetController.ANY, + new YouGainedLifeCondition(ComparisonType.MORE_THAN, 4), + false + ), new PlayerGainedLifeWatcher()); + + // {3}{W}{W}{W}: Until end of turn, Resplendent Angel gets +2/+2 and gains lifelink. + Ability ability = new SimpleActivatedAbility( + new BoostSourceEffect( + 2, 2, Duration.EndOfTurn + ).setText("until end of turn, {this} gets +2/+2"), + new ManaCostsImpl("{3}{W}{W}{W}") + ); + ability.addEffect(new GainAbilitySourceEffect( + LifelinkAbility.getInstance(), + Duration.EndOfTurn + ).setText("and gains lifelink")); + this.addAbility(ability); + } + + public ResplendentAngel(final ResplendentAngel card) { + super(card); + } + + @Override + public ResplendentAngel copy() { + return new ResplendentAngel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java b/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java index 5ea0c1d82eb..eb2ca73672b 100644 --- a/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java +++ b/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.AscendAbility; import mage.abilities.keyword.FlyingAbility; @@ -35,7 +35,7 @@ public final class ResplendentGriffin extends CardImpl { this.addAbility(new AscendAbility()); // Whenever Resplendent Griffin attacks, if you have the city's blessing, put a +1/+1 counter on it. - this.addAbility(new ConditionalTriggeredAbility(new AttacksTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false), CitysBlessingCondition.instance, "Whenever {this} attacks, if you have the city's blessing, put a +1/+1 counter on it.")); } diff --git a/Mage.Sets/src/mage/cards/r/Retribution.java b/Mage.Sets/src/mage/cards/r/Retribution.java index f5167bcbed9..2c0a7214ad3 100644 --- a/Mage.Sets/src/mage/cards/r/Retribution.java +++ b/Mage.Sets/src/mage/cards/r/Retribution.java @@ -107,7 +107,7 @@ class TargetCreaturePermanentOpponentSameController extends TargetCreaturePerman Permanent targetPermanent = game.getPermanent(targetId); if (targetPermanent != null) { if (!firstTargetPermanent.getId().equals(targetPermanent.getId())) { - if (!firstTargetPermanent.getControllerId().equals(targetPermanent.getOwnerId())) { + if (!firstTargetPermanent.isControlledBy(targetPermanent.getOwnerId())) { return false; } } diff --git a/Mage.Sets/src/mage/cards/r/RetrofitterFoundry.java b/Mage.Sets/src/mage/cards/r/RetrofitterFoundry.java new file mode 100644 index 00000000000..56c55ec9f0b --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RetrofitterFoundry.java @@ -0,0 +1,81 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.UntapSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.permanent.token.RetrofitterFoundryToken; +import mage.game.permanent.token.ServoToken; +import mage.game.permanent.token.ThopterColorlessToken; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class RetrofitterFoundry extends CardImpl { + + private static final FilterControlledPermanent filter1 = new FilterControlledPermanent("a Servo"); + private static final FilterControlledPermanent filter2 = new FilterControlledPermanent("a Thopter"); + + static { + filter1.add(new SubtypePredicate(SubType.SERVO)); + filter2.add(new SubtypePredicate(SubType.THOPTER)); + } + + public RetrofitterFoundry(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + + // {3}: Untap Retrofitter Foundry. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new UntapSourceEffect(), + new GenericManaCost(3)) + ); + + // {2}, {T}: Create a 1/1 colorless Servo artifact creature token. + Ability ability = new SimpleActivatedAbility( + new CreateTokenEffect(new ServoToken()), + new GenericManaCost(2) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // {1}, {T}, Sacrifice a Servo: Create a 1/1 colorless Thopter artifact creature token with flying. + ability = new SimpleActivatedAbility( + new CreateTokenEffect(new ThopterColorlessToken()), + new GenericManaCost(1) + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter1))); + this.addAbility(ability); + + // {T}, Sacrifice a Thopter: Create a 4/4 colorless Construct artifact creature token. + ability = new SimpleActivatedAbility( + new CreateTokenEffect(new RetrofitterFoundryToken()), + new TapSourceCost() + ); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter2))); + this.addAbility(ability); + } + + public RetrofitterFoundry(final RetrofitterFoundry card) { + super(card); + } + + @Override + public RetrofitterFoundry copy() { + return new RetrofitterFoundry(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/ReturnToDust.java b/Mage.Sets/src/mage/cards/r/ReturnToDust.java index 9cdef129d82..c57d35ac043 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnToDust.java +++ b/Mage.Sets/src/mage/cards/r/ReturnToDust.java @@ -37,7 +37,7 @@ public final class ReturnToDust extends CardImpl { @Override public void adjustTargets(Ability ability, Game game) { if (ability instanceof SpellAbility) { - if (game.getActivePlayerId().equals(ability.getControllerId()) && game.isMainPhase()) { + if (game.isActivePlayer(ability.getControllerId()) && game.isMainPhase()) { ability.addTarget(new TargetPermanent(1, 2, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT, false)); } else { diff --git a/Mage.Sets/src/mage/cards/r/RevelInRiches.java b/Mage.Sets/src/mage/cards/r/RevelInRiches.java index 136ad97e5c2..bdd47cd8c06 100644 --- a/Mage.Sets/src/mage/cards/r/RevelInRiches.java +++ b/Mage.Sets/src/mage/cards/r/RevelInRiches.java @@ -6,7 +6,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class RevelInRiches extends CardImpl { this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new TreasureToken("XLN")), false, filter)); // At the beginning of your upkeep, if you control ten or more Treasures, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 9), "At the beginning of your upkeep, if you control ten or more Treasures, you win the game.")); diff --git a/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java b/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java index c62f3cf1f9f..50b1fd07e85 100644 --- a/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java +++ b/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.CantBlockAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SkipNextCombatEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,7 +32,7 @@ public final class RevenantPatriarch extends CardImpl { // When Revenant Patriarch enters the battlefield, if {W} was spent to cast it, target player skips their next combat phase. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SkipNextCombatEffect(), false); ability.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.W), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.W), "if {W} was spent to cast it, target player skips their next combat phase."), new ManaSpentToCastWatcher()); // Revenant Patriarch can't block. this.addAbility(new CantBlockAbility()); diff --git a/Mage.Sets/src/mage/cards/r/Revitalize.java b/Mage.Sets/src/mage/cards/r/Revitalize.java index 241448f180b..f4464efc4af 100644 --- a/Mage.Sets/src/mage/cards/r/Revitalize.java +++ b/Mage.Sets/src/mage/cards/r/Revitalize.java @@ -1,4 +1,3 @@ - package mage.cards.r; import java.util.UUID; @@ -18,7 +17,7 @@ public final class Revitalize extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // You gain 3 life. - this.getSpellAbility().addEffect(new GainLifeEffect(4)); + this.getSpellAbility().addEffect(new GainLifeEffect(3)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); diff --git a/Mage.Sets/src/mage/cards/r/Rey.java b/Mage.Sets/src/mage/cards/r/Rey.java new file mode 100644 index 00000000000..042ed7829d7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Rey.java @@ -0,0 +1,97 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldOrLeavesSourceTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author NinthWorld + */ +public final class Rey extends CardImpl { + + public Rey(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Whenever Rey enters or leaves the battlefield, reveal the top card of target player's library. You gain life equal to that card's converted mana cost. + Ability ability = new EntersBattlefieldOrLeavesSourceTriggeredAbility(new ReyEffect(), false); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public Rey(final Rey card) { + super(card); + } + + @Override + public Rey copy() { + return new Rey(this); + } +} + +class ReyEffect extends OneShotEffect { + + public ReyEffect() { + super(Outcome.Detriment); + staticText = "reveal the top card of target player's library. You gain life equal to that card's converted mana cost"; + } + + public ReyEffect(final ReyEffect effect) { + super(effect); + } + + @Override + public ReyEffect copy() { + return new ReyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); + if(targetPlayer != null && controller != null) { + if(targetPlayer.getLibrary().hasCards()) { + // reveal the top card of target player's library. + Card topCard = targetPlayer.getLibrary().getFromTop(game); + CardsImpl reveal = new CardsImpl(); + reveal.add(topCard); + targetPlayer.revealCards(source, reveal, game); + + // You gain life equal to that card's converted mana cost. + if (topCard != null) { + controller.gainLife(topCard.getConvertedManaCost(), game, source); + } + } + + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java b/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java index cb01ebdf412..3d95cc5195a 100644 --- a/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java +++ b/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java @@ -1,4 +1,3 @@ - package mage.cards.r; import java.util.UUID; @@ -91,25 +90,25 @@ class ReyhanLastOfTheAbzanTriggeredAbility extends TriggeredAbilityImpl { if (zcEvent.getToZone() != Zone.GRAVEYARD && zcEvent.getToZone() != Zone.COMMAND) { return false; } - - // A creature + + // A creature Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); if (permanent == null || !permanent.isCreature()) { return false; } - + // You control Player player = game.getPlayer(this.getControllerId()); - if (player == null || !player.getId().equals(this.getControllerId())) { + if (player == null || !permanent.isControlledBy(getControllerId())) { return false; } - + // If it had one or more +1/+1 counters on it int countersOn = permanent.getCounters(game).getCount(CounterType.P1P1); if (countersOn == 0) { return false; } - + // You may put that may +1/+1 counters on target creature this.getEffects().clear(); this.addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(countersOn))); diff --git a/Mage.Sets/src/mage/cards/r/RhoxMeditant.java b/Mage.Sets/src/mage/cards/r/RhoxMeditant.java index 06b3b703ec5..b089d90e15b 100644 --- a/Mage.Sets/src/mage/cards/r/RhoxMeditant.java +++ b/Mage.Sets/src/mage/cards/r/RhoxMeditant.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -40,7 +40,7 @@ public final class RhoxMeditant extends CardImpl { // When Rhox Meditant enters the battlefield, if you control a green permanent, draw a card. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); } diff --git a/Mage.Sets/src/mage/cards/r/RhoxOracle.java b/Mage.Sets/src/mage/cards/r/RhoxOracle.java new file mode 100644 index 00000000000..3a672ecdc40 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RhoxOracle.java @@ -0,0 +1,38 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class RhoxOracle extends CardImpl { + + public RhoxOracle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.subtype.add(SubType.RHINO); + this.subtype.add(SubType.MONK); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // When Rhox Oracle enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); + } + + public RhoxOracle(final RhoxOracle card) { + super(card); + } + + @Override + public RhoxOracle copy() { + return new RhoxOracle(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java b/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java index e87bf81a3f8..1a46092cb31 100644 --- a/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java +++ b/Mage.Sets/src/mage/cards/r/RhysTheRedeemed.java @@ -91,7 +91,7 @@ class RhysTheRedeemedEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)) { - if (permanent.getControllerId().equals(source.getControllerId())) { + if (permanent.isControlledBy(source.getControllerId())) { CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(); effect.setTargetPointer(new FixedTarget(permanent, game)); effect.apply(game, source); diff --git a/Mage.Sets/src/mage/cards/r/RhythmicWaterVortex.java b/Mage.Sets/src/mage/cards/r/RhythmicWaterVortex.java new file mode 100644 index 00000000000..01f4b225acf --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RhythmicWaterVortex.java @@ -0,0 +1,44 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +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.predicate.mageobject.NamePredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class RhythmicWaterVortex extends CardImpl { + + private final static FilterCard filter = new FilterCard("Mu Yanling"); + + static { + filter.add(new NamePredicate("Mu Yanling")); + } + + public RhythmicWaterVortex(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); + + // Return up to two target creatures to their owner's hand. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); + + // Search your library and/or graveyard for a card named Mu Yanling, reveal it, and put it into your hand. If you searched your library this way, shuffle it. + this.getSpellAbility().addEffect(new SearchLibraryGraveyardPutInHandEffect(filter)); + } + + public RhythmicWaterVortex(final RhythmicWaterVortex card) { + super(card); + } + + @Override + public RhythmicWaterVortex copy() { + return new RhythmicWaterVortex(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java b/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java new file mode 100644 index 00000000000..19516ddb9d0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java @@ -0,0 +1,46 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class RiddlemasterSphinx extends CardImpl { + + public RiddlemasterSphinx(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}"); + + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Riddlemaster Sphinx enters the battlefield, you may return target creature an opponent controls to its owner's hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); + ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.addAbility(ability); + } + + public RiddlemasterSphinx(final RiddlemasterSphinx card) { + super(card); + } + + @Override + public RiddlemasterSphinx copy() { + return new RiddlemasterSphinx(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RingOfEvosIsle.java b/Mage.Sets/src/mage/cards/r/RingOfEvosIsle.java index 192863a23e1..b22c0262b8d 100644 --- a/Mage.Sets/src/mage/cards/r/RingOfEvosIsle.java +++ b/Mage.Sets/src/mage/cards/r/RingOfEvosIsle.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.counter.AddPlusOneCountersAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -46,7 +46,7 @@ public final class RingOfEvosIsle extends CardImpl { // At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's blue. TriggeredAbility triggeredAbility = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddPlusOneCountersAttachedEffect(1), TargetController.YOU, false); - ConditionalTriggeredAbility ability2 = new ConditionalTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's blue."); + ConditionalInterveningIfTriggeredAbility ability2 = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's blue."); this.addAbility(ability2); // Equip {1} diff --git a/Mage.Sets/src/mage/cards/r/RingOfKalonia.java b/Mage.Sets/src/mage/cards/r/RingOfKalonia.java index 01ed42e9a00..e63365df303 100644 --- a/Mage.Sets/src/mage/cards/r/RingOfKalonia.java +++ b/Mage.Sets/src/mage/cards/r/RingOfKalonia.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.counter.AddPlusOneCountersAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -40,7 +40,7 @@ public final class RingOfKalonia extends CardImpl { // At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's green. TriggeredAbility triggeredAbility = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddPlusOneCountersAttachedEffect(1), TargetController.YOU, false); - ConditionalTriggeredAbility ability = new ConditionalTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's green"); + ConditionalInterveningIfTriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's green"); this.addAbility(ability); // Equip {1} diff --git a/Mage.Sets/src/mage/cards/r/RingOfMaruf.java b/Mage.Sets/src/mage/cards/r/RingOfMaruf.java index a836a3a52c8..3b39d23e7d1 100644 --- a/Mage.Sets/src/mage/cards/r/RingOfMaruf.java +++ b/Mage.Sets/src/mage/cards/r/RingOfMaruf.java @@ -80,6 +80,6 @@ class RingOfMarufEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/r/RingOfThune.java b/Mage.Sets/src/mage/cards/r/RingOfThune.java index f18f48f0561..3b988e6c7e7 100644 --- a/Mage.Sets/src/mage/cards/r/RingOfThune.java +++ b/Mage.Sets/src/mage/cards/r/RingOfThune.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.counter.AddPlusOneCountersAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -40,7 +40,7 @@ public final class RingOfThune extends CardImpl { // At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's white. TriggeredAbility triggeredAbility = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddPlusOneCountersAttachedEffect(1), TargetController.YOU, false); - ConditionalTriggeredAbility ability = new ConditionalTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's white."); + ConditionalInterveningIfTriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's white."); this.addAbility(ability); // Equip {1} diff --git a/Mage.Sets/src/mage/cards/r/RingOfValkas.java b/Mage.Sets/src/mage/cards/r/RingOfValkas.java index 7ac3d446faf..c783b1ca999 100644 --- a/Mage.Sets/src/mage/cards/r/RingOfValkas.java +++ b/Mage.Sets/src/mage/cards/r/RingOfValkas.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.counter.AddPlusOneCountersAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -40,7 +40,7 @@ public final class RingOfValkas extends CardImpl { // At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's red. TriggeredAbility triggeredAbility = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddPlusOneCountersAttachedEffect(1), TargetController.YOU, false); - ConditionalTriggeredAbility ability = new ConditionalTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's red"); + ConditionalInterveningIfTriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's red"); this.addAbility(ability); // Equip {1} diff --git a/Mage.Sets/src/mage/cards/r/RingOfXathrid.java b/Mage.Sets/src/mage/cards/r/RingOfXathrid.java index 907388c4f73..9f9dc5a2776 100644 --- a/Mage.Sets/src/mage/cards/r/RingOfXathrid.java +++ b/Mage.Sets/src/mage/cards/r/RingOfXathrid.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.RegenerateAttachedEffect; import mage.abilities.effects.common.counter.AddPlusOneCountersAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -39,7 +39,7 @@ public final class RingOfXathrid extends CardImpl { // At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's black. TriggeredAbility triggeredAbility = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddPlusOneCountersAttachedEffect(1), TargetController.YOU, false); - ConditionalTriggeredAbility ability = new ConditionalTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's black"); + ConditionalInterveningIfTriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, new AttachedToMatchesFilterCondition(filter), "At the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's black"); this.addAbility(ability); // Equip {1} diff --git a/Mage.Sets/src/mage/cards/r/RiotTrooper.java b/Mage.Sets/src/mage/cards/r/RiotTrooper.java new file mode 100644 index 00000000000..47e14b1107c --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RiotTrooper.java @@ -0,0 +1,50 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureAllEffect; +import mage.constants.Duration; +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.mageobject.SubtypePredicate; + +/** + * + * @author NinthWorld + */ +public final class RiotTrooper extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("trooper creatures you control"); + + static { + filter.add(new SubtypePredicate(SubType.TROOPER)); + } + + public RiotTrooper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.TROOPER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Each trooper creature you control can block an additional creature each combat. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new CanBlockAdditionalCreatureAllEffect(1, filter, Duration.WhileOnBattlefield) + .setText("Each trooper creature you control can block an additional creature each combat"))); + } + + public RiotTrooper(final RiotTrooper card) { + super(card); + } + + @Override + public RiotTrooper copy() { + return new RiotTrooper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java b/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java index cd75e26ce68..26ae787668c 100644 --- a/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java +++ b/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java @@ -1,14 +1,11 @@ - package mage.cards.r; import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.MorphAbility; import mage.cards.CardImpl; @@ -16,17 +13,13 @@ 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.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; /** * @@ -47,7 +40,6 @@ public final class RiptideEntrancer extends CardImpl { // Morph {U}{U} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{U}{U}"))); - } public RiptideEntrancer(final RiptideEntrancer card) { @@ -63,7 +55,10 @@ public final class RiptideEntrancer extends CardImpl { class RiptideEntrancerTriggeredAbility extends TriggeredAbilityImpl { public RiptideEntrancerTriggeredAbility() { - super(Zone.BATTLEFIELD, new RiptideEntrancerEffect(), true); + super(Zone.BATTLEFIELD, new DoIfCostPaid( + new GainControlTargetEffect(Duration.Custom), + new SacrificeSourceCost() + ), true); } public RiptideEntrancerTriggeredAbility(final RiptideEntrancerTriggeredAbility ability) { @@ -95,48 +90,7 @@ class RiptideEntrancerTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, you may sacrifice it. If you do, gain control of target creature that player controls"; - } -} - -class RiptideEntrancerEffect extends OneShotEffect { - - public RiptideEntrancerEffect() { - super(Outcome.DestroyPermanent); - staticText = "sacrifice {this}"; - } - - public RiptideEntrancerEffect(final RiptideEntrancerEffect effect) { - super(effect); - } - - @Override - public RiptideEntrancerEffect copy() { - return new RiptideEntrancerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject == null) { - if (source.getSourceObject(game) instanceof Spell) { - sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null && sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { - return false; - } - } - } - if (sourceObject instanceof Permanent) { - Permanent permanent = (Permanent) sourceObject; - if (source.getControllerId().equals(permanent.getControllerId())) { - ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom); - effect.setTargetPointer(new FixedTarget(targetPermanent.getId())); - game.addEffect(effect, source); - return permanent.sacrifice(source.getSourceId(), game); - } - return true; - } - return false; + return "Whenever {this} deals combat damage to a player, you may sacrifice it. " + + "If you do, gain control of target creature that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/r/RisenExecutioner.java b/Mage.Sets/src/mage/cards/r/RisenExecutioner.java index df4278b14bd..40c1b4c7997 100644 --- a/Mage.Sets/src/mage/cards/r/RisenExecutioner.java +++ b/Mage.Sets/src/mage/cards/r/RisenExecutioner.java @@ -91,7 +91,7 @@ class RisenExecutionerCastEffect extends AsThoughEffectImpl { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(source.getSourceId()); if (card != null - && card.getOwnerId().equals(affectedControllerId) + && card.isOwnedBy(affectedControllerId) && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { return true; } diff --git a/Mage.Sets/src/mage/cards/r/RocEgg.java b/Mage.Sets/src/mage/cards/r/RocEgg.java index b8c949457b6..126df90a82a 100644 --- a/Mage.Sets/src/mage/cards/r/RocEgg.java +++ b/Mage.Sets/src/mage/cards/r/RocEgg.java @@ -22,7 +22,7 @@ public final class RocEgg extends CardImpl { public RocEgg(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); - this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.BIRD, SubType.EGG); this.power = new MageInt(0); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/r/RoninWarclub.java b/Mage.Sets/src/mage/cards/r/RoninWarclub.java index 8cf766bef6d..d3f6624f420 100644 --- a/Mage.Sets/src/mage/cards/r/RoninWarclub.java +++ b/Mage.Sets/src/mage/cards/r/RoninWarclub.java @@ -71,7 +71,7 @@ public final class RoninWarclub extends CardImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent.isCreature() - && (permanent.getControllerId().equals(this.controllerId))) { + && (permanent.isControlledBy(this.controllerId))) { if (!this.getTargets().isEmpty()) { // remove previous target diff --git a/Mage.Sets/src/mage/cards/r/RootSliver.java b/Mage.Sets/src/mage/cards/r/RootSliver.java index 08126a40049..69c57f6a76b 100644 --- a/Mage.Sets/src/mage/cards/r/RootSliver.java +++ b/Mage.Sets/src/mage/cards/r/RootSliver.java @@ -43,7 +43,7 @@ public final class RootSliver extends CardImpl { // Root Sliver can't be countered. this.addAbility(new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect())); - // Sliver spells can't be countered by spells or abilities. + // Sliver spells can't be countered. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RootSliverEffect())); } @@ -62,7 +62,7 @@ class RootSliverEffect extends ContinuousRuleModifyingEffectImpl { public RootSliverEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "Sliver spells can't be countered by spells or abilities"; + staticText = "Sliver spells can't be countered"; } public RootSliverEffect(final RootSliverEffect effect) { @@ -89,7 +89,7 @@ class RootSliverEffect extends ContinuousRuleModifyingEffectImpl { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.hasSubtype(SubType.SLIVER, game)) { MageObject sourceObject = game.getObject(event.getSourceId()); - if (sourceObject != null && sourceObject instanceof StackObject) { + if (sourceObject instanceof StackObject) { return true; } } diff --git a/Mage.Sets/src/mage/cards/r/RootSnare.java b/Mage.Sets/src/mage/cards/r/RootSnare.java new file mode 100644 index 00000000000..7807e8e58a1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RootSnare.java @@ -0,0 +1,31 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; + +/** + * + * @author TheElk801 + */ +public final class RootSnare extends CardImpl { + + public RootSnare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + // Prevent all combat damage that would be dealt this turn. + this.getSpellAbility().addEffect(new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true)); + } + + public RootSnare(final RootSnare card) { + super(card); + } + + @Override + public RootSnare copy() { + return new RootSnare(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RootingKavu.java b/Mage.Sets/src/mage/cards/r/RootingKavu.java index 75a5bd2d071..b70328f3584 100644 --- a/Mage.Sets/src/mage/cards/r/RootingKavu.java +++ b/Mage.Sets/src/mage/cards/r/RootingKavu.java @@ -1,4 +1,3 @@ - package mage.cards.r; import java.util.UUID; @@ -15,7 +14,7 @@ import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; -import mage.filter.common.FilterCreatureCard; +import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; @@ -26,7 +25,7 @@ import mage.players.Player; public final class RootingKavu extends CardImpl { public RootingKavu(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); this.subtype.add(SubType.KAVU); this.power = new MageInt(4); this.toughness = new MageInt(3); @@ -44,33 +43,34 @@ public final class RootingKavu extends CardImpl { return new RootingKavu(this); } - static class RootingKavuEffect extends OneShotEffect { +} - public RootingKavuEffect() { - super(Outcome.Benefit); - this.staticText = "shuffle all creature cards from your graveyard into your library."; - } +class RootingKavuEffect extends OneShotEffect { - public RootingKavuEffect(final RootingKavuEffect effect) { - super(effect); - } + public RootingKavuEffect() { + super(Outcome.Benefit); + this.staticText = "shuffle all creature cards from your graveyard into your library."; + } - @Override - public RootingKavuEffect copy() { - return new RootingKavuEffect(this); - } + public RootingKavuEffect(final RootingKavuEffect effect) { + super(effect); + } - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Cards cards = new CardsImpl(); - cards.addAll(controller.getGraveyard().getCards(new FilterCreatureCard(), game)); - controller.putCardsOnTopOfLibrary(cards, game, source, false); - controller.shuffleLibrary(source, game); - return true; - } - return false; + @Override + public RootingKavuEffect copy() { + return new RootingKavuEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Cards cards = new CardsImpl(); + cards.addAll(controller.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game)); + controller.putCardsOnTopOfLibrary(cards, game, source, false); + controller.shuffleLibrary(source, game); + return true; } + return false; } } diff --git a/Mage.Sets/src/mage/cards/r/RowanKenrith.java b/Mage.Sets/src/mage/cards/r/RowanKenrith.java index b32b883391f..a3a6678dfd4 100644 --- a/Mage.Sets/src/mage/cards/r/RowanKenrith.java +++ b/Mage.Sets/src/mage/cards/r/RowanKenrith.java @@ -107,14 +107,14 @@ class RowanKenrithAttackEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - return permanent.getControllerId().equals(source.getFirstTarget()); + return permanent.isControlledBy(source.getFirstTarget()); } @Override public boolean isInactive(Ability source, Game game) { return (startingTurn != game.getTurnNum() && (game.getPhase().getType() == TurnPhase.END - && game.getActivePlayerId().equals(source.getFirstTarget()))) + && game.isActivePlayer(source.getFirstTarget()))) || // 6/15/2010: If a creature controlled by the affected player can't attack Gideon Jura (because he's no longer on the battlefield, for example), that player may have it attack you, another one of your planeswalkers, or nothing at all. creatingPermanent.getPermanent(game) == null; } diff --git a/Mage.Sets/src/mage/cards/r/Rowen.java b/Mage.Sets/src/mage/cards/r/Rowen.java index de7dc8e4fbe..c44d050a386 100644 --- a/Mage.Sets/src/mage/cards/r/Rowen.java +++ b/Mage.Sets/src/mage/cards/r/Rowen.java @@ -65,7 +65,7 @@ class RowenAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(this.getControllerId())) { - if (game.getActivePlayerId().equals(this.getControllerId()) && this.lastTriggeredTurn != game.getTurnNum()) { + if (game.isActivePlayer(this.getControllerId()) && this.lastTriggeredTurn != game.getTurnNum()) { Card card = game.getCard(event.getTargetId()); Player controller = game.getPlayer(this.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(this.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/r/RuinRaider.java b/Mage.Sets/src/mage/cards/r/RuinRaider.java index 0fa94bb55a6..60ccfd72691 100644 --- a/Mage.Sets/src/mage/cards/r/RuinRaider.java +++ b/Mage.Sets/src/mage/cards/r/RuinRaider.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class RuinRaider extends CardImpl { this.toughness = new MageInt(2); // Raid — At the beginning of your end step, if you attacked with a creature this turn, reveal the top card of your library and put that card into your hand. You lose life equal to the card's converted mana cost. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new RuinRaiderEffect(), TargetController.YOU, false), RaidCondition.instance, "Raid — At the beginning of your end step, if you attacked with a creature this turn, " diff --git a/Mage.Sets/src/mage/cards/r/RukhEgg.java b/Mage.Sets/src/mage/cards/r/RukhEgg.java index 7d6c19cfb6a..6cb6036d6ea 100644 --- a/Mage.Sets/src/mage/cards/r/RukhEgg.java +++ b/Mage.Sets/src/mage/cards/r/RukhEgg.java @@ -23,7 +23,8 @@ public final class RukhEgg extends CardImpl { public RukhEgg(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); - this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.BIRD, SubType.EGG); + this.power = new MageInt(0); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/r/RumblingAftershocks.java b/Mage.Sets/src/mage/cards/r/RumblingAftershocks.java index 20245e932a4..74f8e3b0255 100644 --- a/Mage.Sets/src/mage/cards/r/RumblingAftershocks.java +++ b/Mage.Sets/src/mage/cards/r/RumblingAftershocks.java @@ -78,7 +78,7 @@ class RumblingAftershocksTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getControllerId().equals(controllerId)) { + if (spell != null && spell.isControlledBy(controllerId)) { int damageAmount = 0; for (Ability ability: spell.getAbilities()) { if (ability instanceof KickerAbility) { diff --git a/Mage.Sets/src/mage/cards/r/RunedArch.java b/Mage.Sets/src/mage/cards/r/RunedArch.java index bba0a64ba4a..ea9d5642021 100644 --- a/Mage.Sets/src/mage/cards/r/RunedArch.java +++ b/Mage.Sets/src/mage/cards/r/RunedArch.java @@ -42,7 +42,7 @@ public final class RunedArch extends CardImpl { // {X}, {tap}, Sacrifice Runed Arch: X target creatures with power 2 or less are unblockable this turn. Ability ability = new SimpleActivatedAbility( new CantBeBlockedTargetEffect(Duration.EndOfGame) - .setText("X target creatures with power 2 or less can’t be blocked this turn."), + .setText("X target creatures with power 2 or less can't be blocked this turn."), new ManaCostsImpl("{X}") ); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/r/RunedHalo.java b/Mage.Sets/src/mage/cards/r/RunedHalo.java index 49b871326e4..3800320f377 100644 --- a/Mage.Sets/src/mage/cards/r/RunedHalo.java +++ b/Mage.Sets/src/mage/cards/r/RunedHalo.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class RunedHalo extends CardImpl { // As Runed Halo enters the battlefield, name a card. - Ability ability = new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL)); + Ability ability = new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); // You have protection from the chosen name. ability.addEffect(new RunedHaloSetProtectionEffect()); this.addAbility(ability); @@ -67,7 +67,7 @@ class RunedHaloSetProtectionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (controller != null && cardName != null && !cardName.isEmpty()) { FilterObject filter = new FilterObject("the name [" + cardName + ']'); filter.add(new NamePredicate(cardName)); diff --git a/Mage.Sets/src/mage/cards/r/RunicArmasaur.java b/Mage.Sets/src/mage/cards/r/RunicArmasaur.java new file mode 100644 index 00000000000..4c589622b4a --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RunicArmasaur.java @@ -0,0 +1,82 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityType; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.stack.StackAbility; + +/** + * + * @author LevelX2 + */ +public final class RunicArmasaur extends CardImpl { + + public RunicArmasaur(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{G}"); + + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // Whenever an opponent activates an ability of a creature or a land that is not a mana ability, you may draw a card. + this.addAbility(new RunicArmasaurTriggeredAbility()); + } + + public RunicArmasaur(final RunicArmasaur card) { + super(card); + } + + @Override + public RunicArmasaur copy() { + return new RunicArmasaur(this); + } +} + +class RunicArmasaurTriggeredAbility extends TriggeredAbilityImpl { + + RunicArmasaurTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true); + } + + RunicArmasaurTriggeredAbility(final RunicArmasaurTriggeredAbility ability) { + super(ability); + } + + @Override + public RunicArmasaurTriggeredAbility copy() { + return new RunicArmasaurTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ACTIVATED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); + if (stackAbility != null + && stackAbility.getAbilityType() == AbilityType.ACTIVATED + && game.getOpponents(this.getControllerId()).contains(stackAbility.getControllerId())) { + MageObject abilitySourceObject = stackAbility.getSourceObject(game); + return abilitySourceObject != null && (abilitySourceObject.isLand() || abilitySourceObject.isCreature()); + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent activates an ability of a creature or a land that is not a mana ability, you may draw a card."; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RushingTideZubera.java b/Mage.Sets/src/mage/cards/r/RushingTideZubera.java index 82e5c657797..f80c8015a46 100644 --- a/Mage.Sets/src/mage/cards/r/RushingTideZubera.java +++ b/Mage.Sets/src/mage/cards/r/RushingTideZubera.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class RushingTideZubera extends CardImpl { this.toughness = new MageInt(3); // When Rushing-Tide Zubera dies, if 4 or more damage was dealt to it this turn, draw three cards. - Ability ability = new ConditionalTriggeredAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(3)), new RushingTideZuberaCondition(), + Ability ability = new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(3)), new RushingTideZuberaCondition(), "When {this} dies, if 4 or more damage was dealt to it this turn, draw three cards."); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RushwoodLegate.java b/Mage.Sets/src/mage/cards/r/RushwoodLegate.java index fa6cac12a70..6267bdf3d58 100644 --- a/Mage.Sets/src/mage/cards/r/RushwoodLegate.java +++ b/Mage.Sets/src/mage/cards/r/RushwoodLegate.java @@ -35,7 +35,7 @@ public final class RushwoodLegate extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); - // If an opponent controls an Island and you control a Forest, you may cast Rushwood Legate without paying its mana cost. + // If an opponent controls an Island and you control a Forest, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls an Island and you control a Forest", new OpponentControlsPermanentCondition(filterIsland), new PermanentsOnTheBattlefieldCondition(filterForest)); diff --git a/Mage.Sets/src/mage/cards/r/Rust.java b/Mage.Sets/src/mage/cards/r/Rust.java index 7e3bf39efde..1e88687beb4 100644 --- a/Mage.Sets/src/mage/cards/r/Rust.java +++ b/Mage.Sets/src/mage/cards/r/Rust.java @@ -7,6 +7,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterAbility; +import mage.filter.FilterStackObject; import mage.filter.predicate.ability.ArtifactSourcePredicate; import mage.target.common.TargetActivatedAbility; @@ -16,7 +17,7 @@ import mage.target.common.TargetActivatedAbility; */ public final class Rust extends CardImpl { - private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source"); + private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source"); static { filter.add(new ArtifactSourcePredicate()); diff --git a/Mage.Sets/src/mage/cards/r/RustedRelic.java b/Mage.Sets/src/mage/cards/r/RustedRelic.java index b1303c1436e..95014e11eb4 100644 --- a/Mage.Sets/src/mage/cards/r/RustedRelic.java +++ b/Mage.Sets/src/mage/cards/r/RustedRelic.java @@ -29,7 +29,7 @@ public final class RustedRelic extends CardImpl { new ConditionalContinuousEffect( new BecomesCreatureSourceEffect(new RustedRelicToken(), "artifact", Duration.WhileOnBattlefield), MetalcraftCondition.instance, - "Metalcraft - {this} is a 5/5 Golem artifact creature as long as you control three or more artifacts"))); + "Metalcraft — {this} is a 5/5 Golem artifact creature as long as you control three or more artifacts"))); } public RustedRelic (final RustedRelic card) { diff --git a/Mage.Sets/src/mage/cards/r/RysorianBadger.java b/Mage.Sets/src/mage/cards/r/RysorianBadger.java new file mode 100644 index 00000000000..0b188d906f4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RysorianBadger.java @@ -0,0 +1,105 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.cards.Card; +import mage.constants.SubType; +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.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.permanent.DefendingPlayerOwnsCardPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author TheElk801 + */ +public final class RysorianBadger extends CardImpl { + + private static final FilterCreatureCard filter = new FilterCreatureCard("creature cards from defending player's graveyard"); + + static { + filter.add(new DefendingPlayerOwnsCardPredicate()); + } + + public RysorianBadger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.BADGER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Rysorian Badger attacks and isn't blocked, you may exile up to two target creature cards from defending player's graveyard. If you do, you gain 1 life for each card exiled this way and Rysorian Badger assigns no combat damage this turn. + Ability ability = new AttacksAndIsNotBlockedTriggeredAbility( + new RysorianBadgerEffect(), true + ); + ability.addTarget(new TargetCardInGraveyard(0, 2, filter)); + this.addAbility(ability); + } + + public RysorianBadger(final RysorianBadger card) { + super(card); + } + + @Override + public RysorianBadger copy() { + return new RysorianBadger(this); + } +} + +class RysorianBadgerEffect extends OneShotEffect { + + public RysorianBadgerEffect() { + super(Outcome.Benefit); + this.staticText = "you may exile up to two target creature cards " + + "from defending player's graveyard. If you do, " + + "you gain 1 life for each card exiled this way " + + "and {this} assigns no combat damage this turn."; + } + + public RysorianBadgerEffect(final RysorianBadgerEffect effect) { + super(effect); + } + + @Override + public RysorianBadgerEffect copy() { + return new RysorianBadgerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Cards cardsToExile = new CardsImpl(); + for (UUID cardId : this.getTargetPointer().getTargets(game, source)) { + Card card = game.getCard(cardId); + if (card != null) { + cardsToExile.add(card); + } + } + int cardsExiled = 0; + player.moveCardsToExile(cardsToExile.getCards(game), source, game, false, null, null); + for (Card card : cardsToExile.getCards(game)) { + if (game.getState().getZone(card.getId()) == Zone.EXILED) { + cardsExiled++; + } + } + player.gainLife(cardsExiled, game, source); + game.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java b/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java index 0b6dc15602f..a11e4e7b266 100644 --- a/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java +++ b/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TrampleAbility; @@ -32,7 +32,7 @@ public final class SabertoothOutrider extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Formidable — Whenever Sabertooth Outrider attacks, if creatures you control have total power 8 or greater, Sabertooth Outrider gains first strike until end of turn. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), false), FormidableCondition.instance, "Formidable — Whenever {this} attacks, if creatures you control have total power 8 or greater, {this} gains first strike until end of turn." diff --git a/Mage.Sets/src/mage/cards/s/SacredGround.java b/Mage.Sets/src/mage/cards/s/SacredGround.java index bfe3c54d2d0..93a2b21b08f 100644 --- a/Mage.Sets/src/mage/cards/s/SacredGround.java +++ b/Mage.Sets/src/mage/cards/s/SacredGround.java @@ -64,7 +64,7 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zce = (ZoneChangeEvent) event; if (Zone.BATTLEFIELD == zce.getFromZone() && Zone.GRAVEYARD == zce.getToZone()) { Permanent targetPermanent = zce.getTarget(); - if (targetPermanent.isLand() && targetPermanent.getControllerId().equals(getControllerId())) { + if (targetPermanent.isLand() && targetPermanent.isControlledBy(getControllerId())) { getEffects().get(0).setTargetPointer(new FixedTarget(targetPermanent.getId(), game.getState().getZoneChangeCounter(targetPermanent.getId()))); return true; } diff --git a/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java b/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java new file mode 100644 index 00000000000..78b2188a008 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java @@ -0,0 +1,62 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author TheElk801 + */ +public final class SacredWhiteDeer extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("you control a Yanggu planeswalker"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(new CardTypePredicate(CardType.PLANESWALKER)); + filter.add(new SubtypePredicate(SubType.YANGGU)); + } + + public SacredWhiteDeer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.ELK); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {3}{G}, {T}: You gain 4 life. Activate this ability only if you control a Yanggu planeswalker. + Ability ability = new ConditionalActivatedAbility( + Zone.BATTLEFIELD, + new GainLifeEffect(4), + new ManaCostsImpl("{3}{G}"), + new PermanentsOnTheBattlefieldCondition(filter) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public SacredWhiteDeer(final SacredWhiteDeer card) { + super(card); + } + + @Override + public SacredWhiteDeer copy() { + return new SacredWhiteDeer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SaffiEriksdotter.java b/Mage.Sets/src/mage/cards/s/SaffiEriksdotter.java index cb54538d81e..da707f54caf 100644 --- a/Mage.Sets/src/mage/cards/s/SaffiEriksdotter.java +++ b/Mage.Sets/src/mage/cards/s/SaffiEriksdotter.java @@ -106,7 +106,7 @@ class SaffiEriksdotterDelayedTriggeredAbility extends DelayedTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { if (((ZoneChangeEvent) event).isDiesEvent()) { if (fixedTarget.getFirst(game, this).equals(event.getTargetId())) { - if (this.getControllerId().equals(event.getPlayerId())) { + if (this.isControlledBy(event.getPlayerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java index 898fafa3726..e2d5f375dd0 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java +++ b/Mage.Sets/src/mage/cards/s/SageOfAncientLore.java @@ -10,7 +10,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -55,7 +55,7 @@ public final class SageOfAncientLore extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Sage of Ancient Lore. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public SageOfAncientLore(final SageOfAncientLore card) { diff --git a/Mage.Sets/src/mage/cards/s/SageOfFables.java b/Mage.Sets/src/mage/cards/s/SageOfFables.java index 1b5b3119905..fb238129d5b 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfFables.java +++ b/Mage.Sets/src/mage/cards/s/SageOfFables.java @@ -71,7 +71,7 @@ class SageOfFablesReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - return creature != null && creature.getControllerId().equals(source.getControllerId()) + return creature != null && creature.isControlledBy(source.getControllerId()) && creature.isCreature() && creature.hasSubtype(SubType.WIZARD, game) && !event.getTargetId().equals(source.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/s/SagesOfTheAnima.java b/Mage.Sets/src/mage/cards/s/SagesOfTheAnima.java index 05a8e44e5c6..397a44cedaa 100644 --- a/Mage.Sets/src/mage/cards/s/SagesOfTheAnima.java +++ b/Mage.Sets/src/mage/cards/s/SagesOfTheAnima.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -53,7 +52,10 @@ class SagesOfTheAnimaReplacementEffect extends ReplacementEffectImpl { public SagesOfTheAnimaReplacementEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "If you would draw a card, instead reveal the top three 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"; + staticText = "If you would draw a card, instead " + + "reveal the top three 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"; } public SagesOfTheAnimaReplacementEffect(final SagesOfTheAnimaReplacementEffect effect) { @@ -77,7 +79,7 @@ class SagesOfTheAnimaReplacementEffect extends ReplacementEffectImpl { Cards revealedCards = new CardsImpl(player.getLibrary().getTopCards(game, 3)); player.revealCards(source, revealedCards, game); Cards creatures = new CardsImpl(revealedCards.getCards(StaticFilters.FILTER_CARD_CREATURE, game)); - player.moveCards(creatures, Zone.BATTLEFIELD, source, game); + player.moveCards(creatures, Zone.HAND, source, game); revealedCards.removeAll(creatures); player.putCardsOnBottomOfLibrary(revealedCards, game, source, true); return true; diff --git a/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java b/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java new file mode 100644 index 00000000000..4e31f691b7f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SaheeliTheGifted.java @@ -0,0 +1,162 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.SpellAbility; +import mage.abilities.common.CanBeYourCommanderAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.constants.SubType; +import mage.constants.SuperType; +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.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ServoToken; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * + * @author TheElk801 + */ +public final class SaheeliTheGifted extends CardImpl { + + public SaheeliTheGifted(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{U}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SAHEELI); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Create a 1/1 colorless Servo artifact creature token. + this.addAbility(new LoyaltyAbility( + new CreateTokenEffect(new ServoToken()), 1 + )); + + // +1: The next spell you cast this turn costs {1} less to cast for each artifact you control as you cast it. + this.addAbility(new LoyaltyAbility( + new SaheeliTheGiftedCostReductionEffect(), 1 + )); + + // -7: For each artifact you control, create a token that's a copy of it. Those tokens gain haste. Exile those tokens at the beginning of the next end step. + this.addAbility(new LoyaltyAbility( + new SaheeliTheGiftedTokenEffect(), -7 + )); + + // Saheeli, the Gifted can be your commander. + this.addAbility(CanBeYourCommanderAbility.getInstance()); + } + + public SaheeliTheGifted(final SaheeliTheGifted card) { + super(card); + } + + @Override + public SaheeliTheGifted copy() { + return new SaheeliTheGifted(this); + } +} + +class SaheeliTheGiftedCostReductionEffect extends CostModificationEffectImpl { + + private int spellsCast; + + public SaheeliTheGiftedCostReductionEffect() { + super(Duration.EndOfTurn, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "the next spell you cast this turn costs {1} less to cast " + + "for each artifact you control as you cast it"; + } + + protected SaheeliTheGiftedCostReductionEffect(final SaheeliTheGiftedCostReductionEffect effect) { + super(effect); + this.spellsCast = effect.spellsCast; + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + if (watcher != null) { + spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()); + } + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + int artifactCount = game.getBattlefield().getAllActivePermanents( + StaticFilters.FILTER_PERMANENT_ARTIFACT_AN, + source.getControllerId(), game + ).size(); + CardUtil.reduceCost(abilityToModify, artifactCount); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); + if (watcher != null) { + if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) > spellsCast) { + discard(); // only one use + return false; + } + } + if (abilityToModify instanceof SpellAbility) { + return abilityToModify.isControlledBy(source.getControllerId()); + } + return false; + } + + @Override + public SaheeliTheGiftedCostReductionEffect copy() { + return new SaheeliTheGiftedCostReductionEffect(this); + } +} + +class SaheeliTheGiftedTokenEffect extends OneShotEffect { + + public SaheeliTheGiftedTokenEffect() { + super(Outcome.Benefit); + this.staticText = "for each artifact you control, " + + "create a token that's a copy of it. " + + "Those tokens gain haste. " + + "Exile those tokens at the beginning of the next end step."; + } + + public SaheeliTheGiftedTokenEffect(final SaheeliTheGiftedTokenEffect effect) { + super(effect); + } + + @Override + public SaheeliTheGiftedTokenEffect copy() { + return new SaheeliTheGiftedTokenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents( + StaticFilters.FILTER_PERMANENT_ARTIFACT_AN, + source.getControllerId(), game + )) { + if (permanent != null) { + CreateTokenCopyTargetEffect effect + = new CreateTokenCopyTargetEffect(); + effect.setTargetPointer(new FixedTarget(permanent, game)); + effect.setHasHaste(true); + effect.apply(game, source); + effect.exileTokensCreatedAtNextEndStep(game, source); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SaheelisDirective.java b/Mage.Sets/src/mage/cards/s/SaheelisDirective.java new file mode 100644 index 00000000000..4f3c0b21c89 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SaheelisDirective.java @@ -0,0 +1,91 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ImproviseAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterArtifactCard; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; + +/** + * + * @author TheElk801 + */ +public final class SaheelisDirective extends CardImpl { + + public SaheelisDirective(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}{R}{R}"); + + + // Improvise + this.addAbility(new ImproviseAbility()); + + // Reveal the top X cards of your library. You may put any number of artifact cards with converted mana cost X or less from among them onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield into your graveyard. + this.getSpellAbility().addEffect(new SaheelisDirectiveEffect()); + } + + public SaheelisDirective(final SaheelisDirective card) { + super(card); + } + + @Override + public SaheelisDirective copy() { + return new SaheelisDirective(this); + } +} +class SaheelisDirectiveEffect extends OneShotEffect { + + public SaheelisDirectiveEffect() { + super(Outcome.PutCardInPlay); + staticText = "Reveal the top X cards of your library. " + + "You may put any number of artifact cards with " + + "converted mana cost X or less from among them onto the battlefield. " + + "Then put all cards revealed this way that weren't " + + "put onto the battlefield into your graveyard."; + } + + public SaheelisDirectiveEffect(final SaheelisDirectiveEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + int xValue = source.getManaCostsToPay().getX(); + Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, xValue)); + if (!cards.isEmpty()) { + controller.revealCards(source, cards, game); + FilterCard filter = new FilterArtifactCard("artifact cards with converted mana cost " + xValue + " or less to put onto the battlefield"); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + TargetCard target1 = new TargetCard(0, Integer.MAX_VALUE, Zone.LIBRARY, filter); + target1.setNotTarget(true); + controller.choose(Outcome.PutCardInPlay, cards, target1, game); + Cards toBattlefield = new CardsImpl(target1.getTargets()); + cards.removeAll(toBattlefield); + controller.moveCards(toBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, false, false, false, null); + controller.moveCards(cards, Zone.GRAVEYARD, source, game); + } + return true; + } + + @Override + public SaheelisDirectiveEffect copy() { + return new SaheelisDirectiveEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SaiMasterThopterist.java b/Mage.Sets/src/mage/cards/s/SaiMasterThopterist.java new file mode 100644 index 00000000000..2729425cf22 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SaiMasterThopterist.java @@ -0,0 +1,69 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.permanent.token.ThopterColorlessToken; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class SaiMasterThopterist extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("an artifact spell"); + private static final FilterControlledArtifactPermanent filter2 = new FilterControlledArtifactPermanent("artifacts"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + + public SaiMasterThopterist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Whenever you cast an artifact spell, create a 1/1 colorless Thopter artifact creature token with flying. + this.addAbility(new SpellCastControllerTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken()), filter, false)); + + // {1}{U}, Sacrifice two artifacts: Draw a card. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(1), + new ManaCostsImpl("{1}{U}") + ); + ability.addCost(new SacrificeTargetCost( + new TargetControlledPermanent(2, 2, filter2, false) + )); + this.addAbility(ability); + } + + public SaiMasterThopterist(final SaiMasterThopterist card) { + super(card); + } + + @Override + public SaiMasterThopterist copy() { + return new SaiMasterThopterist(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SaiTok.java b/Mage.Sets/src/mage/cards/s/SaiTok.java new file mode 100644 index 00000000000..04d1f9daa49 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SaiTok.java @@ -0,0 +1,47 @@ +package mage.cards.s; + +import java.util.UUID; + +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreatureOrPlaneswalker; + +/** + * + * @author NinthWorld + */ +public final class SaiTok extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("creature or planeswalker if it has converted mana cost 4 or less"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new CardTypePredicate(CardType.PLANESWALKER)); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 5)); + } + + public SaiTok(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); + + + // Destroy target creature or planeswalker if it has converted mana cost 4 or less. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + } + + public SaiTok(final SaiTok card) { + super(card); + } + + @Override + public SaiTok copy() { + return new SaiTok(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java b/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java index 936ca9e6695..8fed936baa9 100644 --- a/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java +++ b/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java @@ -37,9 +37,9 @@ public final class SakashimaTheImpostor extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(1); - // You may have Sakashima the Impostor enter the battlefield as a copy of any creature on the battlefield, except its name is still Sakashima the Impostor, it's legendary in addition to its other types, and it gains "{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step." + // You may have Sakashima the Impostor enter the battlefield as a copy of any creature on the battlefield, except its name is Sakashima the Impostor, it's legendary in addition to its other types, and it has "{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step." Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, new SakashimaTheImpostorApplier()); - effect.setText("as a copy of any creature on the battlefield, except its name is still Sakashima the Impostor, it's legendary in addition to its other types, and it gains \"{2}{U}{U}: Return {this} to its owner's hand at the beginning of the next end step.\""); + effect.setText("as a copy of any creature on the battlefield, except its name is Sakashima the Impostor, it's legendary in addition to its other types, and it has \"{2}{U}{U}: Return {this} to its owner's hand at the beginning of the next end step.\""); this.addAbility(new EntersBattlefieldAbility(effect, true)); } diff --git a/Mage.Sets/src/mage/cards/s/SakikoMotherOfSummer.java b/Mage.Sets/src/mage/cards/s/SakikoMotherOfSummer.java index 8b0acd0b560..da0593a803b 100644 --- a/Mage.Sets/src/mage/cards/s/SakikoMotherOfSummer.java +++ b/Mage.Sets/src/mage/cards/s/SakikoMotherOfSummer.java @@ -35,7 +35,7 @@ public final class SakikoMotherOfSummer extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); - // Whenever a creature you control deals combat damage to a player, add that much {G}. Until end of turn, you don’t lose this mana as steps and phases end. + // Whenever a creature you control deals combat damage to a player, add that much {G}. Until end of turn, you don't lose this mana as steps and phases end. this.addAbility(new SakikoMotherOfSummerTriggeredAbility()); } @@ -74,11 +74,11 @@ class SakikoMotherOfSummerTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId)) { + if (creature != null && creature.isControlledBy(controllerId)) { this.getEffects().clear(); Effect effect = new AddManaToManaPoolTargetControllerEffect(Mana.GreenMana(event.getAmount()), "that player", true); effect.setTargetPointer(new FixedTarget(creature.getControllerId())); - effect.setText("add that much {G}. Until end of turn, you don’t lose this mana as steps and phases end"); + effect.setText("add that much {G}. Until end of turn, you don't lose this mana as steps and phases end"); this.addEffect(effect); return true; } @@ -88,6 +88,6 @@ class SakikoMotherOfSummerTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a creature you control deals combat damage to a player, add that much {G}. Until end of turn, you don’t lose this mana as steps and phases end."; + return "Whenever a creature you control deals combat damage to a player, add that much {G}. Until end of turn, you don't lose this mana as steps and phases end."; } } diff --git a/Mage.Sets/src/mage/cards/s/SakuraTribeSpringcaller.java b/Mage.Sets/src/mage/cards/s/SakuraTribeSpringcaller.java index 59d71e38dc4..3f0f949571a 100644 --- a/Mage.Sets/src/mage/cards/s/SakuraTribeSpringcaller.java +++ b/Mage.Sets/src/mage/cards/s/SakuraTribeSpringcaller.java @@ -28,9 +28,9 @@ public final class SakuraTribeSpringcaller extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(4); - // At the beginning of your upkeep, add {G}. Until end of turn, you don’t lose this mana as steps and phases end. + // At the beginning of your upkeep, add {G}. Until end of turn, you don't lose this mana as steps and phases end. Effect effect = new AddManaToManaPoolTargetControllerEffect(new Mana(Mana.GreenMana(1)), "your", true); - effect.setText("add {G}. Until end of turn, you don’t lose this mana as steps and phases end"); + effect.setText("add {G}. Until end of turn, you don't lose this mana as steps and phases end"); this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, false)); } diff --git a/Mage.Sets/src/mage/cards/s/SalvageTrader.java b/Mage.Sets/src/mage/cards/s/SalvageTrader.java new file mode 100644 index 00000000000..ead112bc622 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SalvageTrader.java @@ -0,0 +1,86 @@ +package mage.cards.s; + +import java.util.*; +import mage.MageInt; +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.target.common.TargetArtifactPermanent; + +/** + * + * @author NinthWorld + */ +public final class SalvageTrader extends CardImpl { + + public SalvageTrader(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.CROLUTE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // {T}: Exchange control of target artifact you control and target artifact an opponent controls with the same converted mana cost. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new ExchangeControlTargetEffect(Duration.EndOfGame, + "Exchange control of target artifact you control and target artifact an opponent controls with the same converted mana cost", false, true), + new TapSourceCost()); + FilterArtifactPermanent filterYou = new FilterArtifactPermanent("artifact you control"); + filterYou.add(new ControllerPredicate(TargetController.YOU)); + ability.addTarget(new TargetArtifactPermanent(filterYou)); + FilterArtifactPermanent filterOpponent = new FilterArtifactPermanent("artifact an opponent controls with the same casting cost as your targeted artifact"); + filterOpponent.add(new ControllerPredicate(TargetController.OPPONENT)); + filterOpponent.add(new SameCastingCostPredicate()); + ability.addTarget(new TargetArtifactPermanent(filterOpponent)); + + this.addAbility(ability); + } + + public SalvageTrader(final SalvageTrader card) { + super(card); + } + + @Override + public SalvageTrader copy() { + return new SalvageTrader(this); + } +} + +class SameCastingCostPredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + StackObject source = game.getStack().getStackObject(input.getSourceId()); + if (source != null) { + if (source.getStackAbility().getTargets().isEmpty() + || source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) { + return true; + } + Permanent firstTarget = game.getPermanent( + source.getStackAbility().getTargets().get(0).getTargets().get(0)); + Permanent inputPermanent = game.getPermanent(input.getObject().getId()); + if (firstTarget != null && inputPermanent != null) { + return firstTarget.getConvertedManaCost() == inputPermanent.getConvertedManaCost(); + } + } + return true; + } + + @Override + public String toString() { + return "Target with the same casting cost"; + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SamiteAlchemist.java b/Mage.Sets/src/mage/cards/s/SamiteAlchemist.java new file mode 100644 index 00000000000..2852f255632 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SamiteAlchemist.java @@ -0,0 +1,55 @@ +package mage.cards.s; + +import java.util.UUID; +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.DontUntapInControllersNextUntapStepTargetEffect; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class SamiteAlchemist extends CardImpl { + + public SamiteAlchemist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // {W}{W}, {tap}: Prevent the next 4 damage that would be dealt this turn to target creature you control. Tap that creature. It doesn't untap during your next untap step. + Ability ability = new SimpleActivatedAbility( + new PreventDamageToTargetEffect(Duration.EndOfTurn, 4), + new ManaCostsImpl("{W}{W}") + ); + ability.addCost(new TapSourceCost()); + ability.addEffect(new TapTargetEffect("Tap that creature")); + ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect() + .setText("It doesn't untap during your next untap step") + ); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public SamiteAlchemist(final SamiteAlchemist card) { + super(card); + } + + @Override + public SamiteAlchemist copy() { + return new SamiteAlchemist(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SandStrangler.java b/Mage.Sets/src/mage/cards/s/SandStrangler.java index 345e8df4a5f..94f5abff920 100644 --- a/Mage.Sets/src/mage/cards/s/SandStrangler.java +++ b/Mage.Sets/src/mage/cards/s/SandStrangler.java @@ -8,7 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.OrCondition; import mage.abilities.condition.common.CardsInControllerGraveCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -41,7 +41,7 @@ public final class SandStrangler extends CardImpl { this.toughness = new MageInt(3); // When Sand Strangler enters the battlefield, if you control a Desert or there is a Desert card in your graveyard, you may have Sand Strangler deal 3 damage to target creature. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3), true), new OrCondition( new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(filterDesertPermanent)), diff --git a/Mage.Sets/src/mage/cards/s/SaprazzanLegate.java b/Mage.Sets/src/mage/cards/s/SaprazzanLegate.java index a61a55454a4..c0d57d7e59f 100644 --- a/Mage.Sets/src/mage/cards/s/SaprazzanLegate.java +++ b/Mage.Sets/src/mage/cards/s/SaprazzanLegate.java @@ -32,15 +32,14 @@ public final class SaprazzanLegate extends CardImpl { public SaprazzanLegate(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); - this.subtype.add(SubType.MERFOLK); - this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.MERFOLK, SubType.SOLDIER); this.power = new MageInt(1); this.toughness = new MageInt(3); // Flying this.addAbility(FlyingAbility.getInstance()); - // If an opponent controls a Mountain and you control an Island, you may cast Saprazzan Legate without paying its mana cost. + // If an opponent controls a Mountain and you control an Island, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Mountain and you control an Island", new OpponentControlsPermanentCondition(filterMountain), new PermanentsOnTheBattlefieldCondition(filterIsland)); diff --git a/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java b/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java new file mode 100644 index 00000000000..7fd3df301ee --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java @@ -0,0 +1,68 @@ +package mage.cards.s; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.SaprolingToken; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class SaprolingInfestation extends CardImpl { + + public SaprolingInfestation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + + // Whenever a player kicks a spell, you put a 1/1 green Saproling creature token onto the battlefield. + this.addAbility(new SaprolingInfestationTriggeredAbility()); + } + + public SaprolingInfestation(final SaprolingInfestation card) { + super(card); + } + + @Override + public SaprolingInfestation copy() { + return new SaprolingInfestation(this); + } + + class SaprolingInfestationTriggeredAbility extends TriggeredAbilityImpl { + + SaprolingInfestationTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken("INV")), false); + } + + SaprolingInfestationTriggeredAbility(final SaprolingInfestationTriggeredAbility ability) { + super(ability); + } + + @Override + public SaprolingInfestationTriggeredAbility copy() { + return new SaprolingInfestationTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.KICKED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return true; + } + + @Override + public String getRule() { + return "Whenever a player kicks a spell, you put a 1/1 green Saproling creature token onto the battlefield."; + } + } +} diff --git a/Mage.Sets/src/mage/cards/s/Sarcomancy.java b/Mage.Sets/src/mage/cards/s/Sarcomancy.java index 0a90843240f..92003a9241b 100644 --- a/Mage.Sets/src/mage/cards/s/Sarcomancy.java +++ b/Mage.Sets/src/mage/cards/s/Sarcomancy.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DamageControllerEffect; import mage.cards.CardImpl; @@ -27,7 +27,7 @@ public final class Sarcomancy extends CardImpl { // When Sarcomancy enters the battlefield, create a 2/2 black Zombie creature token. this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 1), false)); // At the beginning of your upkeep, if there are no Zombies on the battlefield, Sarcomancy deals 1 damage to you. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageControllerEffect(1), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(new FilterPermanent(SubType.ZOMBIE, "Zombies"), ComparisonType.EQUAL_TO, 0, false), "At the beginning of your upkeep, if there are no Zombies on the battlefield, {this} deals 1 damage to you.")); diff --git a/Mage.Sets/src/mage/cards/s/SarkhanDragonsoul.java b/Mage.Sets/src/mage/cards/s/SarkhanDragonsoul.java new file mode 100644 index 00000000000..565bbd7c7e2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SarkhanDragonsoul.java @@ -0,0 +1,69 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetPlayerOrPlaneswalker; + +/** + * + * @author TheElk801 + */ +public final class SarkhanDragonsoul extends CardImpl { + + private static final FilterCreatureCard filter = new FilterCreatureCard("Dragon creature cards"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + } + + public SarkhanDragonsoul(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SARKHAN); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: Sarkhan, Dragonsoul deals 1 damage to each opponent and each creature your opponents control. + Ability ability = new LoyaltyAbility(new DamagePlayersEffect(1, TargetController.OPPONENT), 2); + ability.addEffect(new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) + .setText("and each creature your opponents control") + ); + + this.addAbility(ability); + + + // −3: Sarkhan, Dragonsoul deals 4 damage to target player or planeswalker. + Ability ability2 = new LoyaltyAbility(new DamageTargetEffect(4), -3); + ability2.addTarget(new TargetPlayerOrPlaneswalker()); + + this.addAbility(ability2); + + // −9: Search your library for any number of Dragon creature cards, put them onto the battlefield, then shuffle your library. + this.addAbility(new LoyaltyAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, Integer.MAX_VALUE, filter)), -9)); + } + + public SarkhanDragonsoul(final SarkhanDragonsoul card) { + super(card); + } + + @Override + public SarkhanDragonsoul copy() { + return new SarkhanDragonsoul(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SarkhanFireblood.java b/Mage.Sets/src/mage/cards/s/SarkhanFireblood.java new file mode 100644 index 00000000000..f997638c233 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SarkhanFireblood.java @@ -0,0 +1,68 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.mana.AddConditionalManaOfAnyColorEffect; +import mage.abilities.mana.conditional.ConditionalSpellManaBuilder; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.permanent.token.DragonToken2; + +/** + * + * @author TheElk801 + */ +public final class SarkhanFireblood extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("Dragon spells"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + } + + public SarkhanFireblood(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{R}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SARKHAN); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); + + // +1: You may discard a card. If you do, draw a card. + this.addAbility(new LoyaltyAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(1), + new DiscardCardCost() + ), 1)); + + // +1: Add two mana of any combination of colors. Spend this mana only to cast Dragon spells. + this.addAbility(new LoyaltyAbility( + new AddConditionalManaOfAnyColorEffect( + new StaticValue(2), + new ConditionalSpellManaBuilder(filter), + false + ), 1 + )); + + // -7: Create four 5/5 red Dragon creature tokens with flying. + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new DragonToken2(), 4), -7)); + } + + public SarkhanFireblood(final SarkhanFireblood card) { + super(card); + } + + @Override + public SarkhanFireblood copy() { + return new SarkhanFireblood(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SarkhansDragonfire.java b/Mage.Sets/src/mage/cards/s/SarkhansDragonfire.java new file mode 100644 index 00000000000..d61bdcf846d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SarkhansDragonfire.java @@ -0,0 +1,53 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.DamageTargetEffect; +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.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class SarkhansDragonfire extends CardImpl { + + private static final FilterCard filter = new FilterCard("a red card"); + + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + } + + public SarkhansDragonfire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); + + // Sarkhan's Dragonfire deals 3 damage to any target. + this.getSpellAbility().addEffect(new DamageTargetEffect(3)); + this.getSpellAbility().addTarget(new TargetAnyTarget()); + + // Look at the top five cards of your library. You may reveal a red card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect( + new StaticValue(5), false, new StaticValue(1), filter, + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false + ).setBackInRandomOrder(true).setText("Look at the top five cards of your library. " + + "You may reveal a red card from among them and put it into your hand. " + + "Put the rest on the bottom of your library in a random order.") + ); + } + + public SarkhansDragonfire(final SarkhansDragonfire card) { + super(card); + } + + @Override + public SarkhansDragonfire copy() { + return new SarkhansDragonfire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SarkhansUnsealing.java b/Mage.Sets/src/mage/cards/s/SarkhansUnsealing.java new file mode 100644 index 00000000000..95f462deeaa --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SarkhansUnsealing.java @@ -0,0 +1,76 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; +import mage.filter.common.FilterCreatureSpell; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class SarkhansUnsealing extends CardImpl { + + private static final FilterSpell filter = new FilterCreatureSpell("a creature spell with power 4, 5, or 6"); + private static final FilterSpell filter2 = new FilterCreatureSpell("a creature spell with power 7 or greater"); + private static final FilterPermanent filter3 = new FilterPermanent(); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 7)); + filter2.add(new PowerPredicate(ComparisonType.MORE_THAN, 6)); + filter3.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.PLANESWALKER) + )); + filter3.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public SarkhansUnsealing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + + // Whenever you cast a creature spell with power 4, 5, or 6, Sarkhan's Unsealing deals 4 damage to any target. + Ability ability = new SpellCastControllerTriggeredAbility( + new DamageTargetEffect(4), + filter, false + ); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + + // Whenever you cast a creature spell with power 7 or greater, Sarkhan's Unsealing deals 4 damage to each opponent and each creature and planeswalker they control. + ability = new SpellCastControllerTriggeredAbility( + new DamagePlayersEffect(4, TargetController.OPPONENT) + .setText("{this} deals 4 damage to each opponent"), + filter2, false + ); + ability.addEffect( + new DamageAllEffect(4, filter3) + .setText("and each creature and planeswalker they control") + ); + this.addAbility(ability); + } + + public SarkhansUnsealing(final SarkhansUnsealing card) { + super(card); + } + + @Override + public SarkhansUnsealing copy() { + return new SarkhansUnsealing(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SarkhansWhelp.java b/Mage.Sets/src/mage/cards/s/SarkhansWhelp.java new file mode 100644 index 00000000000..ad7ff03b730 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SarkhansWhelp.java @@ -0,0 +1,88 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +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.FilterControlledPlaneswalkerPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class SarkhansWhelp extends CardImpl { + + public SarkhansWhelp(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you activate an ability of a Sarkhan planeswalker, Sarkhan's Whelp deals 1 damage to any target. + this.addAbility(new SarkhansWhelpTriggeredAbility()); + } + + public SarkhansWhelp(final SarkhansWhelp card) { + super(card); + } + + @Override + public SarkhansWhelp copy() { + return new SarkhansWhelp(this); + } +} + +class SarkhansWhelpTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterControlledPlaneswalkerPermanent filter + = new FilterControlledPlaneswalkerPermanent( + SubType.SARKHAN, + "a Sarkhan planeswalker" + ); + + public SarkhansWhelpTriggeredAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(1), false); + this.addTarget(new TargetAnyTarget()); + } + + public SarkhansWhelpTriggeredAbility(final SarkhansWhelpTriggeredAbility ability) { + super(ability); + } + + @Override + public SarkhansWhelpTriggeredAbility copy() { + return new SarkhansWhelpTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent source = game.getPermanentOrLKIBattlefield(event.getSourceId()); + return event.getPlayerId().equals(getControllerId()) + && source != null + && filter.match(source, game); + } + + @Override + public String getRule() { + return "Whenever you activate an ability of a Sarkhan planeswalker, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java b/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java index acfe61d4972..0d7f4450b61 100644 --- a/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java +++ b/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java @@ -6,7 +6,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class SaruliGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Saruli Gatekeepers enters the battlefield, if you control two or more Gates, gain 7 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainLifeEffect(7)), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), "When {this} enters the battlefield, if you control two or more Gates, gain 7 life.")); diff --git a/Mage.Sets/src/mage/cards/s/SasayaOrochiAscendant.java b/Mage.Sets/src/mage/cards/s/SasayaOrochiAscendant.java index cfc27e3a16f..ff3b4d9cbad 100644 --- a/Mage.Sets/src/mage/cards/s/SasayaOrochiAscendant.java +++ b/Mage.Sets/src/mage/cards/s/SasayaOrochiAscendant.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -100,7 +99,7 @@ class SasayasEssence extends TokenImpl { // Whenever a land you control is tapped for mana, for each other land you control with the same name, add one mana of any type that land produced. this.addAbility(new TapForManaAllTriggeredManaAbility( - new SasayasEssenceManaEffectEffect(), + new SasayasEssenceManaEffect(), new FilterControlledLandPermanent(), SetTargetPointer.PERMANENT)); } @@ -114,28 +113,28 @@ class SasayasEssence extends TokenImpl { } } -class SasayasEssenceManaEffectEffect extends ManaEffect { +class SasayasEssenceManaEffect extends ManaEffect { - public SasayasEssenceManaEffectEffect() { + public SasayasEssenceManaEffect() { super(); this.staticText = "for each other land you control with the same name, add one mana of any type that land produced"; } - public SasayasEssenceManaEffectEffect(final SasayasEssenceManaEffectEffect effect) { + public SasayasEssenceManaEffect(final SasayasEssenceManaEffect effect) { super(effect); } @Override - public SasayasEssenceManaEffectEffect copy() { - return new SasayasEssenceManaEffectEffect(this); + public SasayasEssenceManaEffect copy() { + return new SasayasEssenceManaEffect(this); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - controller.getManaPool().addMana(getMana(game, source), game, source); checkToFirePossibleEvents(getMana(game, source), game, source); + controller.getManaPool().addMana(getMana(game, source), game, source); return true; } @@ -211,7 +210,7 @@ class SasayasEssenceManaEffectEffect extends ManaEffect { } } - return mana; + return newMana; } return null; } diff --git a/Mage.Sets/src/mage/cards/s/SatyrEnchanter.java b/Mage.Sets/src/mage/cards/s/SatyrEnchanter.java new file mode 100644 index 00000000000..a4890a89d85 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SatyrEnchanter.java @@ -0,0 +1,48 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; + +/** + * + * @author TheElk801 + */ +public final class SatyrEnchanter extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("an enchantment spell"); + + static { + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + } + + public SatyrEnchanter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}"); + + this.subtype.add(SubType.SATYR); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever you cast an enchantment spell, draw a card. + this.addAbility(new SpellCastControllerTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, true + )); + } + + public SatyrEnchanter(final SatyrEnchanter card) { + super(card); + } + + @Override + public SatyrEnchanter copy() { + return new SatyrEnchanter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java index 52deb05c284..fafe9257058 100644 --- a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java +++ b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java @@ -95,7 +95,7 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getControllerId().equals(game.getControllerId(event.getSourceId()))) { + if (isControlledBy(game.getControllerId(event.getSourceId()))) { MageObject damageSource = game.getObject(event.getSourceId()); if (damageSource != null) { if (game.getOpponents(getControllerId()).contains(event.getTargetId())) { diff --git a/Mage.Sets/src/mage/cards/s/SavageBeating.java b/Mage.Sets/src/mage/cards/s/SavageBeating.java index 8051d086ef1..2cf2654c6b4 100644 --- a/Mage.Sets/src/mage/cards/s/SavageBeating.java +++ b/Mage.Sets/src/mage/cards/s/SavageBeating.java @@ -29,7 +29,7 @@ public final class SavageBeating extends CardImpl { // Cast Savage Beating only during your turn and only during combat. this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(TurnPhase.COMBAT, null, MyTurnCondition.instance, - "Cast {this} only during your turn and only during combat")); + "Cast this spell only during your turn and only during combat")); // Choose one - Creatures you control gain double strike until end of turn; this.getSpellAbility().addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE, false)); diff --git a/Mage.Sets/src/mage/cards/s/SavageStomp.java b/Mage.Sets/src/mage/cards/s/SavageStomp.java index 95968629190..8a080176193 100644 --- a/Mage.Sets/src/mage/cards/s/SavageStomp.java +++ b/Mage.Sets/src/mage/cards/s/SavageStomp.java @@ -84,7 +84,7 @@ enum SavageStompCondition implements Condition { Iterator targets = sourceSpell.getStackAbility().getTargets().iterator(); while (targets.hasNext()) { Permanent permanent = game.getPermanentOrLKIBattlefield(targets.next().getFirstTarget()); - if (permanent != null && filter.match(permanent, game) && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && filter.match(permanent, game) && permanent.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SavageSummoning.java b/Mage.Sets/src/mage/cards/s/SavageSummoning.java index 28c873c4e84..2d19dea4fb8 100644 --- a/Mage.Sets/src/mage/cards/s/SavageSummoning.java +++ b/Mage.Sets/src/mage/cards/s/SavageSummoning.java @@ -103,9 +103,9 @@ class SavageSummoningAsThoughEffect extends AsThoughEffectImpl { if (commander.isCreature() && commander.getControllerId().equals(source.getControllerId())) { return true; } - } else if (mageObject != null && mageObject instanceof Card) { + } else if (mageObject instanceof Card) { Card card = (Card) mageObject; - if (card.isCreature() && card.getOwnerId().equals(source.getControllerId())) { + if (card.isCreature() && card.isOwnedBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SavageVentmaw.java b/Mage.Sets/src/mage/cards/s/SavageVentmaw.java index b757fb815e1..0461dea80dc 100644 --- a/Mage.Sets/src/mage/cards/s/SavageVentmaw.java +++ b/Mage.Sets/src/mage/cards/s/SavageVentmaw.java @@ -31,9 +31,9 @@ public final class SavageVentmaw extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // Whenever Savage Ventmaw attacks, add {R}{R}{R}{G}{G}{G}. Until end of turn, you don’t lose this mana as steps and phases end. + // Whenever Savage Ventmaw attacks, add {R}{R}{R}{G}{G}{G}. Until end of turn, you don't lose this mana as steps and phases end. Effect effect = new SavageVentmawManaEffect(new Mana(3, 3, 0, 0, 0, 0, 0, 0), "your", true); - effect.setText("add {R}{R}{R}{G}{G}{G}. Until end of turn, you don’t lose this mana as steps and phases end"); + effect.setText("add {R}{R}{R}{G}{G}{G}. Until end of turn, you don't lose this mana as steps and phases end"); this.addAbility(new AttacksTriggeredAbility(effect, false)); } diff --git a/Mage.Sets/src/mage/cards/s/SavingGrace.java b/Mage.Sets/src/mage/cards/s/SavingGrace.java index 0ee8ad8d973..bf4a045014f 100644 --- a/Mage.Sets/src/mage/cards/s/SavingGrace.java +++ b/Mage.Sets/src/mage/cards/s/SavingGrace.java @@ -94,7 +94,7 @@ class SavingGraceReplacementEffect extends ReplacementEffectImpl { if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE || event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER) { Permanent targetPermanent = game.getPermanent(event.getTargetId()); if (targetPermanent != null - && targetPermanent.getControllerId().equals(source.getControllerId())) { + && targetPermanent.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java b/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java index 736671801e9..a0c259a67b0 100644 --- a/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java +++ b/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.RenownedSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.HasteAbility; @@ -40,7 +40,7 @@ public final class ScabClanBerserker extends CardImpl { this.addAbility(new RenownAbility(1)); // Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new ScabClanBerserkerTriggeredAbility(), RenownedSourceCondition.instance, "Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player")); diff --git a/Mage.Sets/src/mage/cards/s/ScaldingTongs.java b/Mage.Sets/src/mage/cards/s/ScaldingTongs.java index e1ccd9d088c..b009f6aa4b2 100644 --- a/Mage.Sets/src/mage/cards/s/ScaldingTongs.java +++ b/Mage.Sets/src/mage/cards/s/ScaldingTongs.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +27,7 @@ public final class ScaldingTongs extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), TargetController.YOU, false); ability.addTarget(new TargetOpponentOrPlaneswalker()); CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 4); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, condition, "At the beginning of your upkeep, if you have three or fewer cards in hand, " + "{this} deals 1 damage to target opponent or planeswalker." diff --git a/Mage.Sets/src/mage/cards/s/ScholarOfStars.java b/Mage.Sets/src/mage/cards/s/ScholarOfStars.java index 3c436550e7c..459b6d7825d 100644 --- a/Mage.Sets/src/mage/cards/s/ScholarOfStars.java +++ b/Mage.Sets/src/mage/cards/s/ScholarOfStars.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -28,7 +28,7 @@ public final class ScholarOfStars extends CardImpl { this.toughness = new MageInt(2); // When Scholar of Stars enters the battlefield, if you control an artifact, draw a card. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT), "When {this} enters the battlefield, if you control an artifact, draw a card." diff --git a/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java b/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java index f2f1195143e..0580b379d11 100644 --- a/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java +++ b/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java @@ -1,25 +1,23 @@ - package mage.cards.s; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.CyclingAbility; import mage.abilities.keyword.TrampleAbility; -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.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; @@ -40,8 +38,7 @@ public final class ScionOfDarkness extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever Scion of Darkness deals combat damage to a player, you may put target creature card from that player's graveyard onto the battlefield under your control. - Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ScionOfDarknessEffect(), true, true); - this.addAbility(ability); + this.addAbility(new ScionOfDarknessTriggeredAbility()); // Cycling {3} this.addAbility(new CyclingAbility(new ManaCostsImpl("{3}"))); @@ -57,41 +54,48 @@ public final class ScionOfDarkness extends CardImpl { } } -class ScionOfDarknessEffect extends OneShotEffect { +class ScionOfDarknessTriggeredAbility extends TriggeredAbilityImpl { - public ScionOfDarknessEffect() { - super(Outcome.PutCreatureInPlay); - this.staticText = "you may put target creature card from that player's graveyard onto the battlefield under your control"; + public ScionOfDarknessTriggeredAbility() { + super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), true); } - public ScionOfDarknessEffect(final ScionOfDarknessEffect effect) { - super(effect); + public ScionOfDarknessTriggeredAbility(final ScionOfDarknessTriggeredAbility ability) { + super(ability); } @Override - public ScionOfDarknessEffect copy() { - return new ScionOfDarknessEffect(this); + public ScionOfDarknessTriggeredAbility copy() { + return new ScionOfDarknessTriggeredAbility(this); } @Override - public boolean apply(Game game, Ability source) { - Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null || damagedPlayer == null) { + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { return false; } FilterCard filter = new FilterCard("creature in " + damagedPlayer.getName() + "'s graveyard"); filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new OwnerIdPredicate(damagedPlayer.getId())); TargetCardInGraveyard target = new TargetCardInGraveyard(filter); - if (target.canChoose(source.getSourceId(), controller.getId(), game)) { - if (controller.chooseTarget(Outcome.PutCreatureInPlay, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - } + this.getTargets().clear(); + this.addTarget(target); return true; } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may put target creature card from that player's " + + "graveyard onto the battlefield under your control"; + } } diff --git a/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java b/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java index 3001ef6568a..35d37c2cee9 100644 --- a/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java +++ b/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.PopulateEffect; import mage.cards.CardImpl; @@ -29,9 +29,10 @@ public final class ScionOfVituGhazi extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); + //When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, create a 1/1 white Bird creature token with flying, then populate. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken()), false); ability.addEffect(new PopulateEffect("then")); - this.addAbility(new ConditionalTriggeredAbility(ability, CastFromHandSourceCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, create a 1/1 white Bird creature token with flying, then populate."), new CastFromHandWatcher()); } diff --git a/Mage.Sets/src/mage/cards/s/ScorchingWinds.java b/Mage.Sets/src/mage/cards/s/ScorchingWinds.java index 7046a4b3ba5..36abefd104b 100644 --- a/Mage.Sets/src/mage/cards/s/ScorchingWinds.java +++ b/Mage.Sets/src/mage/cards/s/ScorchingWinds.java @@ -26,7 +26,7 @@ public final class ScorchingWinds extends CardImpl { // Cast Scorching Winds only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/ScornedVillager.java b/Mage.Sets/src/mage/cards/s/ScornedVillager.java index 74ffb0a4a3b..87ba993c597 100644 --- a/Mage.Sets/src/mage/cards/s/ScornedVillager.java +++ b/Mage.Sets/src/mage/cards/s/ScornedVillager.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.abilities.mana.GreenManaAbility; @@ -39,7 +39,7 @@ public final class ScornedVillager extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Scorned Villager. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfNelToth.java b/Mage.Sets/src/mage/cards/s/ScourgeOfNelToth.java index e6a1cb64b54..4e09668db0b 100644 --- a/Mage.Sets/src/mage/cards/s/ScourgeOfNelToth.java +++ b/Mage.Sets/src/mage/cards/s/ScourgeOfNelToth.java @@ -76,7 +76,7 @@ class ScourgeOfNelTothPlayEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(source.getSourceId()) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(source.getSourceId()) && source.isControlledBy(affectedControllerId)) { if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { Player player = game.getPlayer(affectedControllerId); if (player != null) { diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java b/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java index ee2e29ab12d..ab0fe7c32f8 100644 --- a/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java +++ b/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.AttacksFirstTimeTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; import mage.abilities.effects.common.UntapAllControllerEffect; import mage.abilities.keyword.DethroneAbility; @@ -45,7 +45,7 @@ public final class ScourgeOfTheThrone extends CardImpl { ), false ); ability.addEffect(new AdditionalCombatPhaseEffect()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, ScourgeOfTheThroneCondition.instance, "Whenever {this} attacks for the first time each turn, " diff --git a/Mage.Sets/src/mage/cards/s/ScoutsWarning.java b/Mage.Sets/src/mage/cards/s/ScoutsWarning.java index c2a22fd2811..5ddb9e6c3a5 100644 --- a/Mage.Sets/src/mage/cards/s/ScoutsWarning.java +++ b/Mage.Sets/src/mage/cards/s/ScoutsWarning.java @@ -87,7 +87,7 @@ class ScoutsWarningAsThoughEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { if (watcher.isScoutsWarningSpellActive(source.getSourceId(), zoneChangeCounter)) { Card card = game.getCard(sourceId); - if (card != null && card.isCreature() && source.getControllerId().equals(affectedControllerId)) { + if (card != null && card.isCreature() && source.isControlledBy(affectedControllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/ScrapTrawler.java b/Mage.Sets/src/mage/cards/s/ScrapTrawler.java index 60546eaa7aa..65de4ee26e5 100644 --- a/Mage.Sets/src/mage/cards/s/ScrapTrawler.java +++ b/Mage.Sets/src/mage/cards/s/ScrapTrawler.java @@ -78,7 +78,7 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); - if (permanent.getControllerId().equals(this.getControllerId()) && permanent.isArtifact()) { + if (permanent.isControlledBy(this.getControllerId()) && permanent.isArtifact()) { FilterCard filter = new FilterArtifactCard("artifact card in your graveyard with converted mana cost less than " + permanent.getManaCost().convertedManaCost()); filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, permanent.getManaCost().convertedManaCost())); TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter); diff --git a/Mage.Sets/src/mage/cards/s/Scrapheap.java b/Mage.Sets/src/mage/cards/s/Scrapheap.java index c38b844d81c..b57e7f95e6f 100644 --- a/Mage.Sets/src/mage/cards/s/Scrapheap.java +++ b/Mage.Sets/src/mage/cards/s/Scrapheap.java @@ -64,7 +64,7 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent != null && permanent.getOwnerId().equals(this.getControllerId())) { + if (permanent != null && permanent.isOwnedBy(this.getControllerId())) { if (StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT.match(permanent, sourceId, controllerId, game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java b/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java index 2f5abb4406a..dc4727c6409 100644 --- a/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java +++ b/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -17,8 +16,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.StaticFilters; /** * @@ -27,7 +25,7 @@ import mage.filter.common.FilterControlledArtifactPermanent; public final class ScrapyardMongrel extends CardImpl { public ScrapyardMongrel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); this.subtype.add(SubType.HOUND); this.color.setRed(true); @@ -35,14 +33,13 @@ public final class ScrapyardMongrel extends CardImpl { this.toughness = new MageInt(3); // As long as you control an artifact, Scrapyard Mongrel gets +2/+0 and has trample. - FilterPermanent filter = new FilterControlledArtifactPermanent(); Effect boostEffect = new ConditionalContinuousEffect( new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), - new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT), "As long as you control an artifact, {this} gets +2/+0"); Effect gainAbilityEffect = new ConditionalContinuousEffect( new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield), - new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT), "and has trample"); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, boostEffect); ability.addEffect(gainAbilityEffect); diff --git a/Mage.Sets/src/mage/cards/s/ScreechingPhoenix.java b/Mage.Sets/src/mage/cards/s/ScreechingPhoenix.java new file mode 100644 index 00000000000..41151bb2b21 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScreechingPhoenix.java @@ -0,0 +1,48 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class ScreechingPhoenix extends CardImpl { + + public ScreechingPhoenix(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); + + this.subtype.add(SubType.PHOENIX); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {2}{R}: Creatures you control get +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect(1, 0, Duration.EndOfTurn), + new ManaCostsImpl("{2}{R}") + )); + } + + public ScreechingPhoenix(final ScreechingPhoenix card) { + super(card); + } + + @Override + public ScreechingPhoenix copy() { + return new ScreechingPhoenix(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java index 5f8e08f58c8..b356cdac110 100644 --- a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java +++ b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.MetalcraftCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -20,7 +20,7 @@ import mage.constants.SubType; */ public final class ScreechingSilcaw extends CardImpl { - private static final String text = "Metalcraft - Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard."; + private static final String text = "Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard."; public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); @@ -31,7 +31,8 @@ public final class ScreechingSilcaw extends CardImpl { this.addAbility(FlyingAbility.getInstance()); - TriggeredAbility conditional = new ConditionalTriggeredAbility( + //"Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard. + TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility( new DealsCombatDamageToAPlayerTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), false, true), MetalcraftCondition.instance, text); this.addAbility(conditional); diff --git a/Mage.Sets/src/mage/cards/s/ScrollRack.java b/Mage.Sets/src/mage/cards/s/ScrollRack.java index 8ad4e5a55b3..dff971eb118 100644 --- a/Mage.Sets/src/mage/cards/s/ScrollRack.java +++ b/Mage.Sets/src/mage/cards/s/ScrollRack.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -16,6 +15,7 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; +import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; @@ -27,7 +27,7 @@ import mage.target.common.TargetCardInHand; public final class ScrollRack extends CardImpl { public ScrollRack(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // {1}, {tap}: Exile any number of cards from your hand face down. Put that many cards from the top of your library into your hand. Then look at the exiled cards and put them on top of your library in any order. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScrollRackEffect(), new GenericManaCost(1)); @@ -62,7 +62,6 @@ class ScrollRackEffect extends OneShotEffect { MageObject sourceObject = game.getObject(source.getSourceId()); if (controller != null && sourceObject != null) { FilterCard filter = new FilterCard("card in your hand to exile"); -// FilterCard filter2 = new FilterCard("(move the window) card exiled by " + sourceObject.getIdName() + " to put on top of library"); TargetCardInHand target = new TargetCardInHand(0, controller.getHand().size(), filter); target.setRequired(false); int amountExiled = 0; @@ -76,8 +75,11 @@ class ScrollRackEffect extends OneShotEffect { } } controller.moveCardsToExile(new CardsImpl(target.getTargets()).getCards(game), source, game, false, source.getSourceId(), sourceObject.getIdName()); - for (Card card : game.getExile().getExileZone(source.getSourceId()).getCards(game)) { - card.setFaceDown(true, game); + ExileZone exileZone = game.getExile().getExileZone(source.getSourceId()); + if (exileZone != null) { + for (Card card : exileZone.getCards(game)) { + card.setFaceDown(true, game); + } } } } diff --git a/Mage.Sets/src/mage/cards/s/SeaTroll.java b/Mage.Sets/src/mage/cards/s/SeaTroll.java new file mode 100644 index 00000000000..09a364ec860 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SeaTroll.java @@ -0,0 +1,118 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.condition.OrCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.RegenerateSourceEffect; +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; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; +import mage.watchers.common.BlockedAttackerWatcher; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class SeaTroll extends CardImpl { + + public SeaTroll(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.TROLL); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {U}: Regenerate Sea Troll. Activate this ability only if Sea Troll blocked or was blocked by a blue creature this turn. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{U}"), new SeaTrollCondition()); + ability.addWatcher(new SeaTrollWatcher()); + this.addAbility(ability); + } + + public SeaTroll(final SeaTroll card) { + super(card); + } + + @Override + public SeaTroll copy() { + return new SeaTroll(this); + } +} + +class SeaTrollWatcher extends Watcher { + + private final Set blockedOrBlockedByBlueThisTurnCreatures; + + public SeaTrollWatcher() { + super(SeaTrollWatcher.class.getSimpleName(), WatcherScope.GAME); + blockedOrBlockedByBlueThisTurnCreatures = new HashSet<>(); + } + + public SeaTrollWatcher(SeaTrollWatcher watcher) { + super(watcher); + this.blockedOrBlockedByBlueThisTurnCreatures = new HashSet<>(watcher.blockedOrBlockedByBlueThisTurnCreatures); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { + MageObjectReference blocker = new MageObjectReference(event.getSourceId(), game); + MageObjectReference attacker = new MageObjectReference(event.getTargetId(), game); + if (blocker.getPermanentOrLKIBattlefield(game).getColor(game).isBlue()){ + blockedOrBlockedByBlueThisTurnCreatures.add(attacker); + } + if (attacker.getPermanentOrLKIBattlefield(game).getColor(game).isBlue()){ + blockedOrBlockedByBlueThisTurnCreatures.add(blocker); + } + } + } + + @Override + public void reset() { + super.reset(); + blockedOrBlockedByBlueThisTurnCreatures.clear(); + } + + public boolean blockedOrBlockedByBlueCreatureThisTurn(MageObjectReference creature){ + return blockedOrBlockedByBlueThisTurnCreatures.contains(creature); + } + + @Override + public SeaTrollWatcher copy() { + return new SeaTrollWatcher(this); + } +} + +class SeaTrollCondition implements Condition { + + @Override + 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()); + if (watcher != null) { + return watcher.blockedOrBlockedByBlueCreatureThisTurn(new MageObjectReference(sourcePermanent, game)); + } + } + return false; + } + + @Override + public String toString() { + return "{this} blocked or was blocked by a blue creature this turn"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SealOfTheGuildpact.java b/Mage.Sets/src/mage/cards/s/SealOfTheGuildpact.java index 3cd5899623d..6bd3881998a 100644 --- a/Mage.Sets/src/mage/cards/s/SealOfTheGuildpact.java +++ b/Mage.Sets/src/mage/cards/s/SealOfTheGuildpact.java @@ -143,7 +143,7 @@ class SealOfTheGuildpactCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify.getControllerId().equals(source.getControllerId()) + return abilityToModify.isControlledBy(source.getControllerId()) && abilityToModify instanceof SpellAbility; } diff --git a/Mage.Sets/src/mage/cards/s/SearingBlaze.java b/Mage.Sets/src/mage/cards/s/SearingBlaze.java index 1bf68abbae3..cda4d3ce257 100644 --- a/Mage.Sets/src/mage/cards/s/SearingBlaze.java +++ b/Mage.Sets/src/mage/cards/s/SearingBlaze.java @@ -53,7 +53,7 @@ class SearingBlazeEffect extends OneShotEffect { public SearingBlazeEffect() { super(Outcome.Damage); - staticText = "{this} deals 1 damage to target player or planeswalker and 1 damage to target creature that player or that planeswalker’s controller controls. \nLandfall - If you had a land enter the battlefield under your control this turn, {this} deals 3 damage to that player or planeswalker and 3 damage to that creature instead."; + staticText = "{this} deals 1 damage to target player or planeswalker and 1 damage to target creature that player or that planeswalker's controller controls. \nLandfall - If you had a land enter the battlefield under your control this turn, {this} deals 3 damage to that player or planeswalker and 3 damage to that creature instead."; } public SearingBlazeEffect(final SearingBlazeEffect effect) { @@ -100,7 +100,7 @@ class SearingBlazeTarget extends TargetPermanent { } UUID firstTarget = player.getId(); Permanent permanent = game.getPermanent(id); - if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + if (firstTarget != null && permanent != null && permanent.isControlledBy(firstTarget)) { return super.canTarget(id, source, game); } return false; @@ -117,7 +117,7 @@ class SearingBlazeTarget extends TargetPermanent { if (player != null) { for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.getControllerId().equals(player.getId())) { + if (permanent != null && permanent.isControlledBy(player.getId())) { possibleTargets.add(targetId); } } diff --git a/Mage.Sets/src/mage/cards/s/SearingRays.java b/Mage.Sets/src/mage/cards/s/SearingRays.java new file mode 100644 index 00000000000..bbd65ef0e15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SearingRays.java @@ -0,0 +1,79 @@ +package mage.cards.s; + +import java.util.UUID; + +import mage.abilities.Ability; +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.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author noahg + */ +public final class SearingRays extends CardImpl { + + public SearingRays(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); + + + // Choose a color. Searing Rays deals damage to each player equal to the number of creatures of that color that player controls. + this.getSpellAbility().addEffect(new SearingRaysEffect()); + } + + public SearingRays(final SearingRays card) { + super(card); + } + + @Override + public SearingRays copy() { + return new SearingRays(this); + } +} + +class SearingRaysEffect extends OneShotEffect { + + public SearingRaysEffect() { + super(Outcome.Damage); + this.staticText = "Choose a color. {this} deals damage to each player equal to the number of creatures of that color that player controls"; + } + + public SearingRaysEffect(final SearingRaysEffect effect) { + super(effect); + } + + @Override + public SearingRaysEffect copy() { + return new SearingRaysEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + ChoiceColor choice = new ChoiceColor(); + if (controller != null && controller.choose(outcome, choice, game) && choice.getColor() != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent(choice.getColor().getDescription()+" creatures"); + filter.add(new ColorPredicate(choice.getColor())); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + int amount = game.getBattlefield().countAll(filter , playerId, game); + if (amount > 0) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.damage(amount, source.getSourceId(), game, false, true); + } + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SecondChance.java b/Mage.Sets/src/mage/cards/s/SecondChance.java index dd82b15e413..8fdc60199d7 100644 --- a/Mage.Sets/src/mage/cards/s/SecondChance.java +++ b/Mage.Sets/src/mage/cards/s/SecondChance.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.XorLessLifeCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; import mage.cards.CardImpl; @@ -27,7 +27,7 @@ public final class SecondChance extends CardImpl { // At the beginning of your upkeep, if you have 5 or less life, sacrifice Second Chance and take an extra turn after this one. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU, false); ability.addEffect(new AddExtraTurnControllerEffect()); - this.addAbility(new ConditionalTriggeredAbility(ability, new XorLessLifeCondition(XorLessLifeCondition.CheckType.CONTROLLER, 5), "At the beginning of your upkeep, if you have 5 or less life, sacrifice {this} and take an extra turn after this one")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new XorLessLifeCondition(XorLessLifeCondition.CheckType.CONTROLLER, 5), "At the beginning of your upkeep, if you have 5 or less life, sacrifice {this} and take an extra turn after this one")); } diff --git a/Mage.Sets/src/mage/cards/s/SecondGuess.java b/Mage.Sets/src/mage/cards/s/SecondGuess.java index 282676df4f4..140e9f74a2c 100644 --- a/Mage.Sets/src/mage/cards/s/SecondGuess.java +++ b/Mage.Sets/src/mage/cards/s/SecondGuess.java @@ -10,7 +10,7 @@ import mage.constants.CardType; import mage.filter.FilterSpell; import mage.filter.predicate.Predicate; import mage.game.Game; -import mage.game.stack.Spell; +import mage.game.stack.StackObject; import mage.target.TargetSpell; import mage.watchers.common.CastSpellLastTurnWatcher; @@ -45,10 +45,10 @@ public final class SecondGuess extends CardImpl { } } -class SecondSpellPredicate implements Predicate { +class SecondSpellPredicate implements Predicate { @Override - public boolean apply(Spell input, Game game) { + public boolean apply(StackObject input, Game game) { CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); if (watcher.getSpellOrder(new MageObjectReference(input.getId(), game), game) == 2) { diff --git a/Mage.Sets/src/mage/cards/s/SecretsOfTheDead.java b/Mage.Sets/src/mage/cards/s/SecretsOfTheDead.java index 12f8fb89407..bea3c1c1eb7 100644 --- a/Mage.Sets/src/mage/cards/s/SecretsOfTheDead.java +++ b/Mage.Sets/src/mage/cards/s/SecretsOfTheDead.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -9,9 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.FilterSpell; -import mage.filter.predicate.Predicate; -import mage.game.Game; -import mage.game.stack.Spell; +import mage.filter.predicate.other.SpellZonePredicate; /** * @@ -26,8 +23,7 @@ public final class SecretsOfTheDead extends CardImpl { } public SecretsOfTheDead(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // Whenever you cast a spell from your graveyard, draw a card. this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), filter, false)); @@ -42,22 +38,3 @@ public final class SecretsOfTheDead extends CardImpl { return new SecretsOfTheDead(this); } } - -class SpellZonePredicate implements Predicate { - - private final Zone zone; - - public SpellZonePredicate(Zone zone) { - this.zone = zone; - } - - @Override - public boolean apply(Spell input, Game game) { - return input.getFromZone().match(zone); - } - - @Override - public String toString() { - return "SpellZone(" + zone + ')'; - } -} diff --git a/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java b/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java index cf9d71ff692..5ea609409f2 100644 --- a/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java +++ b/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -42,7 +42,7 @@ public final class SedraxisAlchemist extends CardImpl { // When Sedraxis Alchemist enters the battlefield, if you control a blue permanent, return target nonland permanent to its owner's hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); ability.addTarget(new TargetNonlandPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); } diff --git a/Mage.Sets/src/mage/cards/s/SeeRed.java b/Mage.Sets/src/mage/cards/s/SeeRed.java index 2f67b7eeb98..c74b3dd096f 100644 --- a/Mage.Sets/src/mage/cards/s/SeeRed.java +++ b/Mage.Sets/src/mage/cards/s/SeeRed.java @@ -7,7 +7,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.ControllerAttackedThisTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.SacrificeSourceEffect; @@ -54,7 +54,7 @@ public final class SeeRed extends CardImpl { this.addAbility(ability); // At the beginning of your end step, if you didn't attack with a creature this turn, sacrifice See Red. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AtTheBeginOfNextEndStepDelayedTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU), new InvertCondition(ControllerAttackedThisTurnCondition.instance), "At the beginning of your end step, if you didn't attack with a creature this turn, sacrifice {this}."), new AttackedThisTurnWatcher()); diff --git a/Mage.Sets/src/mage/cards/s/Seedtime.java b/Mage.Sets/src/mage/cards/s/Seedtime.java index a6288f05533..dd90232dcf7 100644 --- a/Mage.Sets/src/mage/cards/s/Seedtime.java +++ b/Mage.Sets/src/mage/cards/s/Seedtime.java @@ -22,7 +22,7 @@ import mage.watchers.common.SpellsCastWatcher; */ public final class Seedtime extends CardImpl { - private final static String rule = "Cast {this} only during your turn."; + private final static String rule = "Cast this spell only during your turn."; private final static String rule2 = "Take an extra turn after this one if an opponent cast a blue spell this turn."; public Seedtime(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/s/SelflessSquire.java b/Mage.Sets/src/mage/cards/s/SelflessSquire.java index a77aa097ecb..eac10d15e67 100644 --- a/Mage.Sets/src/mage/cards/s/SelflessSquire.java +++ b/Mage.Sets/src/mage/cards/s/SelflessSquire.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -11,8 +10,8 @@ import mage.abilities.keyword.FlashAbility; 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.counters.CounterType; import mage.game.Game; @@ -75,7 +74,7 @@ class SelflessSquireTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getTargetId().equals(getControllerId())) { + if (isControlledBy(event.getTargetId())) { getEffects().clear(); getEffects().add(new AddCountersSourceEffect(CounterType.P1P1.createInstance(event.getAmount()))); return true; diff --git a/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java b/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java index 3855bb3394c..5cec078a867 100644 --- a/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java +++ b/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; @@ -49,11 +49,11 @@ public final class SelkieHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Selkie Hedge-Mage enters the battlefield, if you control two or more Forests, you may gain 3 life. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); this.addAbility(ability); // When Selkie Hedge-Mage enters the battlefield, if you control two or more Islands, you may return target tapped creature to its owner's hand. - Ability ability2 = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); + Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); ability2.addTarget(new TargetPermanent(filter3)); this.addAbility(ability2); diff --git a/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java b/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java index 1f39b373f4e..34372611f2f 100644 --- a/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java +++ b/Mage.Sets/src/mage/cards/s/SemblanceAnvil.java @@ -109,7 +109,7 @@ class SemblanceAnvilCostReductionEffect extends CostModificationEffectImpl { public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); - if (sourceCard != null && sourceCard.getOwnerId().equals(source.getControllerId())) { + if (sourceCard != null && sourceCard.isOwnedBy(source.getControllerId())) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { List imprinted = permanent.getImprinted(); diff --git a/Mage.Sets/src/mage/cards/s/SenTriplets.java b/Mage.Sets/src/mage/cards/s/SenTriplets.java index e0681a13080..142c2d25c23 100644 --- a/Mage.Sets/src/mage/cards/s/SenTriplets.java +++ b/Mage.Sets/src/mage/cards/s/SenTriplets.java @@ -56,7 +56,7 @@ class SenTripletsRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl { public SenTripletsRuleModifyingEffect() { super(Duration.EndOfTurn, Outcome.Benefit); - staticText = "At the beginning of your upkeep, choose target opponent. This turn, that player can't cast spells or activate abilities"; + staticText = "choose target opponent. This turn, that player can't cast spells or activate abilities"; } public SenTripletsRuleModifyingEffect(final SenTripletsRuleModifyingEffect effect) { @@ -147,7 +147,7 @@ class SenTripletsPlayFromOpponentsHandEffect extends AsThoughEffectImpl { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { Card card = game.getCard(objectId); return card != null && - card.getOwnerId().equals(getTargetPointer().getFirst(game, source)) && + card.isOwnedBy(getTargetPointer().getFirst(game, source)) && game.getState().getZone(objectId) == Zone.HAND && affectedControllerId.equals(source.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/s/SenatorLottDod.java b/Mage.Sets/src/mage/cards/s/SenatorLottDod.java index 903bb71b243..2c6f13cddcc 100644 --- a/Mage.Sets/src/mage/cards/s/SenatorLottDod.java +++ b/Mage.Sets/src/mage/cards/s/SenatorLottDod.java @@ -75,7 +75,7 @@ class SenatorLottDodSpellsTargetingCreatureCostReductionEffect extends CostModif for (Target target : mode.getTargets()) { for (UUID targetUUID : target.getTargets()) { Permanent permanent = game.getPermanent(targetUUID); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SentinelTower.java b/Mage.Sets/src/mage/cards/s/SentinelTower.java index d00278a7eeb..9988c741ccc 100644 --- a/Mage.Sets/src/mage/cards/s/SentinelTower.java +++ b/Mage.Sets/src/mage/cards/s/SentinelTower.java @@ -46,7 +46,7 @@ public final class SentinelTower extends CardImpl { class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility { SentinelTowerTriggeredAbility() { - super(new DamageTargetEffect(0), StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL, false); + super(new DamageTargetEffect(0), StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false); this.addTarget(new TargetAnyTarget()); } @@ -61,7 +61,7 @@ class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(getControllerId()) + if (game.isActivePlayer(getControllerId()) && super.checkTrigger(event, game)) { SentinelTowerWatcher watcher = (SentinelTowerWatcher) game.getState().getWatchers().get(SentinelTowerWatcher.class.getSimpleName()); if (watcher == null) { diff --git a/Mage.Sets/src/mage/cards/s/SerraAvenger.java b/Mage.Sets/src/mage/cards/s/SerraAvenger.java index 065adc24a34..1ddb5e47d22 100644 --- a/Mage.Sets/src/mage/cards/s/SerraAvenger.java +++ b/Mage.Sets/src/mage/cards/s/SerraAvenger.java @@ -80,7 +80,7 @@ class CantCastSerraAvengerEffect extends ContinuousRuleModifyingEffectImpl { if (event.getType() == EventType.CAST_SPELL && event.getSourceId().equals(source.getSourceId())) { Player controller = game.getPlayer(source.getControllerId()); // it can be cast on other players turn 1 - 3 if some effect let allow you to do this - if (controller != null && controller.getTurns() <= 3 && game.getActivePlayerId().equals(source.getControllerId())) { + if (controller != null && controller.getTurns() <= 3 && game.isActivePlayer(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SerraInquisitors.java b/Mage.Sets/src/mage/cards/s/SerraInquisitors.java new file mode 100644 index 00000000000..dacf3b265cd --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SerraInquisitors.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility; +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 mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class SerraInquisitors extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("black creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + public SerraInquisitors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever Serra Inquisitors blocks or becomes blocked by one or more black creatures, Serra Inquisitors gets +2/+0 until end of turn. + this.addAbility(new BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(new BoostSourceEffect(2, 0, Duration.EndOfTurn), filter, false)); + } + + public SerraInquisitors(final SerraInquisitors card) { + super(card); + } + + @Override + public SerraInquisitors copy() { + return new SerraInquisitors(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SerrasGuardian.java b/Mage.Sets/src/mage/cards/s/SerrasGuardian.java new file mode 100644 index 00000000000..e58e5e18d56 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SerrasGuardian.java @@ -0,0 +1,56 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.constants.SubType; +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.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class SerrasGuardian extends CardImpl { + + public SerrasGuardian(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Other creatures you control have vigilance. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), + Duration.WhileOnBattlefield, + StaticFilters.FILTER_CONTROLLED_CREATURES, + true + ) + )); + } + + public SerrasGuardian(final SerrasGuardian card) { + super(card); + } + + @Override + public SerrasGuardian copy() { + return new SerrasGuardian(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SerumPowder.java b/Mage.Sets/src/mage/cards/s/SerumPowder.java index cdc8e4b6e8b..955f9a5bf62 100644 --- a/Mage.Sets/src/mage/cards/s/SerumPowder.java +++ b/Mage.Sets/src/mage/cards/s/SerumPowder.java @@ -87,7 +87,7 @@ class SerumPowderReplaceEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/s/SeshiroTheAnointed.java b/Mage.Sets/src/mage/cards/s/SeshiroTheAnointed.java index af2cdf3a2a8..cca4023c354 100644 --- a/Mage.Sets/src/mage/cards/s/SeshiroTheAnointed.java +++ b/Mage.Sets/src/mage/cards/s/SeshiroTheAnointed.java @@ -81,7 +81,7 @@ class SeshiroTheAnointedAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && p != null && p.hasSubtype(SubType.SNAKE, game) && p.getControllerId().equals(controllerId)) { + if (damageEvent.isCombatDamage() && p != null && p.hasSubtype(SubType.SNAKE, game) && p.isControlledBy(controllerId)) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java b/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java index b68584e3c43..4a2a86accd7 100644 --- a/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java +++ b/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java @@ -73,7 +73,7 @@ class SettleTheWreckageEffect extends OneShotEffect { Iterator creatureIds = game.getCombat().getAttackers().iterator(); while (creatureIds.hasNext()) { Permanent creature = game.getPermanent(creatureIds.next()); - if (creature != null && creature.getControllerId().equals(player.getId())) { + if (creature != null && creature.isControlledBy(player.getId())) { toExile.add(creature); attackers++; } diff --git a/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java b/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java index 8839aaea5e5..c85fcab35df 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java +++ b/Mage.Sets/src/mage/cards/s/ShadowOfTheGrave.java @@ -63,7 +63,7 @@ class ShadowOfTheGraveEffect extends OneShotEffect { && watcher != null) { for (Card card : watcher.getCardsCycledOrDiscardedThisTurn(controller.getId()).getCards(game)) { if (game.getState().getZone(card.getId()) == Zone.GRAVEYARD //must come from their graveyard - && card.getOwnerId().equals(controller.getId())) { //confirm ownership, but it should not be possible to get not ownwd cards here + && card.isOwnedBy(controller.getId())) { //confirm ownership, but it should not be possible to get not ownwd cards here controller.moveCardToHandWithInfo(card, source.getId(), game, true); } } diff --git a/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java b/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java index dec16b639ba..3df0a4f7f86 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java +++ b/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.SacrificeControllerEffect; import mage.abilities.keyword.FlyingAbility; @@ -55,7 +55,7 @@ public final class ShadowbornDemon extends CardImpl { this.addAbility(ability); // At the beginning of your upkeep, if there are fewer than six creature cards in your graveyard, sacrifice a creature. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new SacrificeControllerEffect(StaticFilters.FILTER_PERMANENT_CREATURE, 1, ""), TargetController.YOU, false), new InvertCondition(new CreatureCardsInControllerGraveCondition(6)), "At the beginning of your upkeep, if there are fewer than six creature cards in your graveyard, sacrifice a creature")); diff --git a/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java b/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java index 8a3d88c5ec2..8718cc44df4 100644 --- a/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java +++ b/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java @@ -92,7 +92,7 @@ class ShamanOfForgottenWaysManaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = source.getSourceObject(game); - return object != null && (object instanceof Spell) && object.isCreature(); + return object instanceof Spell && object.isCreature(); } } diff --git a/Mage.Sets/src/mage/cards/s/ShamblingGhoul.java b/Mage.Sets/src/mage/cards/s/ShamblingGhoul.java index feabef83284..3522044fb08 100644 --- a/Mage.Sets/src/mage/cards/s/ShamblingGhoul.java +++ b/Mage.Sets/src/mage/cards/s/ShamblingGhoul.java @@ -16,7 +16,7 @@ import mage.constants.SubType; */ public final class ShamblingGhoul extends CardImpl { - private static final String staticText = "{this} enters the battlefield tapped"; + private static final String staticText = "tapped"; public ShamblingGhoul(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); diff --git a/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java b/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java index 5477904286e..6041c378550 100644 --- a/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java +++ b/Mage.Sets/src/mage/cards/s/ShannaSisaysLegacy.java @@ -104,7 +104,7 @@ class ShannaSisaysLegacyEffect extends ContinuousRuleModifyingEffectImpl { StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); if (targetCard != null && stackObject != null && targetCard.getId().equals(source.getSourceId())) { if (stackObject instanceof Ability) { - if (!stackObject.getControllerId().equals(source.getControllerId())) { + if (!stackObject.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java b/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java new file mode 100644 index 00000000000..3e33b199b6b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShapeOfTheWiitigo.java @@ -0,0 +1,133 @@ +package mage.cards.s; + +import java.util.*; + +import mage.MageObjectReference; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.counter.AddCountersAttachedEffect; +import mage.abilities.effects.common.counter.RemoveCountersAttachedEffect; +import mage.constants.*; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.watchers.Watcher; + +/** + * + * @author noahg + */ +public final class ShapeOfTheWiitigo extends CardImpl { + + public ShapeOfTheWiitigo(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{G}{G}"); + + 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 Shape of the Wiitigo enters the battlefield, put six +1/+1 counters on enchanted creature. + this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersAttachedEffect(CounterType.P1P1.createInstance(6), "enchanted creature"))); + + // At the beginning of your upkeep, put a +1/+1 counter on enchanted creature if it attacked or blocked since your last upkeep. Otherwise, remove a +1/+1 counter from it. + Ability triggeredAbility = new BeginningOfUpkeepTriggeredAbility( + new ConditionalOneShotEffect(new AddCountersAttachedEffect(CounterType.P1P1.createInstance(1), "enchanted creature"), + new RemoveCountersAttachedEffect(CounterType.P1P1.createInstance(1), "it"), + new AttachedAttackedOrBlockedSinceYourLastUpkeepCondition(), + "put a +1/+1 counter on enchanted creature if it attacked or blocked since your last " + + "upkeep. Otherwise, remove a +1/+1 counter from it"), TargetController.YOU, false); + triggeredAbility.addWatcher(new AttackedOrBlockedSinceYourLastUpkeepWatcher()); + this.addAbility(triggeredAbility); + } + + public ShapeOfTheWiitigo(final ShapeOfTheWiitigo card) { + super(card); + } + + @Override + public ShapeOfTheWiitigo copy() { + return new ShapeOfTheWiitigo(this); + } +} + +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()); + if (permanent != null && permanent.getAttachedTo() != null && watcher != null) { + Permanent attachedTo = game.getBattlefield().getPermanent(permanent.getAttachedTo()); + if (attachedTo == null) { + attachedTo = (Permanent) game.getLastKnownInformation(permanent.getAttachedTo(), Zone.BATTLEFIELD); + } + if (attachedTo != null) { + return watcher.attackedSinceLastUpkeep(new MageObjectReference(attachedTo.getId(), attachedTo.getZoneChangeCounter(game), game), source.getControllerId()); + } + } + return false; + } + + @Override + public String toString() { + return "it attacked or blocked since your last upkeep"; + } +} + +class AttackedOrBlockedSinceYourLastUpkeepWatcher extends Watcher{ + + //Map of each player to the creatures that attacked or blocked since their last upkeep + private final Map> attackedOrBlockedCreatures = new HashMap<>(); + + public AttackedOrBlockedSinceYourLastUpkeepWatcher() { + super(AttackedOrBlockedSinceYourLastUpkeepWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public AttackedOrBlockedSinceYourLastUpkeepWatcher(AttackedOrBlockedSinceYourLastUpkeepWatcher watcher) { + super(watcher); + for (Map.Entry> entry : watcher.attackedOrBlockedCreatures.entrySet()) { + Set allAttackersCopy = new HashSet<>(entry.getValue()); + attackedOrBlockedCreatures.put(entry.getKey(), allAttackersCopy); + } + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.UPKEEP_STEP_POST){ + //Clear + attackedOrBlockedCreatures.put(event.getPlayerId(), new HashSet<>()); + } else if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED || event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { + MageObjectReference mor = new MageObjectReference(event.getSourceId(), game); + for (UUID player : game.getPlayerList()){ + if (!attackedOrBlockedCreatures.containsKey(player)) { + attackedOrBlockedCreatures.put(player, new HashSet<>()); + } + attackedOrBlockedCreatures.get(player).add(mor); + } + } + } + + public boolean attackedSinceLastUpkeep(MageObjectReference mor, UUID upkeepPlayer){ + return attackedOrBlockedCreatures.get(upkeepPlayer).contains(mor); + } + + @Override + public AttackedOrBlockedSinceYourLastUpkeepWatcher copy() { + return new AttackedOrBlockedSinceYourLastUpkeepWatcher(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/ShapersSanctuary.java b/Mage.Sets/src/mage/cards/s/ShapersSanctuary.java index 60c09594412..76469436309 100644 --- a/Mage.Sets/src/mage/cards/s/ShapersSanctuary.java +++ b/Mage.Sets/src/mage/cards/s/ShapersSanctuary.java @@ -61,7 +61,7 @@ class CreaturesYouControlTargetedTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); Player targetter = game.getPlayer(event.getPlayerId()); - if (permanent != null && permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { + if (permanent != null && permanent.isControlledBy(this.getControllerId()) && permanent.isCreature()) { Object object = game.getObject(event.getSourceId()); if (object != null && targetter != null && targetter.hasOpponent(this.getControllerId(), game)) { return true; diff --git a/Mage.Sets/src/mage/cards/s/ShieldMare.java b/Mage.Sets/src/mage/cards/s/ShieldMare.java new file mode 100644 index 00000000000..b75a0b10d09 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShieldMare.java @@ -0,0 +1,116 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.constants.SubType; +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.FilterStackObject; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; + +/** + * + * @author TheElk801 + */ +public final class ShieldMare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("red creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + } + + public ShieldMare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + + this.subtype.add(SubType.HORSE); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Shield Mare can't be blocked by red creatures. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ) + )); + + // When Shield Mare enters the battlefield or becomes the target of a spell or ability and opponent controls, you gain 3 life. + this.addAbility(new ShieldMareTriggeredAbility()); + } + + public ShieldMare(final ShieldMare card) { + super(card); + } + + @Override + public ShieldMare copy() { + return new ShieldMare(this); + } +} + +class ShieldMareTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterStackObject filter = new FilterStackObject(); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public ShieldMareTriggeredAbility() { + super(Zone.ALL, new GainLifeEffect(3)); + } + + public ShieldMareTriggeredAbility(final ShieldMareTriggeredAbility effect) { + super(effect); + } + + @Override + public ShieldMareTriggeredAbility copy() { + return new ShieldMareTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD + || event.getType() == GameEvent.EventType.TARGETED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { + return event.getTargetId().equals(getSourceId()); + } + if (event.getType() == GameEvent.EventType.TARGETED) { + Permanent permanent = game.getPermanent(getSourceId()); + if (permanent == null) { + return false; + } + StackObject object = game.getStack().getStackObject(event.getSourceId()); + return event.getTargetId().equals(getSourceId()) + && filter.match(object, getSourceId(), getControllerId(), game); + } + return false; + } + + @Override + public String getRule() { + return "When {this} enters the battlefield or becomes the target" + + " of a spell or ability an opponent controls, you gain 3 life"; + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShiningShoal.java b/Mage.Sets/src/mage/cards/s/ShiningShoal.java index 861eef89810..5733872da8c 100644 --- a/Mage.Sets/src/mage/cards/s/ShiningShoal.java +++ b/Mage.Sets/src/mage/cards/s/ShiningShoal.java @@ -111,7 +111,7 @@ class ShiningShoalRedirectDamageTargetEffect extends RedirectDamageFromSourceToT // check creature first Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature()) { - if (permanent.getControllerId().equals(source.getControllerId())) { + if (permanent.isControlledBy(source.getControllerId())) { // it's your creature redirectTarget = source.getTargets().get(1); return true; diff --git a/Mage.Sets/src/mage/cards/s/ShipbreakerKraken.java b/Mage.Sets/src/mage/cards/s/ShipbreakerKraken.java index a0f0afcd480..d43cfaed037 100644 --- a/Mage.Sets/src/mage/cards/s/ShipbreakerKraken.java +++ b/Mage.Sets/src/mage/cards/s/ShipbreakerKraken.java @@ -90,7 +90,7 @@ class ShipbreakerKrakenReplacementEffect extends ContinuousRuleModifyingEffectIm // the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL // event will happen before this effect is applied ever) Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent == null || !sourcePermanent.getControllerId().equals(source.getControllerId())) { + if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { discard(); return false; } diff --git a/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java b/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java index 17765b37768..03ae7cef4b1 100644 --- a/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java +++ b/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -29,7 +29,7 @@ public final class ShipwreckLooter extends CardImpl { this.toughness = new MageInt(1); // Raid - When Shipwreck Looter enters the battlefield,if you attacked with a creature this turn, you may draw a card. If you do, discard a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true)), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, you may draw a card. If you do, discard a card."); diff --git a/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java b/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java index 003933e4937..6e0d7d255f4 100644 --- a/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java +++ b/Mage.Sets/src/mage/cards/s/ShireiShizosCaretaker.java @@ -80,7 +80,7 @@ class ShireiShizosCaretakerTriggeredAbility extends TriggeredAbilityImpl { Card card = game.getCard(zEvent.getTargetId()); if (card != null && LKIpermanent != null - && card.getOwnerId().equals(this.controllerId) + && card.isOwnedBy(this.controllerId) && zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.BATTLEFIELD && card.isCreature() diff --git a/Mage.Sets/src/mage/cards/s/ShivanEmissary.java b/Mage.Sets/src/mage/cards/s/ShivanEmissary.java index 1015ea205b6..ca39be13120 100644 --- a/Mage.Sets/src/mage/cards/s/ShivanEmissary.java +++ b/Mage.Sets/src/mage/cards/s/ShivanEmissary.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -44,7 +44,7 @@ public final class ShivanEmissary extends CardImpl { // When Shivan Emissary enters the battlefield, if it was kicked, destroy target nonblack creature. It can't be regenerated. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target nonblack creature. It can't be regenerated.")); } diff --git a/Mage.Sets/src/mage/cards/s/ShockmawDragon.java b/Mage.Sets/src/mage/cards/s/ShockmawDragon.java index e8c5f932a8b..7945aa60f16 100644 --- a/Mage.Sets/src/mage/cards/s/ShockmawDragon.java +++ b/Mage.Sets/src/mage/cards/s/ShockmawDragon.java @@ -1,22 +1,23 @@ - package mage.cards.s; -import java.util.List; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.filter.StaticFilters; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; /** * @@ -34,7 +35,7 @@ public final class ShockmawDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Shockmaw Dragon deals combat damage to a player, it deals 1 damage to each creature that player controls. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ShockmawDragonEffect(), false, true)); + this.addAbility(new PolisCrusherTriggeredAbility()); } public ShockmawDragon(final ShockmawDragon card) { @@ -47,34 +48,45 @@ public final class ShockmawDragon extends CardImpl { } } -class ShockmawDragonEffect extends OneShotEffect { +class PolisCrusherTriggeredAbility extends TriggeredAbilityImpl { - public ShockmawDragonEffect() { - super(Outcome.Damage); - staticText = "it deals 1 damage to each creature that player controls"; + public PolisCrusherTriggeredAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(1), true); } - public ShockmawDragonEffect(final ShockmawDragonEffect effect) { - super(effect); + public PolisCrusherTriggeredAbility(final PolisCrusherTriggeredAbility ability) { + super(ability); } @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if (player != null) { - List creatures = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game); - for (Permanent creature : creatures) { - if (creature != null) { - creature.damage(1, source.getSourceId(), game, false, true); - } + public PolisCrusherTriggeredAbility copy() { + return new PolisCrusherTriggeredAbility(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 (event.getSourceId().equals(this.sourceId) && ((DamagedPlayerEvent) event).isCombatDamage()) { + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + FilterPermanent filter = new FilterPermanent("a creature controlled by " + player.getLogName()); + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new ControllerIdPredicate(event.getTargetId())); + this.getTargets().clear(); + this.addTarget(new TargetPermanent(filter)); + return true; } - return true; } return false; } @Override - public ShockmawDragonEffect copy() { - return new ShockmawDragonEffect(this); + public String getRule() { + return "Whenever {this} deals combat damage to a player," + + " it deals 1 damage to each creature that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java b/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java index 1c82c152455..3ff22606e00 100644 --- a/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java +++ b/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -38,7 +38,7 @@ public final class ShorelineSalvager extends CardImpl { this.toughness = new MageInt(3); // Whenever Shoreline Salvager deals combat damage to a player, if you control an Island, you may draw a card. - this.addAbility(new ConditionalTriggeredAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true), new PermanentsOnTheBattlefieldCondition(filter), rule)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true), new PermanentsOnTheBattlefieldCondition(filter), rule)); } public ShorelineSalvager(final ShorelineSalvager card) { diff --git a/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java b/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java index f1e30ff4e4f..4cc23ef06a9 100644 --- a/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java +++ b/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class ShriekingGrotesque extends CardImpl { // When Shrieking Grotesque enters the battlefield, if {B} was spent to cast it, target player discards a card. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1), false); ability.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.B), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.B), "if {B} was spent to cast {this}, target player discards a card."), new ManaSpentToCastWatcher()); } diff --git a/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java b/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java index ed1f7861a63..7c3527181ca 100644 --- a/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java +++ b/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TributeAbility; @@ -37,7 +37,7 @@ public final class ShrikeHarpy extends CardImpl { // When Shrike Harpy enters the battlefield, if tribute wasn't paid, target opponent sacrifices a creature. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SacrificeEffect(new FilterCreaturePermanent("a creature"), 1, "target opponent"), false); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, target opponent sacrifices a creature.")); } diff --git a/Mage.Sets/src/mage/cards/s/ShrineOfBoundlessGrowth.java b/Mage.Sets/src/mage/cards/s/ShrineOfBoundlessGrowth.java index 21a00c86465..1ab6e27212c 100644 --- a/Mage.Sets/src/mage/cards/s/ShrineOfBoundlessGrowth.java +++ b/Mage.Sets/src/mage/cards/s/ShrineOfBoundlessGrowth.java @@ -13,10 +13,12 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; +import mage.abilities.meta.OrTriggeredAbility; 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.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; @@ -37,8 +39,9 @@ public final class ShrineOfBoundlessGrowth extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); // At the beginning of your upkeep or whenever you cast a green spell, put a charge counter on Shrine of Boundless Growth. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false), + new SpellCastControllerTriggeredAbility(null, filter, false))); // {T}, Sacrifice Shrine of Boundless Growth: Add {C} for each charge counter on Shrine of Boundless Growth. Ability ability = new DynamicManaAbility(Mana.ColorlessMana(1), new CountersSourceCount(CounterType.CHARGE), new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/s/ShrineOfBurningRage.java b/Mage.Sets/src/mage/cards/s/ShrineOfBurningRage.java index 53e4b55e3ee..c69fa38694a 100644 --- a/Mage.Sets/src/mage/cards/s/ShrineOfBurningRage.java +++ b/Mage.Sets/src/mage/cards/s/ShrineOfBurningRage.java @@ -14,6 +14,7 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.meta.OrTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -37,8 +38,13 @@ public final class ShrineOfBurningRage extends CardImpl { public ShrineOfBurningRage (UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); + + //At the beginning of your upkeep or whenever you cast a red spell, put a charge counter on Shrine of Burning Rage. + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false), + new SpellCastControllerTriggeredAbility(null, filter, false))); + + //{3}, {T}, Sacrifice Shrine of Burning Rage: It deals damage equal to the number of charge counters on it to any target. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(3)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/cards/s/ShrineOfLimitlessPower.java b/Mage.Sets/src/mage/cards/s/ShrineOfLimitlessPower.java index c16b7b9a53c..21585426038 100644 --- a/Mage.Sets/src/mage/cards/s/ShrineOfLimitlessPower.java +++ b/Mage.Sets/src/mage/cards/s/ShrineOfLimitlessPower.java @@ -13,6 +13,7 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.meta.OrTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -38,9 +39,12 @@ public final class ShrineOfLimitlessPower extends CardImpl { public ShrineOfLimitlessPower(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); + //At the beginning of your upkeep or whenever you cast a black spell, put a charge counter on Shrine of Limitless Power. + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false), + new SpellCastControllerTriggeredAbility(null, filter, false))); + //{4}, {T}, Sacrifice Shrine of Limitless Power: Target player discards a card for each charge counter on Shrine of Limitless Power. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/cards/s/ShrineOfLoyalLegions.java b/Mage.Sets/src/mage/cards/s/ShrineOfLoyalLegions.java index 77c8747654c..496428e76fb 100644 --- a/Mage.Sets/src/mage/cards/s/ShrineOfLoyalLegions.java +++ b/Mage.Sets/src/mage/cards/s/ShrineOfLoyalLegions.java @@ -13,6 +13,7 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.meta.OrTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -38,9 +39,12 @@ public final class ShrineOfLoyalLegions extends CardImpl { public ShrineOfLoyalLegions(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); + //At the beginning of your upkeep or whenever you cast a white spell, put a charge counter on Shrine of Loyal Legions. + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false), + new SpellCastControllerTriggeredAbility(null, filter, false))); + //{3}, {T}, Sacrifice Shrine of Loyal Legions: Create a 1/1 colorless Myr artifact creature token for each charge counter on Shrine of Loyal Legions. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new MyrToken("NPH"), new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(3)); diff --git a/Mage.Sets/src/mage/cards/s/ShrineOfPiercingVision.java b/Mage.Sets/src/mage/cards/s/ShrineOfPiercingVision.java index 142899a0de3..1288738d322 100644 --- a/Mage.Sets/src/mage/cards/s/ShrineOfPiercingVision.java +++ b/Mage.Sets/src/mage/cards/s/ShrineOfPiercingVision.java @@ -11,6 +11,7 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.meta.OrTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -45,8 +46,10 @@ public final class ShrineOfPiercingVision extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // At the beginning of your upkeep or whenever you cast a blue spell, put a charge counter on Shrine of Piercing Vision. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); - this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); + this.addAbility(new OrTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), + new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false), + new SpellCastControllerTriggeredAbility(null, filter, false))); + // {tap}, Sacrifice Shrine of Piercing Vision: Look at the top X cards of your library, where X is the number of charge counters on Shrine of Piercing Vision. // Put one of those cards into your hand and the rest on the bottom of your library in any order. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShrineOfPiercingVisionEffect(), new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/s/ShrivelingRot.java b/Mage.Sets/src/mage/cards/s/ShrivelingRot.java index 9d2961830a5..57c8db95357 100644 --- a/Mage.Sets/src/mage/cards/s/ShrivelingRot.java +++ b/Mage.Sets/src/mage/cards/s/ShrivelingRot.java @@ -148,7 +148,7 @@ class ShrivelingRotEffect extends OneShotEffect { Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (permanent != null) { if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId()) - && !game.getState().getZone(permanent.getId()).equals(Zone.GRAVEYARD)) { + && game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) { // A replacement effect has moved the card to another zone as graveyard return true; } diff --git a/Mage.Sets/src/mage/cards/s/SickleDancer.java b/Mage.Sets/src/mage/cards/s/SickleDancer.java index 3275d6c93e8..ec80b693b90 100644 --- a/Mage.Sets/src/mage/cards/s/SickleDancer.java +++ b/Mage.Sets/src/mage/cards/s/SickleDancer.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class SickleDancer extends CardImpl { this.toughness = new MageInt(2); // Whenever Sickle Dancer attacks, if your team controls another Warrior, Sickle Dancer gets +1/+1 until end of turn. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false), new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks, if your team controls another Warrior, {this} gets +1/+1 until end of turn." diff --git a/Mage.Sets/src/mage/cards/s/SidarJabari.java b/Mage.Sets/src/mage/cards/s/SidarJabari.java index 23ece849599..75cd2d644d9 100644 --- a/Mage.Sets/src/mage/cards/s/SidarJabari.java +++ b/Mage.Sets/src/mage/cards/s/SidarJabari.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -13,8 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; 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; /** @@ -23,10 +21,14 @@ import mage.target.common.TargetCreaturePermanent; */ public final class SidarJabari extends CardImpl { - private final UUID originalId; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(new DefendingPlayerControlsPredicate()); + } public SidarJabari(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.KNIGHT); @@ -38,26 +40,12 @@ public final class SidarJabari extends CardImpl { // Whenever Sidar Jabari attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - originalId = ability.getOriginalId(); + ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } public SidarJabari(final SidarJabari 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/s/SidisiBroodTyrant.java b/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java index 3a3c4e1f8a8..933cbb20ce9 100644 --- a/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java +++ b/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java @@ -78,7 +78,7 @@ class SidisiBroodTyrantTriggeredAbility extends TriggeredAbilityImpl { Set cardType = card.getCardType(); if (cardOwnerId != null - && card.getOwnerId().equals(getControllerId()) + && card.isOwnedBy(getControllerId()) && cardType != null && card.isCreature()) { return true; diff --git a/Mage.Sets/src/mage/cards/s/SiegeBehemoth.java b/Mage.Sets/src/mage/cards/s/SiegeBehemoth.java index 2eaaafa5734..96675daffaf 100644 --- a/Mage.Sets/src/mage/cards/s/SiegeBehemoth.java +++ b/Mage.Sets/src/mage/cards/s/SiegeBehemoth.java @@ -3,19 +3,21 @@ package mage.cards.s; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.DamageAsThoughNotBlockedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HexproofAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; /** * @@ -34,15 +36,9 @@ public final class SiegeBehemoth extends CardImpl { // Hexproof this.addAbility(HexproofAbility.getInstance()); + // As long as Siege Behemoth is attacking, for each creature you control, you may have that creature assign its combat damage as though it weren't blocked. - // TODO: DamageAsThoughNotBlockedAbility should be done by rule modifying effect instead of adding ability (if controlled creature looses all abilities it should'nt loose this effect) - this.addAbility(new SimpleStaticAbility( - Zone.BATTLEFIELD, - new ConditionalContinuousEffect( - new GainAbilityControlledEffect(DamageAsThoughNotBlockedAbility.getInstance(), Duration.WhileOnBattlefield, filter), - SourceAttackingCondition.instance, - "As long as {this} is attacking, for each creature you control, you may have that creature assign its combat damage as though it weren't blocked" - ))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SiegeBehemothEffect())); } public SiegeBehemoth(final SiegeBehemoth card) { @@ -54,3 +50,39 @@ public final class SiegeBehemoth extends CardImpl { return new SiegeBehemoth(this); } } + +class SiegeBehemothEffect extends AsThoughEffectImpl { + + public SiegeBehemothEffect() { + super(AsThoughEffectType.DAMAGE_NOT_BLOCKED, Duration.WhileOnBattlefield, Outcome.Damage); + this.staticText = "As long as {this} is attacking, for each creature you control, you may have that creature assign its combat damage as though it weren't blocked"; + } + + public SiegeBehemothEffect(SiegeBehemothEffect effect) { + super(effect); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (sourcePermanent != null && sourcePermanent.isAttacking()){ + Player controller = game.getPlayer(source.getControllerId()); + Permanent otherCreature = game.getPermanent(sourceId); + if (controller != null && otherCreature != null && otherCreature.isControlledBy(controller.getId())){ + return controller.chooseUse(Outcome.Damage, "Do you wish to assign damage for " + + otherCreature.getLogName() + " as though it weren't blocked?", source, game); + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public SiegeBehemothEffect copy() { + return new SiegeBehemothEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SiegebreakerGiant.java b/Mage.Sets/src/mage/cards/s/SiegebreakerGiant.java new file mode 100644 index 00000000000..b8d6b7b5cf0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SiegebreakerGiant.java @@ -0,0 +1,53 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class SiegebreakerGiant extends CardImpl { + + public SiegebreakerGiant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.GIANT); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(6); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // {3}{R}: Target creature can't block this turn. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new CantBlockTargetEffect(Duration.EndOfTurn), + new ManaCostsImpl("{3}{R}") + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public SiegebreakerGiant(final SiegebreakerGiant card) { + super(card); + } + + @Override + public SiegebreakerGiant copy() { + return new SiegebreakerGiant(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SigilCaptain.java b/Mage.Sets/src/mage/cards/s/SigilCaptain.java index c216469dfd1..e14f9428f69 100644 --- a/Mage.Sets/src/mage/cards/s/SigilCaptain.java +++ b/Mage.Sets/src/mage/cards/s/SigilCaptain.java @@ -69,7 +69,7 @@ class SigilCaptainTriggeredAbility extends TriggeredAbilityImpl { if (permanent == null) { return false; } - if (permanent.getControllerId().equals(controllerId) + if (permanent.isControlledBy(controllerId) && permanent.getPower().getValue() == 1 && permanent.getToughness().getValue() == 1) { for (Effect effect : this.getEffects()) { diff --git a/Mage.Sets/src/mage/cards/s/SigilOfValor.java b/Mage.Sets/src/mage/cards/s/SigilOfValor.java index f7954a8225a..aafeddaf209 100644 --- a/Mage.Sets/src/mage/cards/s/SigilOfValor.java +++ b/Mage.Sets/src/mage/cards/s/SigilOfValor.java @@ -75,13 +75,12 @@ class SigilOfValorTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(getControllerId())) { + if (game.isActivePlayer(getControllerId())) { if (game.getCombat().attacksAlone()) { Permanent equipment = game.getPermanent(getSourceId()); UUID attackerId = game.getCombat().getAttackers().get(0); if (equipment != null - && equipment.getAttachedTo() != null - && equipment.getAttachedTo().equals(attackerId)) { + && equipment.isAttachedTo(attackerId)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(attackerId)); return true; } diff --git a/Mage.Sets/src/mage/cards/s/SigilTracer.java b/Mage.Sets/src/mage/cards/s/SigilTracer.java index 62154c42465..bcce031f3be 100644 --- a/Mage.Sets/src/mage/cards/s/SigilTracer.java +++ b/Mage.Sets/src/mage/cards/s/SigilTracer.java @@ -43,7 +43,7 @@ public final class SigilTracer extends CardImpl { // {1}{U}, Tap two untapped Wizards you control: Copy target instant or sorcery spell. You may choose new targets for the copy. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CopyTargetSpellEffect(), new ManaCostsImpl("{1}{U}")); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SigiledSwordOfValeron.java b/Mage.Sets/src/mage/cards/s/SigiledSwordOfValeron.java new file mode 100644 index 00000000000..491e3f5d2b8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SigiledSwordOfValeron.java @@ -0,0 +1,66 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.AddCardSubtypeAttachedEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.game.permanent.token.KnightToken; + +/** + * + * @author TheElk801 + */ +public final class SigiledSwordOfValeron extends CardImpl { + + public SigiledSwordOfValeron(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature gets +2/+0, has vigilance, and is a Knight in addition to its other types. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostEquippedEffect(2, 0) + ); + ability.addEffect(new GainAbilityAttachedEffect( + VigilanceAbility.getInstance(), + AttachmentType.EQUIPMENT + ).setText(", has vigilance")); + ability.addEffect(new AddCardSubtypeAttachedEffect( + SubType.KNIGHT, + Duration.WhileOnBattlefield, + AttachmentType.EQUIPMENT + ).setText(", and is a Knight in addition to its other types")); + this.addAbility(ability); + + // Whenever equipped creature attacks, create a 2/2 white Knight creature token with vigilance that's attacking. + this.addAbility(new AttacksAttachedTriggeredAbility( + new CreateTokenEffect(new KnightToken(), 1, false, true) + )); + + // Equip {3} + this.addAbility(new EquipAbility(3)); + } + + public SigiledSwordOfValeron(final SigiledSwordOfValeron card) { + super(card); + } + + @Override + public SigiledSwordOfValeron copy() { + return new SigiledSwordOfValeron(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SilasRennSeekerAdept.java b/Mage.Sets/src/mage/cards/s/SilasRennSeekerAdept.java index 040f3ae781f..9343d54c7d9 100644 --- a/Mage.Sets/src/mage/cards/s/SilasRennSeekerAdept.java +++ b/Mage.Sets/src/mage/cards/s/SilasRennSeekerAdept.java @@ -79,7 +79,7 @@ class SilasRennSeekerAdeptPlayEffect extends AsThoughEffectImpl { UUID targetId = getTargetPointer().getFirst(game, source); if (targetId != null) { return targetId.equals(objectId) - && source.getControllerId().equals(affectedControllerId); + && source.isControlledBy(affectedControllerId); } else { // the target card has changed zone meanwhile, so the effect is no longer needed discard(); diff --git a/Mage.Sets/src/mage/cards/s/SilkweaverElite.java b/Mage.Sets/src/mage/cards/s/SilkweaverElite.java index 880d19a8266..916511fc096 100644 --- a/Mage.Sets/src/mage/cards/s/SilkweaverElite.java +++ b/Mage.Sets/src/mage/cards/s/SilkweaverElite.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class SilkweaverElite extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Revolt — When Silkweaver Elite enters the battlefield, if a permanent you controlled left the battlefield this turn, draw a card. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new DrawCardSourceControllerEffect(1), false), RevoltCondition.instance, "Revolt — When {this} enters the battlefield, if a permanent you controlled left" + " the battlefield this turn, draw a card."); diff --git a/Mage.Sets/src/mage/cards/s/SilverbeakGriffin.java b/Mage.Sets/src/mage/cards/s/SilverbeakGriffin.java new file mode 100644 index 00000000000..5de1ba58b36 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SilverbeakGriffin.java @@ -0,0 +1,36 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class SilverbeakGriffin extends CardImpl { + + public SilverbeakGriffin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}"); + + this.subtype.add(SubType.GRIFFIN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + } + + public SilverbeakGriffin(final SilverbeakGriffin card) { + super(card); + } + + @Override + public SilverbeakGriffin copy() { + return new SilverbeakGriffin(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SilverfurPartisan.java b/Mage.Sets/src/mage/cards/s/SilverfurPartisan.java index b7c15d5eaad..4caebce8f99 100644 --- a/Mage.Sets/src/mage/cards/s/SilverfurPartisan.java +++ b/Mage.Sets/src/mage/cards/s/SilverfurPartisan.java @@ -75,7 +75,7 @@ class CreaturesYouControlBecomesTargetTriggeredAbility extends TriggeredAbilityI @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(this.controllerId) && (permanent.hasSubtype(SubType.WOLF, game) || permanent.hasSubtype(SubType.WEREWOLF, game))) { + if (permanent != null && permanent.isControlledBy(this.controllerId) && (permanent.hasSubtype(SubType.WOLF, game) || permanent.hasSubtype(SubType.WEREWOLF, game))) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object instanceof Spell) { Card c = (Spell) object; diff --git a/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java b/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java index f45ff2d406e..ec7a60aae03 100644 --- a/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java +++ b/Mage.Sets/src/mage/cards/s/SilverpeltWerewolf.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -39,7 +39,7 @@ public final class SilverpeltWerewolf extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Silverpelt Werewolf. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public SilverpeltWerewolf(final SilverpeltWerewolf card) { diff --git a/Mage.Sets/src/mage/cards/s/SimicGuildmage.java b/Mage.Sets/src/mage/cards/s/SimicGuildmage.java index 8a69eea82fa..45d3b6eec78 100644 --- a/Mage.Sets/src/mage/cards/s/SimicGuildmage.java +++ b/Mage.Sets/src/mage/cards/s/SimicGuildmage.java @@ -110,7 +110,7 @@ class MoveCounterFromTargetToTargetEffect extends OneShotEffect { if (source.getTargets().size() > 1) { toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); } - if (fromPermanent == null || toPermanent == null || !fromPermanent.getControllerId().equals(toPermanent.getControllerId())) { + if (fromPermanent == null || toPermanent == null || !fromPermanent.isControlledBy(toPermanent.getControllerId())) { return false; } fromPermanent.removeCounters(CounterType.P1P1.createInstance(1), game); @@ -136,7 +136,7 @@ class SameControllerPredicate implements ObjectSourcePlayerPredicateHate — When Sith Assassin enters the battlefield, if opponent lost life from source other than combat damage this turn, you may destroy target nonblack creature. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true), HateCondition.instance, "Hate — When {this} enters the battlefield, if an opponent lost life from a source other than combat damage this turn, you may destroy target nonblack creature."); diff --git a/Mage.Sets/src/mage/cards/s/SithInquisitor.java b/Mage.Sets/src/mage/cards/s/SithInquisitor.java index 978fac9b6b4..36da9574376 100644 --- a/Mage.Sets/src/mage/cards/s/SithInquisitor.java +++ b/Mage.Sets/src/mage/cards/s/SithInquisitor.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class SithInquisitor extends CardImpl { this.toughness = new MageInt(1); // Hate — When Sith Assassin enters the battlefield, if opponent lost life from source other than combat damage this turn, target player discard a card at random. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1, true)), HateCondition.instance, "Hate — When {this} enters the battlefield, if an opponent lost life from a source other then combat damage this turn, target player discard a card at random."); diff --git a/Mage.Sets/src/mage/cards/s/SithMagic.java b/Mage.Sets/src/mage/cards/s/SithMagic.java index 1913a8220c5..a45c7569763 100644 --- a/Mage.Sets/src/mage/cards/s/SithMagic.java +++ b/Mage.Sets/src/mage/cards/s/SithMagic.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; @@ -46,7 +46,7 @@ public final class SithMagic extends CardImpl { // Hate — At the beggining of each combat, if opponent lost life from a source other than combat damage this turn, you may return target card from a graveyard to the battlefield under your control. It gains lifelink and haste. Exile it at the beginning of the next end step or if it would leave the battlefield. TriggeredAbility triggeredAbility = new BeginningOfCombatTriggeredAbility(new SithMagicEffect(), TargetController.ANY, true); triggeredAbility.addEffect(new SithMagicReplacementEffect()); - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( triggeredAbility, HateCondition.instance, "Hate — At the beggining of each combat, if opponent lost life from a source other than combat damage this turn, you may return target card from a graveyard to the battlefield under your control. It gains lifelink and haste. Exile it at the beginning of the next end step or if it would leave the battlefield."); diff --git a/Mage.Sets/src/mage/cards/s/SithManipulator.java b/Mage.Sets/src/mage/cards/s/SithManipulator.java index 3baf0f1b9bc..e115e43cddf 100644 --- a/Mage.Sets/src/mage/cards/s/SithManipulator.java +++ b/Mage.Sets/src/mage/cards/s/SithManipulator.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.ReturnToLibraryPermanentEffect; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class SithManipulator extends CardImpl { this.toughness = new MageInt(2); // When Sith Manipulator enters the battlefield, return target creature to its owner's hand. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), new InvertCondition(HateCondition.instance), "When Sith Manipulator enters the battlefield, return target creature to its owner's hand"); @@ -39,7 +39,7 @@ public final class SithManipulator extends CardImpl { this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); // Hate — If opponent lost life from source other than combat damage this turn, put that card on top of its owner's library instead. - ability = new ConditionalTriggeredAbility( + ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ReturnToLibraryPermanentEffect(true)), HateCondition.instance, "Hate — If opponent lost life from source other than combat damage this turn, put that card on top of its owner's library instead"); diff --git a/Mage.Sets/src/mage/cards/s/SithMarauder.java b/Mage.Sets/src/mage/cards/s/SithMarauder.java index db64255463a..9ccbb83b4eb 100644 --- a/Mage.Sets/src/mage/cards/s/SithMarauder.java +++ b/Mage.Sets/src/mage/cards/s/SithMarauder.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class SithMarauder extends CardImpl { this.toughness = new MageInt(4); // Hate — When Sith Marauder enters the battlefield, if an opponent lost life from a source other than combat damage this turn, Sith Marauder deals 3 damage to any target. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3)), HateCondition.instance, "Hate — When {this} enters the battlefield, if an opponent lost life from a source other than combat damage this turn, {this} deals 3 damage to any target"); diff --git a/Mage.Sets/src/mage/cards/s/SithMindseer.java b/Mage.Sets/src/mage/cards/s/SithMindseer.java index 0bc20aed3ca..74a76a635f2 100644 --- a/Mage.Sets/src/mage/cards/s/SithMindseer.java +++ b/Mage.Sets/src/mage/cards/s/SithMindseer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class SithMindseer extends CardImpl { this.toughness = new MageInt(3); // Hate — When Sith Mindseer enters the battlefield, if an opponent loses life from a source other than combat damage, gain control of target creature for as long as Sith Mindseer remains on the battlefield. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.WhileOnBattlefield)), HateCondition.instance, "Hate — When Sith Mindseer enters the battlefield, if an opponent loses life from a source other than combat damage, gain control of target creature for as long as Sith Mindseer remains on the battlefield."); diff --git a/Mage.Sets/src/mage/cards/s/SithSorcerer.java b/Mage.Sets/src/mage/cards/s/SithSorcerer.java index 939bf2013ac..6aeea2a8ba0 100644 --- a/Mage.Sets/src/mage/cards/s/SithSorcerer.java +++ b/Mage.Sets/src/mage/cards/s/SithSorcerer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; @@ -32,7 +32,7 @@ public final class SithSorcerer extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(2))); // Hate — When Sith Assassin enters the battlefield, if opponent lost life from source other than combat damage this turn, draw a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), HateCondition.instance, "Hate — When {this} enters the battlefield, if an opponent lost life from a source other than combat damage this turn, draw a card."); diff --git a/Mage.Sets/src/mage/cards/s/SivvisRuse.java b/Mage.Sets/src/mage/cards/s/SivvisRuse.java index 96368787a74..0ebc135c69e 100644 --- a/Mage.Sets/src/mage/cards/s/SivvisRuse.java +++ b/Mage.Sets/src/mage/cards/s/SivvisRuse.java @@ -34,7 +34,7 @@ public final class SivvisRuse extends CardImpl { public SivvisRuse(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}{W}"); - // If an opponent controls a Mountain and you control a Plains, you may cast Sivvi's Ruse without paying its mana cost. + // If an opponent controls a Mountain and you control a Plains, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Mountain and you control a Plains", new OpponentControlsPermanentCondition(filterMountain), new PermanentsOnTheBattlefieldCondition(filterPlains)); diff --git a/Mage.Sets/src/mage/cards/s/SkallaWolf.java b/Mage.Sets/src/mage/cards/s/SkallaWolf.java new file mode 100644 index 00000000000..130422f9fb8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkallaWolf.java @@ -0,0 +1,56 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class SkallaWolf extends CardImpl { + + private static final FilterCard filter = new FilterCard("a green card"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public SkallaWolf(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + + this.subtype.add(SubType.WOLF); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Skalla Wolf enters the battlefield, look at the top five cards of your library. You may reveal a green card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new LookLibraryAndPickControllerEffect( + new StaticValue(5), false, new StaticValue(1), filter, + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false + ).setBackInRandomOrder(true).setText("look at the top five cards of your library. " + + "You may reveal a green card from among them and put it into your hand. " + + "Put the rest on the bottom of your library in a random order.") + )); + } + + public SkallaWolf(final SkallaWolf card) { + super(card); + } + + @Override + public SkallaWolf copy() { + return new SkallaWolf(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkeletonArcher.java b/Mage.Sets/src/mage/cards/s/SkeletonArcher.java new file mode 100644 index 00000000000..59609d28126 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkeletonArcher.java @@ -0,0 +1,42 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class SkeletonArcher extends CardImpl { + + public SkeletonArcher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.SKELETON); + this.subtype.add(SubType.ARCHER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Skeleton Archer enters the battlefield, it deals 1 damage to any target. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(1), false); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + public SkeletonArcher(final SkeletonArcher card) { + super(card); + } + + @Override + public SkeletonArcher copy() { + return new SkeletonArcher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkilledAnimator.java b/Mage.Sets/src/mage/cards/s/SkilledAnimator.java new file mode 100644 index 00000000000..5366cf5e80d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkilledAnimator.java @@ -0,0 +1,107 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.SubLayer; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.TokenImpl; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class SkilledAnimator extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact you control"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + + public SkilledAnimator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // When Skilled Animator enters the battlefield, target artifact you control becomes an artifact creature with base power and toughness 5/5 for as long as Skilled Animator remains on the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new SkilledAnimatorBecomesCreatureEffect(), false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public SkilledAnimator(final SkilledAnimator card) { + super(card); + } + + @Override + public SkilledAnimator copy() { + return new SkilledAnimator(this); + } +} + +class SkilledAnimatorBecomesCreatureEffect extends BecomesCreatureTargetEffect { + + public SkilledAnimatorBecomesCreatureEffect() { + super(new SkilledAnimatorToken(), false, false, Duration.WhileOnBattlefield); + } + + public SkilledAnimatorBecomesCreatureEffect(final SkilledAnimatorBecomesCreatureEffect effect) { + super(effect); + } + + @Override + public SkilledAnimatorBecomesCreatureEffect copy() { + return new SkilledAnimatorBecomesCreatureEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent == null) { + this.discard(); + return false; + } + return super.apply(layer, sublayer, source, game); + } + + @Override + public String getText(Mode mode) { + return "target artifact you control becomes an artifact creature with base power and toughness 5/5 for as long as {this} remains on the battlefield"; + } +} + +class SkilledAnimatorToken extends TokenImpl { + + public SkilledAnimatorToken() { + super("", "5/5 artifact creature as long as {this} is on the battlefield"); + cardType.add(CardType.ARTIFACT); + cardType.add(CardType.CREATURE); + power = new MageInt(5); + toughness = new MageInt(5); + } + + public SkilledAnimatorToken(final SkilledAnimatorToken token) { + super(token); + } + + public SkilledAnimatorToken copy() { + return new SkilledAnimatorToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java b/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java index ffb876f5998..15b2be1cafd 100644 --- a/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java +++ b/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java @@ -41,7 +41,7 @@ public final class SkirsdagHighPriest extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); - // Morbid - {tap}, Tap two untapped creatures you control: Create a 5/5 black Demon creature token with flying. Activate this ability only if a creature died this turn. + // Morbid — {tap}, Tap two untapped creatures you control: Create a 5/5 black Demon creature token with flying. Activate this ability only if a creature died this turn. Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new DemonToken()), new TapSourceCost(), MorbidCondition.instance); ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); diff --git a/Mage.Sets/src/mage/cards/s/SkullStorm.java b/Mage.Sets/src/mage/cards/s/SkullStorm.java new file mode 100644 index 00000000000..164cf6e3033 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkullStorm.java @@ -0,0 +1,88 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeEffect; +import mage.abilities.keyword.CommanderStormAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class SkullStorm extends CardImpl { + + public SkullStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{B}{B}"); + + // When you cast this spell, copy it for each time you've cast your commander from the command zone this game. + this.addAbility(new CommanderStormAbility()); + + // Each opponent sacrifices a creature. Each opponent who can't loses half their life, rounded up. + this.getSpellAbility().addEffect(new SkullStormEffect()); + } + + public SkullStorm(final SkullStorm card) { + super(card); + } + + @Override + public SkullStorm copy() { + return new SkullStorm(this); + } +} + +class SkullStormEffect extends OneShotEffect { + + public SkullStormEffect() { + super(Outcome.Benefit); + this.staticText = "Each opponent sacrifices a creature. " + + "Each opponent who can't loses half their life, rounded up."; + } + + public SkullStormEffect(final SkullStormEffect effect) { + super(effect); + } + + @Override + public SkullStormEffect copy() { + return new SkullStormEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.getOpponents(source.getControllerId()).forEach((playerId) -> { + Player player = game.getPlayer(playerId); + if (!(player == null)) { + FilterPermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(playerId)); + if (game.getBattlefield().getActivePermanents( + filter, source.getControllerId(), game + ).isEmpty()) { + int lifeToLose = (int) Math.ceil(player.getLife() / 2); + player.loseLife(lifeToLose, game, false); + } else { + Effect effect = new SacrificeEffect( + StaticFilters.FILTER_PERMANENT_CREATURE, 1, null + ); + effect.setTargetPointer(new FixedTarget(playerId, game)); + effect.apply(game, source); + } + } + }); + return true; + } +} +//doot doot diff --git a/Mage.Sets/src/mage/cards/s/SkylineDespot.java b/Mage.Sets/src/mage/cards/s/SkylineDespot.java index 3dcb09c97b7..6746688b0a0 100644 --- a/Mage.Sets/src/mage/cards/s/SkylineDespot.java +++ b/Mage.Sets/src/mage/cards/s/SkylineDespot.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; @@ -37,7 +37,7 @@ public final class SkylineDespot extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect(), false)); // At the beginning of your upkeep, if you're the monarch, put a 5/5 red Dragon creature token with flying onto the battlefield. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new DragonToken2()), TargetController.YOU, false), MonarchIsSourceControllerCondition.instance, "At the beginning of your upkeep, if you're the monarch, put a 5/5 red Dragon creature token with flying onto the battlefield.")); diff --git a/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java b/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java new file mode 100644 index 00000000000..25fde9c0a68 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java @@ -0,0 +1,136 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.SendOptionUsedEventEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.constants.SubType; +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.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class SkyriderPatrol extends CardImpl { + + public SkyriderPatrol(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.SCOUT); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of combat on your turn, you may pay {G}{U}. When you do, put a +1/+1 counter on another target creature you control, and that creature gains flying until end of turn. + this.addAbility(new BeginningOfCombatTriggeredAbility( + new DoIfCostPaid( + new SkyriderPatrolCreateReflexiveTriggerEffect(), + new ManaCostsImpl("{G}{U}"), + "Pay {G}{U} to put a +1/+1 counter on another" + + " creature you control and give it flying?" + ).setText("you may pay {G}{U}. When you do, " + + "put a +1/+1 counter on another target creature you control, " + + "and that creature gains flying until end of turn."), + TargetController.YOU, false + )); + } + + public SkyriderPatrol(final SkyriderPatrol card) { + super(card); + } + + @Override + public SkyriderPatrol copy() { + return new SkyriderPatrol(this); + } +} + +class SkyriderPatrolCreateReflexiveTriggerEffect extends OneShotEffect { + + public SkyriderPatrolCreateReflexiveTriggerEffect() { + super(Outcome.Benefit); + } + + public SkyriderPatrolCreateReflexiveTriggerEffect(final SkyriderPatrolCreateReflexiveTriggerEffect effect) { + super(effect); + } + + @Override + public SkyriderPatrolCreateReflexiveTriggerEffect copy() { + return new SkyriderPatrolCreateReflexiveTriggerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.addDelayedTriggeredAbility(new SkyriderPatrolReflexiveTriggeredAbility(), source); + return new SendOptionUsedEventEffect().apply(game, source); + } +} + +class SkyriderPatrolReflexiveTriggeredAbility extends DelayedTriggeredAbility { + + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("another creature you control"); + + static { + filter.add(new AnotherPredicate()); + } + + public SkyriderPatrolReflexiveTriggeredAbility() { + super(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), Duration.OneUse, true); + this.addEffect(new GainAbilityTargetEffect( + FlyingAbility.getInstance(), + Duration.EndOfTurn + )); + this.addTarget(new TargetPermanent(filter)); + } + + public SkyriderPatrolReflexiveTriggeredAbility(final SkyriderPatrolReflexiveTriggeredAbility ability) { + super(ability); + } + + @Override + public SkyriderPatrolReflexiveTriggeredAbility copy() { + return new SkyriderPatrolReflexiveTriggeredAbility(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 "When you pay {G}{U}, put a +1/+1 counter " + + "on another target creature you control, " + + "and that creature gains flying until end of turn."; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SkyshroudClaim.java b/Mage.Sets/src/mage/cards/s/SkyshroudClaim.java index a76bfc71737..1828f9646af 100644 --- a/Mage.Sets/src/mage/cards/s/SkyshroudClaim.java +++ b/Mage.Sets/src/mage/cards/s/SkyshroudClaim.java @@ -17,7 +17,7 @@ import mage.target.common.TargetCardInLibrary; */ public final class SkyshroudClaim extends CardImpl { - private static final FilterLandCard filter = new FilterLandCard("Forest"); + private static final FilterLandCard filter = new FilterLandCard("Forest cards"); static { filter.add(new SubtypePredicate(SubType.FOREST)); } diff --git a/Mage.Sets/src/mage/cards/s/SlaughterGames.java b/Mage.Sets/src/mage/cards/s/SlaughterGames.java index bfd58589489..e1cf56315e1 100644 --- a/Mage.Sets/src/mage/cards/s/SlaughterGames.java +++ b/Mage.Sets/src/mage/cards/s/SlaughterGames.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CantBeCounteredSourceEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -24,15 +24,15 @@ public final class SlaughterGames extends CardImpl { public SlaughterGames(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}{R}"); - // Slaughter Games can't be countered by spells or abilities. + // Slaughter Games can't be countered. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, effect); ability.setRuleAtTheTop(true); this.addAbility(ability); // Name a nonland card. Search target opponent's graveyard, hand, and library for any number of cards with that name and exile them. Then that player shuffles their library. - this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME)); this.getSpellAbility().addEffect(new SlaughterGamesEffect()); this.getSpellAbility().addTarget(new TargetOpponent()); } @@ -59,7 +59,7 @@ class SlaughterGamesEffect extends SearchTargetGraveyardHandLibraryForCardNameAn @Override public boolean apply(Game game, Ability source) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); return super.applySearchAndExile(game, source, cardName, targetPointer.getFirst(game, source)); } diff --git a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java index 53ef0de512d..b68d8d3a68e 100644 --- a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java +++ b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class SlaughterhouseBouncer extends CardImpl { this.toughness = new MageInt(3); // Hellbent - When Slaughterhouse Bouncer dies, if you have no cards in hand, target creature gets -3/-3 until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new DiesTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)), HellbentCondition.instance, "When {this} dies, if you have no cards in hand, target creature gets -3/-3 until end of turn." diff --git a/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java b/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java index d3c8095860a..7a2cbd69482 100644 --- a/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java +++ b/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -48,7 +48,7 @@ public final class SlinnVodaTheRisingDeep extends CardImpl { this.addAbility(new KickerAbility("{1}{U}")); // When Slinn Voda, the Rising Deep enters the battlefield, if it was kicked, return all creatures to their owners' hands except for Merfolk, Krakens, Leviathans, Octopuses, and Serpents. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ReturnToHandFromBattlefieldAllEffect(filter)), KickedCondition.instance, "when {this} enters the battlefield, if it was kicked, " diff --git a/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java b/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java index fea07807db5..e607e3faf67 100644 --- a/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java +++ b/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java @@ -7,7 +7,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -46,7 +46,7 @@ public final class SmeltWardGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Smelt-Ward Gatekeepers enters the battlefield, if you control two or more Gates, gain control of target creature an opponent controls until end of turn. Untap that creature. That creature gains haste until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn)), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), "When {this} enters the battlefield, if you control two or more Gates, gain control of target creature an opponent controls until end of turn. Untap that creature. That creature gains haste until end of turn."); diff --git a/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java b/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java index 611eee6e94f..be18600eaf2 100644 --- a/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java +++ b/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class SnakeOfTheGoldenGrove extends CardImpl { this.addAbility(new TributeAbility(3)); // When Snake of the Golden Grove enters the battlefield, if tribute wasn't paid, you gain 4 life. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(4), false); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, you gain 4 life.")); } diff --git a/Mage.Sets/src/mage/cards/s/SnapsailGlider.java b/Mage.Sets/src/mage/cards/s/SnapsailGlider.java index 0650452dde5..7cc55dd5da2 100644 --- a/Mage.Sets/src/mage/cards/s/SnapsailGlider.java +++ b/Mage.Sets/src/mage/cards/s/SnapsailGlider.java @@ -23,7 +23,7 @@ import mage.constants.Zone; */ public final class SnapsailGlider extends CardImpl { - protected static String rule = "Metalcraft - Snapsail Glider has flying as long as you control three or more artifacts"; + protected static String rule = "Metalcraft — Snapsail Glider has flying as long as you control three or more artifacts"; public SnapsailGlider (UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}"); diff --git a/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java b/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java index a11ba94adc0..dbe3caa7a95 100644 --- a/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java +++ b/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -42,7 +42,7 @@ public final class SokenzanRenegade extends CardImpl { // Bushido 1 this.addAbility(new BushidoAbility(1)); // At the beginning of your upkeep, if a player has more cards in hand than each other player, the player who has the most cards in hand gains control of Sokenzan Renegade. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SokenzanRenegadeEffect(), TargetController.YOU, false), OnePlayerHasTheMostCards.instance, "At the beginning of your upkeep, if a player has more cards in hand than each other player, the player who has the most cards in hand gains control of {this}" @@ -97,7 +97,7 @@ class SokenzanRenegadeEffect extends OneShotEffect { ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, newController.getId()); effect.setTargetPointer(new FixedTarget(sourcePermanent.getId())); game.addEffect(effect, source); - if (!source.getControllerId().equals(newController.getId())) { + if (!source.isControlledBy(newController.getId())) { game.informPlayers(newController.getLogName() + " got control of " + sourcePermanent.getLogName()); } return true; diff --git a/Mage.Sets/src/mage/cards/s/SolemnRecruit.java b/Mage.Sets/src/mage/cards/s/SolemnRecruit.java index 75a4d4f5b30..ba5ae0e00c8 100644 --- a/Mage.Sets/src/mage/cards/s/SolemnRecruit.java +++ b/Mage.Sets/src/mage/cards/s/SolemnRecruit.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.DoubleStrikeAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class SolemnRecruit extends CardImpl { this.addAbility(DoubleStrikeAbility.getInstance()); // Revolt — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, put a +1/+1 counter on Solemn Recruit. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfYourEndStepTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false diff --git a/Mage.Sets/src/mage/cards/s/SolitaryHunter.java b/Mage.Sets/src/mage/cards/s/SolitaryHunter.java index fd0868745ed..917b5e1e716 100644 --- a/Mage.Sets/src/mage/cards/s/SolitaryHunter.java +++ b/Mage.Sets/src/mage/cards/s/SolitaryHunter.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class SolitaryHunter extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Solitary Hunter. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public SolitaryHunter(final SolitaryHunter card) { diff --git a/Mage.Sets/src/mage/cards/s/SomberwaldSpider.java b/Mage.Sets/src/mage/cards/s/SomberwaldSpider.java index 4fb9b1ec7dd..177a0ec798f 100644 --- a/Mage.Sets/src/mage/cards/s/SomberwaldSpider.java +++ b/Mage.Sets/src/mage/cards/s/SomberwaldSpider.java @@ -28,7 +28,7 @@ public final class SomberwaldSpider extends CardImpl { this.toughness = new MageInt(4); this.addAbility(ReachAbility.getInstance()); - // Morbid - Somberwald Spider enters the battlefield with two +1/+1 counters on it if a creature died this turn. + // Morbid — Somberwald Spider enters the battlefield with two +1/+1 counters on it if a creature died this turn. this.addAbility(new EntersBattlefieldAbility( new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), MorbidCondition.instance, ""), "with two +1/+1 counters on it if a creature died this turn")); diff --git a/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java b/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java index 01df8ffbb3c..1e1735f9a22 100644 --- a/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java +++ b/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java @@ -8,7 +8,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityType; @@ -47,10 +47,10 @@ public final class SorcerousSpyglass extends CardImpl { } } -class SorcerousSpyglassEntersEffect extends NameACardEffect { +class SorcerousSpyglassEntersEffect extends ChooseACardNameEffect { SorcerousSpyglassEntersEffect() { - super(NameACardEffect.TypeOfName.ALL); + super(ChooseACardNameEffect.TypeOfName.ALL); staticText = "look at an opponent's hand, then choose any card name"; } @@ -114,7 +114,7 @@ class SorcerousSpyglassActivationEffect extends ContinuousRuleModifyingEffectImp if (ability.isPresent() && object != null) { if (game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range && ability.get().getAbilityType() != AbilityType.MANA - && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SosukeSonOfSeshiro.java b/Mage.Sets/src/mage/cards/s/SosukeSonOfSeshiro.java index d359eca5328..a59212166dc 100644 --- a/Mage.Sets/src/mage/cards/s/SosukeSonOfSeshiro.java +++ b/Mage.Sets/src/mage/cards/s/SosukeSonOfSeshiro.java @@ -88,7 +88,7 @@ class SosukeSonOfSeshiroTriggeredAbility extends TriggeredAbilityImpl { if (((DamagedCreatureEvent) event).isCombatDamage()) { Permanent sourceCreature = game.getPermanent(event.getSourceId()); Permanent targetCreature = game.getPermanent(event.getTargetId()); - if (sourceCreature != null && sourceCreature.getControllerId().equals(this.getControllerId()) + if (sourceCreature != null && sourceCreature.isControlledBy(this.getControllerId()) && targetCreature != null && sourceCreature.hasSubtype(SubType.WARRIOR, game)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId())); return true; diff --git a/Mage.Sets/src/mage/cards/s/SoulEcho.java b/Mage.Sets/src/mage/cards/s/SoulEcho.java index 7042b2539b2..7adefc2cb6f 100644 --- a/Mage.Sets/src/mage/cards/s/SoulEcho.java +++ b/Mage.Sets/src/mage/cards/s/SoulEcho.java @@ -106,7 +106,7 @@ class SoulEchoReplacementEffect extends ReplacementEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) { - if (!sameStep && game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { return true; } } else { diff --git a/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java b/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java index 560920aa898..8beb8d1b661 100644 --- a/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java +++ b/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java @@ -70,7 +70,7 @@ class SoulOfShandalarEffect extends OneShotEffect { public SoulOfShandalarEffect() { super(Outcome.Damage); staticText = "{this} deals 3 damage to target player or planeswalker " - + "and 3 damage to up to one target creature that player or that planeswalker’s controller controls"; + + "and 3 damage to up to one target creature that player or that planeswalker's controller controls"; } public SoulOfShandalarEffect(final SoulOfShandalarEffect effect) { @@ -111,7 +111,7 @@ class SoulOfShandalarTarget extends TargetPermanent { } UUID firstTarget = player.getId(); Permanent permanent = game.getPermanent(id); - if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + if (firstTarget != null && permanent != null && permanent.isControlledBy(firstTarget)) { return super.canTarget(id, source, game); } return false; @@ -138,7 +138,7 @@ class SoulOfShandalarTarget extends TargetPermanent { if (player != null) { for (UUID targetId : availablePossibleTargets) { Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.getControllerId().equals(player.getId())) { + if (permanent != null && permanent.isControlledBy(player.getId())) { possibleTargets.add(targetId); } } diff --git a/Mage.Sets/src/mage/cards/s/SoulSwallower.java b/Mage.Sets/src/mage/cards/s/SoulSwallower.java index 676d646661c..db981fbebb8 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSwallower.java +++ b/Mage.Sets/src/mage/cards/s/SoulSwallower.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -32,7 +32,7 @@ public final class SoulSwallower extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, put three +1/+1 counters on Soul Swallower. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), TargetController.YOU, false), DeliriumCondition.instance, "Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/s/SovereignsOfLostAlara.java b/Mage.Sets/src/mage/cards/s/SovereignsOfLostAlara.java index 749155607d6..bf9a5c6d90d 100644 --- a/Mage.Sets/src/mage/cards/s/SovereignsOfLostAlara.java +++ b/Mage.Sets/src/mage/cards/s/SovereignsOfLostAlara.java @@ -77,7 +77,7 @@ class CreatureControlledAttacksAloneTriggeredAbility extends TriggeredAbilityImp @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.isActivePlayer(this.controllerId)) { if (game.getCombat().attacksAlone()) { this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); return true; diff --git a/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java b/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java new file mode 100644 index 00000000000..18d91f47571 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java @@ -0,0 +1,162 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +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.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class SowerOfDiscord extends CardImpl { + + public SowerOfDiscord(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + + this.subtype.add(SubType.DEMON); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // As Sower of Discord enters the battlefield, choose two players. + this.addAbility(new AsEntersBattlefieldAbility( + new SowerOfDiscordEntersBattlefieldEffect() + )); + + // Whenever damage is dealt to one of the chosen players, the other chosen player also loses that much life. + this.addAbility(new SowerOfDiscordTriggeredAbility()); + } + + public SowerOfDiscord(final SowerOfDiscord card) { + super(card); + } + + @Override + public SowerOfDiscord copy() { + return new SowerOfDiscord(this); + } +} + +class SowerOfDiscordEntersBattlefieldEffect extends OneShotEffect { + + public SowerOfDiscordEntersBattlefieldEffect() { + super(Outcome.Damage); + staticText = "choose two players"; + } + + public SowerOfDiscordEntersBattlefieldEffect(final SowerOfDiscordEntersBattlefieldEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanentEntering(source.getSourceId()); + if (controller == null || permanent == null) { + return false; + } + TargetPlayer target = new TargetPlayer(2, 2, true); + controller.chooseTarget(outcome, target, source, game); + Player player1 = game.getPlayer(target.getFirstTarget()); + if (target.getTargets().size() <= 1) { + return false; + } + Player player2 = game.getPlayer(target.getTargets().get(1)); + if (player1 == null || player2 == null) { + return false; + } + game.getState().setValue(source.getSourceId() + "_player1", player1); + game.getState().setValue(source.getSourceId() + "_player2", player2); + game.informPlayers(permanent.getLogName() + ": " + + controller.getLogName() + " has chosen " + + player1.getLogName() + " and " + player2.getLogName() + ); + permanent.addInfo( + "chosen players", + "Chosen players: " + + player1.getName() + ", " + + player2.getName() + "", game + ); + return true; + } + + @Override + public SowerOfDiscordEntersBattlefieldEffect copy() { + return new SowerOfDiscordEntersBattlefieldEffect(this); + } + +} + +class SowerOfDiscordTriggeredAbility extends TriggeredAbilityImpl { + + public SowerOfDiscordTriggeredAbility() { + super(Zone.BATTLEFIELD, null); + } + + public SowerOfDiscordTriggeredAbility(final SowerOfDiscordTriggeredAbility ability) { + super(ability); + } + + @Override + public SowerOfDiscordTriggeredAbility copy() { + return new SowerOfDiscordTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + int damage = event.getAmount(); + Player player1 = (Player) game.getState().getValue( + this.getSourceId() + "_player1" + ); + Player player2 = (Player) game.getState().getValue( + this.getSourceId() + "_player2" + ); + if (player1 == null || player2 == null || damage == 0) { + return false; + } + Effect effect = new LoseLifeTargetEffect(damage); + if (event.getTargetId().equals(player1.getId())) { + this.getEffects().clear(); + effect.setTargetPointer(new FixedTarget(player2.getId())); + this.addEffect(effect); + return true; + } else if (event.getTargetId().equals(player2.getId())) { + this.getEffects().clear(); + effect.setTargetPointer(new FixedTarget(player1.getId())); + this.addEffect(effect); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever damage is dealt to one of the chosen players, " + + "the other chosen player also loses that much life."; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SparkFiend.java b/Mage.Sets/src/mage/cards/s/SparkFiend.java new file mode 100644 index 00000000000..0de02f16fdb --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SparkFiend.java @@ -0,0 +1,133 @@ + +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +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.constants.TargetController; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; +/** + * + * @author L_J + */ +public final class SparkFiend extends CardImpl { + + public SparkFiend(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}"); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(5); + this.toughness = new MageInt(6); + + // When Spark Fiend enters the battlefield, roll two six-sided dice. If you rolled 2, 3, or 12, sacrifice Spark Fiend. If you rolled 7 or 11, don't roll dice for Spark Fiend during any of your following upkeeps. If you rolled any other total, note that total. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SparkFiendEffect(), false)); + + // At the beginning of your upkeep, roll two six-sided dice. If you rolled 7, sacrifice Spark Fiend. If you roll the noted total, don't roll dice for Spark Fiend during any of your following upkeeps. Otherwise, do nothing. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SparkFiendUpkeepEffect(), TargetController.YOU, false)); + } + + public SparkFiend(final SparkFiend card) { + super(card); + } + + @Override + public SparkFiend copy() { + return new SparkFiend(this); + } +} + +class SparkFiendEffect extends OneShotEffect { + + public SparkFiendEffect() { + super(Outcome.Sacrifice); + this.staticText = "roll two six-sided dice. If you rolled 2, 3, or 12, sacrifice Spark Fiend. If you rolled 7 or 11, don't roll dice for Spark Fiend during any of your following upkeeps. If you rolled any other total, note that total"; + } + + public SparkFiendEffect(final SparkFiendEffect effect) { + super(effect); + } + + @Override + public SparkFiendEffect copy() { + return new SparkFiendEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int roll = controller.rollDice(game, 6) + controller.rollDice(game, 6); + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null && mageObject instanceof Permanent) { + Permanent sourcePermanent = (Permanent) mageObject; + if (roll == 2 || roll == 3 || roll == 12) { + // sacrifice + sourcePermanent.sacrifice(source.getSourceId(), game); + } else if (roll == 7 || roll == 11) { + // don't roll again + game.getState().setValue("SparkFiend" + source.getSourceId().toString(), 0); + sourcePermanent.addInfo("roll counter", CardUtil.addToolTipMarkTags(""), game); // might apply if this ability was copied + } else { + // note that total + game.getState().setValue("SparkFiend" + source.getSourceId().toString(), roll); + sourcePermanent.addInfo("roll counter", CardUtil.addToolTipMarkTags("Noted roll: " + roll), game); + } + } + return true; + } + return false; + } +} + +class SparkFiendUpkeepEffect extends OneShotEffect { + + public SparkFiendUpkeepEffect() { + super(Outcome.Sacrifice); + this.staticText = "roll two six-sided dice. If you rolled 7, sacrifice Spark Fiend. If you roll the noted total, don't roll dice for Spark Fiend during any of your following upkeeps. Otherwise, do nothing"; + } + + public SparkFiendUpkeepEffect(final SparkFiendUpkeepEffect effect) { + super(effect); + } + + @Override + public SparkFiendUpkeepEffect copy() { + return new SparkFiendUpkeepEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + if (game.getState().getValue("SparkFiend" + source.getSourceId().toString()) != null + && (Integer) game.getState().getValue("SparkFiend" + source.getSourceId().toString()) != 0) { + int roll = controller.rollDice(game, 6) + controller.rollDice(game, 6); + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null && mageObject instanceof Permanent) { + Permanent sourcePermanent = (Permanent) mageObject; + if (roll == 7) { + // sacrifice + sourcePermanent.sacrifice(source.getSourceId(), game); + } else if (roll == (Integer) game.getState().getValue("SparkFiend" + source.getSourceId().toString())) { + // don't roll again + game.getState().setValue("SparkFiend" + source.getSourceId().toString(), 0); + sourcePermanent.addInfo("roll counter", CardUtil.addToolTipMarkTags(""), game); + } // otherwise, do nothing + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SparktongueDragon.java b/Mage.Sets/src/mage/cards/s/SparktongueDragon.java new file mode 100644 index 00000000000..ae8dae4410c --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SparktongueDragon.java @@ -0,0 +1,114 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +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.constants.SubType; +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.game.events.GameEvent; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class SparktongueDragon extends CardImpl { + + public SparktongueDragon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Sparktongue Dragon enters the battlefield, you may pay {2}{R}. When you do, it deals 3 damage to any target. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DoIfCostPaid( + new SparktongueDragonCreateReflexiveTriggerEffect(), + new ManaCostsImpl("{2}{R}"), + "Pay {2}{R} to deal 3 damage?" + ).setText("you may pay {2}{R}. When you do, it deals 3 damage to any target") + )); + } + + public SparktongueDragon(final SparktongueDragon card) { + super(card); + } + + @Override + public SparktongueDragon copy() { + return new SparktongueDragon(this); + } +} + +class SparktongueDragonCreateReflexiveTriggerEffect extends OneShotEffect { + + public SparktongueDragonCreateReflexiveTriggerEffect() { + super(Outcome.Benefit); + this.staticText = "When you do, it deals 3 damage to any target"; + } + + public SparktongueDragonCreateReflexiveTriggerEffect(final SparktongueDragonCreateReflexiveTriggerEffect effect) { + super(effect); + } + + @Override + public SparktongueDragonCreateReflexiveTriggerEffect copy() { + return new SparktongueDragonCreateReflexiveTriggerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + game.addDelayedTriggeredAbility(new SparktongueDragonReflexiveTriggeredAbility(), source); + return new SendOptionUsedEventEffect().apply(game, source); + } +} + +class SparktongueDragonReflexiveTriggeredAbility extends DelayedTriggeredAbility { + + public SparktongueDragonReflexiveTriggeredAbility() { + super(new DamageTargetEffect(3), Duration.OneUse, true); + this.addTarget(new TargetAnyTarget()); + } + + public SparktongueDragonReflexiveTriggeredAbility(final SparktongueDragonReflexiveTriggeredAbility ability) { + super(ability); + } + + @Override + public SparktongueDragonReflexiveTriggeredAbility copy() { + return new SparktongueDragonReflexiveTriggeredAbility(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 "When you pay {2}{R}, {this} deals 3 damage to any target"; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpectralSearchlight.java b/Mage.Sets/src/mage/cards/s/SpectralSearchlight.java index f3cfc623c7d..4575ce3930f 100644 --- a/Mage.Sets/src/mage/cards/s/SpectralSearchlight.java +++ b/Mage.Sets/src/mage/cards/s/SpectralSearchlight.java @@ -26,9 +26,9 @@ public final class SpectralSearchlight extends CardImpl { public SpectralSearchlight(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - // {T}: Choose a player. That player adds one mana of any color he or she chooses. + // {T}: Choose a player. That player adds one mana of any color they chooses. ManaEffect effect = new SpectralSearchlightManaEffect("chosen player"); - effect.setText("That player adds one mana of any color he or she chooses"); + effect.setText("That player adds one mana of any color they choose"); Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); // choosing player as first effect, before adding mana effect ability.getEffects().add(0, new ChoosePlayerEffect(Outcome.PutManaInPool)); diff --git a/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java b/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java index fe5b922eb39..f276a9393e8 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java +++ b/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java @@ -81,7 +81,7 @@ class SphinxAmbassadorEffect extends OneShotEffect { TreeSet choices = new TreeSet<>(); Collection cards = game.getCards(); for (Card gameCard : cards) { - if (gameCard.getOwnerId().equals(targetPlayer.getId())) { + if (gameCard.isOwnedBy(targetPlayer.getId())) { choices.add(gameCard.getName()); } } diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java b/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java index ac11909475a..ac834db3c28 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java +++ b/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java @@ -46,7 +46,7 @@ public final class SphinxOfTheFinalWord extends CardImpl { // Hexproof this.addAbility(HexproofAbility.getInstance()); - // Instant and sorcery spells you control can't be countered by spells or abilities. + // Instant and sorcery spells you control can't be countered. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield))); } diff --git a/Mage.Sets/src/mage/cards/s/SphinxsDecree.java b/Mage.Sets/src/mage/cards/s/SphinxsDecree.java index ec0f5cb46b3..2b841942ca1 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxsDecree.java +++ b/Mage.Sets/src/mage/cards/s/SphinxsDecree.java @@ -103,7 +103,7 @@ class SphinxsDecreeCantCastEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { UUID opponentId = getTargetPointer().getFirst(game, source); - if (game.getActivePlayerId().equals(opponentId)) { + if (game.isActivePlayer(opponentId)) { if (playersNextTurn == 0) { playersNextTurn = game.getTurnNum(); } diff --git a/Mage.Sets/src/mage/cards/s/SpikeRogue.java b/Mage.Sets/src/mage/cards/s/SpikeRogue.java index 18e9739ca7d..e612ab71d48 100644 --- a/Mage.Sets/src/mage/cards/s/SpikeRogue.java +++ b/Mage.Sets/src/mage/cards/s/SpikeRogue.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -17,7 +16,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -44,7 +43,7 @@ public final class SpikeRogue extends CardImpl { // {2}, Remove a +1/+1 counter from a creature you control: Put a +1/+1 counter on Spike Rogue. Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), new GenericManaCost(2)); - ability2.addCost(new RemoveCounterCost(new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent(), true), CounterType.P1P1)); + ability2.addCost(new RemoveCounterCost(new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_CREATURE, true), CounterType.P1P1)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/s/SpiralingDuelist.java b/Mage.Sets/src/mage/cards/s/SpiralingDuelist.java index fe37f728610..52af0e6edc4 100644 --- a/Mage.Sets/src/mage/cards/s/SpiralingDuelist.java +++ b/Mage.Sets/src/mage/cards/s/SpiralingDuelist.java @@ -22,7 +22,7 @@ import mage.constants.Zone; */ public final class SpiralingDuelist extends CardImpl { - private static final String effectText = "Metalcraft - Spiraling Duelist has double strike as long as you control three or more artifacts."; + private static final String effectText = "Metalcraft — Spiraling Duelist has double strike as long as you control three or more artifacts."; public SpiralingDuelist(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}"); diff --git a/Mage.Sets/src/mage/cards/s/SpireSerpent.java b/Mage.Sets/src/mage/cards/s/SpireSerpent.java index 0023dc7d2e2..a8338bd6519 100644 --- a/Mage.Sets/src/mage/cards/s/SpireSerpent.java +++ b/Mage.Sets/src/mage/cards/s/SpireSerpent.java @@ -25,7 +25,7 @@ import mage.constants.Zone; */ public final class SpireSerpent extends CardImpl { - private static final String abilityText1 = "Metalcraft - As long as you control three or more artifacts, {this} gets +2/+2"; + private static final String abilityText1 = "Metalcraft — As long as you control three or more artifacts, {this} gets +2/+2"; public SpireSerpent(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); diff --git a/Mage.Sets/src/mage/cards/s/SpiritMirror.java b/Mage.Sets/src/mage/cards/s/SpiritMirror.java index 9c1317a1706..136789f012e 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritMirror.java +++ b/Mage.Sets/src/mage/cards/s/SpiritMirror.java @@ -7,7 +7,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class SpiritMirror extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new ReflectionToken()), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(filterToken, ComparisonType.EQUAL_TO, 0, false), "At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token.")); diff --git a/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java b/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java index 99061732faa..f588f7091cd 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java +++ b/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java @@ -4,7 +4,7 @@ package mage.cards.s; import java.util.UUID; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,7 +32,7 @@ public final class SpiritualSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of each player's upkeep, if that player controls a Plains, he or she gains 1 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility( new GainLifeTargetEffect(1).setText("they gain 1 life"), TargetController.ANY, false diff --git a/Mage.Sets/src/mage/cards/s/SpitFlame.java b/Mage.Sets/src/mage/cards/s/SpitFlame.java new file mode 100644 index 00000000000..cd3652c86bd --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpitFlame.java @@ -0,0 +1,51 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +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.filter.FilterPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class SpitFlame extends CardImpl { + + private static final FilterPermanent filter + = new FilterPermanent(SubType.DRAGON, "a Dragon"); + + public SpitFlame(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); + + // Spit Flame deals 4 damage to target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Whenever a Dragon enters the battlefield under your control, you may pay {R}. If you do, return Spit Flame from your graveyard to your hand. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.GRAVEYARD, + new DoIfCostPaid( + new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl("{R}") + ), filter, false + )); + } + + public SpitFlame(final SpitFlame card) { + super(card); + } + + @Override + public SpitFlame copy() { + return new SpitFlame(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpitefulReturned.java b/Mage.Sets/src/mage/cards/s/SpitefulReturned.java index d0728b58953..3bca683888a 100644 --- a/Mage.Sets/src/mage/cards/s/SpitefulReturned.java +++ b/Mage.Sets/src/mage/cards/s/SpitefulReturned.java @@ -86,7 +86,7 @@ class SpitefulReturnedTriggeredAbility extends TriggeredAbilityImpl { return true; } } else { - if (sourcePermanent.getAttachedTo() != null && sourcePermanent.getAttachedTo().equals(event.getSourceId())) { + if (sourcePermanent.isAttachedTo(event.getSourceId())) { UUID defender = game.getCombat().getDefendingPlayerId(sourcePermanent.getAttachedTo(), game); this.getEffects().get(0).setTargetPointer(new FixedTarget(defender)); return true; diff --git a/Mage.Sets/src/mage/cards/s/SplinterTwin.java b/Mage.Sets/src/mage/cards/s/SplinterTwin.java index 4ced5c998c6..cd942fa6694 100644 --- a/Mage.Sets/src/mage/cards/s/SplinterTwin.java +++ b/Mage.Sets/src/mage/cards/s/SplinterTwin.java @@ -43,7 +43,7 @@ public final class SplinterTwin extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - // Enchanted creature has "{tap}: Create a token that's a copy of this creature. That token has haste. Exile it at the beginning of the next end step." + // Enchanted creature has "{tap}: Create a token that's a copy of this creature, except it has haste. Exile it at the beginning of the next end step." SimpleActivatedAbility gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SplinterTwinEffect(), new TapSourceCost()); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA))); } @@ -62,7 +62,7 @@ class SplinterTwinEffect extends OneShotEffect { public SplinterTwinEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Create a token that's a copy of this creature. That token has haste. Exile it at the beginning of the next end step"; + this.staticText = "Create a token that's a copy of this creature, except it has haste. Exile it at the beginning of the next end step"; } public SplinterTwinEffect(final SplinterTwinEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/SplitDecision.java b/Mage.Sets/src/mage/cards/s/SplitDecision.java index 1523154b11a..adc84052372 100644 --- a/Mage.Sets/src/mage/cards/s/SplitDecision.java +++ b/Mage.Sets/src/mage/cards/s/SplitDecision.java @@ -25,7 +25,7 @@ public final class SplitDecision extends CardImpl { // Will of the council - Choose target instant or sorcery spell. Starting with you, each player votes for denial or duplication. If denial gets more votes, counter the spell. If duplication gets more votes or the vote is tied, copy the spell. You may choose new targets for the copy. this.getSpellAbility().addEffect(new SplitDecisionEffect()); - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); } public SplitDecision(final SplitDecision card) { diff --git a/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java b/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java index d1a377ab461..622bf0c7f37 100644 --- a/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java +++ b/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java @@ -1,11 +1,10 @@ - package mage.cards.s; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,7 +26,7 @@ public final class SpoilsOfTheVault extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); // Name a card. Reveal cards from the top of your library until you reveal the named card, then put that card into your hand. Exile all other cards revealed this way, and you lose 1 life for each of the exiled cards. - this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); this.getSpellAbility().addEffect(new SpoilsOfTheVaultEffect()); } @@ -45,7 +44,8 @@ class SpoilsOfTheVaultEffect extends OneShotEffect { public SpoilsOfTheVaultEffect() { super(Outcome.Damage); - this.staticText = "Reveal cards from the top of your library until you reveal the named card, then put that card into your hand. Exile all other cards revealed this way, and you lose 1 life for each of the exiled cards"; + this.staticText = "Reveal cards from the top of your library until you reveal a card with that name, " + + "then put that card into your hand. Exile all other cards revealed this way, and you lose 1 life for each of the exiled cards"; } public SpoilsOfTheVaultEffect(final SpoilsOfTheVaultEffect effect) { @@ -61,7 +61,7 @@ class SpoilsOfTheVaultEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { MageObject sourceObject = game.getObject(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (sourceObject == null || controller == null || cardName == null || cardName.isEmpty()) { return false; } diff --git a/Mage.Sets/src/mage/cards/s/SqueeTheImmortal.java b/Mage.Sets/src/mage/cards/s/SqueeTheImmortal.java index adfc361ed05..4e08bb419d1 100644 --- a/Mage.Sets/src/mage/cards/s/SqueeTheImmortal.java +++ b/Mage.Sets/src/mage/cards/s/SqueeTheImmortal.java @@ -71,7 +71,7 @@ class SqueePlayEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(source.getSourceId()); - if (card != null && card.getOwnerId().equals(affectedControllerId) + if (card != null && card.isOwnedBy(affectedControllerId) && (game.getState().getZone(source.getSourceId()) == Zone.EXILED || game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD)) { return true; diff --git a/Mage.Sets/src/mage/cards/s/SquirrelPoweredScheme.java b/Mage.Sets/src/mage/cards/s/SquirrelPoweredScheme.java index 3534b19b439..d717fb812e4 100644 --- a/Mage.Sets/src/mage/cards/s/SquirrelPoweredScheme.java +++ b/Mage.Sets/src/mage/cards/s/SquirrelPoweredScheme.java @@ -62,7 +62,7 @@ class SquirrelPoweredSchemeEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { // ignore planar dies (dice roll amount of planar dies is equal to 0) - return event.getAmount() > 0 && source.getControllerId().equals(event.getPlayerId()); + return event.getAmount() > 0 && source.isControlledBy(event.getPlayerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/s/StainTheMind.java b/Mage.Sets/src/mage/cards/s/StainTheMind.java index 7ba35dcfbb2..509edcca9b1 100644 --- a/Mage.Sets/src/mage/cards/s/StainTheMind.java +++ b/Mage.Sets/src/mage/cards/s/StainTheMind.java @@ -3,7 +3,7 @@ package mage.cards.s; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect; import mage.abilities.keyword.ConvokeAbility; import mage.cards.CardImpl; @@ -24,7 +24,7 @@ public final class StainTheMind extends CardImpl { // Convoke this.addAbility(new ConvokeAbility()); // Name a nonland card. Search target player's graveyard, hand, and library for any number of card's with that name and exile them. Then that player shuffles their library. - this.getSpellAbility().addEffect((new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); this.getSpellAbility().addEffect(new StainTheMindEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); } @@ -51,7 +51,7 @@ class StainTheMindEffect extends SearchTargetGraveyardHandLibraryForCardNameAndE @Override public boolean apply(Game game, Ability source) { - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); return super.applySearchAndExile(game, source, cardName, targetPointer.getFirst(game, source)); } diff --git a/Mage.Sets/src/mage/cards/s/StalkingLeonin.java b/Mage.Sets/src/mage/cards/s/StalkingLeonin.java index c07650cbe7e..851483b435b 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingLeonin.java +++ b/Mage.Sets/src/mage/cards/s/StalkingLeonin.java @@ -1,19 +1,15 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; -import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.RevealSecretOpponentCost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseSecretOpponentEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import static mage.cards.s.StalkingLeonin.SECRET_OPPONENT; -import static mage.cards.s.StalkingLeonin.SECRET_OWNER; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -23,8 +19,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.FilterCreatureAttackingYou; import mage.target.common.TargetCreaturePermanent; -import mage.target.common.TargetOpponent; -import mage.util.CardUtil; + +import java.util.UUID; /** * @@ -32,9 +28,6 @@ import mage.util.CardUtil; */ public final class StalkingLeonin extends CardImpl { - static final String SECRET_OPPONENT = "_secOpp"; - static final String SECRET_OWNER = "_secOwn"; - public StalkingLeonin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -43,9 +36,9 @@ public final class StalkingLeonin extends CardImpl { this.toughness = new MageInt(3); // When Stalking Leonin enters the battlefield, secretly choose an opponent. - this.addAbility(new EntersBattlefieldTriggeredAbility(new StalkingLeoninChooseOpponent(), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new ChooseSecretOpponentEffect(), false)); // Reveal the player you chose: Exile target creature that's attacking you if it's controlled by the chosen player. Activate this ability only once. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StalkingLeoninEffect(), new StalkingLeoninRevealOpponentCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StalkingLeoninEffect(), new RevealSecretOpponentCost()); ability.addTarget(new TargetCreaturePermanent(new FilterCreatureAttackingYou())); this.addAbility(ability); } @@ -60,105 +53,6 @@ public final class StalkingLeonin extends CardImpl { } } -class StalkingLeoninChooseOpponent extends OneShotEffect { - - public StalkingLeoninChooseOpponent() { - super(Outcome.Neutral); - staticText = "secretly choose an opponent"; - } - - public StalkingLeoninChooseOpponent(final StalkingLeoninChooseOpponent effect) { - super(effect); - } - - @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) { - TargetOpponent targetOpponent = new TargetOpponent(); - targetOpponent.setTargetName("opponent (secretly)"); - while (!controller.choose(outcome, targetOpponent, source.getSourceId(), game)) { - if (!controller.canRespond()) { - return false; - } - } - if (targetOpponent.getTargets().isEmpty()) { - return false; - } - if (!game.isSimulation()) { - game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has secretly chosen an opponent."); - } - game.getState().setValue(mageObject.getId() + SECRET_OPPONENT, targetOpponent.getTargets().get(0)); - game.getState().setValue(mageObject.getId() + SECRET_OWNER, controller.getId()); - if (mageObject instanceof Permanent) { - ((Permanent) mageObject).addInfo(SECRET_OPPONENT, - CardUtil.addToolTipMarkTags(controller.getLogName() + " has secretly chosen an opponent."), game); - } - } - return false; - } - - @Override - public StalkingLeoninChooseOpponent copy() { - return new StalkingLeoninChooseOpponent(this); - } - -} - -class StalkingLeoninRevealOpponentCost extends CostImpl { - - public StalkingLeoninRevealOpponentCost() { - this.text = "Reveal the player you chose"; - } - - public StalkingLeoninRevealOpponentCost(final StalkingLeoninRevealOpponentCost cost) { - super(cost); - } - - @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + SECRET_OWNER); - if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { - return false; - } - UUID opponentId = (UUID) game.getState().getValue(sourceId + SECRET_OPPONENT); - return opponentId != null; - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + SECRET_OWNER); - if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { - return false; - } - UUID opponentId = (UUID) game.getState().getValue(sourceId + SECRET_OPPONENT); - if (opponentId != null) { - game.getState().setValue(sourceId + SECRET_OWNER, null); // because only once, the vale is set to null - Player controller = game.getPlayer(controllerId); - Player opponent = game.getPlayer(opponentId); - MageObject sourceObject = game.getObject(sourceId); - if (controller != null && opponent != null && sourceObject != null) { - if (sourceObject instanceof Permanent) { - ((Permanent) sourceObject).addInfo(SECRET_OPPONENT, null, game); - } - game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " reveals the secretly chosen opponent " + opponent.getLogName()); - } - paid = true; - } - return paid; - } - - @Override - public StalkingLeoninRevealOpponentCost copy() { - return new StalkingLeoninRevealOpponentCost(this); - } - -} - class StalkingLeoninEffect extends OneShotEffect { public StalkingLeoninEffect() { @@ -181,7 +75,7 @@ class StalkingLeoninEffect extends OneShotEffect { if (controller != null) { Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (targetCreature != null) { - UUID opponentId = (UUID) game.getState().getValue(source.getSourceId() + SECRET_OPPONENT); + UUID opponentId = (UUID) game.getState().getValue(source.getSourceId() + ChooseSecretOpponentEffect.SECRET_OPPONENT); if (opponentId != null && opponentId.equals(targetCreature.getControllerId())) { controller.moveCards(targetCreature, Zone.EXILED, source, game); } diff --git a/Mage.Sets/src/mage/cards/s/StalkingVampire.java b/Mage.Sets/src/mage/cards/s/StalkingVampire.java index 7c6fbd13ecd..3c0c39ef049 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingVampire.java +++ b/Mage.Sets/src/mage/cards/s/StalkingVampire.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; @@ -10,6 +9,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * @author nantuko */ diff --git a/Mage.Sets/src/mage/cards/s/StalkingYeti.java b/Mage.Sets/src/mage/cards/s/StalkingYeti.java index 5d336566cf1..8f9b22eb30a 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingYeti.java +++ b/Mage.Sets/src/mage/cards/s/StalkingYeti.java @@ -8,7 +8,7 @@ import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.constants.SubType; @@ -37,7 +37,7 @@ public final class StalkingYeti extends CardImpl { this.toughness = new MageInt(3); // When Stalking Yeti enters the battlefield, if it's on the battlefield, it deals damage equal to its power to target creature an opponent controls and that creature deals damage equal to its power to Stalking Yeti. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new StalkingYetiEffect()), SourceOnBattlefieldCondition.instance, "When {this} enters the battlefield, if it's on the battlefield, " diff --git a/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java b/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java index 9d373df45aa..a56b8a1700f 100644 --- a/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java +++ b/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -28,7 +28,7 @@ public final class StampedingElkHerd extends CardImpl { this.toughness = new MageInt(5); // Formidable — Whenever Stampeding Elk Herd attacks, if creatures you control have total power 8 or greater, creatures you control gain trample until end of turn. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent()), false), FormidableCondition.instance, "Formidable — Whenever {this} attacks, if creatures you control have total power 8 or greater, creatures you control gain trample until end of turn." diff --git a/Mage.Sets/src/mage/cards/s/StarCrownedStag.java b/Mage.Sets/src/mage/cards/s/StarCrownedStag.java new file mode 100644 index 00000000000..e05d794229b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StarCrownedStag.java @@ -0,0 +1,49 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.TapTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class StarCrownedStag extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + + static { + filter.add(new DefendingPlayerControlsPredicate()); + } + + public StarCrownedStag(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.ELK); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever attacks, tap target creature defending player controls. + Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public StarCrownedStag(final StarCrownedStag card) { + super(card); + } + + @Override + public StarCrownedStag copy() { + return new StarCrownedStag(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java b/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java index 49fd6e28d0d..6cc807ea45e 100644 --- a/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java +++ b/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class SteamcoreWeird extends CardImpl { // When Steamcore Weird enters the battlefield, if {R} was spent to cast Steamcore Weird, it deals 2 damage to any target. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "it")); ability.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.R), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.R), "if {R} was spent to cast {this}, it deals 2 damage to any target."), new ManaSpentToCastWatcher()); } diff --git a/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java b/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java index eded96e94b8..f30cd75e2a5 100644 --- a/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java +++ b/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java @@ -1,11 +1,9 @@ - package mage.cards.s; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -17,7 +15,6 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate.filter; /** * @@ -25,6 +22,9 @@ import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate. */ public final class SteamfloggerBoss extends CardImpl { + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent(SubType.RIGGER, "Rigger creatures"); + public SteamfloggerBoss(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); @@ -34,15 +34,28 @@ public final class SteamfloggerBoss extends CardImpl { this.toughness = new MageInt(3); // Other Rigger creatures you control get +1/+0 and have haste. - Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, - new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield, new FilterCreaturePermanent(SubType.RIGGER, "Rigger creatures"), true)); - Effect effect = new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter); - effect.setText("and have haste"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 0, Duration.WhileOnBattlefield, + filter, true + ) + ); + ability.addEffect(new GainAbilityControlledEffect( + HasteAbility.getInstance(), + Duration.WhileOnBattlefield, + filter + ).setText("and have haste")); this.addAbility(ability); // If a Rigger you control would assemble a Contraption, it assembles two Contraptions instead. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("If a Rigger you control would assemble a Contraption, it assembles two Contraptions instead. (NOT IMPLEMENTED)"))); + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new InfoEffect( + "If a Rigger you control would assemble a Contraption, " + + "it assembles two Contraptions instead. (NOT IMPLEMENTED)" + ) + )); } diff --git a/Mage.Sets/src/mage/cards/s/SteelSquirrel.java b/Mage.Sets/src/mage/cards/s/SteelSquirrel.java index 0a5f82b69c2..c8f992ceec2 100644 --- a/Mage.Sets/src/mage/cards/s/SteelSquirrel.java +++ b/Mage.Sets/src/mage/cards/s/SteelSquirrel.java @@ -76,7 +76,7 @@ class SteelSquirrelTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + if (this.isControlledBy(event.getPlayerId()) && event.getFlag()) { if (event.getAmount() >= 5) { for (Effect effect : this.getEffects()) { effect.setValue("rolled", event.getAmount()); diff --git a/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java b/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java index 3716bc5fa36..61f2a5dc8ac 100644 --- a/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java +++ b/Mage.Sets/src/mage/cards/s/StensiaMasquerade.java @@ -88,7 +88,7 @@ class StensiaMasqueradeTriggeredAbility extends TriggeredAbilityImpl { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent permanent = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage() && permanent != null - && permanent.hasSubtype(SubType.VAMPIRE, game) && permanent.getControllerId().equals(controllerId)) { + && permanent.hasSubtype(SubType.VAMPIRE, game) && permanent.isControlledBy(controllerId)) { this.getEffects().clear(); AddCountersTargetEffect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setTargetPointer(new FixedTarget(permanent.getId())); diff --git a/Mage.Sets/src/mage/cards/s/StitchersSupplier.java b/Mage.Sets/src/mage/cards/s/StitchersSupplier.java new file mode 100644 index 00000000000..4c91980fe62 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StitchersSupplier.java @@ -0,0 +1,39 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldOrDiesSourceTriggeredAbility; +import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class StitchersSupplier extends CardImpl { + + public StitchersSupplier(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Stitcher's Supplier enters the battlefield or dies, put the top three cards of your library into your graveyard. + this.addAbility(new EntersBattlefieldOrDiesSourceTriggeredAbility( + new PutTopCardOfLibraryIntoGraveControllerEffect(3), false) + ); + } + + public StitchersSupplier(final StitchersSupplier card) { + super(card); + } + + @Override + public StitchersSupplier copy() { + return new StitchersSupplier(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StoicRebuttal.java b/Mage.Sets/src/mage/cards/s/StoicRebuttal.java index 7722c315e80..a9340141640 100644 --- a/Mage.Sets/src/mage/cards/s/StoicRebuttal.java +++ b/Mage.Sets/src/mage/cards/s/StoicRebuttal.java @@ -23,7 +23,7 @@ public final class StoicRebuttal extends CardImpl { public StoicRebuttal(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}"); - // Metalcraft - Stoic Rebuttal costs {1} less to cast if you control three or more artifacts. + // Metalcraft — Stoic Rebuttal costs {1} less to cast if you control three or more artifacts. Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(1, MetalcraftCondition.instance)); ability.setRuleAtTheTop(true); ability.setAbilityWord(AbilityWord.METALCRAFT); diff --git a/Mage.Sets/src/mage/cards/s/StolenStrategy.java b/Mage.Sets/src/mage/cards/s/StolenStrategy.java index 07b0556f1e9..18e01088465 100644 --- a/Mage.Sets/src/mage/cards/s/StolenStrategy.java +++ b/Mage.Sets/src/mage/cards/s/StolenStrategy.java @@ -133,7 +133,7 @@ class StolenStrategyCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(cardId) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(cardId) && source.isControlledBy(affectedControllerId)) { ExileZone exileZone = game.getState().getExile().getExileZone(exileId); return exileZone != null && exileZone.contains(cardId); } @@ -164,7 +164,7 @@ class StolenStrategySpendAnyManaEffect extends AsThoughEffectImpl implements AsT @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && Objects.equals(objectId, ((FixedTarget) getTargetPointer()).getTarget()) && ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId) && (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId)) diff --git a/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java b/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java index 3d4421c55d0..ec704870134 100644 --- a/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java +++ b/Mage.Sets/src/mage/cards/s/StoneIdolTrap.java @@ -1,4 +1,3 @@ - package mage.cards.s; import mage.abilities.Ability; @@ -57,7 +56,7 @@ class StoneIdolTrapCostReductionEffect extends CostModificationEffectImpl { public StoneIdolTrapCostReductionEffect() { super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST); - staticText = "{this} costs {1} less to cast for each attacking creature"; + staticText = "This spell costs {1} less to cast for each attacking creature"; } protected StoneIdolTrapCostReductionEffect(StoneIdolTrapCostReductionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java b/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java index 1bfd99ad2ff..cee0f71bf46 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class StormFleetArsonist extends CardImpl { this.toughness = new MageInt(4); // Raid - When Storm Fleet Arsonist enters the battlefield, if you attacked with a creature this turn, target opponent sacrifices a permanent. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new SacrificeEffect(new FilterPermanent(), 1, "Target opponent")), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, target opponent sacrifices a permanent."); diff --git a/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java b/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java index d59a4bfbe5c..ee368746844 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class StormFleetPyromancer extends CardImpl { this.toughness = new MageInt(2); // Raid - When Storm Fleet Pyromancer enters the battlefield, if you attacked with a creature this turn, Storm Fleet Pyromancer deals 2 damage to any target. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, {this} deals 2 damage to any target."); diff --git a/Mage.Sets/src/mage/cards/s/StormFleetSprinter.java b/Mage.Sets/src/mage/cards/s/StormFleetSprinter.java index bdf110a1470..8b284496863 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetSprinter.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetSprinter.java @@ -26,7 +26,7 @@ public final class StormFleetSprinter extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); - // Storm Fleet Sprinter can’t be blocked. + // Storm Fleet Sprinter can't be blocked. this.addAbility(new CantBeBlockedSourceAbility()); } diff --git a/Mage.Sets/src/mage/cards/s/StormFleetSpy.java b/Mage.Sets/src/mage/cards/s/StormFleetSpy.java index d6cd125a510..c3b029d4266 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetSpy.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetSpy.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class StormFleetSpy extends CardImpl { this.toughness = new MageInt(2); // Raid — When Storm Fleet Spy enters the battlefield, if you attacked with a creature this turn, draw a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, draw a card."); diff --git a/Mage.Sets/src/mage/cards/s/StormTheVault.java b/Mage.Sets/src/mage/cards/s/StormTheVault.java index 0edc06c35f4..968f3b72d52 100644 --- a/Mage.Sets/src/mage/cards/s/StormTheVault.java +++ b/Mage.Sets/src/mage/cards/s/StormTheVault.java @@ -2,10 +2,14 @@ package mage.cards.s; import java.util.UUID; + +import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -17,6 +21,7 @@ import mage.constants.ComparisonType; import mage.constants.SuperType; import mage.constants.TargetController; import mage.filter.StaticFilters; +import mage.game.Game; import mage.game.permanent.token.TreasureToken; /** @@ -38,13 +43,15 @@ public final class StormTheVault extends CardImpl { // At the beginning of your end step, if you control five or more artifacts, transform Storm the Vault. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, ComparisonType.MORE_THAN, 4), "At the beginning of your end step, if you control five or more artifacts, transform {this}")); } + + public StormTheVault(final StormTheVault card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/s/StormcloudSpirit.java b/Mage.Sets/src/mage/cards/s/StormcloudSpirit.java new file mode 100644 index 00000000000..3b476bf1d5a --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StormcloudSpirit.java @@ -0,0 +1,36 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class StormcloudSpirit extends CardImpl { + + public StormcloudSpirit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + } + + public StormcloudSpirit(final StormcloudSpirit card) { + super(card); + } + + @Override + public StormcloudSpirit copy() { + return new StormcloudSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StormscaleAnarch.java b/Mage.Sets/src/mage/cards/s/StormscaleAnarch.java new file mode 100644 index 00000000000..95c6653fdc3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StormscaleAnarch.java @@ -0,0 +1,86 @@ +package mage.cards.s; + +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.common.DiscardCardCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author TheElk801 + */ +public final class StormscaleAnarch extends CardImpl { + + public StormscaleAnarch(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {2}{R}, Discard a card at random: Stormscale Anarch deals 2 damage to any target. If the discarded card was multicolored, Stormscale Anarch deals 4 damage to that creature or player instead. + Ability ability = new SimpleActivatedAbility(new StormscaleAnarchEffect(), new ManaCostsImpl("{2}{R}")); + ability.addCost(new DiscardCardCost(true)); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + public StormscaleAnarch(final StormscaleAnarch card) { + super(card); + } + + @Override + public StormscaleAnarch copy() { + return new StormscaleAnarch(this); + } +} + +class StormscaleAnarchEffect extends OneShotEffect { + + public StormscaleAnarchEffect() { + super(Outcome.Benefit); + this.staticText = "{this} deals 2 damage to any target. " + + "If the discarded card was multicolored, " + + "{this} deals 4 damage to that permanent or player instead."; + } + + public StormscaleAnarchEffect(final StormscaleAnarchEffect effect) { + super(effect); + } + + @Override + public StormscaleAnarchEffect copy() { + return new StormscaleAnarchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int damageToDeal = 2; + outerloop: + for (Cost cost : source.getCosts()) { + if (cost instanceof DiscardCardCost) { + for (Card card : ((DiscardCardCost) cost).getCards()) { + if (card.getColor(game).isMulticolored()) { + damageToDeal = 4; + break outerloop; + } + } + } + } + return new DamageTargetEffect(damageToDeal).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java b/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java index 45e6b24d3f1..39f93230343 100644 --- a/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.KickerAbility; @@ -45,7 +45,7 @@ public final class StormscapeBattlemage extends CardImpl { this.addAbility(kickerAbility); // When Stormscape Battlemage enters the battlefield, if it was kicked with its {W} kicker, you gain 3 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3),false), new KickedCostCondition("{W}"), "When Stormscape Battlemage enters the battlefield, if it was kicked with its {W} kicker, you gain 3 life.")); @@ -53,7 +53,7 @@ public final class StormscapeBattlemage extends CardImpl { // When Stormscape Battlemage enters the battlefield, if it was kicked with its {2}{B} kicker, destroy target nonblack creature. That creature can't be regenerated. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true),false); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, new KickedCostCondition("{2}{B}"), "When Stormscape Battlemage enters the battlefield, if it was kicked with its {2}{B} kicker, destroy target nonblack creature. That creature can't be regenerated.")); } diff --git a/Mage.Sets/src/mage/cards/s/StranglingSpores.java b/Mage.Sets/src/mage/cards/s/StranglingSpores.java new file mode 100644 index 00000000000..9ff0cda687f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StranglingSpores.java @@ -0,0 +1,33 @@ +package mage.cards.s; + +import java.util.UUID; +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.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class StranglingSpores extends CardImpl { + + public StranglingSpores(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}"); + + // Target creature gets -3/-3 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public StranglingSpores(final StranglingSpores card) { + super(card); + } + + @Override + public StranglingSpores copy() { + return new StranglingSpores(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StratusDancer.java b/Mage.Sets/src/mage/cards/s/StratusDancer.java index 70f8123dffa..897d67d0198 100644 --- a/Mage.Sets/src/mage/cards/s/StratusDancer.java +++ b/Mage.Sets/src/mage/cards/s/StratusDancer.java @@ -40,7 +40,7 @@ public final class StratusDancer extends CardImpl { Effect effect = new CounterTargetEffect(); effect.setText("counter target instant or sorcery spell"); Ability ability = new TurnedFaceUpSourceTriggeredAbility(effect, false); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StreetSavvy.java b/Mage.Sets/src/mage/cards/s/StreetSavvy.java new file mode 100644 index 00000000000..f7d89d9b120 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StreetSavvy.java @@ -0,0 +1,80 @@ +package mage.cards.s; + +import java.util.UUID; + +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; + +/** + * + * @author noahg + */ +public final class StreetSavvy extends CardImpl { + + public StreetSavvy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + + 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 gets +0/+2 and can block creatures with landwalk abilities as though they didn't have those abilities. + SimpleStaticAbility staticAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(0 ,2) + .setText("Enchanted creature gets +0/+2 and can block creatures with landwalk abilities as though they didn't have those abilities.")); + staticAbility.addEffect(new StreetSavvyEffect()); + this.addAbility(staticAbility); + } + + public StreetSavvy(final StreetSavvy card) { + super(card); + } + + @Override + public StreetSavvy copy() { + return new StreetSavvy(this); + } +} + +class StreetSavvyEffect extends AsThoughEffectImpl { + + public StreetSavvyEffect() { + super(AsThoughEffectType.BLOCK_LANDWALK, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = ""; + } + + public StreetSavvyEffect(final StreetSavvyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public StreetSavvyEffect copy() { + return new StreetSavvyEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + return sourcePermanent != null && sourceId.equals(sourcePermanent.getAttachedTo()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/StromkirkOccultist.java b/Mage.Sets/src/mage/cards/s/StromkirkOccultist.java index 7e0974aa053..ff3405bd2a5 100644 --- a/Mage.Sets/src/mage/cards/s/StromkirkOccultist.java +++ b/Mage.Sets/src/mage/cards/s/StromkirkOccultist.java @@ -117,7 +117,7 @@ class StromkirkOccultistPlayFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/s/Submerge.java b/Mage.Sets/src/mage/cards/s/Submerge.java index c8bf389e0c3..aeacf5422e1 100644 --- a/Mage.Sets/src/mage/cards/s/Submerge.java +++ b/Mage.Sets/src/mage/cards/s/Submerge.java @@ -34,7 +34,7 @@ public final class Submerge extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{U}"); - // If an opponent controls a Forest and you control an Island, you may cast Submerge without paying its mana cost. + // If an opponent controls a Forest and you control an Island, you may cast this spell without paying its mana cost. Condition condition = new CompoundCondition("If an opponent controls a Forest and you control an Island", new OpponentControlsPermanentCondition(filterForest), new PermanentsOnTheBattlefieldCondition(filterIsland)); diff --git a/Mage.Sets/src/mage/cards/s/SummonersEgg.java b/Mage.Sets/src/mage/cards/s/SummonersEgg.java index 89d2ae46d02..055eb812370 100644 --- a/Mage.Sets/src/mage/cards/s/SummonersEgg.java +++ b/Mage.Sets/src/mage/cards/s/SummonersEgg.java @@ -29,7 +29,7 @@ public final class SummonersEgg extends CardImpl { public SummonersEgg(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); - this.subtype.add(SubType.CONSTRUCT); + this.subtype.add(SubType.EGG); this.power = new MageInt(0); this.toughness = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/s/SunDroplet.java b/Mage.Sets/src/mage/cards/s/SunDroplet.java index 3e8be1a94a8..6ff432b37d1 100644 --- a/Mage.Sets/src/mage/cards/s/SunDroplet.java +++ b/Mage.Sets/src/mage/cards/s/SunDroplet.java @@ -7,7 +7,7 @@ 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.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DoIfCostPaid; @@ -36,8 +36,9 @@ public final class SunDroplet extends CardImpl { // 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 ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.ANY, false), + 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")); } diff --git a/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java b/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java index 4bba3ef9154..10dcad1ec4d 100644 --- a/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java +++ b/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -65,8 +64,8 @@ class SunbirdsInvocationTriggeredAbility extends SpellCastControllerTriggeredAbi if (event.getPlayerId().equals(getControllerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null - && spell.getFromZone().equals(Zone.HAND) - && spell.getOwnerId().equals(getControllerId())) { // must be from the controller's hand + && spell.getFromZone() == Zone.HAND + && spell.isOwnedBy(getControllerId())) { // must be from the controller's hand if (spell.getCard() != null) { for (Effect effect : getEffects()) { effect.setTargetPointer(new FixedTarget(spell.getId())); @@ -136,14 +135,7 @@ class SunbirdsInvocationEffect extends OneShotEffect { } } } - } - - while (!cards.isEmpty()) { - Card card = cards.getRandom(game); - if (card != null) { - cards.remove(card); - card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); - } + controller.putCardsOnBottomOfLibrary(cards, game, source, false); } return true; } diff --git a/Mage.Sets/src/mage/cards/s/Suncleanser.java b/Mage.Sets/src/mage/cards/s/Suncleanser.java new file mode 100644 index 00000000000..8575b71920b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Suncleanser.java @@ -0,0 +1,143 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.OneShotEffect; +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.counters.Counter; +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.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class Suncleanser extends CardImpl { + + public Suncleanser(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(1); + this.toughness = new MageInt(4); + + // When Suncleanser enters the battlefield, choose one — + // • Remove all counters from target creature. It can't have counters put on it for as long as Suncleanser remains on the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility( + new SuncleanserRemoveCountersEffect(false), false + ); + ability.addEffect(new SuncleanserPreventCountersEffect(false)); + ability.addTarget(new TargetCreaturePermanent()); + + // • Target opponent loses all counters. That player can't get counters for as long as Suncleanser remains on the battlefield. + Mode mode = new Mode(); + mode.getEffects().add(new SuncleanserRemoveCountersEffect(true)); + mode.getEffects().add(new SuncleanserPreventCountersEffect(true)); + mode.getTargets().add(new TargetOpponent()); + ability.addMode(mode); + this.addAbility(ability); + } + + public Suncleanser(final Suncleanser card) { + super(card); + } + + @Override + public Suncleanser copy() { + return new Suncleanser(this); + } +} + +class SuncleanserRemoveCountersEffect extends OneShotEffect { + + public SuncleanserRemoveCountersEffect(boolean player) { + super(Outcome.Benefit); + if (player) { + staticText = "Target opponent loses all counters."; + } else { + staticText = "Remove all counters from target creature."; + } + } + + public SuncleanserRemoveCountersEffect(SuncleanserRemoveCountersEffect effect) { + super(effect); + } + + @Override + public SuncleanserRemoveCountersEffect copy() { + return new SuncleanserRemoveCountersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + for (Counter counter : permanent.getCounters(game).copy().values()) { // copy to prevent ConcurrentModificationException + permanent.removeCounters(counter, game); + } + return true; + } + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null) { + for (Counter counter : player.getCounters().copy().values()) { // copy to prevent ConcurrentModificationException + player.removeCounters(counter.getName(), counter.getCount(), source, game); + } + return true; + } + return false; + } + +} + +class SuncleanserPreventCountersEffect extends ContinuousRuleModifyingEffectImpl { + + public SuncleanserPreventCountersEffect(boolean player) { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + if (player) { + staticText = "That player can't get counters for as long as {this} remains on the battlefield."; + } else { + staticText = "It can't have counters put on it for as long as {this} remains on the battlefield"; + } + } + + public SuncleanserPreventCountersEffect(final SuncleanserPreventCountersEffect effect) { + super(effect); + } + + @Override + public SuncleanserPreventCountersEffect copy() { + return new SuncleanserPreventCountersEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ADD_COUNTERS; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!source.getFirstTarget().equals(event.getTargetId())) { + return false; + } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + discard(); + return false; + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/Sunforger.java b/Mage.Sets/src/mage/cards/s/Sunforger.java index 870522a8ec8..f6bc12430a8 100644 --- a/Mage.Sets/src/mage/cards/s/Sunforger.java +++ b/Mage.Sets/src/mage/cards/s/Sunforger.java @@ -92,7 +92,7 @@ class SunforgerEffect extends OneShotEffect { /** * 10/1/2005 Any card you find must be legally castable (for * example, you have to be able to choose a legal target for - * it). If you can’t find a castable card (or choose not to), + * it). If you can't find a castable card (or choose not to), * nothing happens and you shuffle your library. */ diff --git a/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java b/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java index 137753dc7af..8c296177d31 100644 --- a/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; @@ -45,11 +45,11 @@ public final class SunscapeBattlemage extends CardImpl { // When {this} enters the battlefield, if it was kicked with its {1}{G} kicker, destroy target creature with flying. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalTriggeredAbility(ability, new KickedCostCondition("{1}{G}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{1}{G}"), "When {this} enters the battlefield, if it was kicked with its {1}{G} kicker, destroy target creature with flying.")); // When {this} enters the battlefield, if it was kicked with its {2}{U} kicker, draw two cards. - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( new DrawCardSourceControllerEffect(2)), new KickedCostCondition("{2}{U}"), "When {this} enters the battlefield, if it was kicked with its {2}{U} kicker, draw two cards.")); } diff --git a/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java b/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java index b336d901301..2817418444f 100644 --- a/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java +++ b/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java @@ -5,7 +5,7 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -40,7 +40,7 @@ public final class SunspireGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Sunspire Gatekeepers enter the battlefield, if you control two or more Gates, create a 2/2 white Knight creature token with vigilance. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KnightToken())), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), "When {this} enters the battlefield, if you control two or more Gates, create a 2/2 white Knight creature token with vigilance.")); diff --git a/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java b/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java index f82ca5af3cf..3f67103eff5 100644 --- a/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java +++ b/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -23,7 +22,9 @@ public final class SupernaturalStamina extends CardImpl { // Until end of turn, target creature gets +2/+0 and gains "When this creature dies, return it to the battlefield tapped under its owner's control." getSpellAbility().addTarget(new TargetCreaturePermanent()); - getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn)); + getSpellAbility().addEffect(new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("Until end of turn, target creature gets +2/+0") + ); getSpellAbility().addEffect(new GainAbilityTargetEffect( new DiesTriggeredAbility( new ReturnSourceFromGraveyardToBattlefieldEffect(true, true), diff --git a/Mage.Sets/src/mage/cards/s/SupplyCaravan.java b/Mage.Sets/src/mage/cards/s/SupplyCaravan.java index ae52f0a59ba..cb76066914c 100644 --- a/Mage.Sets/src/mage/cards/s/SupplyCaravan.java +++ b/Mage.Sets/src/mage/cards/s/SupplyCaravan.java @@ -4,7 +4,7 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -36,7 +36,7 @@ public final class SupplyCaravan extends CardImpl { this.toughness = new MageInt(5); // When Supply Caravan enters the battlefield, if you control a tapped creature, create a 1/1 white Warrior creature token with vigilance. - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorVigilantToken())), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorVigilantToken())), new PermanentsOnTheBattlefieldCondition(filter), "When {this} enters the battlefield, if you control a tapped creature, create a 1/1 white Warrior creature token with vigilance.")); } diff --git a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java new file mode 100644 index 00000000000..b434075e19d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java @@ -0,0 +1,156 @@ +package mage.cards.s; + +import java.util.Iterator; +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.PayVariableLoyaltyCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.OpponentsLostLifeCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.*; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.Counter; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.players.PlayerList; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.PlayerLostLifeNonCombatWatcher; +import mage.watchers.common.PlayerLostLifeWatcher; + +/** + * + * @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 PlanswalkerEntersWithLoyalityCountersAbility(3)); + + // +1: Put a loyalty counter on Supreme Leader Snoke for each life lost by all opponents from noncombat sources this turn. + Ability ability1 = new LoyaltyAbility(new SupremeLeaderSnokeCounterEffect(CounterType.LOYALTY.createInstance()), 1); + this.addAbility(ability1); + + // -1: Draw a card and lose 1 life. + Ability ability2 = new LoyaltyAbility(new DrawCardSourceControllerEffect(1), -1); + ability2.addEffect(new LoseLifeSourceControllerEffect(1).setText("and lose 1 life")); + this.addAbility(ability2); + + // -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")); + 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()); + 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 + public SupremeLeaderSnoke copy() { + return new SupremeLeaderSnoke(this); + } +} + +class OpponentNoncombatLostLifeCount implements DynamicValue { + + @Override + public int calculate(Game game, Ability source, Effect effect) { + PlayerLostLifeNonCombatWatcher watcher = (PlayerLostLifeNonCombatWatcher) game.getState().getWatchers().get(PlayerLostLifeNonCombatWatcher.class.getSimpleName()); + if(watcher != null) { + return watcher.getAllOppLifeLost(source.getControllerId(), game); + } + return 0; + } + + @Override + public DynamicValue copy() { + return new OpponentNoncombatLostLifeCount(); + } + + @Override + public String getMessage() { + return "life lost by all opponents from noncombat sources this turn"; + } +} + +class SupremeLeaderSnokeCounterEffect extends OneShotEffect { + + protected final Counter counter; + + public SupremeLeaderSnokeCounterEffect(Counter counter) { + super(Outcome.Benefit); + this.counter = counter; + staticText = "Put a loyalty counter on {this} for each life lost by all opponents from noncombat sources this turn"; + } + + public SupremeLeaderSnokeCounterEffect(final SupremeLeaderSnokeCounterEffect effect) { + super(effect); + this.counter = effect.counter; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if(permanent != null) { + int amount = new OpponentNoncombatLostLifeCount().calculate(game, source, this); + if(amount > 0) { + Counter counterToAdd = counter.copy(); + counterToAdd.add(amount - counter.getCount()); + permanent.addCounters(counterToAdd, source, game); + } + } + return true; + } + + @Override + public SupremeLeaderSnokeCounterEffect copy() { + return new SupremeLeaderSnokeCounterEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SupremePhantom.java b/Mage.Sets/src/mage/cards/s/SupremePhantom.java new file mode 100644 index 00000000000..bcb8f301377 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SupremePhantom.java @@ -0,0 +1,52 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class SupremePhantom extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.SPIRIT, "Spirits"); + + public SupremePhantom(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Other Spirits you control get +1/+1. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, + filter, true + ) + )); + } + + public SupremePhantom(final SupremePhantom card) { + super(card); + } + + @Override + public SupremePhantom copy() { + return new SupremePhantom(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SurgeMare.java b/Mage.Sets/src/mage/cards/s/SurgeMare.java new file mode 100644 index 00000000000..e8930320847 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SurgeMare.java @@ -0,0 +1,73 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class SurgeMare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public SurgeMare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{U}"); + + this.subtype.add(SubType.HORSE); + this.subtype.add(SubType.FISH); + this.power = new MageInt(0); + this.toughness = new MageInt(5); + + // Surge Mare can't be blocked by green creatures. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ) + )); + + // Whenever Surge Mare deals damage to an opponent, you may draw a card. If you do, discard a card. + this.addAbility(new DealsDamageToOpponentTriggeredAbility( + new DrawDiscardControllerEffect(1, 1) + .setText("you may draw a card. If you do, discard a card"), + true + )); + + // {1}{U}: Surge Mare gets +2/-2 until end of turn. + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(2, -2, Duration.EndOfTurn), + new ManaCostsImpl("{1}{U}") + )); + } + + public SurgeMare(final SurgeMare card) { + super(card); + } + + @Override + public SurgeMare copy() { + return new SurgeMare(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java b/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java index 60022980f38..dfed6f8d655 100644 --- a/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java +++ b/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class SurrakTheHuntCaller extends CardImpl { this.toughness = new MageInt(4); // Formidable — At the beginning of combat on your turn, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfCombatTriggeredAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), TargetController.YOU, false), FormidableCondition.instance, "Formidable — At the beginning of combat on your turn, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn."); diff --git a/Mage.Sets/src/mage/cards/s/SurveyorsScope.java b/Mage.Sets/src/mage/cards/s/SurveyorsScope.java index 51cb6bc1ae6..aa0c1ee5501 100644 --- a/Mage.Sets/src/mage/cards/s/SurveyorsScope.java +++ b/Mage.Sets/src/mage/cards/s/SurveyorsScope.java @@ -75,7 +75,7 @@ class SurveyorsScopeEffect extends OneShotEffect { } } game.informPlayers(new StringBuilder("Surveyor's Scope: X = ").append(numberOfLands).toString()); - // 10/17/2013 If no players control at least two more lands than you when the ability resolves, you’ll still search and shuffle your library. + // 10/17/2013 If no players control at least two more lands than you when the ability resolves, you'll still search and shuffle your library. return new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, numberOfLands, StaticFilters.FILTER_CARD_BASIC_LAND)).apply(game, source); } return false; diff --git a/Mage.Sets/src/mage/cards/s/SuspiciousBookcase.java b/Mage.Sets/src/mage/cards/s/SuspiciousBookcase.java new file mode 100644 index 00000000000..e4dcdc04102 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SuspiciousBookcase.java @@ -0,0 +1,51 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class SuspiciousBookcase extends CardImpl { + + public SuspiciousBookcase(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); + + this.subtype.add(SubType.WALL); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // {3}, {T}: Target creature can't be blocked this turn. + Ability ability = new SimpleActivatedAbility( + new CantBeBlockedTargetEffect(), + new GenericManaCost(3) + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public SuspiciousBookcase(final SuspiciousBookcase card) { + super(card); + } + + @Override + public SuspiciousBookcase copy() { + return new SuspiciousBookcase(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SwiftSilence.java b/Mage.Sets/src/mage/cards/s/SwiftSilence.java new file mode 100644 index 00000000000..d0619b05d60 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SwiftSilence.java @@ -0,0 +1,79 @@ +package mage.cards.s; + +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +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.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; + +/** + * + * @author noahg + */ +public final class SwiftSilence extends CardImpl { + + public SwiftSilence(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}{U}{U}"); + + + // Counter all other spells. Draw a card for each spell countered this way. + this.getSpellAbility().addEffect(new SwiftSilenceEffect()); + } + + public SwiftSilence(final SwiftSilence card) { + super(card); + } + + @Override + public SwiftSilence copy() { + return new SwiftSilence(this); + } +} + +class SwiftSilenceEffect extends OneShotEffect { + + public SwiftSilenceEffect() { + super(Outcome.Detriment); + staticText = "Counter all other spells. Draw a card for each spell countered this way."; + } + + public SwiftSilenceEffect(final SwiftSilenceEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + List spellsToCounter = new LinkedList<>(); + for (StackObject stackObject : game.getStack()) { + if (stackObject instanceof Spell && !stackObject.getId().equals(source.getSourceObject(game).getId())) { + spellsToCounter.add((Spell) stackObject); + } + } + int toDraw = 0; + for (Spell spell : spellsToCounter) { + if (game.getStack().counter(spell.getId(), source.getSourceId(), game)){ + toDraw++; + } + } + Player controller = game.getPlayer(source.getControllerId()); + if (toDraw > 0 && controller != null){ + controller.drawCards(toDraw, game); + } + return true; + } + + @Override + public SwiftSilenceEffect copy() { + return new SwiftSilenceEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TIESilencer.java b/Mage.Sets/src/mage/cards/t/TIESilencer.java new file mode 100644 index 00000000000..4a5d60d45e6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TIESilencer.java @@ -0,0 +1,89 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class TIESilencer extends CardImpl { + + public TIESilencer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{B}{R}"); + + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // Whenever TIE Silencer attacks, it deals 1 damage to defending player and 1 damage to up to one target creature that player controls. + Ability ability = new AttacksTriggeredAbility(new TIESilencerEffect(), false); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + } + + public TIESilencer(final TIESilencer card) { + super(card); + } + + @Override + public TIESilencer copy() { + return new TIESilencer(this); + } +} + +class TIESilencerEffect extends OneShotEffect { + + public TIESilencerEffect() { + super(Outcome.Damage); + staticText = "it deals 1 damage to defending player and 1 damage to up to one target creature that player controls"; + } + + public TIESilencerEffect(final TIESilencerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID defender = game.getCombat().getDefendingPlayerId(source.getSourceId(), game); + if(defender != null) { + game.damagePlayerOrPlaneswalker(defender, 1, source.getSourceId(), game, false, true); + + UUID target = source.getTargets().getFirstTarget(); + Permanent permanent = game.getPermanent(target); + if(permanent != null) { + permanent.damage(1, source.getSourceId(), game, false, true); + } + + return true; + } + return false; + } + + public TIESilencerEffect copy() { + return new TIESilencerEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TIEStriker.java b/Mage.Sets/src/mage/cards/t/TIEStriker.java new file mode 100644 index 00000000000..6d81f390cb6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TIEStriker.java @@ -0,0 +1,36 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author NinthWorld + */ +public final class TIEStriker extends CardImpl { + + public TIEStriker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + } + + public TIEStriker(final TIEStriker card) { + super(card); + } + + @Override + public TIEStriker copy() { + return new TIEStriker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java index 0c6d366a551..2ea1bd128ee 100644 --- a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java +++ b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.AttackedThisTurnSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CantBeCounteredControlledEffect; @@ -56,11 +56,11 @@ public final class TaigamOjutaiMaster extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); - // Instant, sorcery, and Dragon spells you control can't be countered by spells or abilities. + // Instant, sorcery, and Dragon spells you control can't be countered. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeCounteredControlledEffect(filter, new FilterStackObject(), Duration.WhileOnBattlefield))); // Whenever you cast an instant or sorcery spell from your hand, if Taigam, Ojutai Master attacked this turn, that spell gains rebound. - Ability ability = new ConditionalTriggeredAbility(new TaigamOjutaiMasterTriggeredAbility(), + Ability ability = new ConditionalInterveningIfTriggeredAbility(new TaigamOjutaiMasterTriggeredAbility(), AttackedThisTurnSourceCondition.instance, effectText); this.addAbility(ability, new AttackedThisTurnWatcher()); diff --git a/Mage.Sets/src/mage/cards/t/TajuruPreserver.java b/Mage.Sets/src/mage/cards/t/TajuruPreserver.java index f077b37d8d7..27f8fac2ced 100644 --- a/Mage.Sets/src/mage/cards/t/TajuruPreserver.java +++ b/Mage.Sets/src/mage/cards/t/TajuruPreserver.java @@ -72,7 +72,7 @@ class TajuruPreserverEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { MageObject object = game.getObject(event.getSourceId()); if (object instanceof PermanentCard) { if (game.getOpponents(source.getControllerId()).contains(((PermanentCard)object).getControllerId())) { diff --git a/Mage.Sets/src/mage/cards/t/TakeVengeance.java b/Mage.Sets/src/mage/cards/t/TakeVengeance.java new file mode 100644 index 00000000000..5a229b0ba18 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TakeVengeance.java @@ -0,0 +1,40 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class TakeVengeance extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(new TappedPredicate()); + } + + public TakeVengeance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}"); + + // Destroy target tapped creature. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public TakeVengeance(final TakeVengeance card) { + super(card); + } + + @Override + public TakeVengeance copy() { + return new TakeVengeance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TalarasBattalion.java b/Mage.Sets/src/mage/cards/t/TalarasBattalion.java index e41c574d5cc..c7ea37d9da9 100644 --- a/Mage.Sets/src/mage/cards/t/TalarasBattalion.java +++ b/Mage.Sets/src/mage/cards/t/TalarasBattalion.java @@ -61,7 +61,7 @@ class TalarasBattalionEffect extends ContinuousRuleModifyingEffectImpl { TalarasBattalionEffect() { super(Duration.EndOfGame, Outcome.Detriment); - staticText = "Cast {this} only if you've cast another green spell this turn"; + staticText = "Cast this spell only if you've cast another green spell this turn"; } TalarasBattalionEffect(final TalarasBattalionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/TalonsOfWildwood.java b/Mage.Sets/src/mage/cards/t/TalonsOfWildwood.java new file mode 100644 index 00000000000..a843c1a9464 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TalonsOfWildwood.java @@ -0,0 +1,69 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +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.AttachEffect; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class TalonsOfWildwood extends CardImpl { + + public TalonsOfWildwood(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + 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 gets +1/+1 and has trample. + ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield) + ); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), + AttachmentType.AURA + ).setText("and has trample")); + this.addAbility(ability); + + // {2}{G}: Return Talons of Wildwood from your graveyard to your hand. + this.addAbility(new SimpleActivatedAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl("{2}{G}") + )); + } + + public TalonsOfWildwood(final TalonsOfWildwood card) { + super(card); + } + + @Override + public TalonsOfWildwood copy() { + return new TalonsOfWildwood(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TalusPaladin.java b/Mage.Sets/src/mage/cards/t/TalusPaladin.java index 87db0899133..2619c545e02 100644 --- a/Mage.Sets/src/mage/cards/t/TalusPaladin.java +++ b/Mage.Sets/src/mage/cards/t/TalusPaladin.java @@ -82,7 +82,7 @@ class TalusPaladinTriggeredAbility extends TriggeredAbilityImpl { Permanent ally = game.getPermanent(event.getTargetId()); if (ally != null) { if (ally.hasSubtype(SubType.ALLY, game) - && ally.getControllerId().equals(this.getControllerId())) { + && ally.isControlledBy(this.getControllerId())) { if (event.getTargetId().equals(this.getSourceId()) || event.getTargetId().equals(ally.getId())) { return true; diff --git a/Mage.Sets/src/mage/cards/t/Tamanoa.java b/Mage.Sets/src/mage/cards/t/Tamanoa.java index 58d3f70fed5..a567e0c2c0c 100644 --- a/Mage.Sets/src/mage/cards/t/Tamanoa.java +++ b/Mage.Sets/src/mage/cards/t/Tamanoa.java @@ -72,7 +72,7 @@ class TamanoaDealsDamageTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { MageObject eventSourceObject = game.getObject(event.getSourceId()); if (eventSourceObject != null && !eventSourceObject.isCreature()) { - if (getControllerId().equals(game.getControllerId(event.getSourceId()))) { + if (isControlledBy(game.getControllerId(event.getSourceId()))) { this.getEffects().forEach((effect) -> { effect.setValue("damage", event.getAmount()); }); diff --git a/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java b/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java index f3316cca383..c7d568a392c 100644 --- a/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java +++ b/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java @@ -150,7 +150,7 @@ class TamiyoFieldResearcherDelayedTriggeredAbility extends DelayedTriggeredAbili @Override public boolean isInactive(Game game) { - return game.getActivePlayerId().equals(getControllerId()) && game.getTurnNum() != startingTurn; + return game.isActivePlayer(getControllerId()) && game.getTurnNum() != startingTurn; } @Override diff --git a/Mage.Sets/src/mage/cards/t/TangleKelp.java b/Mage.Sets/src/mage/cards/t/TangleKelp.java index 25ae12d2858..d4dde772dfe 100644 --- a/Mage.Sets/src/mage/cards/t/TangleKelp.java +++ b/Mage.Sets/src/mage/cards/t/TangleKelp.java @@ -106,7 +106,7 @@ class DontUntapIfAttackedLastTurnEnchantedEffect extends ContinuousRuleModifying Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null && event.getTargetId().equals(enchantment.getAttachedTo())) { Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null && permanent.getControllerId().equals(game.getActivePlayerId())) { + if (permanent != null && permanent.isControlledBy(game.getActivePlayerId())) { AttackedLastTurnWatcher watcher = (AttackedLastTurnWatcher) game.getState().getWatchers().get(AttackedLastTurnWatcher.class.getSimpleName()); if (watcher != null) { Set attackingCreatures = watcher.getAttackedLastTurnCreatures(permanent.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/t/Taunt.java b/Mage.Sets/src/mage/cards/t/Taunt.java index 377d64a8993..cff6d3e77c2 100644 --- a/Mage.Sets/src/mage/cards/t/Taunt.java +++ b/Mage.Sets/src/mage/cards/t/Taunt.java @@ -55,14 +55,14 @@ class TauntEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - return permanent.getControllerId().equals(this.getTargetPointer().getFirst(game, source)); + return permanent.isControlledBy(this.getTargetPointer().getFirst(game, source)); } @Override public boolean isInactive(Ability source, Game game) { return startingTurn != game.getTurnNum() && (game.getPhase().getType() == TurnPhase.END && - game.getActivePlayerId().equals(this.getTargetPointer().getFirst(game, source))); + game.isActivePlayer(this.getTargetPointer().getFirst(game, source))); } @Override diff --git a/Mage.Sets/src/mage/cards/t/TawnosUrzasApprentice.java b/Mage.Sets/src/mage/cards/t/TawnosUrzasApprentice.java new file mode 100644 index 00000000000..e4db5140e72 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TawnosUrzasApprentice.java @@ -0,0 +1,101 @@ +package mage.cards.t; + +import java.util.UUID; +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.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.HasteAbility; +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.FilterStackObject; +import mage.filter.predicate.ability.ArtifactSourcePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackAbility; +import mage.players.Player; +import mage.target.common.TargetActivatedOrTriggeredAbility; + +/** + * + * @author TheElk801 + */ +public final class TawnosUrzasApprentice extends CardImpl { + + private final static FilterStackObject filter = new FilterStackObject("activated or triggered ability you control from an artifact source"); + + static { + filter.add(new ArtifactSourcePredicate()); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public TawnosUrzasApprentice(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // {U}{R}, {T}: Copy target activated or triggered ability you control from an artifact source. You may choose new targets for the copy. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TawnosUrzasApprenticeEffect(), new ManaCostsImpl("{U}{R}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetActivatedOrTriggeredAbility(filter)); + this.addAbility(ability); + } + + public TawnosUrzasApprentice(final TawnosUrzasApprentice card) { + super(card); + } + + @Override + public TawnosUrzasApprentice copy() { + return new TawnosUrzasApprentice(this); + } +} + +class TawnosUrzasApprenticeEffect extends OneShotEffect { + + public TawnosUrzasApprenticeEffect() { + super(Outcome.Copy); + this.staticText = "copy target activated or triggered ability you control from an artifact source. You may choose new targets for the copy"; + } + + public TawnosUrzasApprenticeEffect(final TawnosUrzasApprenticeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(targetPointer.getFirst(game, source)); + if (stackAbility != null) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + stackAbility.createCopyOnStack(game, source, source.getControllerId(), true); + game.informPlayers(sourcePermanent.getIdName() + ": " + controller.getLogName() + " copied an ability"); + return true; + } + } + return false; + + } + + @Override + public TawnosUrzasApprenticeEffect copy() { + return new TawnosUrzasApprenticeEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TearsOfValakut.java b/Mage.Sets/src/mage/cards/t/TearsOfValakut.java index ecd4666d1a9..ee55e4d06e0 100644 --- a/Mage.Sets/src/mage/cards/t/TearsOfValakut.java +++ b/Mage.Sets/src/mage/cards/t/TearsOfValakut.java @@ -31,9 +31,9 @@ public final class TearsOfValakut extends CardImpl { public TearsOfValakut(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); - // Tears of Valakut can't be countered by spells or abilities. + // Tears of Valakut can't be countered. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, effect); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java b/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java index 9f9672c7285..be586c41a5b 100644 --- a/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java +++ b/Mage.Sets/src/mage/cards/t/TeferiMageOfZhalfir.java @@ -89,13 +89,13 @@ class TeferiMageOfZhalfirAddFlashEffect extends ContinuousEffectImpl { } // in Exile for (Card card : game.getState().getExile().getAllCards(game)) { - if (card.getOwnerId().equals(controller.getId()) && card.isCreature()) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } // in Library (e.g. for Mystical Teachings) for (Card card : controller.getLibrary().getCards(game)) { - if (card.getOwnerId().equals(controller.getId()) && card.isCreature()) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { game.getState().addOtherAbility(card, FlashAbility.getInstance()); } } diff --git a/Mage.Sets/src/mage/cards/t/TeferisProtection.java b/Mage.Sets/src/mage/cards/t/TeferisProtection.java index d6d40476710..32af72c7cd7 100644 --- a/Mage.Sets/src/mage/cards/t/TeferisProtection.java +++ b/Mage.Sets/src/mage/cards/t/TeferisProtection.java @@ -59,11 +59,11 @@ class TeferisProtectionEffect extends OneShotEffect { * * 25.08.2017 If a player has protection from everything, it means three * things: 1) All damage that would be dealt to that player is prevented. 2) - * Auras can’t be attached to that player. 3) That player can’t be the + * Auras can't be attached to that player. 3) That player can't be the * target of spells or abilities. * * 25.08.2017 Nothing other than the specified events are prevented or - * illegal. An effect that doesn’t target you could still cause you to + * illegal. An effect that doesn't target you could still cause you to * discard cards, for example. Creatures can still attack you while you have * protection from everything, although combat damage that they would deal * to you will be prevented. diff --git a/Mage.Sets/src/mage/cards/t/TelimTorsEdict.java b/Mage.Sets/src/mage/cards/t/TelimTorsEdict.java index 7b3b24804dd..e065dbebbbb 100644 --- a/Mage.Sets/src/mage/cards/t/TelimTorsEdict.java +++ b/Mage.Sets/src/mage/cards/t/TelimTorsEdict.java @@ -58,7 +58,7 @@ class TelimTorsEdictPredicate implements ObjectPlayerPredicate input, Game game) { Permanent permanent = input.getObject(); UUID playerId = input.getPlayerId(); - if (permanent.getControllerId().equals(playerId) || permanent.getOwnerId().equals(playerId)) { + if (permanent.isControlledBy(playerId) || permanent.isOwnedBy(playerId)) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/t/TempestCaller.java b/Mage.Sets/src/mage/cards/t/TempestCaller.java index 00916df9a6d..992120fcf17 100644 --- a/Mage.Sets/src/mage/cards/t/TempestCaller.java +++ b/Mage.Sets/src/mage/cards/t/TempestCaller.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.UUID; @@ -10,7 +9,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; import mage.target.common.TargetOpponent; /** @@ -28,7 +27,7 @@ public final class TempestCaller extends CardImpl { this.toughness = new MageInt(3); // When Tempest Caller enters the battlefield, tap all creatures target opponent controls. - Ability ability = new EntersBattlefieldTriggeredAbility(new TapAllTargetPlayerControlsEffect(new FilterCreaturePermanent("creatures"))); + Ability ability = new EntersBattlefieldTriggeredAbility(new TapAllTargetPlayerControlsEffect(FILTER_PERMANENT_CREATURES)); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TempestOwl.java b/Mage.Sets/src/mage/cards/t/TempestOwl.java index edfd053a6a6..9f907999b4e 100644 --- a/Mage.Sets/src/mage/cards/t/TempestOwl.java +++ b/Mage.Sets/src/mage/cards/t/TempestOwl.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -38,7 +38,7 @@ public final class TempestOwl extends CardImpl { // When Tempest Owl enters the battlefield, if it was kicked, tap up to three target permanents. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), false); ability.addTarget(new TargetPermanent(0, 3, new FilterPermanent(), false)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, tap up to three target permanents.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, tap up to three target permanents.")); } public TempestOwl(final TempestOwl card) { diff --git a/Mage.Sets/src/mage/cards/t/TempleAltisaur.java b/Mage.Sets/src/mage/cards/t/TempleAltisaur.java index 2f07f760a1c..c4f1afe7dd5 100644 --- a/Mage.Sets/src/mage/cards/t/TempleAltisaur.java +++ b/Mage.Sets/src/mage/cards/t/TempleAltisaur.java @@ -77,7 +77,7 @@ class TempleAltisaurPreventEffect extends PreventionEffectImpl { if (permanent != null && !permanent.getId().equals(source.getSourceId()) && permanent.hasSubtype(SubType.DINOSAUR, game) - && permanent.getControllerId().equals(source.getControllerId())) { + && permanent.isControlledBy(source.getControllerId())) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java b/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java index c8676da8ed7..6db23b4324d 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfAclazotz.java @@ -35,7 +35,7 @@ public final class TempleOfAclazotz extends CardImpl { // {T}: Add {B} this.addAbility(new BlackManaAbility()); - // {T}, Sacrifice a creature: You gain life equal to the sacrificed creature’s toughness. + // {T}, Sacrifice a creature: You gain life equal to the sacrificed creature's toughness. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TempleOfAclazotzEffect(), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TemptWithImmortality.java b/Mage.Sets/src/mage/cards/t/TemptWithImmortality.java index e570ca2a7ca..ad8c586bcad 100644 --- a/Mage.Sets/src/mage/cards/t/TemptWithImmortality.java +++ b/Mage.Sets/src/mage/cards/t/TemptWithImmortality.java @@ -28,7 +28,7 @@ public final class TemptWithImmortality extends CardImpl { public TemptWithImmortality(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}"); - // Tempting offer - Return a creature card from your graveyard to the battlefield. Each opponent may return a creature card from their graveyard to the battlefield. For each player who does, return a creature card from your graveyard to the battlefield. + // Tempting offer - Return a creature card from your graveyard to the battlefield. Each opponent may return a creature card from their graveyard to the battlefield. For each opponent who does, return a creature card from your graveyard to the battlefield. this.getSpellAbility().addEffect(new TemptWithImmortalityEffect()); } @@ -46,7 +46,7 @@ class TemptWithImmortalityEffect extends OneShotEffect { public TemptWithImmortalityEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Tempting offer — Return a creature card from your graveyard to the battlefield. Each opponent may return a creature card from their graveyard to the battlefield. For each player who does, return a creature card from your graveyard to the battlefield"; + this.staticText = "Tempting offer — Return a creature card from your graveyard to the battlefield. Each opponent may return a creature card from their graveyard to the battlefield. For each opponent who does, return a creature card from your graveyard to the battlefield"; } diff --git a/Mage.Sets/src/mage/cards/t/TemptWithVengeance.java b/Mage.Sets/src/mage/cards/t/TemptWithVengeance.java index 12355839571..be648e61b6b 100644 --- a/Mage.Sets/src/mage/cards/t/TemptWithVengeance.java +++ b/Mage.Sets/src/mage/cards/t/TemptWithVengeance.java @@ -23,7 +23,7 @@ public final class TemptWithVengeance extends CardImpl { public TemptWithVengeance(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{R}"); - // Tempting offer - create X 1/1 red Elemental creature tokens with haste. Each opponent may create X 1/1 red Elemental creature tokens with haste. For each player who does, create X 1/1 red Elemental creature tokens with haste. + // Tempting offer - create X 1/1 red Elemental creature tokens with haste. Each opponent may create X 1/1 red Elemental creature tokens with haste. For each opponent who does, create X 1/1 red Elemental creature tokens with haste. this.getSpellAbility().addEffect(new TemptWithVengeanceEffect()); } @@ -41,7 +41,7 @@ class TemptWithVengeanceEffect extends OneShotEffect { public TemptWithVengeanceEffect() { super(Outcome.PutLandInPlay); - this.staticText = "Tempting offer — create X 1/1 red Elemental creature tokens with haste. Each opponent may create X 1/1 red Elemental creature tokens with haste. For each player who does, create X 1/1 red Elemental creature tokens with haste"; + this.staticText = "Tempting offer — create X 1/1 red Elemental creature tokens with haste. Each opponent may create X 1/1 red Elemental creature tokens with haste. For each opponent who does, create X 1/1 red Elemental creature tokens with haste"; } public TemptWithVengeanceEffect(final TemptWithVengeanceEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java b/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java index e503c10e77d..b13f74ec870 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class TerritorialAllosaurus extends CardImpl { // When Territorial Allosaurus enters the battlefield, if it was kicked, it fights another target creature. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect()); - Ability conditionalAbility = new ConditionalTriggeredAbility(ability, KickedCondition.instance, + 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()); diff --git a/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java b/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java index be174fcc6a2..0b2b8cbe9d4 100644 --- a/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java +++ b/Mage.Sets/src/mage/cards/t/TerrorOfKruinPass.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; @@ -55,7 +55,7 @@ public final class TerrorOfKruinPass extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Terror of Kruin Pass. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public TerrorOfKruinPass(final TerrorOfKruinPass card) { diff --git a/Mage.Sets/src/mage/cards/t/TestOfEndurance.java b/Mage.Sets/src/mage/cards/t/TestOfEndurance.java index 0c2782dcacb..c26c75408e7 100644 --- a/Mage.Sets/src/mage/cards/t/TestOfEndurance.java +++ b/Mage.Sets/src/mage/cards/t/TestOfEndurance.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class TestOfEndurance extends CardImpl { // At the beginning of your upkeep, if you have 50 or more life, you win the game. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, new FiftyOrMoreLifeCondition(), "At the beginning of your upkeep, if you have 50 or more life, you win the game.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new FiftyOrMoreLifeCondition(), "At the beginning of your upkeep, if you have 50 or more life, you win the game.")); } public TestOfEndurance(final TestOfEndurance card) { diff --git a/Mage.Sets/src/mage/cards/t/Tetravus.java b/Mage.Sets/src/mage/cards/t/Tetravus.java index 7a7820f44e1..ace6165e8ed 100644 --- a/Mage.Sets/src/mage/cards/t/Tetravus.java +++ b/Mage.Sets/src/mage/cards/t/Tetravus.java @@ -1,35 +1,40 @@ - package mage.cards.t; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.StaticAbility; +import mage.MageObjectReference; +import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.Cost; import mage.abilities.costs.common.ExileTargetCost; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; 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.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.game.permanent.token.TetraviteToken; +import mage.players.Player; import mage.target.common.TargetControlledPermanent; +import mage.util.CardUtil; /** * - * @author MarcoMarin + * @author TheElk801 */ public final class Tetravus extends CardImpl { @@ -41,15 +46,24 @@ public final class Tetravus extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Tetravus enters the battlefield with three +1/+1 counters on it. - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), "{this} enters the battlefield with three +1/+1 counters on it")); + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), + "with three +1/+1 counters on it" + )); + // At the beginning of your upkeep, you may remove any number of +1/+1 counters from Tetravus. If you do, create that many 1/1 colorless Tetravite artifact creature tokens. They each have flying and "This creature can't be enchanted." - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new CreateTokenEffect(new TetraviteToken()), - new RemoveCountersSourceCost(CounterType.P1P1.createInstance(1))), TargetController.YOU, true), - new SourceHasCounterCondition(CounterType.P1P1, 1), "At the beginning of your upkeep, you may remove any number of +1/+1 counters from Tetravus. If you do, create that many 1/1 colorless Tetravite artifact creature tokens. They each have flying and \"This creature can't be enchanted.\"")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new TetravusCreateTokensEffect(), + TargetController.YOU, true + )); + // At the beginning of your upkeep, you may exile any number of tokens created with Tetravus. If you do, put that many +1/+1 counters on Tetravus. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), - new ExileTargetCost(new TargetControlledPermanent(new FilterControlledPermanent("Tetravite")))), TargetController.YOU, true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new TetravusAddCountersEffect(), + TargetController.YOU, true + )); } @@ -63,27 +77,120 @@ public final class Tetravus extends CardImpl { } } -class CantBeEnchantedAbility extends StaticAbility { +class TetravusCreateTokensEffect extends OneShotEffect { - public CantBeEnchantedAbility() { - super(Zone.BATTLEFIELD, null); + public TetravusCreateTokensEffect() { + super(Outcome.Benefit); + this.staticText = "remove any number of +1/+1 counters from {this}. " + + "If you do, create that many 1/1 colorless Tetravite artifact creature tokens. " + + "They each have flying and \"This creature can't be enchanted.\""; } - public CantBeEnchantedAbility(final CantBeEnchantedAbility ability) { - super(ability); + public TetravusCreateTokensEffect(final TetravusCreateTokensEffect effect) { + super(effect); } @Override - public CantBeEnchantedAbility copy() { - return new CantBeEnchantedAbility(this); + public TetravusCreateTokensEffect copy() { + return new TetravusCreateTokensEffect(this); } - public boolean canTarget(MageObject source, Game game) { - if (source.isEnchantment() - && source.hasSubtype(SubType.AURA, game)) { + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (player == null || permanent == null) { return false; } - return true; + int countersToRemove = permanent.getCounters(game).getCount(CounterType.P1P1); + if (countersToRemove == 0) { + return false; + } + countersToRemove = player.getAmount(0, countersToRemove, "Choose an amount of counters to remove", game); + Cost cost = new RemoveCountersSourceCost(CounterType.P1P1.createInstance(countersToRemove)); + if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) { + CreateTokenEffect effect = new CreateTokenEffect(new TetraviteToken(), countersToRemove); + effect.apply(game, source); + Object object = game.getState().getValue(CardUtil.getObjectZoneString("_tokensCreated", permanent, game)); + Set tokensCreated; + if (object != null) { + tokensCreated = (Set) object; + } else { + tokensCreated = new HashSet<>(); + } + for (UUID tokenId : effect.getLastAddedTokenIds()) { + if (tokenId != null) { + tokensCreated.add(tokenId); + } + } + game.getState().setValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game), tokensCreated); + } + return false; + } +} + +class TetravusAddCountersEffect extends OneShotEffect { + + public TetravusAddCountersEffect() { + super(Outcome.Benefit); + this.staticText = "exile any number of tokens created with {this}. " + + "If you do, put that many +1/+1 counters on {this}"; } + public TetravusAddCountersEffect(final TetravusAddCountersEffect effect) { + super(effect); + } + + @Override + public TetravusAddCountersEffect copy() { + return new TetravusAddCountersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (player == null || permanent == null) { + return false; + } + FilterControlledPermanent filter = new FilterControlledPermanent("tokens created with " + permanent.getName()); + filter.add(new TetravusPredicate(new MageObjectReference(permanent, game))); + filter.add(new TokenPredicate()); + 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); + } + return false; + } +} + +class TetravusPredicate implements Predicate { + + private final MageObjectReference mor; + + public TetravusPredicate(MageObjectReference mor) { + this.mor = mor; + } + + @Override + public boolean apply(Permanent input, Game game) { + if (mor == null) { + return false; + } + Permanent permanent = mor.getPermanent(game); + if (permanent == null) { + return false; + } + Object object = game.getState().getValue(CardUtil.getObjectZoneString("_tokensCreated", permanent, game)); + if (object == null) { + return false; + } + Set tokensCreated = (Set) object; + return tokensCreated.contains(input.getId()); + } + + @Override + public String toString() { + return ""; + } } diff --git a/Mage.Sets/src/mage/cards/t/TetsukoUmezawaFugitive.java b/Mage.Sets/src/mage/cards/t/TetsukoUmezawaFugitive.java index 8074148df42..7b4c760e121 100644 --- a/Mage.Sets/src/mage/cards/t/TetsukoUmezawaFugitive.java +++ b/Mage.Sets/src/mage/cards/t/TetsukoUmezawaFugitive.java @@ -43,9 +43,9 @@ public final class TetsukoUmezawaFugitive extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(3); - // Creatures you control with power or toughness 1 or less can’t be blocked. + // Creatures you control with power or toughness 1 or less can't be blocked. Effect effect = new CantBeBlockedAllEffect(filter, Duration.Custom); - effect.setText("Creatures you control with power or toughness 1 or less can’t be blocked"); + effect.setText("Creatures you control with power or toughness 1 or less can't be blocked"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } diff --git a/Mage.Sets/src/mage/cards/t/TezzeretArtificeMaster.java b/Mage.Sets/src/mage/cards/t/TezzeretArtificeMaster.java new file mode 100644 index 00000000000..a1843d84532 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TezzeretArtificeMaster.java @@ -0,0 +1,58 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.condition.common.MetalcraftCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.command.emblems.TezzeretArtificeMasterEmblem; +import mage.game.permanent.token.ThopterColorlessToken; + +/** + * + * @author TheElk801 + */ +public final class TezzeretArtificeMaster extends CardImpl { + + public TezzeretArtificeMaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{U}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.TEZZERET); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +1: Create a colorless Thopter artifact creature token with flying. + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new ThopterColorlessToken()), 1)); + + // 0: Draw a card. If you control three or more artifacts, draw two cards instead. + this.addAbility(new LoyaltyAbility(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(2), + new DrawCardSourceControllerEffect(1), + MetalcraftCondition.instance, + "Draw a card. If you control three or " + + "more artifacts, draw two cards instead" + ), 0)); + + // −9: You get an emblem with "At the beginning of your end step, search your library for a permanent card, put it into the battlefield, then shuffle your library." + this.addAbility(new LoyaltyAbility( + new GetEmblemEffect(new TezzeretArtificeMasterEmblem()), -9 + )); + } + + public TezzeretArtificeMaster(final TezzeretArtificeMaster card) { + super(card); + } + + @Override + public TezzeretArtificeMaster copy() { + return new TezzeretArtificeMaster(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java b/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java new file mode 100644 index 00000000000..352c1c8c59d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TezzeretCruelMachinist.java @@ -0,0 +1,174 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.AddCardTypeTargetEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessTargetEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.constants.SuperType; +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.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInHand; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class TezzeretCruelMachinist extends CardImpl { + + public TezzeretCruelMachinist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{U}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.TEZZERET); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Draw a card. + this.addAbility(new LoyaltyAbility(new DrawCardSourceControllerEffect(1), 1)); + + // 0: Until your next turn, target artifact you control becomes a 5/5 creature in addition to its other types. + Ability ability = new LoyaltyAbility(new AddCardTypeTargetEffect( + Duration.UntilYourNextTurn, + CardType.ARTIFACT, + CardType.CREATURE + ).setText("Until your next turn, target artifact you control becomes an artifact creature"), 0); + ability.addEffect(new SetPowerToughnessTargetEffect( + 5, 5, Duration.UntilYourNextTurn + ).setText("with base power and toughness 5/5")); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)); + this.addAbility(ability); + + // −7: Put any number of cards from your hand onto the battlefield face down. They're 5/5 artifact creatures. + this.addAbility(new LoyaltyAbility(new TezzeretCruelMachinistEffect(), -7)); + } + + public TezzeretCruelMachinist(final TezzeretCruelMachinist card) { + super(card); + } + + @Override + public TezzeretCruelMachinist copy() { + return new TezzeretCruelMachinist(this); + } +} + +class TezzeretCruelMachinistEffect extends OneShotEffect { + + public TezzeretCruelMachinistEffect() { + super(Outcome.Benefit); + this.staticText = "put any number of cards from your hand onto the battlefield face down. They're 5/5 artifact creatures"; + } + + public TezzeretCruelMachinistEffect(final TezzeretCruelMachinistEffect effect) { + super(effect); + } + + @Override + public TezzeretCruelMachinistEffect copy() { + return new TezzeretCruelMachinistEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Target target = new TargetCardInHand(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD); + if (!player.choose(outcome, target, source.getSourceId(), game)) { + return false; + } + Cards cardsToMove = new CardsImpl(); + for (UUID cardId : target.getTargets()) { + Card card = game.getCard(cardId); + if (card == null) { + continue; + } + cardsToMove.add(card); + ContinuousEffect effect = new TezzeretCruelMachinistCardTypeEffect(); + effect.setTargetPointer(new FixedTarget( + card.getId(), + card.getZoneChangeCounter(game) + 1 + )); + game.addEffect(effect, source); + effect = new TezzeretCruelMachinistPowerToughnessEffect(); + effect.setTargetPointer(new FixedTarget( + card.getId(), + card.getZoneChangeCounter(game) + 1 + )); + game.addEffect(effect, source); + } + return player.moveCards(cardsToMove.getCards(game), Zone.BATTLEFIELD, source, game, false, true, true, null); + } +} + +class TezzeretCruelMachinistCardTypeEffect extends AddCardTypeTargetEffect { + + public TezzeretCruelMachinistCardTypeEffect() { + super(Duration.WhileOnBattlefield, CardType.ARTIFACT, CardType.CREATURE); + } + + public TezzeretCruelMachinistCardTypeEffect(final TezzeretCruelMachinistCardTypeEffect effect) { + super(effect); + } + + @Override + public TezzeretCruelMachinistCardTypeEffect copy() { + return new TezzeretCruelMachinistCardTypeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null || !permanent.isFaceDown(game)) { + this.discard(); + return false; + } + return super.apply(game, source); + } +} + +class TezzeretCruelMachinistPowerToughnessEffect extends SetPowerToughnessTargetEffect { + + public TezzeretCruelMachinistPowerToughnessEffect() { + super(5, 5, Duration.WhileOnBattlefield); + } + + public TezzeretCruelMachinistPowerToughnessEffect(final TezzeretCruelMachinistPowerToughnessEffect effect) { + super(effect); + } + + @Override + public TezzeretCruelMachinistPowerToughnessEffect copy() { + return new TezzeretCruelMachinistPowerToughnessEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null || !permanent.isFaceDown(game)) { + this.discard(); + return false; + } + return super.apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TezzeretsGatebreaker.java b/Mage.Sets/src/mage/cards/t/TezzeretsGatebreaker.java new file mode 100644 index 00000000000..4ea0fddeadd --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TezzeretsGatebreaker.java @@ -0,0 +1,74 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +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.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.combat.CantBeBlockedAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class TezzeretsGatebreaker extends CardImpl { + + private static final FilterCard filter = new FilterCard("a blue or artifact card"); + + static { + filter.add(Predicates.or( + new ColorPredicate(ObjectColor.BLUE), + new CardTypePredicate(CardType.ARTIFACT) + )); + } + + public TezzeretsGatebreaker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + // When Tezzeret's Gatebreaker enters the battlefield, look at the top five cards of your library. You may reveal a blue or artifact card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new LookLibraryAndPickControllerEffect( + new StaticValue(5), false, new StaticValue(1), filter, + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false + ).setBackInRandomOrder(true).setText("look at the top five cards of your library. " + + "You may reveal a blue or artifact card from among them and put it into your hand. " + + "Put the rest on the bottom of your library in a random order.") + )); + + // {5}{U}, {T}, Sacrifice Tezzeret's Gatebreaker: Creatures you control can't be blocked this turn. + Ability ability = new SimpleActivatedAbility( + new CantBeBlockedAllEffect( + StaticFilters.FILTER_CONTROLLED_CREATURES, + Duration.EndOfTurn + ), + new ManaCostsImpl("{5}{U}") + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public TezzeretsGatebreaker(final TezzeretsGatebreaker card) { + super(card); + } + + @Override + public TezzeretsGatebreaker copy() { + return new TezzeretsGatebreaker(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TezzeretsStrider.java b/Mage.Sets/src/mage/cards/t/TezzeretsStrider.java new file mode 100644 index 00000000000..536928f7b12 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TezzeretsStrider.java @@ -0,0 +1,59 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +/** + * + * @author TheElk801 + */ +public final class TezzeretsStrider extends CardImpl { + + private static final FilterControlledPlaneswalkerPermanent filter + = new FilterControlledPlaneswalkerPermanent( + SubType.TEZZERET, + "a Tezzeret planeswalker" + ); + + public TezzeretsStrider(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // As long as you control a Tezzeret planeswalker, Tezzeret's Strider has menace. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + new MenaceAbility(), + Duration.WhileOnBattlefield + ), + new PermanentsOnTheBattlefieldCondition(filter), + "As long as you control a Tezzeret planeswalker, {this} has menace" + ) + )); + } + + public TezzeretsStrider(final TezzeretsStrider card) { + super(card); + } + + @Override + public TezzeretsStrider copy() { + return new TezzeretsStrider(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThadaAdelAcquisitor.java b/Mage.Sets/src/mage/cards/t/ThadaAdelAcquisitor.java index 5c0bcb2aa94..e5777b82a6e 100644 --- a/Mage.Sets/src/mage/cards/t/ThadaAdelAcquisitor.java +++ b/Mage.Sets/src/mage/cards/t/ThadaAdelAcquisitor.java @@ -116,7 +116,7 @@ class ThadaAdelPlayFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) + return source.isControlledBy(affectedControllerId) && sourceId.equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/cards/t/ThantisTheWarweaver.java b/Mage.Sets/src/mage/cards/t/ThantisTheWarweaver.java new file mode 100644 index 00000000000..75fc2ef69b9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThantisTheWarweaver.java @@ -0,0 +1,65 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class ThantisTheWarweaver extends CardImpl { + + public ThantisTheWarweaver(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SPIDER); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // All creatures attack each combat if able. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new AttacksIfAbleAllEffect( + StaticFilters.FILTER_PERMANENT_CREATURES, + Duration.WhileOnBattlefield, true + ).setText("All creatures attack each combat if able") + )); + + // Whenever a creature attacks you or a planeswalker you control, put a +1/+1 counter on Thantis the Warweaver. + this.addAbility(new AttacksAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + false, true + )); + } + + public ThantisTheWarweaver(final ThantisTheWarweaver card) { + super(card); + } + + @Override + public ThantisTheWarweaver copy() { + return new ThantisTheWarweaver(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java index 2a1a11f8f20..b87140dc64f 100644 --- a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java +++ b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.TransformAbility; @@ -45,7 +45,7 @@ public final class ThaumaticCompass extends CardImpl { // At the beginning of your end step, if you control seven or more lands, transform Thaumatic Compass. this.addAbility(new TransformAbility()); TriggeredAbility ability2 = new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability2, new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), ComparisonType.MORE_THAN, 6, true), "At the beginning of your end step, if you control seven or more lands, transform {this}.")); diff --git a/Mage.Sets/src/mage/cards/t/TheBigIdea.java b/Mage.Sets/src/mage/cards/t/TheBigIdea.java index 44d3391a6b5..6bb1285d164 100644 --- a/Mage.Sets/src/mage/cards/t/TheBigIdea.java +++ b/Mage.Sets/src/mage/cards/t/TheBigIdea.java @@ -118,7 +118,7 @@ class TheBigIdeaReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (!this.used) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/t/TheEldestReborn.java b/Mage.Sets/src/mage/cards/t/TheEldestReborn.java index f38a938116b..666e52d657f 100644 --- a/Mage.Sets/src/mage/cards/t/TheEldestReborn.java +++ b/Mage.Sets/src/mage/cards/t/TheEldestReborn.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterCard; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.common.TargetCardInGraveyard; @@ -33,6 +34,15 @@ public final class TheEldestReborn extends CardImpl { )); } + private static final FilterControlledPermanent filterSacrifice = new FilterControlledPermanent("creature or planeswalker"); + static { + filterSacrifice.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.PLANESWALKER) + )); + + } + public TheEldestReborn(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}"); @@ -42,7 +52,7 @@ public final class TheEldestReborn extends CardImpl { SagaAbility sagaAbility = new SagaAbility(this, SagaChapter.CHAPTER_III); // I — Each opponent sacrifices a creature or planeswalker. sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, - new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_CREATURE_OR_PLANESWALKER_A) + new SacrificeOpponentsEffect(filterSacrifice) ); // II — Each opponent discards a card. diff --git a/Mage.Sets/src/mage/cards/t/TheFallen.java b/Mage.Sets/src/mage/cards/t/TheFallen.java index 59388577ce8..8676d61c573 100644 --- a/Mage.Sets/src/mage/cards/t/TheFallen.java +++ b/Mage.Sets/src/mage/cards/t/TheFallen.java @@ -65,7 +65,7 @@ class TheFallenEffect extends OneShotEffect { TheFallenWatcher watcher = (TheFallenWatcher) game.getState().getWatchers().get(TheFallenWatcher.class.getSimpleName()); if (watcher != null && watcher.getPlayersAndWalkersDealtDamageThisGame(source.getSourceId()) != null) { for (UUID playerId : watcher.getPlayersAndWalkersDealtDamageThisGame(source.getSourceId())) { - if (!source.getControllerId().equals(playerId)) { + if (!source.isControlledBy(playerId)) { game.damagePlayerOrPlaneswalker(playerId, 1, source.getSourceId(), game, false, true); } } diff --git a/Mage.Sets/src/mage/cards/t/TheFlameOfKeld.java b/Mage.Sets/src/mage/cards/t/TheFlameOfKeld.java index 0e7bcab7161..1fb9383bfb7 100644 --- a/Mage.Sets/src/mage/cards/t/TheFlameOfKeld.java +++ b/Mage.Sets/src/mage/cards/t/TheFlameOfKeld.java @@ -83,7 +83,7 @@ class TheFlameOfKeldDamageEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getControllerId().equals(game.getControllerId(event.getSourceId()))) { + if (source.isControlledBy(game.getControllerId(event.getSourceId()))) { MageObject sourceObject; Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId()); if (sourcePermanent == null) { diff --git a/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java b/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java index b126d89cbbd..8fc2ee9ce18 100644 --- a/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java +++ b/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java @@ -83,7 +83,7 @@ class TheGitrogMonsterTriggeredAbility extends TriggeredAbilityImpl { UUID cardOwnerId = card.getOwnerId(); Set cardType = card.getCardType(); if (cardOwnerId != null - && card.getOwnerId().equals(getControllerId()) + && card.isOwnedBy(getControllerId()) && cardType != null && card.isLand()) { return true; diff --git a/Mage.Sets/src/mage/cards/t/TheUrDragon.java b/Mage.Sets/src/mage/cards/t/TheUrDragon.java index ca68b29fa0a..ac9fbb04948 100644 --- a/Mage.Sets/src/mage/cards/t/TheUrDragon.java +++ b/Mage.Sets/src/mage/cards/t/TheUrDragon.java @@ -1,16 +1,12 @@ - package mage.cards.t; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; import mage.abilities.keyword.FlyingAbility; @@ -22,8 +18,6 @@ import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.watchers.Watcher; /** * @author TheElk801 @@ -60,7 +54,7 @@ public final class TheUrDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever one or more Dragons you control attack, draw that many cards, then you may put a permanent card from your hand onto the battlefield - this.addAbility(new TheUrDragonTriggeredAbility(), new DragonsAttackedWatcher()); + this.addAbility(new TheUrDragonTriggeredAbility()); } public TheUrDragon(final TheUrDragon card) { @@ -73,46 +67,10 @@ public final class TheUrDragon extends CardImpl { } } -class DragonsAttackedWatcher extends Watcher { - - public final Set attackedThisTurnCreatures = new HashSet<>(); - - public DragonsAttackedWatcher() { - super(DragonsAttackedWatcher.class.getSimpleName(), WatcherScope.GAME); - } - - public DragonsAttackedWatcher(final DragonsAttackedWatcher watcher) { - super(watcher); - this.attackedThisTurnCreatures.addAll(watcher.attackedThisTurnCreatures); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.BEGIN_COMBAT_STEP_PRE) { - this.attackedThisTurnCreatures.clear(); - } - if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) { - if (game.getPermanent(event.getSourceId()).hasSubtype(SubType.DRAGON, game)) { - this.attackedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game)); - } - } - } - - public Set getAttackedThisTurnCreatures() { - return this.attackedThisTurnCreatures; - } - - @Override - public DragonsAttackedWatcher copy() { - return new DragonsAttackedWatcher(this); - } - -} - class TheUrDragonTriggeredAbility extends TriggeredAbilityImpl { public TheUrDragonTriggeredAbility() { - super(Zone.BATTLEFIELD, new TheUrDragonEffect(), false); + super(Zone.BATTLEFIELD, null, false); } public TheUrDragonTriggeredAbility(final TheUrDragonTriggeredAbility ability) { @@ -131,58 +89,27 @@ class TheUrDragonTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { + int attackingDragons = 0; for (UUID attacker : game.getCombat().getAttackers()) { Permanent creature = game.getPermanent(attacker); if (creature != null && creature.getControllerId() != null - && creature.getControllerId().equals(this.getControllerId()) + && creature.isControlledBy(this.getControllerId()) && creature.hasSubtype(SubType.DRAGON, game)) { - return true; + attackingDragons++; } } + if (attackingDragons > 0) { + this.getEffects().clear(); + addEffect(new DrawCardSourceControllerEffect(attackingDragons)); + addEffect(new PutCardFromHandOntoBattlefieldEffect()); + return true; + } return false; } @Override public String getRule() { - return "Whenever one or more Dragons you control attack, " + super.getRule(); - } -} - -class TheUrDragonEffect extends OneShotEffect { - - public TheUrDragonEffect() { - super(Outcome.Benefit); - this.staticText = "draw that many cards, then you may put a permanent card from your hand onto the battlefield"; - } - - public TheUrDragonEffect(final TheUrDragonEffect effect) { - super(effect); - } - - @Override - public TheUrDragonEffect copy() { - return new TheUrDragonEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - DragonsAttackedWatcher watcher = (DragonsAttackedWatcher) game.getState().getWatchers().get(DragonsAttackedWatcher.class.getSimpleName()); - if (watcher != null) { - int attackingDragons = 0; - for (MageObjectReference attacker : watcher.getAttackedThisTurnCreatures()) { - if (attacker.getPermanentOrLKIBattlefield(game).getControllerId().equals(controller.getId())) { - attackingDragons++; - } - } - if (attackingDragons > 0) { - controller.drawCards(attackingDragons, game); - } - return new PutCardFromHandOntoBattlefieldEffect().apply(game, source); - } - } - return false; + return "Whenever one or more Dragons you control attack, draw that many cards, then you may put a permanent card from your hand onto the battlefield."; } } diff --git a/Mage.Sets/src/mage/cards/t/ThermalDetonator.java b/Mage.Sets/src/mage/cards/t/ThermalDetonator.java new file mode 100644 index 00000000000..a4c5546db4e --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThermalDetonator.java @@ -0,0 +1,51 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureOrPlayer; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author NinthWorld + */ +public final class ThermalDetonator extends CardImpl { + + private static final FilterCreatureOrPlayer filter = new FilterCreatureOrPlayer("creature without spaceflight or target player"); + private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent(); + + static { + filter.getCreatureFilter().add(Predicates.not(new AbilityPredicate(SpaceflightAbility.class))); + } + + public ThermalDetonator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + + // {2}, Sacrifice Thermal Detonator: Thermal Detonator deals 2 damage to target creature without spaceflight or target player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new ManaCostsImpl("{2}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreatureOrPlayer(filter)); + this.addAbility(ability); + } + + public ThermalDetonator(final ThermalDetonator card) { + super(card); + } + + @Override + public ThermalDetonator copy() { + return new ThermalDetonator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThespiansStage.java b/Mage.Sets/src/mage/cards/t/ThespiansStage.java index 58bd72d8813..5b9ca21040d 100644 --- a/Mage.Sets/src/mage/cards/t/ThespiansStage.java +++ b/Mage.Sets/src/mage/cards/t/ThespiansStage.java @@ -30,7 +30,7 @@ public final class ThespiansStage extends CardImpl { // {T}: Add 1. this.addAbility(new ColorlessManaAbility()); - // 2, {T}: Thespian's Stage becomes a copy of target land and gains this ability. + // 2, {T}: Thespian's Stage becomes a copy of target land, except it has this ability. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThespiansStageCopyEffect(), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetLandPermanent()); @@ -52,7 +52,7 @@ class ThespiansStageCopyEffect extends OneShotEffect { public ThespiansStageCopyEffect() { super(Outcome.Benefit); - this.staticText = "{this} becomes a copy of target land and gains this ability"; + this.staticText = "{this} becomes a copy of target land, except it has this ability"; } public ThespiansStageCopyEffect(final ThespiansStageCopyEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/ThickSkinnedGoblin.java b/Mage.Sets/src/mage/cards/t/ThickSkinnedGoblin.java new file mode 100644 index 00000000000..912a17476f8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThickSkinnedGoblin.java @@ -0,0 +1,76 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.*; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author noahg + */ +public final class ThickSkinnedGoblin extends CardImpl { + + public ThickSkinnedGoblin(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); + + // You may pay {0} rather than pay the echo cost for permanents you control. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThickSkinnedGoblinCostModificationEffect())); + + // {R}: Thick-Skinned Goblin gains protection from red until end of turn. + this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect(ProtectionAbility.from(ObjectColor.RED), Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + } + + public ThickSkinnedGoblin(final ThickSkinnedGoblin card) { + super(card); + } + + @Override + public ThickSkinnedGoblin copy() { + return new ThickSkinnedGoblin(this); + } +} + +class ThickSkinnedGoblinCostModificationEffect extends AsThoughEffectImpl { + + public ThickSkinnedGoblinCostModificationEffect(){ + super(AsThoughEffectType.PAY_0_ECHO, Duration.WhileOnBattlefield, Outcome.Benefit); + this.staticText = "You may pay {0} rather than pay the echo cost for permanents you control."; + } + + public ThickSkinnedGoblinCostModificationEffect(ThickSkinnedGoblinCostModificationEffect effect) { + super(effect); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + Permanent sourcePermanent = game.getPermanent(sourceId); + return sourcePermanent != null && sourcePermanent.isControlledBy(source.getControllerId()); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public ThickSkinnedGoblinCostModificationEffect copy() { + return new ThickSkinnedGoblinCostModificationEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/ThicketElemental.java b/Mage.Sets/src/mage/cards/t/ThicketElemental.java index 2fc0bca6802..e5ee92f1eed 100644 --- a/Mage.Sets/src/mage/cards/t/ThicketElemental.java +++ b/Mage.Sets/src/mage/cards/t/ThicketElemental.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.RevealCardsFromLibraryUntilEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class ThicketElemental extends CardImpl { // When Thicket Elemental enters the battlefield, if it was kicked, you may reveal cards from the top of your library until you reveal a creature card. If you do, put that card onto the battlefield and shuffle all other cards revealed this way into your library. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new RevealCardsFromLibraryUntilEffect(new FilterCreatureCard(), Zone.BATTLEFIELD, Zone.LIBRARY, true)); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, you may reveal cards from the top of your library until you reveal a creature card. If you do, put that card onto the battlefield and shuffle all other cards revealed this way into your library.")); } diff --git a/Mage.Sets/src/mage/cards/t/ThirstingAxe.java b/Mage.Sets/src/mage/cards/t/ThirstingAxe.java index 613b3f38f89..e5da2e18739 100644 --- a/Mage.Sets/src/mage/cards/t/ThirstingAxe.java +++ b/Mage.Sets/src/mage/cards/t/ThirstingAxe.java @@ -14,7 +14,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.AttachedCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; @@ -48,7 +48,7 @@ public final class ThirstingAxe extends CardImpl { new InvertCondition(new EquippedDealtCombatDamageToCreatureCondition())); String triggeredAbilityText = "At the beginning of your end step, if equipped creature " + "didn't deal combat damage to a creature this turn, sacrifice it."; - ConditionalTriggeredAbility sacrificeTriggeredAbility = new ConditionalTriggeredAbility(ability, condition, triggeredAbilityText); + ConditionalInterveningIfTriggeredAbility sacrificeTriggeredAbility = new ConditionalInterveningIfTriggeredAbility(ability, condition, triggeredAbilityText); this.addAbility(sacrificeTriggeredAbility, new CombatDamageToCreatureWatcher()); // Equip {2} diff --git a/Mage.Sets/src/mage/cards/t/ThopterSpyNetwork.java b/Mage.Sets/src/mage/cards/t/ThopterSpyNetwork.java index 7b9393e5bb3..8514dc92551 100644 --- a/Mage.Sets/src/mage/cards/t/ThopterSpyNetwork.java +++ b/Mage.Sets/src/mage/cards/t/ThopterSpyNetwork.java @@ -108,7 +108,7 @@ class ThopterSpyNetworkDamageTriggeredAbility extends TriggeredAbilityImpl { if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId) + if (creature != null && creature.isControlledBy(controllerId) && creature.isArtifact() && !damagedPlayerIds.contains(event.getTargetId())) { damagedPlayerIds.add(event.getTargetId()); return true; diff --git a/Mage.Sets/src/mage/cards/t/ThornLieutenant.java b/Mage.Sets/src/mage/cards/t/ThornLieutenant.java new file mode 100644 index 00000000000..11ba8e88dc8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThornLieutenant.java @@ -0,0 +1,53 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; +import mage.game.permanent.token.ElfToken; + +/** + * + * @author TheElk801 + */ +public final class ThornLieutenant extends CardImpl { + + public ThornLieutenant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Whenever Thorn Lieutenant becomes the target of a spell or ability an opponent controls, create a 1/1 green Elf Warrior creature token. + this.addAbility(new BecomesTargetTriggeredAbility( + new CreateTokenEffect(new ElfToken()), + StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS + )); + + // {5}{G}: Thorn Lieutenant gets +4/+4 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(4, 4, Duration.EndOfTurn), + new ManaCostsImpl("{5}{G}") + )); + } + + public ThornLieutenant(final ThornLieutenant card) { + super(card); + } + + @Override + public ThornLieutenant copy() { + return new ThornLieutenant(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java b/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java index b359d9605ac..97cc50c5769 100644 --- a/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -38,13 +38,13 @@ public final class ThornscapeBattlemage extends CardImpl { // When {this} enters the battlefield, if it was kicked with its {R} kicker, it deals 2 damage to any target. TriggeredAbility ability1 = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "it")); ability1.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalTriggeredAbility(ability1, new KickedCostCondition("{R}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability1, new KickedCostCondition("{R}"), "When {this} enters the battlefield, if it was kicked with its {R} kicker, it deals 2 damage to any target.")); // When {this} enters the battlefield, if it was kicked with its {W} kicker, destroy target artifact. TriggeredAbility ability2 = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); ability2.addTarget(new TargetArtifactPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability2, new KickedCostCondition("{W}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new KickedCostCondition("{W}"), "When {this} enters the battlefield, if it was kicked with its {W} kicker, destroy target artifact.")); } diff --git a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java new file mode 100644 index 00000000000..2238235f421 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java @@ -0,0 +1,106 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public final class ThoughtDissector extends CardImpl { + + public ThoughtDissector(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + + // {X}, {tap}: Target opponent reveals cards from the top of their library until an artifact card or X cards are revealed, whichever comes first. If an artifact card is revealed this way, put it onto the battlefield under your control and sacrifice Thought Dissector. Put the rest of the revealed cards into that player's graveyard. + SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtDissectorEffect(), new VariableManaCost()); + abilitiy.addCost(new TapSourceCost()); + abilitiy.addTarget(new TargetOpponent()); + this.addAbility(abilitiy); + } + + public ThoughtDissector(final ThoughtDissector card) { + super(card); + } + + @Override + public ThoughtDissector copy() { + return new ThoughtDissector(this); + } +} + +class ThoughtDissectorEffect extends OneShotEffect { + + private static final ManacostVariableValue amount = new ManacostVariableValue(); + + public ThoughtDissectorEffect() { + super(Outcome.Detriment); + staticText = "Target opponent reveals cards from the top of their library until an artifact card or X cards are revealed, whichever comes first. If an artifact card is revealed this way, put it onto the battlefield under your control and sacrifice {this}. Put the rest of the revealed cards into that player's graveyard."; + } + + public ThoughtDissectorEffect(final ThoughtDissectorEffect effect) { + super(effect); + } + + @Override + public ThoughtDissectorEffect copy() { + return new ThoughtDissectorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source)); + int max = amount.calculate(game, source, this); + if (targetOpponent != null && controller != null && max > 0) { + int numberOfCard = 0; + Card artifact = null; + CardsImpl nonArtifacts = new CardsImpl(); + CardsImpl reveal = new CardsImpl(); + for (Card card : targetOpponent.getLibrary().getCards(game)) { + reveal.add(card); + if (card.isArtifact()) { + artifact = card; + break; + } else { + numberOfCard++; + if (numberOfCard > max){ + break; + } + nonArtifacts.add(card); + } + } + targetOpponent.revealCards(source, reveal, game); + if (artifact != null) { + game.applyEffects(); + controller.moveCards(artifact, Zone.BATTLEFIELD, source, game); + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (sourcePermanent != null) { + sourcePermanent.sacrifice(source.getSourceId(), game); + } + } + targetOpponent.moveCards(nonArtifacts, Zone.GRAVEYARD, source, game); + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java b/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java index 3b51695df99..bec111276c5 100644 --- a/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java +++ b/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.LinkedHashSet; @@ -8,7 +7,7 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +33,7 @@ public final class ThoughtHemorrhage extends CardImpl { // Name a nonland card. Target player reveals their hand. Thought Hemorrhage deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles their library. this.getSpellAbility().addTarget(new TargetPlayer()); - this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME)); this.getSpellAbility().addEffect(new ThoughtHemorrhageEffect()); } @@ -50,7 +49,10 @@ public final class ThoughtHemorrhage extends CardImpl { class ThoughtHemorrhageEffect extends OneShotEffect { - static final String rule = "Target player reveals their hand. {this} deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles their library"; + static final String rule = "Target player reveals their hand. " + + "{this} deals 3 damage to that player for each card with the chosen name revealed this way. " + + "Search that player's graveyard, hand, and library for all cards with that name and exile them. " + + "Then that player shuffles their library"; public ThoughtHemorrhageEffect() { super(Outcome.Exile); @@ -65,7 +67,7 @@ class ThoughtHemorrhageEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (sourceObject != null && controller != null && cardName != null && !cardName.isEmpty()) { Player targetPlayer = game.getPlayer(source.getFirstTarget()); if (targetPlayer != null) { diff --git a/Mage.Sets/src/mage/cards/t/ThousandYearElixir.java b/Mage.Sets/src/mage/cards/t/ThousandYearElixir.java index c41b0293b9f..41ed3921e2d 100644 --- a/Mage.Sets/src/mage/cards/t/ThousandYearElixir.java +++ b/Mage.Sets/src/mage/cards/t/ThousandYearElixir.java @@ -76,6 +76,6 @@ class ThousandYearElixirEffect extends AsThoughEffectImpl { Permanent permanent = game.getPermanent(sourceId); return permanent != null && permanent.isCreature() - && permanent.getControllerId().equals(source.getControllerId()); + && permanent.isControlledBy(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/t/ThranQuarry.java b/Mage.Sets/src/mage/cards/t/ThranQuarry.java index cf83652e09a..b9a933395e4 100644 --- a/Mage.Sets/src/mage/cards/t/ThranQuarry.java +++ b/Mage.Sets/src/mage/cards/t/ThranQuarry.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.CreatureCountCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; @@ -25,7 +25,7 @@ public final class ThranQuarry extends CardImpl { // At the beginning of the end step, if you control no creatures, sacrifice Thran Quarry. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.YOU), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.YOU), "At the beginning of the end step, if you control no creatures, sacrifice {this}.")); // {tap}: Add one mana of any color. diff --git a/Mage.Sets/src/mage/cards/t/ThreeWishes.java b/Mage.Sets/src/mage/cards/t/ThreeWishes.java index b6d14874cca..a88b1df88d8 100644 --- a/Mage.Sets/src/mage/cards/t/ThreeWishes.java +++ b/Mage.Sets/src/mage/cards/t/ThreeWishes.java @@ -187,7 +187,7 @@ class ThreeWishesPlayFromExileEffect extends AsThoughEffectImpl { return exile != null && getTargetPointer().getFirst(game, source) != null && getTargetPointer().getFirst(game, source).equals(sourceId) - && source.getControllerId().equals(affectedControllerId) + && source.isControlledBy(affectedControllerId) && game.getState().getZone(sourceId) == Zone.EXILED && exile.contains(sourceId); } diff --git a/Mage.Sets/src/mage/cards/t/ThroneofGeth.java b/Mage.Sets/src/mage/cards/t/ThroneOfGeth.java similarity index 80% rename from Mage.Sets/src/mage/cards/t/ThroneofGeth.java rename to Mage.Sets/src/mage/cards/t/ThroneOfGeth.java index 1707d089180..329851cf1b1 100644 --- a/Mage.Sets/src/mage/cards/t/ThroneofGeth.java +++ b/Mage.Sets/src/mage/cards/t/ThroneOfGeth.java @@ -20,27 +20,31 @@ import mage.target.common.TargetControlledPermanent; * * @author Loki */ -public final class ThroneofGeth extends CardImpl { +public final class ThroneOfGeth extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact"); static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); } - public ThroneofGeth (UUID ownerId, CardSetInfo setInfo) { + public ThroneOfGeth(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + + // {T}, Sacrifice an artifact: Proliferate. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ProliferateEffect(), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); this.addAbility(ability); } - public ThroneofGeth (final ThroneofGeth card) { + public ThroneOfGeth(final ThroneOfGeth card) { super(card); } @Override - public ThroneofGeth copy() { - return new ThroneofGeth(this); + public ThroneOfGeth copy() { + return new ThroneOfGeth(this); } } diff --git a/Mage.Sets/src/mage/cards/t/Thud.java b/Mage.Sets/src/mage/cards/t/Thud.java new file mode 100644 index 00000000000..54c775bc203 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/Thud.java @@ -0,0 +1,41 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesPower; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class Thud extends CardImpl { + + public Thud(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}"); + + // As an additional cost to cast this spell, sacrifice a creature. + this.getSpellAbility().addCost(new SacrificeTargetCost( + new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT) + )); + + // Thud deals damage equal to the sacrificed creature's power to any target. + this.getSpellAbility().addEffect(new DamageTargetEffect(new SacrificeCostCreaturesPower())); + this.getSpellAbility().addTarget(new TargetAnyTarget()); + } + + public Thud(final Thud card) { + super(card); + } + + @Override + public Thud copy() { + return new Thud(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/Thumbscrews.java b/Mage.Sets/src/mage/cards/t/Thumbscrews.java index 21d1d60b765..0c69be1eb06 100644 --- a/Mage.Sets/src/mage/cards/t/Thumbscrews.java +++ b/Mage.Sets/src/mage/cards/t/Thumbscrews.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +29,7 @@ public final class Thumbscrews extends CardImpl { new DamageTargetEffect(1), TargetController.YOU, false); ability.addTarget(new TargetOpponentOrPlaneswalker()); CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 4); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, condition, "At the beginning of your upkeep, if you have five or more cards in hand, " + "{this} deals 1 damage to target opponent or planeswalker." diff --git a/Mage.Sets/src/mage/cards/t/ThunderBrute.java b/Mage.Sets/src/mage/cards/t/ThunderBrute.java index e0ae92e287c..d37b3f752db 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderBrute.java +++ b/Mage.Sets/src/mage/cards/t/ThunderBrute.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; @@ -36,7 +36,7 @@ public final class ThunderBrute extends CardImpl { this.addAbility(new TributeAbility(3)); // When Thunder Brute enters the battlefield, if tribute wasn't paid, it gains haste until end of turn. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), false); - this.addAbility(new ConditionalTriggeredAbility(ability, TributeNotPaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, "When {this} enters the battlefield, if its tribute wasn't paid, it gains haste until end of turn.")); } diff --git a/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java b/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java index ab097e840fc..6eb9bd53520 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -38,13 +38,13 @@ public final class ThunderscapeBattlemage extends CardImpl { // When {this} enters the battlefield, if it was kicked with its {1}{B} kicker, target player discards two cards. TriggeredAbility ability1 = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(2)); ability1.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalTriggeredAbility(ability1, new KickedCostCondition("{1}{B}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability1, new KickedCostCondition("{1}{B}"), "When {this} enters the battlefield, if it was kicked with its {1}{B} kicker, target player discards two cards.")); // When {this} enters the battlefield, if it was kicked with its {G} kicker, destroy target enchantment. TriggeredAbility ability2 = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); ability2.addTarget(new TargetEnchantmentPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability2, new KickedCostCondition("{G}"), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new KickedCostCondition("{G}"), "When {this} enters the battlefield, if it was kicked with its {G} kicker, destroy target enchantment.")); } diff --git a/Mage.Sets/src/mage/cards/t/TianaShipsCaretaker.java b/Mage.Sets/src/mage/cards/t/TianaShipsCaretaker.java index 4c4d968a162..832e96d5de7 100644 --- a/Mage.Sets/src/mage/cards/t/TianaShipsCaretaker.java +++ b/Mage.Sets/src/mage/cards/t/TianaShipsCaretaker.java @@ -96,7 +96,7 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl { && zEvent.getFromZone() == Zone.BATTLEFIELD && (permanent.isArtifact() && permanent.hasSubtype(SubType.EQUIPMENT, game) || permanent.isEnchantment() && permanent.hasSubtype(SubType.AURA, game)) - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { this.getEffects().setTargetPointer(new FixedTarget(zEvent.getTargetId())); return true; } diff --git a/Mage.Sets/src/mage/cards/t/TidebinderMage.java b/Mage.Sets/src/mage/cards/t/TidebinderMage.java index cdc97d7c4a8..bc6348a8590 100644 --- a/Mage.Sets/src/mage/cards/t/TidebinderMage.java +++ b/Mage.Sets/src/mage/cards/t/TidebinderMage.java @@ -97,7 +97,7 @@ class TidebinderMageEffect extends ContinuousRuleModifyingEffectImpl { // the battlefield triggered ability the source dies (or will be exiled), then the ZONE_CHANGE or LOST_CONTROL // event will happen before this effect is applied ever) Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent == null || !sourcePermanent.getControllerId().equals(source.getControllerId())) { + if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { discard(); return false; } @@ -118,7 +118,7 @@ class TidebinderMageEffect extends ContinuousRuleModifyingEffectImpl { if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP) { if (event.getTargetId().equals(targetPointer.getFirst(game, source))) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && game.getActivePlayerId().equals(permanent.getControllerId())) { + if (permanent != null && game.isActivePlayer(permanent.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TilonallisKnight.java b/Mage.Sets/src/mage/cards/t/TilonallisKnight.java index 37f95210587..367079b3c5a 100644 --- a/Mage.Sets/src/mage/cards/t/TilonallisKnight.java +++ b/Mage.Sets/src/mage/cards/t/TilonallisKnight.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class TilonallisKnight extends CardImpl { this.toughness = new MageInt(2); // Whenever Tilonalli's Knight attacks, if you control a Dinosaur, Tilonalli's Knight gets +1/+1 until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false), new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks, if you control a Dinosaur, {this} gets +1/+1 until end of turn." diff --git a/Mage.Sets/src/mage/cards/t/TimberShredder.java b/Mage.Sets/src/mage/cards/t/TimberShredder.java index cc51136e375..b90ac0f1af4 100644 --- a/Mage.Sets/src/mage/cards/t/TimberShredder.java +++ b/Mage.Sets/src/mage/cards/t/TimberShredder.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TransformAbility; @@ -38,7 +38,7 @@ public final class TimberShredder extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Timber Shredder. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public TimberShredder(final TimberShredder card) { diff --git a/Mage.Sets/src/mage/cards/t/TimeOfIce.java b/Mage.Sets/src/mage/cards/t/TimeOfIce.java index fddf8a086e0..10780d7b643 100644 --- a/Mage.Sets/src/mage/cards/t/TimeOfIce.java +++ b/Mage.Sets/src/mage/cards/t/TimeOfIce.java @@ -119,7 +119,7 @@ class TimeOfIceEffect extends ContinuousRuleModifyingEffectImpl { if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getTargetId().equals(targetPointer.getFirst(game, source))) { Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source)); if (targetCreature != null) { - return targetCreature.getControllerId().equals(game.getActivePlayerId()); + return targetCreature.isControlledBy(game.getActivePlayerId()); } else { discard(); return false; diff --git a/Mage.Sets/src/mage/cards/t/TimeToFeed.java b/Mage.Sets/src/mage/cards/t/TimeToFeed.java index b35dce2746d..71c71441f21 100644 --- a/Mage.Sets/src/mage/cards/t/TimeToFeed.java +++ b/Mage.Sets/src/mage/cards/t/TimeToFeed.java @@ -31,11 +31,11 @@ import mage.target.common.TargetCreaturePermanent; /** * Time to Feed has two targets: a creature an opponent controls and a creature you control. * If only one of those creatures is a legal target when Time to Feed tries to resolve, the - * creatures won’t fight and neither will deal or be dealt damage. However, you’ll still gain - * 3 life when the creature you don’t control dies that turn, even if it was the illegal target as Time to Feed resolved. + * creatures won't fight and neither will deal or be dealt damage. However, you'll still gain + * 3 life when the creature you don't control dies that turn, even if it was the illegal target as Time to Feed resolved. * If neither creature is a legal target when Time to Feed tries to resolve, the spell will * be countered and none of its effects will happen. - * If the first target creature dies that turn, you’ll gain 3 life no matter what caused the creature to die or who controls the creature at that time. + * If the first target creature dies that turn, you'll gain 3 life no matter what caused the creature to die or who controls the creature at that time. * * @author LevelX2 */ diff --git a/Mage.Sets/src/mage/cards/t/TimeVault.java b/Mage.Sets/src/mage/cards/t/TimeVault.java index 3e559518512..7586d9f3a89 100644 --- a/Mage.Sets/src/mage/cards/t/TimeVault.java +++ b/Mage.Sets/src/mage/cards/t/TimeVault.java @@ -78,7 +78,7 @@ class TimeVaultReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getControllerId().equals(event.getPlayerId())) { + if (source.isControlledBy(event.getPlayerId())) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && permanent.isTapped()) { return true; diff --git a/Mage.Sets/src/mage/cards/t/TimelyHordemate.java b/Mage.Sets/src/mage/cards/t/TimelyHordemate.java index 5f20d2bfaef..bdf734ed072 100644 --- a/Mage.Sets/src/mage/cards/t/TimelyHordemate.java +++ b/Mage.Sets/src/mage/cards/t/TimelyHordemate.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +39,7 @@ public final class TimelyHordemate extends CardImpl { this.toughness = new MageInt(2); // Raid — When Timely Hordemate enters the battlefield, if you attacked this turn, return target creature card with converted mana cost 2 or less from your graveyard to the battlefield. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), RaidCondition.instance, + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, return target creature card with converted mana cost 2 or less from your graveyard to the battlefield."); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability, new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java b/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java index cf20bfb6d8f..81e2a7a1453 100644 --- a/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java +++ b/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class TinStreetHooligan extends CardImpl { this.toughness = new MageInt(1); // When Tin Street Hooligan enters the battlefield, if {G} was spent to cast Tin Street Hooligan, destroy target artifact. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()), new ManaWasSpentCondition(ColoredManaSymbol.G), "When {this} enters the battlefield, if {G} was spent to cast Tin Street Hooligan, destroy target artifact."); diff --git a/Mage.Sets/src/mage/cards/t/TinderWall.java b/Mage.Sets/src/mage/cards/t/TinderWall.java index db670850d16..948a334c794 100644 --- a/Mage.Sets/src/mage/cards/t/TinderWall.java +++ b/Mage.Sets/src/mage/cards/t/TinderWall.java @@ -1,8 +1,5 @@ - package mage.cards.t; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import mage.MageInt; import mage.Mana; @@ -17,14 +14,10 @@ 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.filter.common.FilterAttackingCreature; import mage.filter.predicate.permanent.BlockedByIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.common.TargetCreaturePermanent; -import mage.watchers.Watcher; /** * @@ -33,7 +26,7 @@ import mage.watchers.Watcher; public final class TinderWall extends CardImpl { public TinderWall(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.PLANT); this.subtype.add(SubType.WALL); @@ -50,7 +43,7 @@ public final class TinderWall extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new ManaCostsImpl("{R}")); ability.addTarget(new TargetCreaturePermanent(filter)); ability.addCost(new SacrificeSourceCost()); - this.addAbility(ability, new BlockedByWatcher()); + this.addAbility(ability); } public TinderWall(final TinderWall card) { @@ -62,38 +55,3 @@ public final class TinderWall extends CardImpl { return new TinderWall(this); } } - -class BlockedByWatcher extends Watcher { - - public List blockedByWatcher = new ArrayList<>(); - - public BlockedByWatcher() { - super("BlockedByWatcher", WatcherScope.CARD); - } - - public BlockedByWatcher(final BlockedByWatcher watcher) { - super(watcher); - this.blockedByWatcher.addAll(watcher.blockedByWatcher); - } - - @Override - public BlockedByWatcher copy() { - return new BlockedByWatcher(this); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { - if (sourceId.equals(event.getSourceId()) && !blockedByWatcher.contains(event.getTargetId())) { - blockedByWatcher.add(event.getTargetId()); - } - } - } - - @Override - public void reset() { - super.reset(); - blockedByWatcher.clear(); - } - -} diff --git a/Mage.Sets/src/mage/cards/t/TobiasBeckett.java b/Mage.Sets/src/mage/cards/t/TobiasBeckett.java new file mode 100644 index 00000000000..041b8a6e1f0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TobiasBeckett.java @@ -0,0 +1,185 @@ +package mage.cards.t; + +import java.util.Objects; +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.*; +import mage.abilities.effects.common.ExileCardsFromTopOfLibraryTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.BountyAbility; +import mage.cards.Card; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.ManaPoolItem; +import mage.players.Player; +import mage.target.common.TargetOpponentsCreaturePermanent; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +/** + * + * @author NinthWorld + */ +public final class TobiasBeckett extends CardImpl { + + public TobiasBeckett(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.HUNTER); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // When Tobias Becket enters the battlefield, put a bounty counter on target creature an opponent controls. + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance())); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + + // Bounty - Whenever a creature an opponent controls with a bounty counter on it dies, exile the top card of that player's library. You may cast cards exiled this way and spend mana as though it were mana of any type to cast that spell. + this.addAbility(new BountyAbility(new TobiasBeckettEffect(), false, true)); + } + + public TobiasBeckett(final TobiasBeckett card) { + super(card); + } + + @Override + public TobiasBeckett copy() { + return new TobiasBeckett(this); + } +} + +// Based on GrenzoHavocRaiserEffect +class TobiasBeckettEffect extends OneShotEffect { + + public TobiasBeckettEffect() { + super(Outcome.Exile); + staticText = "exile the top card of that player's library. You may cast cards exiled this way and spend mana as though it were mana of any type to cast that spell"; + } + + public TobiasBeckettEffect(final TobiasBeckettEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent bountyTriggered = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if(bountyTriggered != null) { + Player opponent = game.getPlayer(bountyTriggered.getControllerId()); + if (opponent != null) { + MageObject sourceObject = game.getObject(source.getSourceId()); + UUID exileId = CardUtil.getCardExileZoneId(game, source); + Card card = opponent.getLibrary().getFromTop(game); + if (card != null) { + // move card to exile + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + // Add effects only if the card has a spellAbility (e.g. not for lands). + if (card.getSpellAbility() != null) { + // allow to cast the card + game.addEffect(new TobiasBeckettCastFromExileEffect(card.getId(), exileId), source); + // and you may spend mana as though it were mana of any color to cast it + ContinuousEffect effect = new TobiasBeckettSpendAnyManaEffect(); + effect.setTargetPointer(new FixedTarget(card.getId())); + game.addEffect(effect, source); + } + } + return true; + } + } + } + return false; + } + + @Override + public TobiasBeckettEffect copy() { + return new TobiasBeckettEffect(this); + } +} + +// Based on GrenzoHavocRaiserCastFromExileEffect +class TobiasBeckettCastFromExileEffect extends AsThoughEffectImpl { + + private UUID cardId; + private UUID exileId; + + public TobiasBeckettCastFromExileEffect(UUID cardId, UUID exileId) { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit); + staticText = "You may cast that card and you may spend mana as though it were mana of any color to cast it"; + this.cardId = cardId; + this.exileId = exileId; + } + + public TobiasBeckettCastFromExileEffect(final TobiasBeckettCastFromExileEffect effect) { + super(effect); + this.cardId = effect.cardId; + this.exileId = effect.exileId; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public TobiasBeckettCastFromExileEffect copy() { + return new TobiasBeckettCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (sourceId.equals(cardId) && source.isControlledBy(affectedControllerId)) { + ExileZone exileZone = game.getState().getExile().getExileZone(exileId); + return exileZone != null && exileZone.contains(cardId); + } + return false; + } +} + +// Based on GrenzoHavocRaiserSpendAnyManaEffect +class TobiasBeckettSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { + + public TobiasBeckettSpendAnyManaEffect() { + super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.EndOfTurn, Outcome.Benefit); + staticText = "you may spend mana as though it were mana of any color to cast it"; + } + + public TobiasBeckettSpendAnyManaEffect(final TobiasBeckettSpendAnyManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public TobiasBeckettSpendAnyManaEffect copy() { + return new TobiasBeckettSpendAnyManaEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return source.isControlledBy(affectedControllerId) + && Objects.equals(objectId, ((FixedTarget) getTargetPointer()).getTarget()) + && ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId) + && (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId)) + && game.getState().getZone(objectId) == Zone.STACK; + } + + @Override + public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) { + return mana.getFirstAvailable(); + } + +} diff --git a/Mage.Sets/src/mage/cards/t/TolarianEmissary.java b/Mage.Sets/src/mage/cards/t/TolarianEmissary.java index 7dcbab2def4..09bbde4386c 100644 --- a/Mage.Sets/src/mage/cards/t/TolarianEmissary.java +++ b/Mage.Sets/src/mage/cards/t/TolarianEmissary.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -37,7 +37,7 @@ public final class TolarianEmissary extends CardImpl { // When Tolarian Emissary enters the battlefield, if it was kicked, destroy target enchantment. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); ability.addTarget(new TargetEnchantmentPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target enchantment.")); } diff --git a/Mage.Sets/src/mage/cards/t/TombRobber.java b/Mage.Sets/src/mage/cards/t/TombRobber.java index 9b36f323b0e..284104058d2 100644 --- a/Mage.Sets/src/mage/cards/t/TombRobber.java +++ b/Mage.Sets/src/mage/cards/t/TombRobber.java @@ -33,7 +33,7 @@ public final class TombRobber extends CardImpl { // Menace this.addAbility(new MenaceAbility(false)); - // {1}, Discard a card: Tomb Robber explores. (Reveal the top card of your library. Put that card into your hand if it’s a land. Otherwise, put a +1/+1 counter on this creature, then put the card back or put it into your graveyard.) + // {1}, Discard a card: Tomb Robber explores. (Reveal the top card of your library. Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on this creature, then put the card back or put it into your graveyard.) Effect effect = new ExploreSourceEffect(true, "{this}"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new DiscardCardCost()); ability.addCost(new ManaCostsImpl("{1}")); diff --git a/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java b/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java index fb6c84046d1..3f6c7634b6f 100644 --- a/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java +++ b/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -40,7 +40,7 @@ public final class ToolcraftExemplar extends CardImpl { Effect effect = new ConditionalContinuousEffect( new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new LockedInCondition(new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent(), ComparisonType.MORE_THAN, 2)), null); - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new BeginningOfCombatTriggeredAbility(new BoostSourceEffect(2, 1, Duration.EndOfTurn), TargetController.YOU, false), new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent()), "At the beginning of combat on your turn, if you control an artifact, {this} gets +2/+1 until end of turn." diff --git a/Mage.Sets/src/mage/cards/t/ToothCollector.java b/Mage.Sets/src/mage/cards/t/ToothCollector.java index 528abf642e9..ff87e8bff20 100644 --- a/Mage.Sets/src/mage/cards/t/ToothCollector.java +++ b/Mage.Sets/src/mage/cards/t/ToothCollector.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -51,7 +51,7 @@ public final class ToothCollector extends CardImpl { // {Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // target creature that player controls gets -1/-1 until end of turn. - ability = new ConditionalTriggeredAbility( + ability = new ConditionalInterveningIfTriggeredAbility( new ToothCollectorAbility(), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/t/Topple.java b/Mage.Sets/src/mage/cards/t/Topple.java index 87a044d4938..9c888e6de3d 100644 --- a/Mage.Sets/src/mage/cards/t/Topple.java +++ b/Mage.Sets/src/mage/cards/t/Topple.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.HashSet; @@ -11,10 +10,9 @@ import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; /** * @@ -40,11 +38,10 @@ public final class Topple extends CardImpl { } } -class ToppleTargetCreature extends TargetPermanent { +class ToppleTargetCreature extends TargetCreaturePermanent { public ToppleTargetCreature() { super(); - filter.add(new CardTypePredicate(CardType.CREATURE)); setTargetName("creature with the greatest power among creatures on the battlefield"); } diff --git a/Mage.Sets/src/mage/cards/t/Topplegeist.java b/Mage.Sets/src/mage/cards/t/Topplegeist.java index d077bcc239d..daf722048d6 100644 --- a/Mage.Sets/src/mage/cards/t/Topplegeist.java +++ b/Mage.Sets/src/mage/cards/t/Topplegeist.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -53,7 +53,7 @@ public final class Topplegeist extends CardImpl { // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // tap target creature that player controls. - ability = new ConditionalTriggeredAbility( + ability = new ConditionalInterveningIfTriggeredAbility( new TopplegeistAbility(), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " diff --git a/Mage.Sets/src/mage/cards/t/TorchSlinger.java b/Mage.Sets/src/mage/cards/t/TorchSlinger.java index 30e14a429b0..1b0ed80609f 100644 --- a/Mage.Sets/src/mage/cards/t/TorchSlinger.java +++ b/Mage.Sets/src/mage/cards/t/TorchSlinger.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class TorchSlinger extends CardImpl { // When Torch Slinger enters the battlefield, if it was kicked, it deals 2 damage to target creature. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), false); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, it deals 2 damage to target creature.")); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, it deals 2 damage to target creature.")); } public TorchSlinger(final TorchSlinger card) { diff --git a/Mage.Sets/src/mage/cards/t/TormentOfScarabs.java b/Mage.Sets/src/mage/cards/t/TormentOfScarabs.java index 4d3fbc6db7a..bda573aa8b2 100644 --- a/Mage.Sets/src/mage/cards/t/TormentOfScarabs.java +++ b/Mage.Sets/src/mage/cards/t/TormentOfScarabs.java @@ -80,7 +80,7 @@ class TormentOfScarabsAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent enchantment = game.getPermanent(this.getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null) { - if (game.getActivePlayerId().equals(enchantment.getAttachedTo())) { + if (game.isActivePlayer(enchantment.getAttachedTo())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TormentedPariah.java b/Mage.Sets/src/mage/cards/t/TormentedPariah.java index 40ec42bdb15..2dbaaaac84f 100644 --- a/Mage.Sets/src/mage/cards/t/TormentedPariah.java +++ b/Mage.Sets/src/mage/cards/t/TormentedPariah.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -36,7 +36,7 @@ public final class TormentedPariah extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Tormented Pariah. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public TormentedPariah(final TormentedPariah card) { diff --git a/Mage.Sets/src/mage/cards/t/TorrentElemental.java b/Mage.Sets/src/mage/cards/t/TorrentElemental.java index 499ad0e6fe6..d193acdd9a7 100644 --- a/Mage.Sets/src/mage/cards/t/TorrentElemental.java +++ b/Mage.Sets/src/mage/cards/t/TorrentElemental.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.UUID; @@ -15,11 +14,11 @@ 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.SetTargetPointer; +import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES; import mage.game.Game; import mage.players.Player; @@ -30,7 +29,7 @@ import mage.players.Player; public final class TorrentElemental extends CardImpl { public TorrentElemental(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.ELEMENTAL); this.power = new MageInt(3); this.toughness = new MageInt(5); @@ -38,7 +37,7 @@ public final class TorrentElemental extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever Torrent Elemental attacks, tap all creatures defending player controls. - Effect effect = new TapAllTargetPlayerControlsEffect(new FilterCreaturePermanent()); + Effect effect = new TapAllTargetPlayerControlsEffect(FILTER_PERMANENT_CREATURES); effect.setText("tap all creatures defending player controls."); this.addAbility(new AttacksTriggeredAbility(effect, false, null, SetTargetPointer.PLAYER)); // {3}{B/G}{B/G}: Put Torrent Elemental from exile onto the battlefield tapped. Activate this ability only any time you could cast a sorcery. diff --git a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java index 012565abd0c..863c0c2b992 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java +++ b/Mage.Sets/src/mage/cards/t/TovolarsMagehunter.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -44,7 +44,7 @@ public final class TovolarsMagehunter extends CardImpl { this.addAbility(new TovolarsMagehunterTriggeredAbility()); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Tovolar's Magehunter. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/t/TragicSlip.java b/Mage.Sets/src/mage/cards/t/TragicSlip.java index 6b5b595f2c2..af22f6aa801 100644 --- a/Mage.Sets/src/mage/cards/t/TragicSlip.java +++ b/Mage.Sets/src/mage/cards/t/TragicSlip.java @@ -23,12 +23,12 @@ public final class TragicSlip extends CardImpl { // Target creature gets -1/-1 until end of turn. - // Morbid - That creature gets -13/-13 until end of turn instead if a creature died this turn. + // Morbid — That creature gets -13/-13 until end of turn instead if a creature died this turn. this.getSpellAbility().addEffect(new ConditionalContinuousEffect( new BoostTargetEffect(-13, -13, Duration.EndOfTurn), new BoostTargetEffect(-1, -1, Duration.EndOfTurn), new LockedInCondition(MorbidCondition.instance), - "Target creature gets -1/-1 until end of turn. Morbid - That creature gets -13/-13 until end of turn instead if a creature died this turn")); + "Target creature gets -1/-1 until end of turn. Morbid — That creature gets -13/-13 until end of turn instead if a creature died this turn")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java b/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java new file mode 100644 index 00000000000..2ba2dfd68e2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TransmogrifyingWand.java @@ -0,0 +1,91 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenTargetEffect; +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.Outcome; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.OxToken; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author TheElk801 + */ +public final class TransmogrifyingWand extends CardImpl { + + public TransmogrifyingWand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // Transmogrifying Wand enters the battlefield with three charge counters on it. + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.CHARGE.createInstance(3)), + "{this} enters the battlefield with three charge counters on it" + )); + + // {1}, {T}, Remove a charge counter from Transmogrifying Wand: Destroy target creature. Its controller creates a 2/4 white Ox creature token. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, + new TransmogrifyingWandEffect(), + new GenericManaCost(1) + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance())); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public TransmogrifyingWand(final TransmogrifyingWand card) { + super(card); + } + + @Override + public TransmogrifyingWand copy() { + return new TransmogrifyingWand(this); + } +} + +class TransmogrifyingWandEffect extends OneShotEffect { + + public TransmogrifyingWandEffect() { + super(Outcome.Benefit); + this.staticText = "Destroy target creature. Its controller creates a 2/4 white Ox creature token."; + } + + public TransmogrifyingWandEffect(final TransmogrifyingWandEffect effect) { + super(effect); + } + + @Override + public TransmogrifyingWandEffect copy() { + return new TransmogrifyingWandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = game.getPermanent(source.getFirstTarget()); + if (creature == null) { + return false; + } + Effect effect = new CreateTokenTargetEffect(new OxToken()); + effect.setTargetPointer(new FixedTarget(creature.getControllerId(), game)); + new DestroyTargetEffect().apply(game, source); + return effect.apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TravelersCloak.java b/Mage.Sets/src/mage/cards/t/TravelersCloak.java index 02f4ef13dcc..9145af115df 100644 --- a/Mage.Sets/src/mage/cards/t/TravelersCloak.java +++ b/Mage.Sets/src/mage/cards/t/TravelersCloak.java @@ -50,7 +50,7 @@ public final class TravelersCloak extends CardImpl { // Enchanted creature has landwalk of the chosen type. FilterLandPermanent filter = new FilterLandPermanent("Landwalk of the chosen type"); - filter.add(new ChosenSubtypePredicate(this.getId())); + filter.add(new ChosenSubtypePredicate()); Ability landwalkAbility = new LandwalkAbility(filter); Effect effect = new GainAbilityAttachedEffect(landwalkAbility, AttachmentType.AURA); effect.setText("Enchanted creature has landwalk of the chosen type"); diff --git a/Mage.Sets/src/mage/cards/t/TravelingPlague.java b/Mage.Sets/src/mage/cards/t/TravelingPlague.java index 148be5c523b..d079c2c44b4 100644 --- a/Mage.Sets/src/mage/cards/t/TravelingPlague.java +++ b/Mage.Sets/src/mage/cards/t/TravelingPlague.java @@ -135,7 +135,7 @@ class TravelingPlagueEffect extends OneShotEffect { if (enchantedCreature != null) { Player controllerOfEnchantedCreature = game.getPlayer(enchantedCreature.getControllerId()); if (travelingPlague != null - && game.getState().getZone(travelingPlague.getId()).equals(Zone.GRAVEYARD) // aura must come from the graveyard + && game.getState().getZone(travelingPlague.getId()) == Zone.GRAVEYARD // aura must come from the graveyard && controllerOfEnchantedCreature != null) { TargetPermanent target = new TargetPermanent(new FilterCreaturePermanent("creature to enchant with " + travelingPlague.getName())); target.setNotTarget(true); diff --git a/Mage.Sets/src/mage/cards/t/TreacherousTerrain.java b/Mage.Sets/src/mage/cards/t/TreacherousTerrain.java index 8650e8c92b0..248c68496b8 100644 --- a/Mage.Sets/src/mage/cards/t/TreacherousTerrain.java +++ b/Mage.Sets/src/mage/cards/t/TreacherousTerrain.java @@ -61,7 +61,7 @@ class TreacherousTerrainEffect extends OneShotEffect { if (player != null) { int amount = 0; for (Permanent permanent : permanents) { - if (permanent.getControllerId().equals(playerId)) { + if (permanent.isControlledBy(playerId)) { amount++; } } diff --git a/Mage.Sets/src/mage/cards/t/TreasureNabber.java b/Mage.Sets/src/mage/cards/t/TreasureNabber.java new file mode 100644 index 00000000000..9a62b20545d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TreasureNabber.java @@ -0,0 +1,146 @@ +package mage.cards.t; + +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.ContinuousEffectImpl; +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.PhaseStep; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; +import mage.target.targetpointer.FixedTargets; + +/** + * + * @author spjspj + */ +public final class TreasureNabber extends CardImpl { + + public TreasureNabber(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever an opponent taps an artifact for mana, gain control of that artifact until the end of your next turn. + this.addAbility(new TreasureNabberAbility()); + } + + public TreasureNabber(final TreasureNabber card) { + super(card); + } + + @Override + public TreasureNabber copy() { + return new TreasureNabber(this); + } +} + +class TreasureNabberAbility extends TriggeredAbilityImpl { + + public TreasureNabberAbility() { + super(Zone.BATTLEFIELD, new TreasureNabberEffect()); + } + + public TreasureNabberAbility(TreasureNabberAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.TAPPED_FOR_MANA; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.getOpponents(controllerId).contains(event.getPlayerId())) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent != null && permanent.isArtifact()) { + getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId())); + return true; + } + } + return false; + } + + @Override + public TreasureNabberAbility copy() { + return new TreasureNabberAbility(this); + } + + @Override + public String getRule() { + return "Whenever an opponent taps an artifact for mana, gain control of that artifact until the end of your next turn"; + } +} + +class TreasureNabberEffect extends ContinuousEffectImpl { + + protected FixedTargets fixedTargets; + protected int startingTurn; + + TreasureNabberEffect() { + super(Duration.Custom, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); + this.staticText = "gain control of that artifact until the end of your next turn"; + startingTurn = 0; + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + startingTurn = game.getTurnNum(); + if (game.getPhase().getStep().getType() == PhaseStep.END_TURN) { + startingTurn = game.getTurnNum() + 1; + } + } + + TreasureNabberEffect(final TreasureNabberEffect effect) { + super(effect); + this.fixedTargets = effect.fixedTargets; + } + + @Override + public TreasureNabberEffect copy() { + return new TreasureNabberEffect(this); + } + + @Override + public boolean isInactive(Ability source, Game game) { + if (startingTurn != 0 && game.getTurnNum() >= startingTurn && game.getPhase().getStep().getType() == PhaseStep.END_TURN) { + if (game.isActivePlayer(source.getControllerId())) { + return true; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + + if (permanent != null) { + permanent.changeControllerId(source.getControllerId(), game); + return true; + } + return false; + } + + public void setTargets(List targetedPermanents, Game game) { + this.fixedTargets = new FixedTargets(targetedPermanents, game); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TreetopBracers.java b/Mage.Sets/src/mage/cards/t/TreetopBracers.java index 59f99ca20ac..a1bcb1f2422 100644 --- a/Mage.Sets/src/mage/cards/t/TreetopBracers.java +++ b/Mage.Sets/src/mage/cards/t/TreetopBracers.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.UUID; @@ -21,12 +20,12 @@ import mage.target.common.TargetCreaturePermanent; /** * * @author Jason E. Wall - + * */ public final class TreetopBracers extends CardImpl { public TreetopBracers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -37,7 +36,7 @@ public final class TreetopBracers extends CardImpl { this.addAbility(ability); // Enchanted creature gets +1/+1 and can't be blocked except by creatures with flying. - ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1,1, Duration.WhileOnBattlefield)); + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield)); ability.addEffect(new TreetopBracersRestrictEffect()); this.addAbility(ability); } @@ -52,7 +51,6 @@ public final class TreetopBracers extends CardImpl { } } - class TreetopBracersRestrictEffect extends RestrictionEffect { public TreetopBracersRestrictEffect() { @@ -69,7 +67,7 @@ class TreetopBracersRestrictEffect extends RestrictionEffect { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent equipped = game.getPermanent(equipment.getAttachedTo()); - if (permanent.getId().equals(equipped.getId())) { + if (permanent != null && permanent.getId().equals(equipped.getId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TreetopDefense.java b/Mage.Sets/src/mage/cards/t/TreetopDefense.java index 101c28fd646..1062accf3f0 100644 --- a/Mage.Sets/src/mage/cards/t/TreetopDefense.java +++ b/Mage.Sets/src/mage/cards/t/TreetopDefense.java @@ -27,7 +27,7 @@ public final class TreetopDefense extends CardImpl { // Cast Treetop Defense only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TriumphOfCruelty.java b/Mage.Sets/src/mage/cards/t/TriumphOfCruelty.java index f33df57ab9c..b16a9e88bf7 100644 --- a/Mage.Sets/src/mage/cards/t/TriumphOfCruelty.java +++ b/Mage.Sets/src/mage/cards/t/TriumphOfCruelty.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.ControlsCreatureGreatestPowerCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class TriumphOfCruelty extends CardImpl { TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new DiscardTargetEffect(1), TargetController.YOU, false); Target target = new TargetOpponent(); ability.addTarget(target); - this.addAbility(new ConditionalTriggeredAbility(ability, ControlsCreatureGreatestPowerCondition.instance, ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ControlsCreatureGreatestPowerCondition.instance, ruleText)); } public TriumphOfCruelty(final TriumphOfCruelty card) { diff --git a/Mage.Sets/src/mage/cards/t/TriumphOfFerocity.java b/Mage.Sets/src/mage/cards/t/TriumphOfFerocity.java index 282df242082..720b1afb66f 100644 --- a/Mage.Sets/src/mage/cards/t/TriumphOfFerocity.java +++ b/Mage.Sets/src/mage/cards/t/TriumphOfFerocity.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.ControlsCreatureGreatestPowerCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +25,7 @@ public final class TriumphOfFerocity extends CardImpl { // At the beginning of your upkeep, draw a card if you control the creature with the greatest power or tied for the greatest power. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability, ControlsCreatureGreatestPowerCondition.instance, ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ControlsCreatureGreatestPowerCondition.instance, ruleText)); } public TriumphOfFerocity(final TriumphOfFerocity card) { diff --git a/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java b/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java index 9e23a771fe8..5d1a729b304 100644 --- a/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java +++ b/Mage.Sets/src/mage/cards/t/TrostaniSelesnyasVoice.java @@ -78,7 +78,7 @@ class TrostaniSelesnyasVoiceTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent.isCreature() - && permanent.getControllerId().equals(this.controllerId) + && permanent.isControlledBy(this.controllerId) && !Objects.equals(event.getTargetId(), this.getSourceId())) { Effect effect = this.getEffects().get(0); // life is determined during resolution so it has to be retrieved there (e.g. Giant Growth before resolution) diff --git a/Mage.Sets/src/mage/cards/t/TrueNameNemesis.java b/Mage.Sets/src/mage/cards/t/TrueNameNemesis.java index 8c84c3077d2..bc5fefd8179 100644 --- a/Mage.Sets/src/mage/cards/t/TrueNameNemesis.java +++ b/Mage.Sets/src/mage/cards/t/TrueNameNemesis.java @@ -21,14 +21,14 @@ import mage.game.stack.StackObject; /** * Protection from a player is a new variant of the protection ability. It means - * the following: -- True-Name Nemesis can’t be the target of spells or - * abilities controlled by the chosen player. -- True-Name Nemesis can’t be + * the following: -- True-Name Nemesis can't be the target of spells or + * abilities controlled by the chosen player. -- True-Name Nemesis can't be * enchanted by Auras or equipped by Equipment controlled by the chosen player. * (The same is true for Fortifications controlled by the chosen player, if - * True-Name Nemesis becomes a land.) -- True-Name Nemesis can’t be blocked by + * True-Name Nemesis becomes a land.) -- True-Name Nemesis can't be blocked by * creatures controlled by the chosen player. -- All damage that would be dealt * to True-Name Nemesis by sources controlled by the chosen player is prevented. - * (The same is true for sources owned by the chosen player that don’t have + * (The same is true for sources owned by the chosen player that don't have * controllers.) * * @author LevelX2 @@ -84,16 +84,16 @@ class ProtectionFromPlayerAbility extends ProtectionAbility { UUID playerId = (UUID) game.getState().getValue(this.getSourceId() + "_player"); if (playerId != null && source != null) { if (source instanceof Permanent) { - return !((Permanent) source).getControllerId().equals(playerId); + return !((Permanent) source).isControlledBy(playerId); } if (source instanceof Spell) { - return !((Spell) source).getControllerId().equals(playerId); + return !((Spell) source).isControlledBy(playerId); } if (source instanceof StackObject) { - return !((StackObject) source).getControllerId().equals(playerId); + return !((StackObject) source).isControlledBy(playerId); } if (source instanceof Card) { // e.g. for Vengeful Pharaoh - return !((Card) source).getOwnerId().equals(playerId); + return !((Card) source).isOwnedBy(playerId); } } return true; diff --git a/Mage.Sets/src/mage/cards/t/TruthOrTale.java b/Mage.Sets/src/mage/cards/t/TruthOrTale.java new file mode 100644 index 00000000000..f76c7eed66e --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TruthOrTale.java @@ -0,0 +1,126 @@ +package mage.cards.t; + +import java.util.*; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Library; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; +import mage.util.GameLog; + +/** + * + * @author noahg + */ +public final class TruthOrTale extends CardImpl { + + public TruthOrTale(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + + // Reveal the top five cards of your library and separate them into two piles. An opponent chooses one of those piles. Put a card from the chosen pile into your hand, then put all other cards revealed this way on the bottom of your library in any order. + this.getSpellAbility().addEffect(new TruthOrTaleEffect()); + } + + public TruthOrTale(final TruthOrTale card) { + super(card); + } + + @Override + public TruthOrTale copy() { + return new TruthOrTale(this); + } +} + +class TruthOrTaleEffect extends OneShotEffect { + + public TruthOrTaleEffect() { + super(Outcome.DrawCard); + this.staticText = "Reveal the top five cards of your library and separate them into two piles. An opponent chooses one of those piles. Put a card from the chosen pile into your hand, then put all other cards revealed this way on the bottom of your library in any order"; + } + + public TruthOrTaleEffect(final TruthOrTaleEffect effect) { + super(effect); + } + + @Override + public TruthOrTaleEffect copy() { + return new TruthOrTaleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || sourceObject == null) { + return false; + } + + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, 5)); + controller.revealCards(sourceObject.getIdName(), cards, game); + + Player opponent; + Set opponents = game.getOpponents(controller.getId()); + if (opponents.size() == 1) { + opponent = game.getPlayer(opponents.iterator().next()); + } else { + Target target = new TargetOpponent(true); + controller.chooseTarget(Outcome.Detriment, target, source, game); + opponent = game.getPlayer(target.getFirstTarget()); + } + + if (opponent != null) { + TargetCard target = new TargetCard(0, cards.size(), Zone.LIBRARY, new FilterCard("cards to put in the first pile")); + List pile1 = new ArrayList<>(); + target.setRequired(false); + if (controller.choose(Outcome.Neutral, cards, target, game)) { + List targets = target.getTargets(); + for (UUID targetId : targets) { + Card card = game.getCard(targetId); + if (card != null) { + pile1.add(card); + } + } + } + List pile2 = new ArrayList<>(); + for (UUID cardId : cards) { + Card card = game.getCard(cardId); + if (card != null && !pile1.contains(card)) { + pile2.add(card); + } + } + boolean choice = opponent.choosePile(Outcome.Detriment, "Choose a pile for " + controller.getName() + " to choose a card from.", pile1, pile2, game); + + List chosen = choice ? pile1 : pile2; + if (!chosen.isEmpty()) { + Cards chosenCards = new CardsImpl(new HashSet<>(chosen)); + TargetCard finalChosenCardTarget = new TargetCard(Zone.LIBRARY,new FilterCard("card to put into your hand")); + if (controller.choose(Outcome.DrawCard, chosenCards, finalChosenCardTarget, game)){ + Card finalChosenCard = game.getCard(finalChosenCardTarget.getFirstTarget()); + if (finalChosenCard != null) { + if (!game.isSimulation()) { + game.informPlayers(controller.getName() + " chose to put " + finalChosenCard.getIdName() + " into their hand."); + } + cards.remove(finalChosenCard); + controller.moveCards(finalChosenCard, Zone.HAND, source, game); + } + } + } + + controller.putCardsOnBottomOfLibrary(cards, game, source, true); + } + + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TsabosDecree.java b/Mage.Sets/src/mage/cards/t/TsabosDecree.java index 325c3479d46..422d34b0756 100644 --- a/Mage.Sets/src/mage/cards/t/TsabosDecree.java +++ b/Mage.Sets/src/mage/cards/t/TsabosDecree.java @@ -84,7 +84,7 @@ class TsabosDecreeEffect extends OneShotEffect { FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent(); filterCreaturePermanent.add(new SubtypePredicate(SubType.byDescription(typeChoice.getChoice()))); for (Permanent creature : game.getBattlefield().getActivePermanents(filterCreaturePermanent, source.getSourceId(), game)) { - if (creature.getControllerId().equals(targetPlayer.getId())) { + if (creature.isControlledBy(targetPlayer.getId())) { creature.destroy(source.getSourceId(), game, true); } } diff --git a/Mage.Sets/src/mage/cards/t/TuktukScrapper.java b/Mage.Sets/src/mage/cards/t/TuktukScrapper.java index f2b30cff515..c7b772f03cf 100644 --- a/Mage.Sets/src/mage/cards/t/TuktukScrapper.java +++ b/Mage.Sets/src/mage/cards/t/TuktukScrapper.java @@ -78,7 +78,7 @@ class TuktukScrapperTriggeredAbility extends TriggeredAbilityImpl { return true; } if (permanent.hasSubtype(SubType.ALLY, game) - && permanent.getControllerId().equals(this.getControllerId())) { + && permanent.isControlledBy(this.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TumbleMagnet.java b/Mage.Sets/src/mage/cards/t/TumbleMagnet.java index 796d70b82bb..c5033485560 100644 --- a/Mage.Sets/src/mage/cards/t/TumbleMagnet.java +++ b/Mage.Sets/src/mage/cards/t/TumbleMagnet.java @@ -1,5 +1,3 @@ - - package mage.cards.t; import java.util.UUID; @@ -15,9 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; /** @@ -25,24 +21,26 @@ import mage.target.TargetPermanent; * @author Loki */ public final class TumbleMagnet extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("artifact or creature"); - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.ARTIFACT), - new CardTypePredicate(CardType.CREATURE))); - } + public TumbleMagnet(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - public TumbleMagnet (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance(3)), "Tumble Magnet enters the battlefield with three charge counters on it")); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost()); + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.CHARGE.createInstance(3)), + "{this} enters the battlefield with three charge counters on it" + )); + + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new TapTargetEffect(), + new TapSourceCost() + ); ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance())); - ability.addTarget(new TargetPermanent(filter)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE)); this.addAbility(ability); } - public TumbleMagnet (final TumbleMagnet card) { + public TumbleMagnet(final TumbleMagnet card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/t/TunnelVision.java b/Mage.Sets/src/mage/cards/t/TunnelVision.java index b3433ed45ea..e7b2e0d9bc2 100644 --- a/Mage.Sets/src/mage/cards/t/TunnelVision.java +++ b/Mage.Sets/src/mage/cards/t/TunnelVision.java @@ -1,10 +1,9 @@ - package mage.cards.t; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,7 +28,7 @@ public final class TunnelVision extends CardImpl { // Name a card. Target player reveals cards from the top of their library until the named card is revealed. // If it is, that player puts the rest of the revealed cards into their graveyard and puts the named card on top of their library. // Otherwise, the player shuffles their library. - this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL)); + this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL)); this.getSpellAbility().addEffect(new TunnelVisionEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); } @@ -48,7 +47,11 @@ class TunnelVisionEffect extends OneShotEffect { public TunnelVisionEffect() { super(Outcome.Benefit); - this.staticText = "Target player reveals cards from the top of their library until the named card is revealed. If it is, that player puts the rest of the revealed cards into their graveyard and puts the named card on top of their library. Otherwise, the player shuffles their library."; + this.staticText = "Target player reveals cards from the top of their library " + + "until a card with that name is revealed. If it is, that player puts " + + "the rest of the revealed cards into their graveyard and " + + "puts the card with the chosen name on top of their library. " + + "Otherwise, the player shuffles their library"; } public TunnelVisionEffect(final TunnelVisionEffect effect) { @@ -63,7 +66,7 @@ class TunnelVisionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); - String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY); + String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); if (targetPlayer == null || cardName == null || cardName.isEmpty()) { return false; } diff --git a/Mage.Sets/src/mage/cards/t/Turnabout.java b/Mage.Sets/src/mage/cards/t/Turnabout.java index 7a0c468d93a..47e2ae27a84 100644 --- a/Mage.Sets/src/mage/cards/t/Turnabout.java +++ b/Mage.Sets/src/mage/cards/t/Turnabout.java @@ -112,14 +112,14 @@ class TurnaboutEffect extends OneShotEffect { if (choiceImpl.getChoice().equals("Untap")) { filter.add(new TappedPredicate()); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (permanent.getControllerId().equals(target)) { + if (permanent.isControlledBy(target)) { permanent.untap(game); } } } else { filter.add(Predicates.not(new TappedPredicate())); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (permanent.getControllerId().equals(target)) { + if (permanent.isControlledBy(target)) { permanent.tap(game); } } diff --git a/Mage.Sets/src/mage/cards/t/TurntimberSower.java b/Mage.Sets/src/mage/cards/t/TurntimberSower.java new file mode 100644 index 00000000000..2db016a36cd --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TurntimberSower.java @@ -0,0 +1,120 @@ +package mage.cards.t; + +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeGroupEvent; +import mage.game.permanent.token.PlantToken; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author TheElk801 + */ +public final class TurntimberSower extends CardImpl { + + private static final FilterControlledPermanent filter + = new FilterControlledCreaturePermanent("three creatures"); + + public TurntimberSower(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever one or more land cards are put into your graveyard from anywhere, create a 0/1 green Plant creature token. + this.addAbility(new TurntimberSowerTriggeredAbility()); + + // {G}, Sacrifice three creatures: Return target land card from your graveyard to your hand. + Ability ability = new SimpleActivatedAbility( + new ReturnToHandTargetEffect() + .setText("Return target land card " + + "from your graveyard to your hand"), + new ManaCostsImpl("{G}") + ); + ability.addCost(new SacrificeTargetCost( + new TargetControlledPermanent(3, 3, filter, true) + )); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_LAND)); + this.addAbility(ability); + } + + public TurntimberSower(final TurntimberSower card) { + super(card); + } + + @Override + public TurntimberSower copy() { + return new TurntimberSower(this); + } +} + +class TurntimberSowerTriggeredAbility extends TriggeredAbilityImpl { + + public TurntimberSowerTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new PlantToken()), false); + } + + public TurntimberSowerTriggeredAbility(final TurntimberSowerTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE_GROUP; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event; + if (zEvent != null + && Zone.GRAVEYARD == zEvent.getToZone() + && zEvent.getCards() != null) { + for (Card card : zEvent.getCards()) { + if (card != null) { + UUID cardOwnerId = card.getOwnerId(); + Set cardType = card.getCardType(); + if (cardOwnerId != null + && card.isOwnedBy(getControllerId()) + && cardType != null + && card.isLand()) { + return true; + } + } + } + } + return false; + } + + @Override + public TurntimberSowerTriggeredAbility copy() { + return new TurntimberSowerTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever one or more land cards are put into your graveyard " + + "from anywhere, create a 0/1 green Plant creature token."; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java b/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java new file mode 100644 index 00000000000..5af7d2b9740 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TuvasaTheSunlit.java @@ -0,0 +1,156 @@ +package mage.cards.t; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +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 mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; +import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.watchers.Watcher; + +/** + * + * @author TheElk801 + */ +public final class TuvasaTheSunlit extends CardImpl { + + public TuvasaTheSunlit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Tuvasa the Sunlit gets +1/+1 for each enchantment you control. + FilterEnchantmentPermanent filter + = new FilterEnchantmentPermanent("enchantment you control"); + filter.add(new ControllerPredicate(TargetController.YOU)); + DynamicValue value + = new PermanentsOnBattlefieldCount(new FilterPermanent(filter)); + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect( + value, value, Duration.WhileOnBattlefield + ).setText("{this} gets +1/+1 for each enchantment you control") + ); + this.addAbility(ability); + + // Whenever you cast your first enchantment spell each turn, draw a card. + this.addAbility( + new TuvasaTheSunlitTriggeredAbility(), + new TuvasaTheSunlitWatcher() + ); + } + + public TuvasaTheSunlit(final TuvasaTheSunlit card) { + super(card); + } + + @Override + public TuvasaTheSunlit copy() { + return new TuvasaTheSunlit(this); + } +} + +class TuvasaTheSunlitTriggeredAbility extends SpellCastControllerTriggeredAbility { + + public TuvasaTheSunlitTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), + (FilterSpell) new FilterSpell("an enchantment spell").add(new CardTypePredicate(CardType.ENCHANTMENT)), false, true); + } + + public TuvasaTheSunlitTriggeredAbility(final TuvasaTheSunlitTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (super.checkTrigger(event, game)) { + TuvasaTheSunlitWatcher watcher = (TuvasaTheSunlitWatcher) game.getState().getWatchers().get( + TuvasaTheSunlitWatcher.class.getSimpleName() + ); + return event.getTargetId().equals(watcher.getFirstEnchantmentThisTurn(this.getControllerId())); + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast your first enchantment spell each turn, draw a card."; + } + + @Override + public TuvasaTheSunlitTriggeredAbility copy() { + return new TuvasaTheSunlitTriggeredAbility(this); + } +} + +class TuvasaTheSunlitWatcher extends Watcher { + + private final Map firstEnchantmentThisTurn = new HashMap(); + + public TuvasaTheSunlitWatcher() { + super(TuvasaTheSunlitWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public TuvasaTheSunlitWatcher(final TuvasaTheSunlitWatcher watcher) { + super(watcher); + this.firstEnchantmentThisTurn.putAll(watcher.firstEnchantmentThisTurn); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.isEnchantment()) { + firstEnchantmentThisTurn.putIfAbsent( + event.getPlayerId(), + spell.getId() + ); + } + } + } + + @Override + public void reset() { + firstEnchantmentThisTurn.clear(); + } + + public UUID getFirstEnchantmentThisTurn(UUID playerId) { + return firstEnchantmentThisTurn.get(playerId); + } + + @Override + public Watcher copy() { + return new TuvasaTheSunlitWatcher(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TwilightProphet.java b/Mage.Sets/src/mage/cards/t/TwilightProphet.java index a2a0943ce04..cced90fe5d1 100644 --- a/Mage.Sets/src/mage/cards/t/TwilightProphet.java +++ b/Mage.Sets/src/mage/cards/t/TwilightProphet.java @@ -7,7 +7,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.keyword.AscendAbility; @@ -46,7 +46,7 @@ public final class TwilightProphet extends CardImpl { // At the beginning of your upkeep, if you have the city's blessing, reveal the top card of your library and put it into your hand. // Each opponent loses X life and you gain X life, where X is that card's converted mana cost. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility( new TwilightProphetEffect(), TargetController.YOU, false), CitysBlessingCondition.instance, "At the beginning of your upkeep, if you have the city's blessing, reveal the top card of your library and put it into your hand." + "Each opponent loses X life and you gain X life, where X is that card's converted mana cost.")); diff --git a/Mage.Sets/src/mage/cards/t/TwilightShepherd.java b/Mage.Sets/src/mage/cards/t/TwilightShepherd.java index a6de912d3dc..fe12c72f726 100644 --- a/Mage.Sets/src/mage/cards/t/TwilightShepherd.java +++ b/Mage.Sets/src/mage/cards/t/TwilightShepherd.java @@ -90,7 +90,7 @@ class TwilightShepherdEffect extends OneShotEffect { if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { Card card = game.getCard(mor.getSourceId()); if (card != null - && card.getOwnerId().equals(source.getControllerId())) { + && card.isOwnedBy(source.getControllerId())) { cardsToHand.add(card); } } diff --git a/Mage.Sets/src/mage/cards/t/Twincast.java b/Mage.Sets/src/mage/cards/t/Twincast.java index cd95320c92b..abe895f4beb 100644 --- a/Mage.Sets/src/mage/cards/t/Twincast.java +++ b/Mage.Sets/src/mage/cards/t/Twincast.java @@ -20,7 +20,7 @@ public final class Twincast extends CardImpl { // Copy target instant or sorcery spell. You may choose new targets for the copy. this.getSpellAbility().addEffect(new CopyTargetSpellEffect()); - this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); } public Twincast(final Twincast card) { diff --git a/Mage.Sets/src/mage/cards/t/Twinflame.java b/Mage.Sets/src/mage/cards/t/Twinflame.java index ecc4f8dadec..c1f6f7cd670 100644 --- a/Mage.Sets/src/mage/cards/t/Twinflame.java +++ b/Mage.Sets/src/mage/cards/t/Twinflame.java @@ -35,7 +35,7 @@ public final class Twinflame extends CardImpl { // Strive - Twinflame costs 2R more to cast for each target beyond the first. this.addAbility(new StriveAbility("{2}{R}")); - // Choose any number of target creatures you control. For each of them, create a token that's a copy of that creature. Those tokens have haste. Exile them at the beginning of the next end step. + // Choose any number of target creatures you control. For each of them, create a token that's a copy of that creature, except it has haste. Exile them at the beginning of the next end step. this.getSpellAbility().addEffect(new TwinflameCopyEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, new FilterControlledCreaturePermanent(), false)); @@ -55,7 +55,7 @@ class TwinflameCopyEffect extends OneShotEffect { public TwinflameCopyEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Choose any number of target creatures you control. For each of them, create a token that's a copy of that creature. Those tokens have haste. Exile them at the beginning of the next end step"; + this.staticText = "Choose any number of target creatures you control. For each of them, create a token that's a copy of that creature, except it has haste. Exile them at the beginning of the next end step"; } public TwinflameCopyEffect(final TwinflameCopyEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/TwistAllegiance.java b/Mage.Sets/src/mage/cards/t/TwistAllegiance.java index 19527d1eab0..625aa011232 100644 --- a/Mage.Sets/src/mage/cards/t/TwistAllegiance.java +++ b/Mage.Sets/src/mage/cards/t/TwistAllegiance.java @@ -67,8 +67,8 @@ class TwistAllegianceEffect extends OneShotEffect { if (controller != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { // only creatures of controller & target opponent - if (permanent.getControllerId().equals(source.getControllerId()) || permanent.getControllerId().equals(targetOpponent.getId())) { - UUID newController = permanent.getControllerId().equals(source.getControllerId()) ? targetOpponent.getId() : source.getControllerId(); + if (permanent.isControlledBy(source.getControllerId()) || permanent.isControlledBy(targetOpponent.getId())) { + UUID newController = permanent.isControlledBy(source.getControllerId()) ? targetOpponent.getId() : source.getControllerId(); ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfTurn, true, newController); effect.setTargetPointer(new FixedTarget(permanent.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/t/TwoHeadedZombie.java b/Mage.Sets/src/mage/cards/t/TwoHeadedZombie.java new file mode 100644 index 00000000000..c7286f32a69 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TwoHeadedZombie.java @@ -0,0 +1,37 @@ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class TwoHeadedZombie extends CardImpl { + + public TwoHeadedZombie(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // Menace + this.addAbility(new MenaceAbility()); + + } + + public TwoHeadedZombie(final TwoHeadedZombie card) { + super(card); + } + + @Override + public TwoHeadedZombie copy() { + return new TwoHeadedZombie(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java b/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java index 203d14f642c..9297159824f 100644 --- a/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java +++ b/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SurgedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.SurgeAbility; @@ -36,7 +36,7 @@ public final class TyrantOfValakut extends CardImpl { // When Tyrant of Valakut enters the battlefield, if its surge cost was paid, it deals 3 damage to any target. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3), false); ability.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalTriggeredAbility(ability, SurgedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, SurgedCondition.instance, "When {this} enters the battlefield, if its surge cost was paid, it deals 3 damage to any target.")); } diff --git a/Mage.Sets/src/mage/cards/u/UWing.java b/Mage.Sets/src/mage/cards/u/UWing.java new file mode 100644 index 00000000000..8496ec7d274 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UWing.java @@ -0,0 +1,73 @@ +package mage.cards.u; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author NinthWorld + */ +public final class UWing extends CardImpl { + + public UWing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // As long as U-Wing is tapped, it gets +1/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostSourceEffect(1, 0, Duration.WhileOnBattlefield), + SourceTappedCondition.instance, + "As long as {this} is tapped, it gets +1/+0"))); + + // As long as U-Wing is untapped, it gets +0/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostSourceEffect(0, 1, Duration.WhileOnBattlefield), + SourceUntappedCondition.instance, + "As long as {this} is untapped, it gets +0/+1"))); + } + + public UWing(final UWing card) { + super(card); + } + + @Override + public UWing copy() { + return new UWing(this); + } +} + +enum SourceUntappedCondition implements Condition { + + instance; + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null) { + return !permanent.isTapped(); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java b/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java index 52c54ca8115..7dcfd6782f1 100644 --- a/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java +++ b/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -41,7 +41,7 @@ public final class UbulSarGatekeepers extends CardImpl { this.toughness = new MageInt(4); // Whenever Ubul Sar Gatekeepers enters the battlefield, if you control two or more Gates, target creature an opponent controls gets -2/-2 until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), "Whenever {this} enters the battlefield, if you control two or more Gates, target creature an opponent controls gets -2/-2 until end of turn."); diff --git a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java index 1d3aeef5143..88ef64e31b8 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java +++ b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.TransformAbility; @@ -43,7 +43,7 @@ public final class UlrichOfTheKrallenhorde extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Ulrich of the Krallenhorde. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public UlrichOfTheKrallenhorde(final UlrichOfTheKrallenhorde card) { diff --git a/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java b/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java index 3e7f37aef0c..f106d6b44cf 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java +++ b/Mage.Sets/src/mage/cards/u/UlrichUncontestedAlpha.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -48,7 +48,7 @@ public final class UlrichUncontestedAlpha extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ulrich, Uncontested Alpha. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public UlrichUncontestedAlpha(final UlrichUncontestedAlpha card) { diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java b/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java index f1e15e4d822..d219c273b84 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,8 +29,8 @@ public final class UlvenwaldBear extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - // Morbid - When Ulvenwald Bear enters the battlefield, if a creature died this turn, put two +1/+1 counters on target creature. - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2), Outcome.BoostCreature)), + // Morbid — When Ulvenwald Bear enters the battlefield, if a creature died this turn, put two +1/+1 counters on target creature. + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2), Outcome.BoostCreature)), MorbidCondition.instance, "When {this} enters the battlefield, if a creature died this turn, put two +1/+1 counters on target creature."); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java b/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java index 383c9309ba3..dd607067544 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldMystics.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class UlvenwaldMystics extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Ulvenwald Mystics. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public UlvenwaldMystics(final UlvenwaldMystics card) { diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java b/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java index c6a9cc5f790..df5e6bf52e1 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldPrimordials.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -41,7 +41,7 @@ public final class UlvenwaldPrimordials extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ulvenwald Primordials. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public UlvenwaldPrimordials(final UlvenwaldPrimordials card) { diff --git a/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java b/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java index edf1e272102..81b45ca9078 100644 --- a/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java +++ b/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java @@ -92,7 +92,7 @@ class UnconventionalTacticsTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent.isCreature() - && permanent.getControllerId().equals(this.controllerId) + && permanent.isControlledBy(this.controllerId) && filter.match(permanent, game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java b/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java index 4a9e3c16905..2953587af90 100644 --- a/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java +++ b/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java @@ -124,7 +124,7 @@ class UndeadAlchemistEffect extends ReplacementEffectImpl { if (damageEvent.isCombatDamage()) { UUID controllerId = source.getControllerId(); Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && permanent.hasSubtype(SubType.ZOMBIE, game) && permanent.getControllerId().equals(controllerId)) { + if (permanent != null && permanent.hasSubtype(SubType.ZOMBIE, game) && permanent.isControlledBy(controllerId)) { return true; } } diff --git a/Mage.Sets/src/mage/cards/u/UndergroundForum.java b/Mage.Sets/src/mage/cards/u/UndergroundForum.java new file mode 100644 index 00000000000..f079faedc1a --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UndergroundForum.java @@ -0,0 +1,62 @@ +package mage.cards.u; + +import java.util.UUID; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ColorlessManaCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.mana.AddManaChosenColorEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.ConditionalColoredManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class UndergroundForum extends CardImpl { + + public UndergroundForum(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + + // T: Add {1}. + this.addAbility(new ColorlessManaAbility()); + + // {1}, {T}: Add {B}, {R}, or {G}. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana(1), new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana(1), new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(1), new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // {2}, {T}: Put a bounty counter on target creature. + Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), new GenericManaCost(2)); + ability2.addCost(new TapSourceCost()); + ability2.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability2); + } + + public UndergroundForum(final UndergroundForum card) { + super(card); + } + + @Override + public UndergroundForum copy() { + return new UndergroundForum(this); + } +} diff --git a/Mage.Sets/src/mage/cards/u/UndiscoveredParadise.java b/Mage.Sets/src/mage/cards/u/UndiscoveredParadise.java index f23896135d5..17395c33701 100644 --- a/Mage.Sets/src/mage/cards/u/UndiscoveredParadise.java +++ b/Mage.Sets/src/mage/cards/u/UndiscoveredParadise.java @@ -89,7 +89,7 @@ class AtBeginningOfUntapDelayedTriggeredAbility extends DelayedTriggeredAbility @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(controllerId)) { + if (game.isActivePlayer(controllerId)) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/u/UndyingFlames.java b/Mage.Sets/src/mage/cards/u/UndyingFlames.java index 15b7ce282c2..acbfe4a5664 100644 --- a/Mage.Sets/src/mage/cards/u/UndyingFlames.java +++ b/Mage.Sets/src/mage/cards/u/UndyingFlames.java @@ -1,4 +1,3 @@ - package mage.cards.u; import java.util.UUID; @@ -64,7 +63,7 @@ class UndyingFlamesEffect extends OneShotEffect { while (controller.getLibrary().hasCards() && controller.isInGame()) { Card card = controller.getLibrary().getFromTop(game); if (card != null) { - controller.moveCards(card, Zone.LIBRARY, source, game); + controller.moveCards(card, Zone.EXILED, source, game); if (!card.isLand()) { new DamageTargetEffect(card.getConvertedManaCost()).apply(game, source); break; diff --git a/Mage.Sets/src/mage/cards/u/UneshCriosphinxSovereign.java b/Mage.Sets/src/mage/cards/u/UneshCriosphinxSovereign.java index 0fe34235226..d48aeec950d 100644 --- a/Mage.Sets/src/mage/cards/u/UneshCriosphinxSovereign.java +++ b/Mage.Sets/src/mage/cards/u/UneshCriosphinxSovereign.java @@ -98,7 +98,7 @@ class UneshCriosphinxSovereignTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null - && permanent.getOwnerId().equals(controllerId) + && permanent.isOwnedBy(controllerId) && permanent.isCreature() && (event.getTargetId().equals(getSourceId()) || filter.match(permanent, game))) { return true; diff --git a/Mage.Sets/src/mage/cards/u/UnexpectedlyAbsent.java b/Mage.Sets/src/mage/cards/u/UnexpectedlyAbsent.java index 3db22ac3366..2fadc33bd9b 100644 --- a/Mage.Sets/src/mage/cards/u/UnexpectedlyAbsent.java +++ b/Mage.Sets/src/mage/cards/u/UnexpectedlyAbsent.java @@ -1,4 +1,3 @@ - package mage.cards.u; import java.util.UUID; @@ -61,7 +60,7 @@ class UnexpectedlyAbsentEffect extends OneShotEffect { if (controller != null) { Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (permanent != null) { - controller.putCardOnTopXOfLibrary(permanent, game, source, source.getManaCostsToPay().getX()); + controller.putCardOnTopXOfLibrary(permanent, game, source, source.getManaCostsToPay().getX() + 1); return true; } } diff --git a/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java b/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java index 28b2044fe92..ad473951440 100644 --- a/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java +++ b/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java @@ -8,7 +8,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.OrCondition; import mage.abilities.condition.common.CardsInControllerGraveCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; import mage.abilities.effects.common.TapEnchantedEffect; @@ -52,7 +52,7 @@ public final class UnquenchableThirst extends CardImpl { this.addAbility(ability); // When Unquenchable Thirst enters the battlefield, if you control a Desert or there is a Desert card in your graveyard, tap enchanted creature. - Ability ability2 = new ConditionalTriggeredAbility( + Ability ability2 = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()), new OrCondition( new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(filterDesertPermanent)), diff --git a/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java b/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java index 9372d887440..99bf8748627 100644 --- a/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java +++ b/Mage.Sets/src/mage/cards/u/UnstableShapeshifter.java @@ -40,7 +40,7 @@ public final class UnstableShapeshifter extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(1); - // Whenever another creature enters the battlefield, Unstable Shapeshifter becomes a copy of that creature and gains this ability. + // Whenever another creature enters the battlefield, Unstable Shapeshifter becomes a copy of that creature, except it has this ability. this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new UnstableShapeshifterEffect(), filterAnotherCreature, false, SetTargetPointer.PERMANENT, "")); } @@ -58,7 +58,7 @@ class UnstableShapeshifterEffect extends OneShotEffect { public UnstableShapeshifterEffect() { super(Outcome.Copy); - this.staticText = "{this} becomes a copy of that creature and gains this ability"; + this.staticText = "{this} becomes a copy of that creature, except it has this ability"; } public UnstableShapeshifterEffect(final UnstableShapeshifterEffect effect) { diff --git a/Mage.Sets/src/mage/cards/u/UnwindingClock.java b/Mage.Sets/src/mage/cards/u/UnwindingClock.java index 51f5f1d1b28..4c0b8767398 100644 --- a/Mage.Sets/src/mage/cards/u/UnwindingClock.java +++ b/Mage.Sets/src/mage/cards/u/UnwindingClock.java @@ -67,7 +67,7 @@ class UnwindingClockEffect extends ContinuousEffectImpl { applied = Boolean.FALSE; } if (!applied && layer == Layer.RulesEffects) { - if (!game.getActivePlayerId().equals(source.getControllerId()) && game.getStep().getType() == PhaseStep.UNTAP) { + if (!game.isActivePlayer(source.getControllerId()) && game.getStep().getType() == PhaseStep.UNTAP) { game.getState().setValue(source.getSourceId() + "applied", true); for (Permanent artifact : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { boolean untap = true; diff --git a/Mage.Sets/src/mage/cards/u/Upheaval.java b/Mage.Sets/src/mage/cards/u/Upheaval.java index 15f24635780..d47a07961fe 100644 --- a/Mage.Sets/src/mage/cards/u/Upheaval.java +++ b/Mage.Sets/src/mage/cards/u/Upheaval.java @@ -1,4 +1,3 @@ - package mage.cards.u; import java.util.UUID; @@ -6,23 +5,19 @@ import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; /** * * @author cbt33 */ - public final class Upheaval extends CardImpl { - - private static final FilterPermanent filter = new FilterPermanent("permanents"); public Upheaval(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{U}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}{U}"); // Return all permanents to their owners' hands. - this.getSpellAbility().addEffect(new ReturnToHandFromBattlefieldAllEffect(filter)); + this.getSpellAbility().addEffect(new ReturnToHandFromBattlefieldAllEffect(StaticFilters.FILTER_PERMANENT)); } public Upheaval(final Upheaval card) { diff --git a/Mage.Sets/src/mage/cards/u/UpsilonClassShuttle.java b/Mage.Sets/src/mage/cards/u/UpsilonClassShuttle.java new file mode 100644 index 00000000000..1fc560a5845 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UpsilonClassShuttle.java @@ -0,0 +1,50 @@ +package mage.cards.u; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.SpaceflightAbility; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class UpsilonClassShuttle extends CardImpl { + + public UpsilonClassShuttle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + + this.subtype.add(SubType.STARSHIP); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Spaceflight + this.addAbility(SpaceflightAbility.getInstance()); + + // Whenever Upsilon-class Shuttle attacks, target creature you control gains spaceflight until end of turn. + Ability ability = new AttacksTriggeredAbility( + new GainAbilityTargetEffect(SpaceflightAbility.getInstance(), Duration.EndOfTurn) + .setText("target creature you control gains spaceflight until end of turn"), + false); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public UpsilonClassShuttle(final UpsilonClassShuttle card) { + super(card); + } + + @Override + public UpsilonClassShuttle copy() { + return new UpsilonClassShuttle(this); + } +} diff --git a/Mage.Sets/src/mage/cards/u/Upwelling.java b/Mage.Sets/src/mage/cards/u/Upwelling.java index 16ad1b7dd10..b5711a62121 100644 --- a/Mage.Sets/src/mage/cards/u/Upwelling.java +++ b/Mage.Sets/src/mage/cards/u/Upwelling.java @@ -46,7 +46,7 @@ class UpwellingRuleEffect extends ContinuousEffectImpl { public UpwellingRuleEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "Players don’t lose unspent mana as steps and phases end"; + staticText = "Players don't lose unspent mana as steps and phases end"; } public UpwellingRuleEffect(final UpwellingRuleEffect effect) { diff --git a/Mage.Sets/src/mage/cards/u/UrbanBurgeoning.java b/Mage.Sets/src/mage/cards/u/UrbanBurgeoning.java index bc55f6d0cb7..2b9c1d2c91d 100644 --- a/Mage.Sets/src/mage/cards/u/UrbanBurgeoning.java +++ b/Mage.Sets/src/mage/cards/u/UrbanBurgeoning.java @@ -82,7 +82,7 @@ class UrbanBurgeoningUntapEffect extends ContinuousEffectImpl { applied = Boolean.FALSE; } if (!applied && layer == Layer.RulesEffects) { - if (!game.getActivePlayerId().equals(source.getControllerId()) && game.getStep().getType() == PhaseStep.UNTAP) { + if (!game.isActivePlayer(source.getControllerId()) && game.getStep().getType() == PhaseStep.UNTAP) { game.getState().setValue(source.getSourceId() + "applied", true); Permanent land = game.getPermanent(source.getSourceId()); boolean untap = true; diff --git a/Mage.Sets/src/mage/cards/u/UrborgEmissary.java b/Mage.Sets/src/mage/cards/u/UrborgEmissary.java index 8673b2edef9..20873c51501 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgEmissary.java +++ b/Mage.Sets/src/mage/cards/u/UrborgEmissary.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class UrborgEmissary extends CardImpl { // When Urborg Emissary enters the battlefield, if it was kicked, return target permanent to its owner's hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); ability.addTarget(new TargetPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, return target permanent to its owner's hand.")); } diff --git a/Mage.Sets/src/mage/cards/u/UrborgStalker.java b/Mage.Sets/src/mage/cards/u/UrborgStalker.java index bd1df9da677..45c70884470 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgStalker.java +++ b/Mage.Sets/src/mage/cards/u/UrborgStalker.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -41,7 +41,7 @@ public final class UrborgStalker extends CardImpl { this.toughness = new MageInt(4); // At the beginning of each player's upkeep, if that player controls a nonblack, nonland permanent, Urborg Stalker deals 1 damage to that player. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(1), TargetController.ANY, false), new PermanentsOnTheBattlefieldCondition(filter), "At the beginning of each player's upkeep, " diff --git a/Mage.Sets/src/mage/cards/u/UrsineChampion.java b/Mage.Sets/src/mage/cards/u/UrsineChampion.java new file mode 100644 index 00000000000..32847388d8e --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UrsineChampion.java @@ -0,0 +1,104 @@ +package mage.cards.u; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.constants.SubType; +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.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class UrsineChampion extends CardImpl { + + public UrsineChampion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.BERSERKER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {5}{G}: Ursine Champion gets +3/+3 and becomes a Bear Berserker until end of turn. Activate this ability only once each turn. + Ability ability = new LimitedTimesPerTurnActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(3, 3, Duration.EndOfTurn) + .setText("{this} gets +3/+3"), + new ManaCostsImpl("{5}{G}") + ); + ability.addEffect(new UrsineChampionEffect()); + this.addAbility(ability); + } + + public UrsineChampion(final UrsineChampion card) { + super(card); + } + + @Override + public UrsineChampion copy() { + return new UrsineChampion(this); + } + + private class UrsineChampionEffect extends ContinuousEffectImpl { + + public UrsineChampionEffect() { + super(Duration.EndOfTurn, Outcome.BecomeCreature); + setText(); + } + + public UrsineChampionEffect(final UrsineChampionEffect effect) { + super(effect); + } + + @Override + public UrsineChampionEffect copy() { + return new UrsineChampionEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + return false; + } + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.getSubtype(game).clear(); + permanent.getSubtype(game).add(SubType.BEAR); + permanent.getSubtype(game).add(SubType.BERSERKER); + } + break; + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + private void setText() { + staticText = "and becomes a Bear Berserker until end of turn"; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4; + } + } +} diff --git a/Mage.Sets/src/mage/cards/u/UrzasRage.java b/Mage.Sets/src/mage/cards/u/UrzasRage.java index 67f12a6ace7..fc7def033c2 100644 --- a/Mage.Sets/src/mage/cards/u/UrzasRage.java +++ b/Mage.Sets/src/mage/cards/u/UrzasRage.java @@ -28,9 +28,9 @@ public final class UrzasRage extends CardImpl { // Kicker {8}{R} this.addAbility(new KickerAbility("{8}{R}")); - // Urza's Rage can't be countered by spells or abilities. + // Urza's Rage can't be countered. Effect effect = new CantBeCounteredSourceEffect(); - effect.setText("{this} can't be countered by spells or abilities"); + effect.setText("this spell can't be countered"); Ability ability = new SimpleStaticAbility(Zone.STACK, effect); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/u/UrzasRuinousBlast.java b/Mage.Sets/src/mage/cards/u/UrzasRuinousBlast.java index b0e6b9cd20e..969569b7436 100644 --- a/Mage.Sets/src/mage/cards/u/UrzasRuinousBlast.java +++ b/Mage.Sets/src/mage/cards/u/UrzasRuinousBlast.java @@ -19,7 +19,7 @@ import mage.filter.predicate.mageobject.SupertypePredicate; */ public final class UrzasRuinousBlast extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("nonland permanents that aren’t legendary"); + private static final FilterPermanent filter = new FilterPermanent("nonland permanents that aren't legendary"); static { filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); @@ -33,7 +33,7 @@ public final class UrzasRuinousBlast extends CardImpl { // (You may cast a legendary sorcery only if you control a legendary creature or planeswalker.) this.addAbility(new LegendarySpellAbility()); - // Exile all nonland permanents that aren’t legendary. + // Exile all nonland permanents that aren't legendary. this.getSpellAbility().addEffect(new ExileAllEffect(filter)); } diff --git a/Mage.Sets/src/mage/cards/u/UyoSilentProphet.java b/Mage.Sets/src/mage/cards/u/UyoSilentProphet.java index ba2429ea932..2ff47b385a5 100644 --- a/Mage.Sets/src/mage/cards/u/UyoSilentProphet.java +++ b/Mage.Sets/src/mage/cards/u/UyoSilentProphet.java @@ -40,7 +40,7 @@ public final class UyoSilentProphet extends CardImpl { // {2}, Return two lands you control to their owner's hand: Copy target instant or sorcery spell. You may choose new targets for the copy. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CopyTargetSpellEffect(), new GenericManaCost(2)); ability.addCost(new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("lands"), false))); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VadersCommand.java b/Mage.Sets/src/mage/cards/v/VadersCommand.java new file mode 100644 index 00000000000..d9facdc1ba9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VadersCommand.java @@ -0,0 +1,74 @@ +package mage.cards.v; + +import java.util.UUID; + +import mage.abilities.Mode; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +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.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; +import mage.target.TargetSpell; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class VadersCommand extends CardImpl { + + private static final FilterPermanent filterPlaneswalker = new FilterPermanent("planeswalker"); + private static final FilterCreaturePermanent filterNonArtifact = new FilterCreaturePermanent("nonartifact creature"); + + static { + filterPlaneswalker.add(new CardTypePredicate(CardType.PLANESWALKER)); + filterNonArtifact.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT))); + } + + public VadersCommand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}{B}"); + + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + + // Counter target spell unless its controller pays 5 life. + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new PayLifeCost(5)) + .setText("Counter target spell unless its controller pays 5 life")); + this.getSpellAbility().addTarget(new TargetSpell()); + + // Destroy target planeswalker. + Mode mode = new Mode(); + mode.getEffects().add(new DestroyTargetEffect()); + mode.getTargets().add(new TargetPermanent(filterPlaneswalker)); + this.getSpellAbility().addMode(mode); + + // Destroy target nonartifact creature. + mode = new Mode(); + mode.getEffects().add(new DestroyTargetEffect()); + mode.getTargets().add(new TargetCreaturePermanent(filterNonArtifact)); + this.getSpellAbility().addMode(mode); + + // Gain 5 life. + mode = new Mode(); + mode.getEffects().add(new GainLifeEffect(5).setText("Gain 5 life")); + this.getSpellAbility().addMode(mode); + } + + public VadersCommand(final VadersCommand card) { + super(card); + } + + @Override + public VadersCommand copy() { + return new VadersCommand(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VaevictisAsmadiTheDire.java b/Mage.Sets/src/mage/cards/v/VaevictisAsmadiTheDire.java new file mode 100644 index 00000000000..70cdd363794 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VaevictisAsmadiTheDire.java @@ -0,0 +1,160 @@ +package mage.cards.v; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.OneShotEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +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.FilterPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class VaevictisAsmadiTheDire extends CardImpl { + + public VaevictisAsmadiTheDire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever Vaevictis Asmadi, the Dire attacks, for each player, choose target permanent that player controls. Those players sacrifice those permanents. Each player who sacrificed a permanent this way reveals the top card of their library, then puts it onto the battlefield if it's a permanent card. + this.addAbility(new VaevictisAsmadiTheDireTriggeredAbility()); + } + + public VaevictisAsmadiTheDire(final VaevictisAsmadiTheDire card) { + super(card); + } + + @Override + public VaevictisAsmadiTheDire copy() { + return new VaevictisAsmadiTheDire(this); + } +} + +class VaevictisAsmadiTheDireTriggeredAbility extends TriggeredAbilityImpl { + + public VaevictisAsmadiTheDireTriggeredAbility() { + super(Zone.BATTLEFIELD, new VaevictisAsmadiTheDireEffect(), false); + } + + public VaevictisAsmadiTheDireTriggeredAbility(final VaevictisAsmadiTheDireTriggeredAbility ability) { + super(ability); + } + + @Override + public VaevictisAsmadiTheDireTriggeredAbility copy() { + return new VaevictisAsmadiTheDireTriggeredAbility(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.getCombat().getAttackers().contains(this.getSourceId())) { + return false; + } + this.getTargets().clear(); + for (UUID playerId : game.getState().getPlayerList(this.getControllerId())) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + FilterPermanent filter = new FilterPermanent("permanent controlled by " + player.getName()); + filter.add(new ControllerIdPredicate(playerId)); + TargetPermanent target = new TargetPermanent(filter); + this.addTarget(target); + } + return true; + } + + @Override + public String getRule() { + return "Whenever {this} attacks, for each player, " + + "choose target permanent that player controls. " + + "Those players sacrifice those permanents. " + + "Each player who sacrificed a permanent this way reveals the top card of their library, " + + "then puts it onto the battlefield if it's a permanent card"; + } +} + +class VaevictisAsmadiTheDireEffect extends OneShotEffect { + + public VaevictisAsmadiTheDireEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "for each player, choose target permanent that player controls. " + + "Those players sacrifice those permanents. " + + "Each player who sacrificed a permanent this way reveals the top card of their library, " + + "then puts it onto the battlefield if it's a permanent card"; + } + + public VaevictisAsmadiTheDireEffect(final VaevictisAsmadiTheDireEffect effect) { + super(effect); + } + + @Override + public VaevictisAsmadiTheDireEffect copy() { + return new VaevictisAsmadiTheDireEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + List playersToFlip = new ArrayList(); + for (Target target : source.getTargets()) { + for (UUID permId : target.getTargets()) { + Permanent permanent = game.getPermanent(permId); + if (permanent == null + || !permanent.sacrifice(source.getSourceId(), game)) { + continue; + } + Player player = game.getPlayer(permanent.getControllerId()); + if (player != null) { + playersToFlip.add(player); + } + } + } + for (Player player : playersToFlip) { + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + continue; + } + player.revealCards(source, new CardsImpl(card), game); + if (card.isPermanent()) { + player.moveCards(card, Zone.BATTLEFIELD, source, game); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/v/ValakutTheMoltenPinnacle.java b/Mage.Sets/src/mage/cards/v/ValakutTheMoltenPinnacle.java index 85ceb9e6644..be270c64770 100644 --- a/Mage.Sets/src/mage/cards/v/ValakutTheMoltenPinnacle.java +++ b/Mage.Sets/src/mage/cards/v/ValakutTheMoltenPinnacle.java @@ -80,7 +80,7 @@ class ValakutTheMoltenPinnacleTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.isLand() && permanent.getControllerId().equals(this.getControllerId())) { + if (permanent != null && permanent.isLand() && permanent.isControlledBy(this.getControllerId())) { if (permanent.hasSubtype(SubType.MOUNTAIN, game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/v/ValeronWardens.java b/Mage.Sets/src/mage/cards/v/ValeronWardens.java index 905fbed1c20..e2d71a168f1 100644 --- a/Mage.Sets/src/mage/cards/v/ValeronWardens.java +++ b/Mage.Sets/src/mage/cards/v/ValeronWardens.java @@ -69,7 +69,7 @@ class ValeronWardensTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - return permanent != null && permanent.getControllerId().equals(getControllerId()); + return permanent != null && permanent.isControlledBy(getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/v/ValiantKnight.java b/Mage.Sets/src/mage/cards/v/ValiantKnight.java new file mode 100644 index 00000000000..c3bcedc7ded --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/ValiantKnight.java @@ -0,0 +1,62 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class ValiantKnight extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent(SubType.KNIGHT, "Knights you control"); + + public ValiantKnight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Other Knights you control get +1/+1. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, + filter, true + ) + )); + + // {3}{W}{W}: Knights you control gain double strike until end of turn. + this.addAbility(new SimpleActivatedAbility( + new GainAbilityControlledEffect( + DoubleStrikeAbility.getInstance(), + Duration.EndOfTurn, filter + ), new ManaCostsImpl("{3}{W}{W}") + )); + } + + public ValiantKnight(final ValiantKnight card) { + super(card); + } + + @Override + public ValiantKnight copy() { + return new ValiantKnight(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VampireNeonate.java b/Mage.Sets/src/mage/cards/v/VampireNeonate.java new file mode 100644 index 00000000000..d679819b791 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VampireNeonate.java @@ -0,0 +1,47 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class VampireNeonate extends CardImpl { + + public VampireNeonate(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // {2}, {T}: Each opponent loses 1 life and you gain 1 life. + Ability ability = new SimpleActivatedAbility( + new LoseLifeOpponentsEffect(1), + new GenericManaCost(2) + ); + ability.addCost(new TapSourceCost()); + ability.addEffect(new GainLifeEffect(1).setText("and you gain 1 life")); + this.addAbility(ability); + } + + public VampireNeonate(final VampireNeonate card) { + super(card); + } + + @Override + public VampireNeonate copy() { + return new VampireNeonate(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VampireSovereign.java b/Mage.Sets/src/mage/cards/v/VampireSovereign.java new file mode 100644 index 00000000000..1cfbfe42b60 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VampireSovereign.java @@ -0,0 +1,47 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetOpponent; + +/** + * + * @author TheElk801 + */ +public final class VampireSovereign extends CardImpl { + + public VampireSovereign(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + + this.subtype.add(SubType.VAMPIRE); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Vampire Sovereign enters the battlefield, target opponent loses 3 life and you gain 3 life. + Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(3)); + ability.addEffect(new GainLifeEffect(3).setText("and you gain 3 life")); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public VampireSovereign(final VampireSovereign card) { + super(card); + } + + @Override + public VampireSovereign copy() { + return new VampireSovereign(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java index b57f1eed130..c29c57a9a21 100644 --- a/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java +++ b/Mage.Sets/src/mage/cards/v/VancesBlastingCannons.java @@ -120,7 +120,7 @@ class CastFromNonHandZoneTargetEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { if (getTargetPointer().getTargets(game, source).contains(objectId) - && source.getControllerId().equals(affectedControllerId)) { + && source.isControlledBy(affectedControllerId)) { Card card = game.getCard(objectId); if (card != null) { return true; diff --git a/Mage.Sets/src/mage/cards/v/VanquishersBanner.java b/Mage.Sets/src/mage/cards/v/VanquishersBanner.java index 327fef11cf4..87a0cc004f9 100644 --- a/Mage.Sets/src/mage/cards/v/VanquishersBanner.java +++ b/Mage.Sets/src/mage/cards/v/VanquishersBanner.java @@ -87,7 +87,7 @@ class DrawCardIfCreatureTypeAbility extends TriggeredAbilityImpl { if (spell != null && spell.isCreature() && spell.hasSubtype(subType, game) - && spell.getControllerId().equals(getControllerId())) { + && spell.isControlledBy(getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VarchildBetrayerOfKjeldor.java b/Mage.Sets/src/mage/cards/v/VarchildBetrayerOfKjeldor.java new file mode 100644 index 00000000000..4aafbd08c86 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VarchildBetrayerOfKjeldor.java @@ -0,0 +1,117 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.combat.CantAttackYouOrPlaneswalkerAllEffect; +import mage.abilities.effects.common.combat.CantBlockAllEffect; +import mage.abilities.effects.common.continuous.GainControlAllEffect; +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.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.token.SurvivorToken; + +/** + * + * @author TheElk801 + */ +public final class VarchildBetrayerOfKjeldor extends CardImpl { + + private static final FilterCreaturePermanent filter1 + = new FilterCreaturePermanent( + SubType.SURVIVOR, + "Survivors your opponents control" + ); + private static final FilterCreaturePermanent filter2 + = new FilterCreaturePermanent( + SubType.SURVIVOR, "all Survivors" + ); + + static { + filter1.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public VarchildBetrayerOfKjeldor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever Varchild, Betrayer of Kjeldor deals combat damage to a player, that player creates that many 1/1 red Survivor creature tokens. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new VarchildBetrayerOfKjeldorEffect(), false, true + )); + + // Survivors your opponents control can't block, and they can't attack you or a planeswalker you control. + Ability ability = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBlockAllEffect( + filter1, Duration.WhileOnBattlefield + ) + ); + ability.addEffect(new CantAttackYouOrPlaneswalkerAllEffect( + Duration.WhileOnBattlefield, filter1 + ).setText("and can't attack you or a planeswalker you control")); + this.addAbility(ability); + + // When Varchild leaves the battlefield, gain control of all Survivors. + this.addAbility(new LeavesBattlefieldTriggeredAbility( + new GainControlAllEffect(Duration.Custom, filter2), false + )); + } + + public VarchildBetrayerOfKjeldor(final VarchildBetrayerOfKjeldor card) { + super(card); + } + + @Override + public VarchildBetrayerOfKjeldor copy() { + return new VarchildBetrayerOfKjeldor(this); + } +} + +class VarchildBetrayerOfKjeldorEffect extends OneShotEffect { + + public VarchildBetrayerOfKjeldorEffect() { + super(Outcome.Benefit); + this.staticText = "that player creates " + + "that many 1/1 red Survivor creature tokens"; + } + + public VarchildBetrayerOfKjeldorEffect(final VarchildBetrayerOfKjeldorEffect effect) { + super(effect); + } + + @Override + public VarchildBetrayerOfKjeldorEffect copy() { + return new VarchildBetrayerOfKjeldorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int damage = (int) this.getValue("damage"); + if (damage > 0) { + return new CreateTokenEffect( + new SurvivorToken(), damage + ).apply(game, source); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VarinaLichQueen.java b/Mage.Sets/src/mage/cards/v/VarinaLichQueen.java new file mode 100644 index 00000000000..514473cd7be --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VarinaLichQueen.java @@ -0,0 +1,117 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExileFromGraveCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ZombieToken; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author TheElk801 + */ +public final class VarinaLichQueen extends CardImpl { + + public VarinaLichQueen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ZOMBIE); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever you attack with one or more Zombies, draw that many cards, then discard that many cards. You gain that much life. + this.addAbility(new VarinaLichQueenTriggeredAbility()); + + // {2}, Exile two cards from your graveyard: Create a tapped 2/2 black Zombie creature token. + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new CreateTokenEffect( + new ZombieToken(), + 1, true, false + ), new GenericManaCost(2) + ); + ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard( + 2, new FilterCard("cards from your graveyard") + ))); + this.addAbility(ability); + } + + public VarinaLichQueen(final VarinaLichQueen card) { + super(card); + } + + @Override + public VarinaLichQueen copy() { + return new VarinaLichQueen(this); + } +} + +class VarinaLichQueenTriggeredAbility extends TriggeredAbilityImpl { + + public VarinaLichQueenTriggeredAbility() { + super(Zone.BATTLEFIELD, null, false); + } + + public VarinaLichQueenTriggeredAbility(final VarinaLichQueenTriggeredAbility ability) { + super(ability); + } + + @Override + public VarinaLichQueenTriggeredAbility copy() { + return new VarinaLichQueenTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + int attackingZombies = 0; + for (UUID attacker : game.getCombat().getAttackers()) { + Permanent creature = game.getPermanent(attacker); + if (creature != null + && creature.getControllerId() != null + && creature.isControlledBy(this.getControllerId()) + && creature.hasSubtype(SubType.ZOMBIE, game)) { + attackingZombies++; + } + } + if (attackingZombies > 0) { + this.getEffects().clear(); + addEffect(new DrawCardSourceControllerEffect(attackingZombies)); + addEffect(new DiscardControllerEffect(attackingZombies, false)); + addEffect(new GainLifeEffect(attackingZombies)); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever you attack with one or more Zombies, " + + "draw that many cards, then discard that many cards. " + + "You gain that much life."; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java b/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java index 2e590c66e38..afa85439ab1 100644 --- a/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java +++ b/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java @@ -43,7 +43,7 @@ public final class VedalkenCertarch extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // Metalcraft - {T}: Tap target artifact, creature, or land. Activate this ability only if you control three or more artifacts. + // Metalcraft — {T}: Tap target artifact, creature, or land. Activate this ability only if you control three or more artifacts. Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost(), MetalcraftCondition.instance); ability.setAbilityWord(AbilityWord.METALCRAFT); ability.addTarget(new TargetPermanent(filter)); diff --git a/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java b/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java new file mode 100644 index 00000000000..9997b830b2d --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java @@ -0,0 +1,61 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.condition.common.MetalcraftCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.continuous.LoseAllAbilitiesAllEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; + +/** + * + * @author TheElk801 + */ +public final class VedalkenHumiliator extends CardImpl { + + public VedalkenHumiliator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.VEDALKEN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Metalcraft — Whenever Vedalken Humiliator attacks, if you control three or more artifacts, creatures your opponents control lose all abilities and have base power and toughness 1/1 until end of turn. + TriggeredAbility ability = new AttacksTriggeredAbility( + new SetPowerToughnessAllEffect( + 1, 1, Duration.EndOfTurn, + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, + true + ), false + ); + ability.addEffect(new LoseAllAbilitiesAllEffect( + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, + Duration.EndOfTurn + )); + this.addAbility(new ConditionalTriggeredAbility( + ability, MetalcraftCondition.instance, + "Metalcraft — Whenever {this} attacks, " + + "if you control three or more artifacts, " + + "creatures your opponents control lose all abilities " + + "and have base power and toughness 1/1 until end of turn." + )); + } + + public VedalkenHumiliator(final VedalkenHumiliator card) { + super(card); + } + + @Override + public VedalkenHumiliator copy() { + return new VedalkenHumiliator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeilstoneAmulet.java b/Mage.Sets/src/mage/cards/v/VeilstoneAmulet.java index 9d8b3643944..b08a759db3c 100644 --- a/Mage.Sets/src/mage/cards/v/VeilstoneAmulet.java +++ b/Mage.Sets/src/mage/cards/v/VeilstoneAmulet.java @@ -72,7 +72,7 @@ class VeilstoneAmuletEffect extends ContinuousRuleModifyingEffectImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { if (permanent.isCreature() && - permanent.getControllerId().equals(ability.getControllerId()) && + permanent.isControlledBy(ability.getControllerId()) && game.getPlayer(ability.getControllerId()).hasOpponent(event.getPlayerId(), game)) { return true; } diff --git a/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java b/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java index a1e545299ff..25d66d6245b 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java +++ b/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java @@ -109,7 +109,7 @@ class VengefulPharaohTriggeredAbility extends TriggeredAbilityImpl { } if (event.getType() == EventType.DAMAGED_PLANESWALKER && ((DamagedEvent) event).isCombatDamage()) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(this.getControllerId())) { + if (permanent != null && permanent.isControlledBy(this.getControllerId())) { if (!game.getPhase().getStep().equals(stepTriggeredPlansewalker) || game.getTurnNum() != turnTriggeredPlaneswalker) { stepTriggeredPlansewalker = game.getPhase().getStep(); turnTriggeredPlaneswalker = game.getTurnNum(); diff --git a/Mage.Sets/src/mage/cards/v/VengefulRebel.java b/Mage.Sets/src/mage/cards/v/VengefulRebel.java index d3116ace195..49f44e1623e 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulRebel.java +++ b/Mage.Sets/src/mage/cards/v/VengefulRebel.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevoltCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -33,7 +33,7 @@ public final class VengefulRebel extends CardImpl { // Revolt — When Vengeful Rebel enters the battlefield, if a permanent you controlled left the battlefield this turn, // target creature an opponent controls gets -3/-3 until end of turn. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn), false), RevoltCondition.instance, "When {this} enters the battlefield, if a permanent you controlled left the battlefield this turn, " diff --git a/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java b/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java index bd9b20228fb..f5c35c82239 100644 --- a/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java +++ b/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java @@ -40,7 +40,7 @@ public final class VenomspoutBrackus extends CardImpl { this.toughness = new MageInt(5); // {1}{G}, {tap}: Venomspout Brackus deals 5 damage to target attacking or blocking creature with flying. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}{G}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(5), new ManaCostsImpl("{1}{G}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/v/VentifactBottle.java b/Mage.Sets/src/mage/cards/v/VentifactBottle.java index 4b43ff6b8b6..92e69ef6516 100644 --- a/Mage.Sets/src/mage/cards/v/VentifactBottle.java +++ b/Mage.Sets/src/mage/cards/v/VentifactBottle.java @@ -10,7 +10,7 @@ import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -42,7 +42,7 @@ public final class VentifactBottle extends CardImpl { this.addAbility(ability); // At the beginning of your precombat main phase, if Ventifact Bottle has a charge counter on it, tap it and remove all charge counters from it. Add {C} for each charge counter removed this way. TriggeredAbility ability2 = new BeginningOfPreCombatMainTriggeredAbility(new VentifactBottleEffect(), TargetController.YOU, false); - this.addAbility(new ConditionalTriggeredAbility(ability2, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new SourceHasCounterCondition(CounterType.CHARGE, 1, Integer.MAX_VALUE), "At the beginning of your precombat main phase, " + "if {this} has a charge counter on it, tap it and remove all charge counters from it. " diff --git a/Mage.Sets/src/mage/cards/v/VerdantSunsAvatar.java b/Mage.Sets/src/mage/cards/v/VerdantSunsAvatar.java index 65c86cf7d69..130a1948602 100644 --- a/Mage.Sets/src/mage/cards/v/VerdantSunsAvatar.java +++ b/Mage.Sets/src/mage/cards/v/VerdantSunsAvatar.java @@ -66,7 +66,7 @@ class VerdantSunsAvatarTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature() - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { Effect effect = this.getEffects().get(0); // Life is determined during resolution so it has to be retrieved there (e.g. Giant Growth before resolution) effect.setValue("lifeSource", event.getTargetId()); diff --git a/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java b/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java index 5f810d301ef..33099a79cdc 100644 --- a/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java +++ b/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; @@ -53,7 +53,7 @@ public final class VerdelothTheAncient extends CardImpl { // When Verdeloth the Ancient enters the battlefield, if it was kicked, create X 1/1 green Saproling creature tokens. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SaprolingToken(), new GetKickerXValue()), false); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, create X 1/1 green Saproling creature tokens.")); } diff --git a/Mage.Sets/src/mage/cards/v/VerduranEmissary.java b/Mage.Sets/src/mage/cards/v/VerduranEmissary.java index 0579f6049a4..2ced42e40a8 100644 --- a/Mage.Sets/src/mage/cards/v/VerduranEmissary.java +++ b/Mage.Sets/src/mage/cards/v/VerduranEmissary.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -34,7 +34,7 @@ public final class VerduranEmissary extends CardImpl { // When {this} enters the battlefield, if it was kicked, destroy target artifact. It can't be regenerated. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); ability.addTarget(new TargetArtifactPermanent()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, destroy target artifact. It can't be regenerated.")); } diff --git a/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java b/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java index e52d2b2506b..540626721f1 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanDoppelganger.java @@ -30,7 +30,7 @@ import mage.util.functions.ApplyToPermanent; */ public final class VesuvanDoppelganger extends CardImpl { - private static final String rule = "You may have {this} enter the battlefield as a copy of any creature on the battlefield except it doesn't copy that creature's color and it gains \"At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability.\""; + private static final String rule = "You may have {this} enter the battlefield as a copy of any creature on the battlefield except it doesn't copy that creature's color and it has \"At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color and it has this ability.\""; public VesuvanDoppelganger(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); @@ -38,7 +38,7 @@ public final class VesuvanDoppelganger extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - // You may have Vesuvan Doppelganger enter the battlefield as a copy of any creature on the battlefield except it doesn't copy that creature's color and it gains "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability." + // You may have Vesuvan Doppelganger enter the battlefield as a copy of any creature on the battlefield except it doesn't copy that creature's color and it has "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color and it has this ability." Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new VesuvanDoppelgangerCopyEffect(), rule, true)); this.addAbility(ability); @@ -56,7 +56,7 @@ public final class VesuvanDoppelganger extends CardImpl { class VesuvanDoppelgangerCopyEffect extends OneShotEffect { - private static final String rule2 = "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability."; + private static final String rule2 = "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color and it has this ability."; public VesuvanDoppelgangerCopyEffect() { super(Outcome.Copy); diff --git a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java index 3e3124ca825..404b0334c3a 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java @@ -58,7 +58,7 @@ public final class VesuvanShapeshifter extends CardImpl { ability.setWorksFaceDown(false); this.addAbility(ability); - // and gains "At the beginning of your upkeep, you may turn this creature face down". + // and has "At the beginning of your upkeep, you may turn this creature face down". effect = new VesuvanShapeshifterFaceDownEffect(); ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.YOU, true); this.addAbility(ability); @@ -102,7 +102,7 @@ class VesuvanShapeshifterEffect extends OneShotEffect { public VesuvanShapeshifterEffect() { super(Outcome.Copy); - staticText = "have {this} become a copy of a creature and gain this ability"; + staticText = "have {this} become a copy of a creature, except it has this ability"; } public VesuvanShapeshifterEffect(final VesuvanShapeshifterEffect effect) { diff --git a/Mage.Sets/src/mage/cards/v/VexingShusher.java b/Mage.Sets/src/mage/cards/v/VexingShusher.java index 357370080ff..a4a58098a46 100644 --- a/Mage.Sets/src/mage/cards/v/VexingShusher.java +++ b/Mage.Sets/src/mage/cards/v/VexingShusher.java @@ -37,7 +37,7 @@ public final class VexingShusher extends CardImpl { // Vexing Shusher can't be countered. this.addAbility(new CantBeCounteredAbility()); - // {R/G}: Target spell can't be countered by spells or abilities. + // {R/G}: Target spell can't be countered. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VexingShusherCantCounterTargetEffect(), new ManaCostsImpl("{R/G}")); ability.addTarget(new TargetSpell()); this.addAbility(ability); @@ -57,7 +57,7 @@ class VexingShusherCantCounterTargetEffect extends ContinuousRuleModifyingEffect public VexingShusherCantCounterTargetEffect() { super(Duration.EndOfTurn, Outcome.Benefit); - staticText = "Target spell can't be countered by spells or abilities"; + staticText = "Target spell can't be countered"; } public VexingShusherCantCounterTargetEffect(final VexingShusherCantCounterTargetEffect effect) { @@ -78,7 +78,7 @@ class VexingShusherCantCounterTargetEffect extends ContinuousRuleModifyingEffect public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject sourceObject = game.getObject(source.getSourceId()); if (sourceObject != null) { - return "This spell can't be countered by spells or abilities (" + sourceObject.getName() + ")."; + return "This spell can't be countered (" + sourceObject.getName() + ")."; } return null; } diff --git a/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java b/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java index 09c5603dce7..2f6d1d3d3f7 100644 --- a/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java +++ b/Mage.Sets/src/mage/cards/v/VialSmasherTheFierce.java @@ -98,7 +98,7 @@ class VialSmasherTheFierceTriggeredAbility extends SpellCastControllerTriggeredA @Override public String getRule() { return "Whenever you cast your first spell each turn, choose an opponent at random. " - + "{this} deals damage equal to that spell’s converted mana cost to that player or a planeswalker that player controls"; + + "{this} deals damage equal to that spell's converted mana cost to that player or a planeswalker that player controls"; } } @@ -106,7 +106,7 @@ class VialSmasherTheFierceEffect extends OneShotEffect { public VialSmasherTheFierceEffect() { super(Outcome.Damage); - this.staticText = "{this} choose an opponent at random. {this} deals damage equal to that spell’s converted mana cost to that player or a planeswalker that player controls"; + this.staticText = "{this} choose an opponent at random. {this} deals damage equal to that spell's converted mana cost to that player or a planeswalker that player controls"; } public VialSmasherTheFierceEffect(final VialSmasherTheFierceEffect effect) { diff --git a/Mage.Sets/src/mage/cards/v/ViashinoPyromancer.java b/Mage.Sets/src/mage/cards/v/ViashinoPyromancer.java new file mode 100644 index 00000000000..d4f6c457168 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/ViashinoPyromancer.java @@ -0,0 +1,42 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetPlayerOrPlaneswalker; + +/** + * + * @author TheElk801 + */ +public final class ViashinoPyromancer extends CardImpl { + + public ViashinoPyromancer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // When Viashino Pyromancer enters the battlefield, it deals 2 damage to target player or planeswalker. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)); + ability.addTarget(new TargetPlayerOrPlaneswalker()); + this.addAbility(ability); + } + + public ViashinoPyromancer(final ViashinoPyromancer card) { + super(card); + } + + @Override + public ViashinoPyromancer copy() { + return new ViashinoPyromancer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VictoryChimes.java b/Mage.Sets/src/mage/cards/v/VictoryChimes.java index dbe69c07e34..54f53653ef5 100644 --- a/Mage.Sets/src/mage/cards/v/VictoryChimes.java +++ b/Mage.Sets/src/mage/cards/v/VictoryChimes.java @@ -4,9 +4,11 @@ package mage.cards.v; import java.util.UUID; import mage.Mana; import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.ChoosePlayerEffect; import mage.abilities.effects.common.ManaEffect; +import mage.abilities.effects.common.continuous.UntapSourceDuringEachOtherPlayersUntapStepEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -26,6 +28,7 @@ public final class VictoryChimes extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // Untap Victory Chimes during each other player's untap step. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new UntapSourceDuringEachOtherPlayersUntapStepEffect())); // {T}: A player of your choice adds {C}. ManaEffect effect = new VictoryChimesManaEffect("chosen player"); effect.setText("a player of your choice adds {C}"); diff --git a/Mage.Sets/src/mage/cards/v/VigeanIntuition.java b/Mage.Sets/src/mage/cards/v/VigeanIntuition.java new file mode 100644 index 00000000000..29f91842a77 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VigeanIntuition.java @@ -0,0 +1,124 @@ +package mage.cards.v; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.*; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.token.SaprolingToken; +import mage.players.Library; +import mage.players.Player; + +/** + * + * @author noahg + */ +public final class VigeanIntuition extends CardImpl { + + public VigeanIntuition(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}{U}"); + + + // Choose a card type, then reveal the top four cards of your library. Put all cards of the chosen type revealed this way into your hand and the rest into your graveyard. + this.getSpellAbility().addEffect(new VigeanIntuitionEffect()); + } + + public VigeanIntuition(final VigeanIntuition card) { + super(card); + } + + @Override + public VigeanIntuition copy() { + return new VigeanIntuition(this); + } +} + +class VigeanIntuitionEffect extends OneShotEffect { + + private static final Set choice = new LinkedHashSet<>(); + + static { + choice.add(CardType.ARTIFACT.toString()); + choice.add(CardType.CREATURE.toString()); + choice.add(CardType.ENCHANTMENT.toString()); + choice.add(CardType.INSTANT.toString()); + choice.add(CardType.LAND.toString()); + choice.add(CardType.PLANESWALKER.toString()); + choice.add(CardType.SORCERY.toString()); + choice.add(CardType.TRIBAL.toString()); + } + + public VigeanIntuitionEffect() { + super(Outcome.Benefit); + staticText = "Choose a card type, then reveal the top four cards of your library. Put all cards of the chosen type revealed this way into your hand and the rest into your graveyard"; + } + + public VigeanIntuitionEffect(final VigeanIntuitionEffect effect) { + super(effect); + } + + @Override + public VigeanIntuitionEffect copy() { + return new VigeanIntuitionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject sourceObject = game.getObject(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + Library library = player.getLibrary(); + if (player != null && sourceObject != null && library != null) { + Choice choiceImpl = new ChoiceImpl(); + choiceImpl.setChoices(choice); + if (player.choose(Outcome.Neutral, choiceImpl, game)) { + CardType type = null; + String choosenType = choiceImpl.getChoice(); + + if (choosenType.equals(CardType.ARTIFACT.toString())) { + type = CardType.ARTIFACT; + } else if (choosenType.equals(CardType.LAND.toString())) { + type = CardType.LAND; + } else if (choosenType.equals(CardType.CREATURE.toString())) { + type = CardType.CREATURE; + } else if (choosenType.equals(CardType.ENCHANTMENT.toString())) { + type = CardType.ENCHANTMENT; + } else if (choosenType.equals(CardType.INSTANT.toString())) { + type = CardType.INSTANT; + } else if (choosenType.equals(CardType.SORCERY.toString())) { + type = CardType.SORCERY; + } else if (choosenType.equals(CardType.PLANESWALKER.toString())) { + type = CardType.PLANESWALKER; + } else if (choosenType.equals(CardType.TRIBAL.toString())) { + type = CardType.TRIBAL; + } + + if (type != null) { + Set top = library.getTopCards(game, 4); + player.revealCards(source, new CardsImpl(top), game); + Cards putInHand = new CardsImpl(); + Cards putInGraveyard = new CardsImpl(); + for (Card card : top) { + if (card != null && card.getCardType().contains(type)) { + putInHand.add(card); + } else { + putInGraveyard.add(card); + } + } + player.moveCards(putInHand, Zone.HAND, source, game); + player.moveCards(putInGraveyard, Zone.GRAVEYARD, source, game); + return true; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/v/VigilForTheLost.java b/Mage.Sets/src/mage/cards/v/VigilForTheLost.java index 463316ebc78..b5de68f55e5 100644 --- a/Mage.Sets/src/mage/cards/v/VigilForTheLost.java +++ b/Mage.Sets/src/mage/cards/v/VigilForTheLost.java @@ -66,7 +66,7 @@ class VigilForTheLostTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent)event).getFromZone() == Zone.BATTLEFIELD) { Permanent p = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (p.getControllerId().equals(this.getControllerId()) && p.isCreature()) { + if (p.isControlledBy(this.getControllerId()) && p.isCreature()) { return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VigilantBaloth.java b/Mage.Sets/src/mage/cards/v/VigilantBaloth.java new file mode 100644 index 00000000000..7eee526c644 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VigilantBaloth.java @@ -0,0 +1,37 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.constants.SubType; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public final class VigilantBaloth extends CardImpl { + + public VigilantBaloth(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + } + + public VigilantBaloth(final VigilantBaloth card) { + super(card); + } + + @Override + public VigilantBaloth copy() { + return new VigilantBaloth(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java b/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java index 912ff5ee593..97834e21513 100644 --- a/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java +++ b/Mage.Sets/src/mage/cards/v/VildinPackAlpha.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -41,7 +41,7 @@ public final class VildinPackAlpha extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Vildin-Pack Alpha. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/v/VillageIronsmith.java b/Mage.Sets/src/mage/cards/v/VillageIronsmith.java index d8cf6d29711..2ab6e27cdec 100644 --- a/Mage.Sets/src/mage/cards/v/VillageIronsmith.java +++ b/Mage.Sets/src/mage/cards/v/VillageIronsmith.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TransformAbility; @@ -38,7 +38,7 @@ public final class VillageIronsmith extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Village Ironsmith. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public VillageIronsmith(final VillageIronsmith card) { diff --git a/Mage.Sets/src/mage/cards/v/VillageMessenger.java b/Mage.Sets/src/mage/cards/v/VillageMessenger.java index 5a4626e6162..ef0a93f8941 100644 --- a/Mage.Sets/src/mage/cards/v/VillageMessenger.java +++ b/Mage.Sets/src/mage/cards/v/VillageMessenger.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TransformAbility; @@ -39,7 +39,7 @@ public final class VillageMessenger extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Village Messenger. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public VillageMessenger(final VillageMessenger card) { diff --git a/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java b/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java index 1f33d977ee7..a320c5a6f3b 100644 --- a/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java +++ b/Mage.Sets/src/mage/cards/v/VillagersOfEstwald.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; @@ -35,7 +35,7 @@ public final class VillagersOfEstwald extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Villagers of Estwald. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public VillagersOfEstwald(final VillagersOfEstwald card) { diff --git a/Mage.Sets/src/mage/cards/v/VineMare.java b/Mage.Sets/src/mage/cards/v/VineMare.java new file mode 100644 index 00000000000..2896c3b6344 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VineMare.java @@ -0,0 +1,58 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author TheElk801 + */ +public final class VineMare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("black creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + public VineMare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.HORSE); + this.power = new MageInt(5); + this.toughness = new MageInt(3); + + // Hexproof + this.addAbility(HexproofAbility.getInstance()); + + // Vine Mare can't be blocked by black creatures. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new CantBeBlockedByCreaturesSourceEffect( + filter, Duration.WhileOnBattlefield + ) + )); + } + + public VineMare(final VineMare card) { + super(card); + } + + @Override + public VineMare copy() { + return new VineMare(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VirtussManeuver.java b/Mage.Sets/src/mage/cards/v/VirtussManeuver.java index 41de39ef5cb..70880e200f5 100644 --- a/Mage.Sets/src/mage/cards/v/VirtussManeuver.java +++ b/Mage.Sets/src/mage/cards/v/VirtussManeuver.java @@ -1,4 +1,3 @@ - package mage.cards.v; import java.util.ArrayList; @@ -17,6 +16,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -67,7 +67,7 @@ class VirtussManeuverEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); ChooseFriendsAndFoes choice = new ChooseFriendsAndFoes(); if (!choice.chooseFriendOrFoe(controller, source, game)) { return false; @@ -77,7 +77,7 @@ class VirtussManeuverEffect extends OneShotEffect { if (player == null) { continue; } - FilterCard filter = new FilterCard("card in your graveyard"); + FilterCard filter = new FilterCreatureCard("creature card in your graveyard"); filter.add(new OwnerIdPredicate(player.getId())); TargetCardInGraveyard target = new TargetCardInGraveyard(filter); getBackMap.put(player.getId(), null); diff --git a/Mage.Sets/src/mage/cards/v/VividFlyingFish.java b/Mage.Sets/src/mage/cards/v/VividFlyingFish.java new file mode 100644 index 00000000000..1433bd52eba --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VividFlyingFish.java @@ -0,0 +1,53 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceAttackingCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public final class VividFlyingFish extends CardImpl { + + public VividFlyingFish(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.FISH); + this.subtype.add(SubType.LIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Vivid Flying Fish has flying as long as it's attacking. + this.addAbility(new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect( + new GainAbilitySourceEffect( + FlyingAbility.getInstance(), + Duration.WhileOnBattlefield + ), + SourceAttackingCondition.instance, + "{this} has flying as long as it's attacking." + ) + )); + } + + public VividFlyingFish(final VividFlyingFish card) { + super(card); + } + + @Override + public VividFlyingFish copy() { + return new VividFlyingFish(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java b/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java new file mode 100644 index 00000000000..f40809e0bb2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java @@ -0,0 +1,77 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.common.DamageWithPowerTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.TrampleAbility; +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.TargetController; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class VivienOfTheArkbow extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + } + + public VivienOfTheArkbow(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{G}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.VIVIEN); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: Put two +1/+1 counters on up to one target creature. + Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)), 2); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + + // −3: Target creature you control deals damage equal to its power to target creature you don't control. + ability = new LoyaltyAbility(new DamageWithPowerTargetEffect(), -3); + ability.addTarget(new TargetControlledCreaturePermanent()); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + + // −9: Creatures you control get +4/+4 and gain trample until end of turn. + ability = new LoyaltyAbility( + new BoostControlledEffect(4, 4, Duration.EndOfTurn) + .setText("Creatures you control get +4/+4"), -9 + ); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), + Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and gain trample until end of turn")); + this.addAbility(ability); + } + + public VivienOfTheArkbow(final VivienOfTheArkbow card) { + super(card); + } + + @Override + public VivienOfTheArkbow copy() { + return new VivienOfTheArkbow(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VivienReid.java b/Mage.Sets/src/mage/cards/v/VivienReid.java new file mode 100644 index 00000000000..219a8c5a3cd --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VivienReid.java @@ -0,0 +1,84 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.command.emblems.VivienReidEmblem; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class VivienReid extends CardImpl { + + private static final FilterCard filter = new FilterCard("a creature or land card"); + private static final FilterPermanent filter2 = new FilterPermanent("artifact, enchantment, or creature with flying"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND) + )); + filter2.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.ENCHANTMENT), + Predicates.and( + new CardTypePredicate(CardType.CREATURE), + new AbilityPredicate(FlyingAbility.class) + ) + )); + } + + public VivienReid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{G}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.VIVIEN); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +1: Look at the top four cards of your library. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in any order. + this.addAbility(new LoyaltyAbility( + new LookLibraryAndPickControllerEffect( + new StaticValue(4), false, new StaticValue(1), filter, + Zone.LIBRARY, false, true, false, Zone.HAND, true, false, false) + .setBackInRandomOrder(true) + .setText("Look at the top four cards of your library. You may reveal a creature or land card from among them" + + " and put it into your hand. Put the rest on the bottom of your library in a random order."), 1 + )); + + // -3: Destroy target artifact, enchantment, or creature with flying. + Ability ability = new LoyaltyAbility(new DestroyTargetEffect(), -3); + ability.addTarget(new TargetPermanent(filter2)); + this.addAbility(ability); + + // -8: You get an emblem with "Creatures you control get +2/+2 and have vigilance, trample, and indestructible. + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new VivienReidEmblem()), -8)); + } + + public VivienReid(final VivienReid card) { + super(card); + } + + @Override + public VivienReid copy() { + return new VivienReid(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/ViviensInvocation.java b/Mage.Sets/src/mage/cards/v/ViviensInvocation.java new file mode 100644 index 00000000000..dec4018466c --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/ViviensInvocation.java @@ -0,0 +1,170 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SendOptionUsedEventEffect; +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.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetOpponentsCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class ViviensInvocation extends CardImpl { + + public ViviensInvocation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{G}{G}"); + + // Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. When a creature is put onto the battlefield this way, it deals damage equals to its power to target creature an opponent controls. + this.getSpellAbility().addEffect(new ViviensInvocationEffect()); + } + + public ViviensInvocation(final ViviensInvocation card) { + super(card); + } + + @Override + public ViviensInvocation copy() { + return new ViviensInvocation(this); + } +} + +class ViviensInvocationEffect extends OneShotEffect { + + public ViviensInvocationEffect(final ViviensInvocationEffect effect) { + super(effect); + } + + public ViviensInvocationEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Look at the top seven cards of your library. " + + "You may put a creature card from among them onto the battlefield. " + + "Put the rest on the bottom of your library in a random order. " + + "When a creature is put onto the battlefield this way, " + + "it deals damage equal to its power to target creature an opponent controls"; + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, 7)); + if (!cards.isEmpty()) { + TargetCard target = new TargetCard( + Zone.LIBRARY, + new FilterCreatureCard("creature card to put on the battlefield") + ); + if (controller.choose(Outcome.PutCreatureInPlay, cards, target, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + game.addDelayedTriggeredAbility( + new ViviensInvocationReflexiveTriggeredAbility( + new MageObjectReference(permanent, game) + ), source); + new SendOptionUsedEventEffect().apply(game, source); + } + } + } + if (!cards.isEmpty()) { + controller.putCardsOnBottomOfLibrary(cards, game, source, false); + } + } + return true; + } + + @Override + public ViviensInvocationEffect copy() { + return new ViviensInvocationEffect(this); + } +} + +class ViviensInvocationReflexiveTriggeredAbility extends DelayedTriggeredAbility { + + public ViviensInvocationReflexiveTriggeredAbility(MageObjectReference mor) { + super(new ViviensInvocationDamageEffect(mor), Duration.OneUse, false); + this.addTarget(new TargetOpponentsCreaturePermanent()); + } + + public ViviensInvocationReflexiveTriggeredAbility(final ViviensInvocationReflexiveTriggeredAbility ability) { + super(ability); + } + + @Override + public ViviensInvocationReflexiveTriggeredAbility copy() { + return new ViviensInvocationReflexiveTriggeredAbility(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 "When a creature is put onto the battlefield with {this}, " + + "it deals damage equal to its power to target creature an opponent controls"; + } +} + +class ViviensInvocationDamageEffect extends OneShotEffect { + + private final MageObjectReference mor; + + public ViviensInvocationDamageEffect(MageObjectReference mor) { + super(Outcome.Benefit); + this.mor = mor; + } + + public ViviensInvocationDamageEffect(final ViviensInvocationDamageEffect effect) { + super(effect); + mor = effect.mor; + } + + @Override + public ViviensInvocationDamageEffect copy() { + return new ViviensInvocationDamageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (mor == null) { + return false; + } + Permanent creature = game.getPermanent(source.getFirstTarget()); + Permanent permanent = mor.getPermanent(game); + if (creature == null || permanent == null) { + return false; + } + return creature.damage(permanent.getPower().getValue(), permanent.getId(), game, false, true) > 0; + } +} diff --git a/Mage.Sets/src/mage/cards/v/ViviensJaguar.java b/Mage.Sets/src/mage/cards/v/ViviensJaguar.java new file mode 100644 index 00000000000..e9576675132 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/ViviensJaguar.java @@ -0,0 +1,59 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; +import mage.constants.SubType; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +/** + * + * @author TheElk801 + */ +public final class ViviensJaguar extends CardImpl { + + private static final FilterControlledPlaneswalkerPermanent filter + = new FilterControlledPlaneswalkerPermanent( + SubType.VIVIEN, + "a Vivien planeswalker" + ); + + public ViviensJaguar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // {2}{G}: Return Vivien's Jaguar from your graveyard to your hand. Activate this ability only if you control a Vivien planeswalker. + this.addAbility(new ConditionalActivatedAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl("{2}{G}"), + new PermanentsOnTheBattlefieldCondition(filter), + "{2}{G}: Return {this} from your graveyard to your hand. " + + "Activate this ability only if you control a Vivien planeswalker" + )); + } + + public ViviensJaguar(final ViviensJaguar card) { + super(card); + } + + @Override + public ViviensJaguar copy() { + return new ViviensJaguar(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java b/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java index 9eb1d5063c2..2823ffa75b1 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java @@ -76,7 +76,7 @@ class VizierOfRemediesReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (source != null && source.getControllerId() != null) { - if (source.getControllerId().equals(game.getControllerId(event.getTargetId())) + if (source.isControlledBy(game.getControllerId(event.getTargetId())) && event.getData() != null && event.getData().equals(CounterType.M1M1.getName()) && event.getAmount() > 0) { return true; diff --git a/Mage.Sets/src/mage/cards/v/VizierOfTheMenagerie.java b/Mage.Sets/src/mage/cards/v/VizierOfTheMenagerie.java index f55d382826a..cfca3c4884a 100644 --- a/Mage.Sets/src/mage/cards/v/VizierOfTheMenagerie.java +++ b/Mage.Sets/src/mage/cards/v/VizierOfTheMenagerie.java @@ -160,7 +160,7 @@ class VizierOfTheMenagerieManaEffect extends AsThoughEffectImpl implements AsTho @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (source.getControllerId().equals(affectedControllerId)) { + if (source.isControlledBy(affectedControllerId)) { MageObject mageObject = game.getObject(objectId); return mageObject != null && mageObject.isCreature(); diff --git a/Mage.Sets/src/mage/cards/v/VodalianMystic.java b/Mage.Sets/src/mage/cards/v/VodalianMystic.java index aae9bde24f7..5fd00eb0735 100644 --- a/Mage.Sets/src/mage/cards/v/VodalianMystic.java +++ b/Mage.Sets/src/mage/cards/v/VodalianMystic.java @@ -31,7 +31,7 @@ public final class VodalianMystic extends CardImpl { // {T}: Target instant or sorcery spell becomes the color of your choice. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesColorTargetEffect(Duration.WhileOnStack), new TapSourceCost()); - ability.addTarget(new TargetSpell(StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL)); + ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VoiceOfResurgence.java b/Mage.Sets/src/mage/cards/v/VoiceOfResurgence.java index 059572e9e73..08b9cd0334a 100644 --- a/Mage.Sets/src/mage/cards/v/VoiceOfResurgence.java +++ b/Mage.Sets/src/mage/cards/v/VoiceOfResurgence.java @@ -1,21 +1,22 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.meta.OrTriggeredAbility; 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.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; +import mage.filter.FilterSpell; import mage.game.permanent.token.VoiceOfResurgenceToken; -import mage.game.stack.Spell; + +import java.util.UUID; /** * @@ -31,7 +32,14 @@ public final class VoiceOfResurgence extends CardImpl { this.toughness = new MageInt(2); // Whenever an opponent casts a spell during your turn or when Voice of Resurgence dies, create a green and white Elemental creature token with "This creature's power and toughness are each equal to the number of creatures you control." - this.addAbility(new VoiceOfResurgenceTriggeredAbility()); + OrTriggeredAbility ability = new OrTriggeredAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new VoiceOfResurgenceToken()), + new ConditionalTriggeredAbility( + new SpellCastOpponentTriggeredAbility(null, new FilterSpell("a spell"), false), + MyTurnCondition.instance, + "Whenever an opponent casts a spell during your turn, "), + new DiesTriggeredAbility(null, false)); + ability.setLeavesTheBattlefieldTrigger(true); + this.addAbility(ability); } @@ -43,50 +51,6 @@ public final class VoiceOfResurgence extends CardImpl { public VoiceOfResurgence copy() { return new VoiceOfResurgence(this); } + } -class VoiceOfResurgenceTriggeredAbility extends TriggeredAbilityImpl { - - public VoiceOfResurgenceTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new VoiceOfResurgenceToken()), false); - setLeavesTheBattlefieldTrigger(true); - } - - public VoiceOfResurgenceTriggeredAbility(final VoiceOfResurgenceTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.SPELL_CAST || event.getType() == EventType.ZONE_CHANGE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - // Opponent casts spell during your turn - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null - && game.getOpponents(super.getControllerId()).contains(spell.getControllerId()) - && game.getActivePlayerId().equals(super.getControllerId())) { - return true; - } - } - // Voice of Resurgence Dies - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && getSourceId().equals(event.getTargetId())) { - ZoneChangeEvent zce = (ZoneChangeEvent) event; - return zce.getFromZone() == Zone.BATTLEFIELD && zce.getToZone() == Zone.GRAVEYARD; - } - return false; - } - - @Override - public String getRule() { - return "Whenever an opponent casts a spell during your turn or when {this} dies, create a green and white Elemental creature token with \"This creature's power and toughness are each equal to the number of creatures you control."; - } - - @Override - public VoiceOfResurgenceTriggeredAbility copy() { - return new VoiceOfResurgenceTriggeredAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/v/VoidstoneGargoyle.java b/Mage.Sets/src/mage/cards/v/VoidstoneGargoyle.java index a538287e177..c2cdda72625 100644 --- a/Mage.Sets/src/mage/cards/v/VoidstoneGargoyle.java +++ b/Mage.Sets/src/mage/cards/v/VoidstoneGargoyle.java @@ -1,4 +1,3 @@ - package mage.cards.v; import java.util.UUID; @@ -8,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,7 +27,7 @@ import mage.game.events.GameEvent.EventType; public final class VoidstoneGargoyle extends CardImpl { public VoidstoneGargoyle(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.GARGOYLE); this.power = new MageInt(3); @@ -37,7 +36,7 @@ public final class VoidstoneGargoyle extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // As Voidstone Gargoyle enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME))); // The named card can't be cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new VoidstoneGargoyleReplacementEffect1())); // Activated abilities of sources with the chosen name can't be activated. @@ -58,7 +57,7 @@ class VoidstoneGargoyleReplacementEffect1 extends ContinuousRuleModifyingEffectI public VoidstoneGargoyleReplacementEffect1() { super(Duration.WhileOnBattlefield, Outcome.Detriment); - staticText = "The named card can't be cast"; + staticText = "Spells with the chosen name can't be cast"; } public VoidstoneGargoyleReplacementEffect1(final VoidstoneGargoyleReplacementEffect1 effect) { @@ -79,7 +78,7 @@ class VoidstoneGargoyleReplacementEffect1 extends ContinuousRuleModifyingEffectI public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); if (mageObject != null) { - return "You can't cast a card with that name (" + mageObject.getIdName() + ")."; + return "You can't cast a spell with that name (" + mageObject.getIdName() + ")."; } return null; } @@ -89,7 +88,7 @@ class VoidstoneGargoyleReplacementEffect1 extends ContinuousRuleModifyingEffectI if (event.getType() == GameEvent.EventType.CAST_SPELL) { MageObject object = game.getObject(event.getSourceId()); if (object != null - && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } @@ -132,7 +131,7 @@ class VoidstoneGargoyleRuleModifyingEffect2 extends ContinuousRuleModifyingEffec public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.ACTIVATE_ABILITY) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VolleyVeteran.java b/Mage.Sets/src/mage/cards/v/VolleyVeteran.java new file mode 100644 index 00000000000..dcd41b2ddd5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VolleyVeteran.java @@ -0,0 +1,54 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetOpponentsCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public final class VolleyVeteran extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("Goblins you control"); + + static { + filter.add(new SubtypePredicate(SubType.GOBLIN)); + } + + public VolleyVeteran(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // When Volley Veteran enters the battlefield, it deals damage to target creature an opponent controls equal to the number of Goblins you control. + Ability ability = new EntersBattlefieldTriggeredAbility( + new DamageTargetEffect(new PermanentsOnBattlefieldCount(filter)) + .setText("it deals damage to target creature an opponent controls equal to the number of Goblins you control") + ); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + public VolleyVeteran(final VolleyVeteran card) { + super(card); + } + + @Override + public VolleyVeteran copy() { + return new VolleyVeteran(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VorinclexVoiceOfHunger.java b/Mage.Sets/src/mage/cards/v/VorinclexVoiceOfHunger.java index d8c1f81c0f4..4a633939796 100644 --- a/Mage.Sets/src/mage/cards/v/VorinclexVoiceOfHunger.java +++ b/Mage.Sets/src/mage/cards/v/VorinclexVoiceOfHunger.java @@ -1,19 +1,18 @@ - package mage.cards.v; import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.TapForManaAllTriggeredManaAbility; -import mage.abilities.effects.mana.AddManaOfAnyTypeProducedEffect; import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; import mage.abilities.effects.common.ManaEffect; +import mage.abilities.effects.mana.AddManaOfAnyTypeProducedEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.SetTargetPointer; +import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterControlledLandPermanent; @@ -30,7 +29,7 @@ import mage.target.targetpointer.FixedTarget; public final class VorinclexVoiceOfHunger extends CardImpl { public VorinclexVoiceOfHunger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}{G}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.PRAETOR); @@ -63,8 +62,6 @@ public final class VorinclexVoiceOfHunger extends CardImpl { class VorinclexTriggeredAbility2 extends TriggeredAbilityImpl { - private static final String staticText = "Whenever an opponent taps a land for mana, that land doesn't untap during its controller's next untap step."; - public VorinclexTriggeredAbility2() { super(Zone.BATTLEFIELD, new DontUntapInControllersNextUntapStepTargetEffect()); } @@ -97,6 +94,6 @@ class VorinclexTriggeredAbility2 extends TriggeredAbilityImpl { @Override public String getRule() { - return staticText; + return "Whenever an opponent taps a land for mana, that land doesn't untap during its controller's next untap step."; } } diff --git a/Mage.Sets/src/mage/cards/v/VoyagerDrake.java b/Mage.Sets/src/mage/cards/v/VoyagerDrake.java index 381911a0f8f..3db5967e0f1 100644 --- a/Mage.Sets/src/mage/cards/v/VoyagerDrake.java +++ b/Mage.Sets/src/mage/cards/v/VoyagerDrake.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -41,7 +41,8 @@ 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. - Ability ability = new ConditionalTriggeredAbility( + //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."); diff --git a/Mage.Sets/src/mage/cards/v/VraskaTheUnseen.java b/Mage.Sets/src/mage/cards/v/VraskaTheUnseen.java index cc1310933b3..7699a25e1ea 100644 --- a/Mage.Sets/src/mage/cards/v/VraskaTheUnseen.java +++ b/Mage.Sets/src/mage/cards/v/VraskaTheUnseen.java @@ -112,7 +112,7 @@ class VraskaTheUnseenGainAbilityEffect extends ContinuousEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (startingTurn != 0 && game.getTurnNum() != startingTurn) { - if (game.getActivePlayerId().equals(source.getControllerId())) { + if (game.isActivePlayer(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VraskasConquistador.java b/Mage.Sets/src/mage/cards/v/VraskasConquistador.java index 8d9b98d775d..f57955f6c7d 100644 --- a/Mage.Sets/src/mage/cards/v/VraskasConquistador.java +++ b/Mage.Sets/src/mage/cards/v/VraskasConquistador.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; @@ -43,7 +43,7 @@ public final class VraskasConquistador extends CardImpl { TriggeredAbility ability = new AttacksOrBlocksTriggeredAbility(new LoseLifeTargetEffect(2), false); ability.addEffect(new GainLifeEffect(2).setText("and you gain 2 life")); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} attacks or blocks, if you control a Vraska planeswalker, target opponent loses 2 life and you gain 2 life.")); } diff --git a/Mage.Sets/src/mage/cards/v/Vulptex.java b/Mage.Sets/src/mage/cards/v/Vulptex.java new file mode 100644 index 00000000000..1c8bcb5c61b --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/Vulptex.java @@ -0,0 +1,42 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author NinthWorld + */ +public final class Vulptex extends CardImpl { + + public Vulptex(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.FOX); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Vulptex enters the battlefield, put a +1/+1 counter on target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public Vulptex(final Vulptex card) { + super(card); + } + + @Override + public Vulptex copy() { + return new Vulptex(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VulshokBattlemaster.java b/Mage.Sets/src/mage/cards/v/VulshokBattlemaster.java index ff55b73e0eb..417f18ace42 100644 --- a/Mage.Sets/src/mage/cards/v/VulshokBattlemaster.java +++ b/Mage.Sets/src/mage/cards/v/VulshokBattlemaster.java @@ -69,7 +69,7 @@ public final class VulshokBattlemaster extends CardImpl { filter.add(new SubtypePredicate(SubType.EQUIPMENT)); for (Permanent equipment : game.getBattlefield().getAllActivePermanents(filter, game)) { if (equipment != null) { - //If an Equipment can’t equip Vulshok Battlemaster, it isn’t attached to the Battlemaster, and it doesn’t become unattached (if it’s attached to a creature). (http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=48125) + //If an Equipment can't equip Vulshok Battlemaster, it isn't attached to the Battlemaster, and it doesn't become unattached (if it's attached to a creature). (http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=48125) if (!battlemaster.cantBeAttachedBy(equipment, game)) { battlemaster.addAttachment(equipment.getId(), game); } diff --git a/Mage.Sets/src/mage/cards/w/WakeThrasher.java b/Mage.Sets/src/mage/cards/w/WakeThrasher.java index c801aba05de..cea61f17380 100644 --- a/Mage.Sets/src/mage/cards/w/WakeThrasher.java +++ b/Mage.Sets/src/mage/cards/w/WakeThrasher.java @@ -67,7 +67,7 @@ class BecomesUntappedControlledPermanentTriggeredAbility extends TriggeredAbilit @Override public boolean checkTrigger(GameEvent event, Game game) { - return game.getPermanent(event.getTargetId()).getControllerId().equals(this.controllerId); + return game.getPermanent(event.getTargetId()).isControlledBy(this.controllerId); } @Override diff --git a/Mage.Sets/src/mage/cards/w/Wakedancer.java b/Mage.Sets/src/mage/cards/w/Wakedancer.java index 0ed65c61edf..2616976978c 100644 --- a/Mage.Sets/src/mage/cards/w/Wakedancer.java +++ b/Mage.Sets/src/mage/cards/w/Wakedancer.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,7 +20,7 @@ import mage.game.permanent.token.ZombieToken; */ public final class Wakedancer extends CardImpl { - private static final String staticText = "Morbid - When {this} enters the battlefield, if a creature died this turn, create a 2/2 black Zombie creature token."; + private static final String staticText = "Morbid — When {this} enters the battlefield, if a creature died this turn, create a 2/2 black Zombie creature token."; public Wakedancer(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}"); @@ -31,9 +31,9 @@ public final class Wakedancer extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - // Morbid - When Wakedancer enters the battlefield, if a creature died this turn, create a 2/2 black Zombie creature token. + // Morbid — When Wakedancer enters the battlefield, if a creature died this turn, create a 2/2 black Zombie creature token. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken())); - this.addAbility(new ConditionalTriggeredAbility(ability, MorbidCondition.instance, staticText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText)); } public Wakedancer(final Wakedancer card) { diff --git a/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java b/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java index f16edf13a39..118d4e572b1 100644 --- a/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java +++ b/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourceCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class WakeningSunsAvatar extends CardImpl { this.toughness = new MageInt(7); // When Wakening Sun's Avatar enters the battlefield, if you cast it from you hand, destroy all non-Dinosaur creatures. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter), false), CastFromHandSourceCondition.instance, "When {this} enters the battlefield, if you cast it from your hand, destroy all non-Dinosaur creatures."), diff --git a/Mage.Sets/src/mage/cards/w/WallOfDiffusion.java b/Mage.Sets/src/mage/cards/w/WallOfDiffusion.java index 0371561cfd8..2e330180827 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfDiffusion.java +++ b/Mage.Sets/src/mage/cards/w/WallOfDiffusion.java @@ -6,6 +6,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.common.CanBlockAsThoughtItHadShadowEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -33,7 +34,7 @@ public final class WallOfDiffusion extends CardImpl { // Defender this.addAbility(DefenderAbility.getInstance()); // Wall of Diffusion can block creatures with shadow as though Wall of Diffusion had shadow. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAsThoughtIthadShadowEffect(Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAsThoughtItHadShadowEffect(Duration.WhileOnBattlefield))); } public WallOfDiffusion(final WallOfDiffusion card) { @@ -44,32 +45,4 @@ public final class WallOfDiffusion extends CardImpl { public WallOfDiffusion copy() { return new WallOfDiffusion(this); } -} - -class CanBlockAsThoughtIthadShadowEffect extends AsThoughEffectImpl { - - public CanBlockAsThoughtIthadShadowEffect(Duration duration) { - super(AsThoughEffectType.BLOCK_SHADOW, duration, Outcome.Benefit); - staticText = "{this} can block creatures with shadow as though {this} had shadow"; - } - - public CanBlockAsThoughtIthadShadowEffect(final CanBlockAsThoughtIthadShadowEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public CanBlockAsThoughtIthadShadowEffect copy() { - return new CanBlockAsThoughtIthadShadowEffect(this); - } - - @Override - public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return sourceId.equals(source.getSourceId()); - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WallOfDust.java b/Mage.Sets/src/mage/cards/w/WallOfDust.java index a9438e53022..5998d54a4c4 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfDust.java +++ b/Mage.Sets/src/mage/cards/w/WallOfDust.java @@ -76,7 +76,7 @@ class WallOfDustRestrictionEffect extends RestrictionEffect { if (targetPermanent == null) { return true; } - if (nextTurnTargetController == 0 && startingTurn != game.getTurnNum() && game.getActivePlayerId().equals(targetPermanent.getControllerId())) { + if (nextTurnTargetController == 0 && startingTurn != game.getTurnNum() && game.isActivePlayer(targetPermanent.getControllerId())) { nextTurnTargetController = game.getTurnNum(); } return game.getPhase().getType() == TurnPhase.END && nextTurnTargetController > 0 && game.getTurnNum() > nextTurnTargetController; @@ -95,7 +95,7 @@ class WallOfDustRestrictionEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { if (permanent.getId().equals(getTargetPointer().getFirst(game, source))) { - if (game.getActivePlayerId().equals(permanent.getControllerId())) { + if (game.isActivePlayer(permanent.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/w/WanderingChampion.java b/Mage.Sets/src/mage/cards/w/WanderingChampion.java index 3c2ae20f245..373afc8dad5 100644 --- a/Mage.Sets/src/mage/cards/w/WanderingChampion.java +++ b/Mage.Sets/src/mage/cards/w/WanderingChampion.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.DiscardCardCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; @@ -40,7 +40,7 @@ public final class WanderingChampion extends CardImpl { // Whenever Wandering Champion deals combat damage to a player, if you control a blue or red permanent, you may discard a card. If you do, draw a card. TriggeredAbility ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new DiscardCardCost()), true); - this.addAbility(new ConditionalTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), "Whenever {this} deals combat damage to a player, if you control a blue or red permanent, you may discard a card. If you do, draw a card.")); } diff --git a/Mage.Sets/src/mage/cards/w/Warbringer.java b/Mage.Sets/src/mage/cards/w/Warbringer.java index bf29775672e..4d40a5f31ed 100644 --- a/Mage.Sets/src/mage/cards/w/Warbringer.java +++ b/Mage.Sets/src/mage/cards/w/Warbringer.java @@ -71,7 +71,7 @@ class WarbringerSpellsCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { return DashedCondition.instance.apply(game, abilityToModify); diff --git a/Mage.Sets/src/mage/cards/w/WarriorsStand.java b/Mage.Sets/src/mage/cards/w/WarriorsStand.java index 61dcb524f40..82eb872f355 100644 --- a/Mage.Sets/src/mage/cards/w/WarriorsStand.java +++ b/Mage.Sets/src/mage/cards/w/WarriorsStand.java @@ -26,7 +26,7 @@ public final class WarriorsStand extends CardImpl { // Cast Warrior's Stand only during the declare attackers step and only if you've been attacked this step. Ability ability = new CastOnlyDuringPhaseStepSourceAbility( TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, - "Cast {this} only during the declare attackers step and only if you've been attacked this step." + "Cast this spell only during the declare attackers step and only if you've been attacked this step." ); ability.addWatcher(new PlayerAttackedStepWatcher()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WarstormSurge.java b/Mage.Sets/src/mage/cards/w/WarstormSurge.java index 0849d7e543b..71475721b2d 100644 --- a/Mage.Sets/src/mage/cards/w/WarstormSurge.java +++ b/Mage.Sets/src/mage/cards/w/WarstormSurge.java @@ -62,7 +62,7 @@ class WarstormSurgeTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent.isCreature() - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { Effect effect = this.getEffects().get(0); effect.setValue("damageSource", event.getTargetId()); return true; diff --git a/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java b/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java index f2371355bde..9db272b67cb 100644 --- a/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java +++ b/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.abilities.effects.common.turn.SkipNextTurnSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -42,7 +42,7 @@ public final class WaterspoutElemental extends CardImpl { // When Waterspout Elemental enters the battlefield, if it was kicked, return all other creatures to their owners' hands and you skip your next turn. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandFromBattlefieldAllEffect(filter)); ability.addEffect(new SkipNextTurnSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.instance, "When {this} enters the battlefield, if it was kicked, return all other creatures to their owners' hands and you skip your next turn.")); } diff --git a/Mage.Sets/src/mage/cards/w/WayfarersBauble.java b/Mage.Sets/src/mage/cards/w/WayfarersBauble.java index eb4331fb97e..7af0de0a833 100644 --- a/Mage.Sets/src/mage/cards/w/WayfarersBauble.java +++ b/Mage.Sets/src/mage/cards/w/WayfarersBauble.java @@ -4,6 +4,7 @@ package mage.cards.w; 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.GenericManaCost; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; @@ -28,6 +29,7 @@ public final class WayfarersBauble extends CardImpl { // {2}, {tap}, Sacrifice Wayfarer's Bauble: Search your library for a basic land card and put that card onto the battlefield tapped. Then shuffle your library. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND),true, true, Outcome.PutLandInPlay), new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WearTear.java b/Mage.Sets/src/mage/cards/w/WearTear.java index 43ae908578d..d4124f84308 100644 --- a/Mage.Sets/src/mage/cards/w/WearTear.java +++ b/Mage.Sets/src/mage/cards/w/WearTear.java @@ -1,4 +1,3 @@ - package mage.cards.w; import java.util.UUID; @@ -31,6 +30,8 @@ public final class WearTear extends SplitCard { getRightHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect()); target = new TargetEnchantmentPermanent(); getRightHalfCard().getSpellAbility().addTarget(target); + + // Fuse (You may cast one or both halves of this card from your hand.) } public WearTear(final WearTear card) { diff --git a/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java b/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java index 88beda16b95..f11ba3ef58a 100644 --- a/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java +++ b/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java @@ -8,7 +8,7 @@ import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -22,7 +22,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; /** * @@ -40,7 +39,7 @@ public final class WeatherseedTotem extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new WeatherseedTotemToken(), "", Duration.EndOfTurn), new ManaCostsImpl<>("{2}{G}{G}{G}"))); // When Weatherseed Totem is put into a graveyard from the battlefield, if it was a creature, return this card to its owner's hand. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ReturnToHandSourceEffect()), new WeatherseedTotemCondition(), "When {this} is put into a graveyard from the battlefield, " diff --git a/Mage.Sets/src/mage/cards/w/WebOfInertia.java b/Mage.Sets/src/mage/cards/w/WebOfInertia.java index 8d099bd7cdf..6739e5cf828 100644 --- a/Mage.Sets/src/mage/cards/w/WebOfInertia.java +++ b/Mage.Sets/src/mage/cards/w/WebOfInertia.java @@ -105,7 +105,7 @@ class WebOfInertiaRestrictionEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - return permanent.getControllerId().equals(attackerID); + return permanent.isControlledBy(attackerID); } @Override diff --git a/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java b/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java index d5e0716bf48..ee3002f48ba 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java +++ b/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class WellOfDiscovery extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}"); // At the beginning of your end step, if you control no untapped lands, draw a card. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new DrawCardSourceControllerEffect(1), TargetController.YOU, false), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), "At the beginning of your end step, if you control no untapped lands, draw a card.")); diff --git a/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java b/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java index e0562104d32..96cd3c87fbe 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java +++ b/Mage.Sets/src/mage/cards/w/WellOfKnowledge.java @@ -66,7 +66,7 @@ class WellOfKnowledgeConditionalActivatedAbility extends ActivatedAbilityImpl { public ActivationStatus canActivate(UUID playerId, Game game) { if (condition.apply(game, this) && costs.canPay(this, sourceId, playerId, game) - && game.getActivePlayerId().equals(playerId)) { + && game.isActivePlayer(playerId)) { this.activatorId = playerId; return ActivationStatus.getTrue(); } diff --git a/Mage.Sets/src/mage/cards/w/WellOfLife.java b/Mage.Sets/src/mage/cards/w/WellOfLife.java index 6110c016574..775e1a02fd3 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfLife.java +++ b/Mage.Sets/src/mage/cards/w/WellOfLife.java @@ -5,7 +5,7 @@ import java.util.UUID; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,7 +31,7 @@ public final class WellOfLife extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); // At the beginning of your end step, if you control no untapped lands, you gain 2 life. - this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( new GainLifeEffect(2), TargetController.YOU, false), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), "At the beginning of your end step, if you control no untapped lands, you gain 2 life.")); } diff --git a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java index dbb43f738bf..b7df1697b46 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfOfAncientHunger.java @@ -9,7 +9,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TransformedCondition; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardsInAllHandsCount; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; @@ -53,7 +53,7 @@ public final class WerewolfOfAncientHunger extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Werewolf of Ancient Hunger. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public WerewolfOfAncientHunger(final WerewolfOfAncientHunger card) { diff --git a/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java b/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java index e72eb481dce..51eef0567f0 100644 --- a/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java +++ b/Mage.Sets/src/mage/cards/w/WerewolfRansacker.java @@ -8,7 +8,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -49,7 +49,7 @@ public final class WerewolfRansacker extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Werewolf Ransacker. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } public WerewolfRansacker(final WerewolfRansacker card) { diff --git a/Mage.Sets/src/mage/cards/w/WharfInfiltrator.java b/Mage.Sets/src/mage/cards/w/WharfInfiltrator.java index a4dc0e26eb4..207fd6e1288 100644 --- a/Mage.Sets/src/mage/cards/w/WharfInfiltrator.java +++ b/Mage.Sets/src/mage/cards/w/WharfInfiltrator.java @@ -83,7 +83,7 @@ class WharfInfiltratorDiscardAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Card card = game.getCard(event.getTargetId()); - if (getControllerId().equals(event.getPlayerId()) && card != null && card.isCreature()) { + if (isControlledBy(event.getPlayerId()) && card != null && card.isCreature()) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/w/WheelOfSunAndMoon.java b/Mage.Sets/src/mage/cards/w/WheelOfSunAndMoon.java index 662038c9b84..af23559ad45 100644 --- a/Mage.Sets/src/mage/cards/w/WheelOfSunAndMoon.java +++ b/Mage.Sets/src/mage/cards/w/WheelOfSunAndMoon.java @@ -85,7 +85,7 @@ class WheelOfSunAndMoonEffect extends ReplacementEffectImpl { if (card != null) { Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null - && card.getOwnerId().equals(enchantment.getAttachedTo())) { + && card.isOwnedBy(enchantment.getAttachedTo())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/w/WhiptongueHydra.java b/Mage.Sets/src/mage/cards/w/WhiptongueHydra.java new file mode 100644 index 00000000000..fae1fde2f16 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WhiptongueHydra.java @@ -0,0 +1,91 @@ +package mage.cards.w; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.SubType; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author TheElk801 + */ +public final class WhiptongueHydra extends CardImpl { + + public WhiptongueHydra(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}"); + + this.subtype.add(SubType.LIZARD); + this.subtype.add(SubType.HYDRA); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // When Whiptongue Hydra enters the battlefield, destroy all creatures with flying. Put a +1/+1 counter on Whiptongue Hydra for each creature destroyed this way. + this.addAbility(new EntersBattlefieldTriggeredAbility(new WhiptongueHydraEffect(), false)); + } + + public WhiptongueHydra(final WhiptongueHydra card) { + super(card); + } + + @Override + public WhiptongueHydra copy() { + return new WhiptongueHydra(this); + } +} + +class WhiptongueHydraEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public WhiptongueHydraEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "destroy all creatures with flying. " + + "Put a +1/+1 counter on {this} for each permanent destroyed this way"; + } + + public WhiptongueHydraEffect(final WhiptongueHydraEffect effect) { + super(effect); + } + + @Override + public WhiptongueHydraEffect copy() { + return new WhiptongueHydraEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int destroyedPermanents = 0; + destroyedPermanents = game.getBattlefield().getActivePermanents( + filter, source.getControllerId(), source.getSourceId(), game + ).stream().filter( + (permanent) -> (permanent.destroy(source.getSourceId(), game, false)) + ).map((_item) -> 1).reduce(destroyedPermanents, Integer::sum); + if (destroyedPermanents > 0) { + return new AddCountersSourceEffect( + CounterType.P1P1.createInstance(destroyedPermanents), true + ).apply(game, source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/w/WhirlingDervish.java b/Mage.Sets/src/mage/cards/w/WhirlingDervish.java index 2e5a230f1f8..e7ff09c4f70 100644 --- a/Mage.Sets/src/mage/cards/w/WhirlingDervish.java +++ b/Mage.Sets/src/mage/cards/w/WhirlingDervish.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.TriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.DealtDamageToAnOpponent; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; @@ -38,7 +38,7 @@ public final class WhirlingDervish extends CardImpl { this.addAbility(ProtectionAbility.from(ObjectColor.BLACK)); // At the beginning of each end step, if Whirling Dervish dealt damage to an opponent this turn, put a +1/+1 counter on it. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); - this.addAbility(new ConditionalTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new DealtDamageToAnOpponent(), ruleText)); } public WhirlingDervish(final WhirlingDervish card) { diff --git a/Mage.Sets/src/mage/cards/w/WildDefiance.java b/Mage.Sets/src/mage/cards/w/WildDefiance.java index fa2787c9955..6d2fd536150 100644 --- a/Mage.Sets/src/mage/cards/w/WildDefiance.java +++ b/Mage.Sets/src/mage/cards/w/WildDefiance.java @@ -63,7 +63,7 @@ class CreaturesYouControlBecomesTargetTriggeredAbility extends TriggeredAbilityI @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(this.controllerId) && permanent.isCreature()) { + if (permanent != null && permanent.isControlledBy(this.controllerId) && permanent.isCreature()) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object instanceof Spell) { Card c = (Spell) object; diff --git a/Mage.Sets/src/mage/cards/w/WildPair.java b/Mage.Sets/src/mage/cards/w/WildPair.java index 6e51f77ef9b..ee5d269b22a 100644 --- a/Mage.Sets/src/mage/cards/w/WildPair.java +++ b/Mage.Sets/src/mage/cards/w/WildPair.java @@ -6,7 +6,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -39,7 +39,7 @@ public final class WildPair extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); // Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new WildPairEffect(), filter, true, SetTargetPointer.PERMANENT, ""), new CastFromHandTargetCondition(), "Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library." diff --git a/Mage.Sets/src/mage/cards/w/WildbloodPack.java b/Mage.Sets/src/mage/cards/w/WildbloodPack.java index 578ce917ae6..2871ec90263 100644 --- a/Mage.Sets/src/mage/cards/w/WildbloodPack.java +++ b/Mage.Sets/src/mage/cards/w/WildbloodPack.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.TrampleAbility; @@ -41,7 +41,7 @@ public final class WildbloodPack extends CardImpl { // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Wildblood Pack. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.instance, TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); } diff --git a/Mage.Sets/src/mage/cards/w/Willbreaker.java b/Mage.Sets/src/mage/cards/w/Willbreaker.java index 32c6e2669c0..0c1faff0ba3 100644 --- a/Mage.Sets/src/mage/cards/w/Willbreaker.java +++ b/Mage.Sets/src/mage/cards/w/Willbreaker.java @@ -67,7 +67,7 @@ class WillbreakerTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (getControllerId().equals(event.getPlayerId())) { + if (isControlledBy(event.getPlayerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature()) { Player controller = game.getPlayer(getControllerId()); diff --git a/Mage.Sets/src/mage/cards/w/WillingTestSubject.java b/Mage.Sets/src/mage/cards/w/WillingTestSubject.java index e68c4c3eb03..5b48449d828 100644 --- a/Mage.Sets/src/mage/cards/w/WillingTestSubject.java +++ b/Mage.Sets/src/mage/cards/w/WillingTestSubject.java @@ -79,7 +79,7 @@ class WillingTestSubjectTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + if (this.isControlledBy(event.getPlayerId()) && event.getFlag()) { if (event.getAmount() >= 4) { return true; } diff --git a/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java b/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java new file mode 100644 index 00000000000..00d95d3090d --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WindgracesJudgment.java @@ -0,0 +1,60 @@ +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; +import mage.constants.CardType; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class WindgracesJudgment extends CardImpl { + + public WindgracesJudgment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{G}"); + + // For any number of opponents, destroy target nonland permanent that player controls. + this.getSpellAbility().addEffect( + new DestroyTargetEffect(). + setText("For any number of opponents, " + + "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)); + } + }); + } + } + + public WindgracesJudgment(final WindgracesJudgment card) { + super(card); + } + + @Override + public WindgracesJudgment copy() { + return new WindgracesJudgment(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WindingConstrictor.java b/Mage.Sets/src/mage/cards/w/WindingConstrictor.java index 0d780cdf00a..3d113229f5e 100644 --- a/Mage.Sets/src/mage/cards/w/WindingConstrictor.java +++ b/Mage.Sets/src/mage/cards/w/WindingConstrictor.java @@ -79,7 +79,7 @@ class WindingConstrictorPermanentEffect extends ReplacementEffectImpl { } return permanent != null && (permanent.isCreature() || permanent.isArtifact()) - && permanent.getControllerId().equals(source.getControllerId()); + && permanent.isControlledBy(source.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/w/WingmateRoc.java b/Mage.Sets/src/mage/cards/w/WingmateRoc.java index 54f5ceccbac..04d872751dd 100644 --- a/Mage.Sets/src/mage/cards/w/WingmateRoc.java +++ b/Mage.Sets/src/mage/cards/w/WingmateRoc.java @@ -6,7 +6,7 @@ import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.AttackingCreatureCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; @@ -36,7 +36,7 @@ public final class WingmateRoc extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Raid - When Wingmate Roc enters the battlefield, if you attacked with a creature this turn, create a 3/4 white Bird creature token with flying. - this.addAbility(new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WingmateRocToken())), RaidCondition.instance, + this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WingmateRocToken())), RaidCondition.instance, "Raid — When {this} enters the battlefield, if you attacked with a creature this turn, create a 3/4 white Bird creature token with flying."), new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/w/Witchstalker.java b/Mage.Sets/src/mage/cards/w/Witchstalker.java index 42b10d3ee86..6c8f6fedd7e 100644 --- a/Mage.Sets/src/mage/cards/w/Witchstalker.java +++ b/Mage.Sets/src/mage/cards/w/Witchstalker.java @@ -78,7 +78,7 @@ class WitchstalkerTriggeredAbility extends TriggeredAbilityImpl { return spell != null && filter.match(spell,game) && game.getOpponents(this.getControllerId()).contains(spell.getControllerId()) - && game.getActivePlayerId().equals(this.getControllerId()); + && game.isActivePlayer(this.getControllerId()); } @Override diff --git a/Mage.Sets/src/mage/cards/w/WitheringWisps.java b/Mage.Sets/src/mage/cards/w/WitheringWisps.java index 544ed387c52..2e275880e65 100644 --- a/Mage.Sets/src/mage/cards/w/WitheringWisps.java +++ b/Mage.Sets/src/mage/cards/w/WitheringWisps.java @@ -7,7 +7,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.CreatureCountCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; @@ -37,7 +37,7 @@ public final class WitheringWisps extends CardImpl { // At the beginning of the end step, if no creatures are on the battlefield, sacrifice Withering Wisps. TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); // {B}: Withering Wisps deals 1 damage to each creature and each player. Activate this ability no more times each turn than the number of snow Swamps you control. this.addAbility(new WitheringWispsActivatedAbility()); diff --git a/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java b/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java index 5299462f48b..b9880a923ae 100644 --- a/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java +++ b/Mage.Sets/src/mage/cards/w/WolfbittenCaptive.java @@ -8,7 +8,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -40,7 +40,7 @@ public final class WolfbittenCaptive extends CardImpl { // At the beginning of each upkeep, if no spells were cast last turn, transform Wolfbitten Captive. this.addAbility(new TransformAbility()); TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), TargetController.ANY, false); - this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.instance, TransformAbility.NO_SPELLS_TRANSFORM_RULE)); } public WolfbittenCaptive(final WolfbittenCaptive card) { diff --git a/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java b/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java index f50cc4a4e3f..bb5b2b2a95e 100644 --- a/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java +++ b/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -27,7 +27,7 @@ import mage.util.RandomUtil; */ public final class WoodlandSleuth extends CardImpl { - private static final String staticText = "Morbid - When {this} enters the battlefield, if a creature died this turn, return a creature card at random from your graveyard to your hand."; + private static final String staticText = "Morbid — When {this} enters the battlefield, if a creature died this turn, return a creature card at random from your graveyard to your hand."; public WoodlandSleuth(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}"); @@ -38,9 +38,9 @@ public final class WoodlandSleuth extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - // Morbid - When Woodland Sleuth enters the battlefield, if a creature died this turn, return a creature card at random from your graveyard to your hand. + // Morbid — When Woodland Sleuth enters the battlefield, if a creature died this turn, return a creature card at random from your graveyard to your hand. TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new WoodlandSleuthEffect()); - this.addAbility(new ConditionalTriggeredAbility(ability, MorbidCondition.instance, staticText)); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText)); } public WoodlandSleuth(final WoodlandSleuth card) { diff --git a/Mage.Sets/src/mage/cards/w/WordOfCommand.java b/Mage.Sets/src/mage/cards/w/WordOfCommand.java new file mode 100644 index 00000000000..d03d0332667 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WordOfCommand.java @@ -0,0 +1,251 @@ + +package mage.cards.w; + +import java.util.UUID; +import mage.MageObject; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.AsThoughEffect; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.RestrictionEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.AsThoughEffectType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.players.ManaPool; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public final class WordOfCommand extends CardImpl { + + public WordOfCommand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}{B}"); + + // Look at target opponent's hand and choose a card from it. You control that player until Word of Command finishes resolving. The player plays that card if able. While doing so, the player can activate mana abilities only if they're from lands that player controls and only if mana they produce is spent to activate other mana abilities of lands the player controls and/or to play that card. If the chosen card is cast as a spell, you control the player while that spell is resolving. + this.getSpellAbility().addEffect(new WordOfCommandEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public WordOfCommand(final WordOfCommand card) { + super(card); + } + + @Override + public WordOfCommand copy() { + return new WordOfCommand(this); + } +} + +class WordOfCommandEffect extends OneShotEffect { + + public WordOfCommandEffect() { + super(Outcome.GainControl); + this.staticText = "Look at target opponent's hand and choose a card from it. You control that player until Word of Command finishes resolving. The player plays that card if able. While doing so, the player can activate mana abilities only if they're from lands that player controls and only if mana they produce is spent to activate other mana abilities of lands the player controls and/or to play that card. If the chosen card is cast as a spell, you control the player while that spell is resolving"; + } + + public WordOfCommandEffect(final WordOfCommandEffect effect) { + super(effect); + } + + @Override + public WordOfCommandEffect copy() { + return new WordOfCommandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player sourceController = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + MageObject sourceObject = game.getObject(source.getSourceId()); + Card card = null; + if (sourceController != null && targetPlayer != null && sourceObject != null) { + Player controller = null; + Spell wordOfCommand = game.getSpell(source.getSourceId()); + if (wordOfCommand != null) { + if (wordOfCommand.getCommandedBy() != null) { + controller = game.getPlayer(wordOfCommand.getCommandedBy()); + } else { + controller = game.getPlayer(sourceController.getTurnControlledBy()); + } + } + if (controller == null) { + controller = sourceController; // reset the controller to avoid NPE + } + + // Look at target opponent's hand and choose a card from it + TargetCard targetCard = new TargetCard(Zone.HAND, new FilterCard()); + if (controller.choose(Outcome.Discard, targetPlayer.getHand(), targetCard, game)) { + card = game.getCard(targetCard.getFirstTarget()); + } + + // You control that player until Word of Command finishes resolving + controller.controlPlayersTurn(game, targetPlayer.getId()); + while (controller != null && controller.canRespond()) { + if (controller.chooseUse(Outcome.Benefit, "Resolve " + sourceObject.getLogName() + " now" + (card != null ? " and play " + card.getLogName() : "") + '?', source, game)) { + // this is used to give the controller a little space to utilize his player controlling effect (look at face down creatures, hand, etc.) + break; + } + } + + // The player plays that card if able + if (card != null) { + // While doing so, the player can activate mana abilities only if they're from lands that player controls + RestrictionEffect effect = new WordOfCommandCantActivateEffect(); + effect.setTargetPointer(new FixedTarget(targetPlayer.getId())); + game.addEffect(effect, source); + + // and only if mana they produce is spent to activate other mana abilities of lands he or she controls and/or play that card + ManaPool manaPool = targetPlayer.getManaPool(); + manaPool.setForcedToPay(true); + manaPool.storeMana(); + int bookmark = game.bookmarkState(); + + boolean canPlay = checkPlayability(card, targetPlayer, game, source); + while (canPlay + && targetPlayer.canRespond() + && !targetPlayer.playCard(card, game, false, true, new MageObjectReference(source.getSourceObject(game), game))) { + SpellAbility spellAbility = card.getSpellAbility(); + if (spellAbility != null) { + spellAbility.getManaCostsToPay().clear(); + spellAbility.getManaCostsToPay().addAll(spellAbility.getManaCosts()); + ((ManaCostsImpl) spellAbility.getManaCostsToPay()).forceManaRollback(game, manaPool); // force rollback if card was deemed playable + canPlay = checkPlayability(card, targetPlayer, game, source); + } else { + break; + } + } + if (!canPlay) { + game.informPlayers(targetPlayer.getLogName() + " didn't play " + card.getLogName() + " (card can't be played)"); + } + + manaPool.setForcedToPay(false); // duplicate in case of a new mana pool existing - probably not necessary, but just in case + manaPool = targetPlayer.getManaPool(); // a rollback creates a new mana pool for the player, so it's necessary to find it again + manaPool.setForcedToPay(false); + game.removeBookmark(bookmark); + targetPlayer.resetStoredBookmark(game); + for (RestrictionEffect eff : game.getContinuousEffects().getRestrictionEffects()) { + if (eff instanceof WordOfCommandCantActivateEffect) { + eff.discard(); + break; + } + } + game.getContinuousEffects().removeInactiveEffects(game); + Spell spell = game.getSpell(card.getId()); + if (spell != null) { + spell.setCommandedBy(controller.getId()); // If the chosen card is cast as a spell, you control the player while that spell is resolving + } + } + + wordOfCommand = game.getSpell(source.getSourceId()); + if (wordOfCommand != null) { + wordOfCommand.setCommandedBy(controller.getId()); // You control the player until Word of Command finishes resolving + } else { + targetPlayer.setGameUnderYourControl(true, false); + if (!targetPlayer.getTurnControlledBy().equals(controller.getId())) { + controller.getPlayersUnderYourControl().remove(targetPlayer.getId()); + } + } + return true; + } + return false; + } + + private boolean checkPlayability(Card card, Player targetPlayer, Game game, Ability source) { + // check for card playability + boolean canPlay = false; + if (card.isLand()) { // we can't use getPlayableInHand(game) in here because it disallows playing lands outside the main step + if (targetPlayer.canPlayLand() + && game.getActivePlayerId().equals(targetPlayer.getId())) { + canPlay = true; + for (Ability ability : card.getAbilities(game)) { + if (!game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), targetPlayer.getId()), ability, game, true)) { + canPlay &= true; + } + } + } + } else { // Word of Command allows the chosen card to be played "as if it had flash" so we need to invoke such effect to bypass the check + AsThoughEffectImpl effect2 = new WordOfCommandTestFlashEffect(); + game.addEffect(effect2, source); + if (targetPlayer.getPlayableInHand(game).contains(card.getId())) { + canPlay = true; + } + for (AsThoughEffect eff : game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.CAST_AS_INSTANT, game)) { + if (eff instanceof WordOfCommandTestFlashEffect) { + eff.discard(); + break; + } + } + } + return canPlay; + } +} + +class WordOfCommandCantActivateEffect extends RestrictionEffect { + + public WordOfCommandCantActivateEffect() { + super(Duration.EndOfTurn); + } + + public WordOfCommandCantActivateEffect(final WordOfCommandCantActivateEffect effect) { + super(effect); + } + + @Override + public WordOfCommandCantActivateEffect copy() { + return new WordOfCommandCantActivateEffect(this); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return !permanent.isLand() && permanent.getControllerId().equals(this.targetPointer.getFirst(game, source)); + } + + @Override + public boolean canUseActivatedAbilities(Permanent permanent, Ability source, Game game) { + return false; + } +} + +class WordOfCommandTestFlashEffect extends AsThoughEffectImpl { + + public WordOfCommandTestFlashEffect() { + super(AsThoughEffectType.CAST_AS_INSTANT, Duration.EndOfTurn, Outcome.Benefit); + } + + public WordOfCommandTestFlashEffect(final WordOfCommandTestFlashEffect effect) { + super(effect); + } + + @Override + public WordOfCommandTestFlashEffect copy() { + return new WordOfCommandTestFlashEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(UUID affectedSpellId, Ability source, UUID affectedControllerId, Game game) { + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/w/WordOfUndoing.java b/Mage.Sets/src/mage/cards/w/WordOfUndoing.java index ba8b5c68a52..af5518c6ff0 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfUndoing.java +++ b/Mage.Sets/src/mage/cards/w/WordOfUndoing.java @@ -27,7 +27,7 @@ public final class WordOfUndoing extends CardImpl { public WordOfUndoing(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}"); - //Return target creature and all white Auras you own attached to it to their owners’ hands. + //Return target creature and all white Auras you own attached to it to their owners' hands. this.getSpellAbility().addEffect(new WordOfUndoingReturnToHandEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -47,7 +47,7 @@ class WordOfUndoingReturnToHandEffect extends OneShotEffect { public WordOfUndoingReturnToHandEffect() { super(Outcome.ReturnToHand); - this.staticText = "Return target creature and all white Auras you own attached to it to their owners’ hands."; + this.staticText = "Return target creature and all white Auras you own attached to it to their owners' hands."; } public WordOfUndoingReturnToHandEffect(final WordOfUndoingReturnToHandEffect effect) { @@ -67,7 +67,7 @@ class WordOfUndoingReturnToHandEffect extends OneShotEffect { if (target != null) { for (UUID attachmentId : target.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getControllerId().equals(source.getControllerId()) + if (attachment != null && attachment.isControlledBy(source.getControllerId()) && attachment.hasSubtype(SubType.AURA, game) && attachment.getColor(game).isWhite()) { attachments.add(attachment); } diff --git a/Mage.Sets/src/mage/cards/w/WordsOfWar.java b/Mage.Sets/src/mage/cards/w/WordsOfWar.java index 86cd074ca96..927d2d5b3e5 100644 --- a/Mage.Sets/src/mage/cards/w/WordsOfWar.java +++ b/Mage.Sets/src/mage/cards/w/WordsOfWar.java @@ -95,7 +95,7 @@ class WordsOfWarEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (!this.used) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/w/WordsOfWaste.java b/Mage.Sets/src/mage/cards/w/WordsOfWaste.java index dbbe02e3d49..3db705865eb 100644 --- a/Mage.Sets/src/mage/cards/w/WordsOfWaste.java +++ b/Mage.Sets/src/mage/cards/w/WordsOfWaste.java @@ -75,6 +75,6 @@ class WordsOfWasteEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/w/WordsOfWilding.java b/Mage.Sets/src/mage/cards/w/WordsOfWilding.java index 4363863c312..ffe65dcdb54 100644 --- a/Mage.Sets/src/mage/cards/w/WordsOfWilding.java +++ b/Mage.Sets/src/mage/cards/w/WordsOfWilding.java @@ -75,6 +75,6 @@ class WordsOfWildingEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/w/WordsOfWind.java b/Mage.Sets/src/mage/cards/w/WordsOfWind.java index 13f7ad58513..da3860a0893 100644 --- a/Mage.Sets/src/mage/cards/w/WordsOfWind.java +++ b/Mage.Sets/src/mage/cards/w/WordsOfWind.java @@ -95,7 +95,7 @@ class WordsOfWindEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (!this.used) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/w/WordsOfWorship.java b/Mage.Sets/src/mage/cards/w/WordsOfWorship.java index 7e2716d8efa..907167a2657 100644 --- a/Mage.Sets/src/mage/cards/w/WordsOfWorship.java +++ b/Mage.Sets/src/mage/cards/w/WordsOfWorship.java @@ -81,7 +81,7 @@ class WordsOfWorshipEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (!this.used) { - return source.getControllerId().equals(event.getPlayerId()); + return source.isControlledBy(event.getPlayerId()); } return false; } diff --git a/Mage.Sets/src/mage/cards/w/WorldheartPhoenix.java b/Mage.Sets/src/mage/cards/w/WorldheartPhoenix.java index 3e0d059b641..12af950b7b8 100644 --- a/Mage.Sets/src/mage/cards/w/WorldheartPhoenix.java +++ b/Mage.Sets/src/mage/cards/w/WorldheartPhoenix.java @@ -80,7 +80,7 @@ public final class WorldheartPhoenix extends CardImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(source.getSourceId()) && source.getControllerId().equals(affectedControllerId)) { + if (sourceId.equals(source.getSourceId()) && source.isControlledBy(affectedControllerId)) { if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { Player player = game.getPlayer(affectedControllerId); if (player != null) { diff --git a/Mage.Sets/src/mage/cards/w/Worldpurge.java b/Mage.Sets/src/mage/cards/w/Worldpurge.java index 91fb453ae36..5fff60ffe75 100644 --- a/Mage.Sets/src/mage/cards/w/Worldpurge.java +++ b/Mage.Sets/src/mage/cards/w/Worldpurge.java @@ -30,7 +30,7 @@ public final class Worldpurge extends CardImpl { public Worldpurge(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W/U}{W/U}{W/U}{W/U}"); - // Return all permanents to their owners’ hands. Each player chooses up to seven cards in their hand, then shuffles the rest into their library. Each player loses all unspent mana. + // Return all permanents to their owners' hands. Each player chooses up to seven cards in their hand, then shuffles the rest into their library. Each player loses all unspent mana. this.getSpellAbility().addEffect(new WorldpurgeEffect()); } @@ -49,7 +49,7 @@ class WorldpurgeEffect extends OneShotEffect { public WorldpurgeEffect() { super(Outcome.Discard); - this.staticText = "Return all permanents to their owners’ hands. Each player chooses up to seven cards in their hand, then shuffles the rest into their library. Each player loses all unspent mana"; + this.staticText = "Return all permanents to their owners' hands. Each player chooses up to seven cards in their hand, then shuffles the rest into their library. Each player loses all unspent mana"; } public WorldpurgeEffect(final WorldpurgeEffect effect) { diff --git a/Mage.Sets/src/mage/cards/w/WormfangNewt.java b/Mage.Sets/src/mage/cards/w/WormfangNewt.java index 6f3ec217b7e..ebb66ead46c 100644 --- a/Mage.Sets/src/mage/cards/w/WormfangNewt.java +++ b/Mage.Sets/src/mage/cards/w/WormfangNewt.java @@ -43,7 +43,7 @@ public final class WormfangNewt extends CardImpl { ability1.addTarget(target); this.addAbility(ability1); - // When Wormfang Turtle leaves the battlefield, return the exiled card to the battlefield under its owner’s control. + // When Wormfang Turtle leaves the battlefield, return the exiled card to the battlefield under its owner's control. Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/w/WormfangTurtle.java b/Mage.Sets/src/mage/cards/w/WormfangTurtle.java index 13ba83782df..b33bec0c8d8 100644 --- a/Mage.Sets/src/mage/cards/w/WormfangTurtle.java +++ b/Mage.Sets/src/mage/cards/w/WormfangTurtle.java @@ -43,7 +43,7 @@ public final class WormfangTurtle extends CardImpl { ability1.addTarget(target); this.addAbility(ability1); - // When Wormfang Turtle leaves the battlefield, return the exiled card to the battlefield under its owner’s control. + // When Wormfang Turtle leaves the battlefield, return the exiled card to the battlefield under its owner's control. Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/w/Worship.java b/Mage.Sets/src/mage/cards/w/Worship.java index 53220fb1e14..3290eea0cfe 100644 --- a/Mage.Sets/src/mage/cards/w/Worship.java +++ b/Mage.Sets/src/mage/cards/w/Worship.java @@ -58,7 +58,7 @@ class WorshipReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (source.getControllerId().equals(event.getPlayerId())) { + if (source.isControlledBy(event.getPlayerId())) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null && (controller.getLife() - event.getAmount()) < 1 diff --git a/Mage.Sets/src/mage/cards/w/WortTheRaidmother.java b/Mage.Sets/src/mage/cards/w/WortTheRaidmother.java index bc160dda183..6fae1461700 100644 --- a/Mage.Sets/src/mage/cards/w/WortTheRaidmother.java +++ b/Mage.Sets/src/mage/cards/w/WortTheRaidmother.java @@ -81,7 +81,7 @@ class WortGainConspireEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { for (StackObject stackObject : game.getStack()) { // only spells cast, so no copies of spells - if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; if (filter.match(stackObject, game)) { game.getState().addOtherAbility(spell.getCard(), conspireAbility); diff --git a/Mage.Sets/src/mage/cards/w/WreathofGeists.java b/Mage.Sets/src/mage/cards/w/WreathOfGeists.java similarity index 86% rename from Mage.Sets/src/mage/cards/w/WreathofGeists.java rename to Mage.Sets/src/mage/cards/w/WreathOfGeists.java index 7a9da11ab0a..8991b23d966 100644 --- a/Mage.Sets/src/mage/cards/w/WreathofGeists.java +++ b/Mage.Sets/src/mage/cards/w/WreathOfGeists.java @@ -23,9 +23,9 @@ import mage.target.common.TargetCreaturePermanent; * * @author nantuko */ -public final class WreathofGeists extends CardImpl { +public final class WreathOfGeists extends CardImpl { - public WreathofGeists(UUID ownerId, CardSetInfo setInfo) { + public WreathOfGeists(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}"); this.subtype.add(SubType.AURA); @@ -43,12 +43,12 @@ public final class WreathofGeists extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(value, value))); } - public WreathofGeists(final WreathofGeists card) { + public WreathOfGeists(final WreathOfGeists card) { super(card); } @Override - public WreathofGeists copy() { - return new WreathofGeists(this); + public WreathOfGeists copy() { + return new WreathOfGeists(this); } } diff --git a/Mage.Sets/src/mage/cards/w/WretchedCamel.java b/Mage.Sets/src/mage/cards/w/WretchedCamel.java index 1b309f28f9d..f4218eff052 100644 --- a/Mage.Sets/src/mage/cards/w/WretchedCamel.java +++ b/Mage.Sets/src/mage/cards/w/WretchedCamel.java @@ -8,7 +8,7 @@ import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.condition.OrCondition; import mage.abilities.condition.common.CardsInControllerGraveCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -42,7 +42,7 @@ public final class WretchedCamel extends CardImpl { this.toughness = new MageInt(1); // When Wretched Camel dies, if you control a Desert or there is a Desert card in your graveyard, target player discards a card. - Ability ability = new ConditionalTriggeredAbility( + Ability ability = new ConditionalInterveningIfTriggeredAbility( new DiesTriggeredAbility(new DiscardTargetEffect(1)), new OrCondition( new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(filterDesertPermanent)), diff --git a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java index f4fa1b822ff..5bb8dfcfd18 100644 --- a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java +++ b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java @@ -1,11 +1,10 @@ - package mage.cards.w; import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.IslandwalkAbility; @@ -19,6 +18,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; @@ -47,7 +47,7 @@ public final class WrexialTheRisenDeep extends CardImpl { this.addAbility(new SwampwalkAbility()); // Whenever Wrexial, the Risen Deep deals combat damage to a player, you may cast target instant or sorcery card from that player's graveyard without paying its mana cost. If that card would be put into a graveyard this turn, exile it instead. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new WrexialEffect(), true, true)); + this.addAbility(new WrexialTheRisenDeepTriggeredAbility()); } public WrexialTheRisenDeep(final WrexialTheRisenDeep card) { @@ -60,47 +60,84 @@ public final class WrexialTheRisenDeep extends CardImpl { } } -class WrexialEffect extends OneShotEffect { +class WrexialTheRisenDeepTriggeredAbility extends TriggeredAbilityImpl { - public WrexialEffect() { - super(Outcome.PlayForFree); - staticText = "you may cast target instant or sorcery card from that player's graveyard without paying its mana cost. If that card would be put into a graveyard this turn, exile it instead"; + public WrexialTheRisenDeepTriggeredAbility() { + super(Zone.BATTLEFIELD, new WrexialTheRisenDeepEffect(), true); } - public WrexialEffect(final WrexialEffect effect) { + public WrexialTheRisenDeepTriggeredAbility(final WrexialTheRisenDeepTriggeredAbility ability) { + super(ability); + } + + @Override + public WrexialTheRisenDeepTriggeredAbility copy() { + return new WrexialTheRisenDeepTriggeredAbility(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 (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterCard("target instant or sorcery card from " + damagedPlayer.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(damagedPlayer.getId())); + filter.add(Predicates.or( + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY))); + + Target target = new TargetCardInGraveyard(filter); + this.getTargets().clear(); + this.addTarget(target); + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may cast target instant or sorcery card " + + "from that player's graveyard without paying its mana cost. " + + "If that card would be put into a graveyard this turn, exile it instead"; + } +} + +class WrexialTheRisenDeepEffect extends OneShotEffect { + + public WrexialTheRisenDeepEffect() { + super(Outcome.PlayForFree); + staticText = "you may cast target instant or sorcery card from " + + "that player's graveyard without paying its mana cost. " + + "If that card would be put into a graveyard this turn, exile it instead"; + } + + public WrexialTheRisenDeepEffect(final WrexialTheRisenDeepEffect effect) { super(effect); } @Override - public WrexialEffect copy() { - return new WrexialEffect(this); + public WrexialTheRisenDeepEffect copy() { + return new WrexialTheRisenDeepEffect(this); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - if (damagedPlayer == null) { - return false; - } - FilterCard filter = new FilterCard("target instant or sorcery card from " + damagedPlayer.getName() + "'s graveyard"); - filter.add(new OwnerIdPredicate(damagedPlayer.getId())); - filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY))); - - Target target = new TargetCardInGraveyard(filter); - if (controller.chooseTarget(Outcome.PlayForFree, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game)); - game.addEffect(new WrexialReplacementEffect(card.getId()), source); - } - } - return true; + Card card = game.getCard(source.getFirstTarget()); + if (controller == null || card == null) { + return false; } - return false; + controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game)); + game.addEffect(new WrexialReplacementEffect(card.getId()), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/w/WritOfPassage.java b/Mage.Sets/src/mage/cards/w/WritOfPassage.java index b2f3a787253..040f218574d 100644 --- a/Mage.Sets/src/mage/cards/w/WritOfPassage.java +++ b/Mage.Sets/src/mage/cards/w/WritOfPassage.java @@ -2,16 +2,15 @@ package mage.cards.w; import java.util.UUID; + +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.target.common.TargetCreaturePermanent; import mage.abilities.Ability; import mage.abilities.common.AttacksAttachedTriggeredAbility; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.combat.CantBeBlockedAttachedEffect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.constants.Outcome; import mage.target.TargetPermanent; @@ -51,7 +50,7 @@ public final class WritOfPassage extends CardImpl { // Whenever enchanted creature attacks, if its power is 2 or less, it's unblockable this turn. FilterPermanent filter = new FilterPermanent("if enchanted creature's power is 2 or less"); filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); - ability = new ConditionalTriggeredAbility(new AttacksAttachedTriggeredAbility( + ability = new ConditionalInterveningIfTriggeredAbility(new AttacksAttachedTriggeredAbility( new WritOfPassageAttachedEffect(AttachmentType.AURA), AttachmentType.AURA, false), new AttachedToMatchesFilterCondition(filter), "Whenever enchanted creature attacks, if its power is 2 or less, it can't be blocked this turn."); this.addAbility(ability); @@ -97,7 +96,6 @@ class WritOfPassageAttachedEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { Permanent attachment = game.getPermanent(source.getSourceId()); - return attachment != null && attachment.getAttachedTo() != null - && attachment.getAttachedTo().equals(permanent.getId()); + return attachment != null && attachment.isAttachedTo(permanent.getId()); } } diff --git a/Mage.Sets/src/mage/cards/x/XantchaSleeperAgent.java b/Mage.Sets/src/mage/cards/x/XantchaSleeperAgent.java new file mode 100644 index 00000000000..a392f415b20 --- /dev/null +++ b/Mage.Sets/src/mage/cards/x/XantchaSleeperAgent.java @@ -0,0 +1,143 @@ +package mage.cards.x; + +import java.util.Objects; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.*; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.RestrictionEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.LoseLifePermanentControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetOpponent; + + + +/** + * + * @author jesusjbr + */ + +public final class XantchaSleeperAgent extends CardImpl { + + + + public XantchaSleeperAgent(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.MINION); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // As Xantcha, Sleeper Agent enters the battlefield, an opponent of your choice gains control of it. + Ability ability = new EntersBattlefieldTriggeredAbility(new XantchaSleeperAgentChangeControlEffect()) ; + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + + // Xantcha attacks each combat if able and can’t attack its owner or planeswalkers its owner controls. + ability = new AttacksEachCombatStaticAbility(); + Effect effect = new XantchaSleeperAgentAttackRestrictionEffect(); + ability.addEffect(effect); + this.addAbility(ability); + + // {3}: Xantcha’s controller loses 2 life and you draw a card. Any player may activate this ability. + effect = new LoseLifePermanentControllerEffect(2); + effect.setText("Xantcha’s controller loses 2 life"); + SimpleActivatedAbility simpleAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{3}")); + + simpleAbility.addEffect(new DrawCardSourceControllerEffect(1).setText("and you draw a card")); + simpleAbility.addEffect(new InfoEffect("Any player may activate this ability")); + simpleAbility.setMayActivate(TargetController.ANY); + this.addAbility(simpleAbility); + + + } + + public XantchaSleeperAgent(final XantchaSleeperAgent card) { + super(card); + } + + @Override + public XantchaSleeperAgent copy() { + return new XantchaSleeperAgent(this); + } +} + + + +class XantchaSleeperAgentChangeControlEffect extends ContinuousEffectImpl { + + public XantchaSleeperAgentChangeControlEffect() { + super(Duration.Custom, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); + staticText = "an opponent of your choice gains control of it"; + } + + public XantchaSleeperAgentChangeControlEffect(final XantchaSleeperAgentChangeControlEffect effect) { + super(effect); + } + + @Override + public XantchaSleeperAgentChangeControlEffect copy() { + return new XantchaSleeperAgentChangeControlEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = (Permanent) source.getSourceObjectIfItStillExists(game); + if (permanent != null) { + return permanent.changeControllerId(source.getFirstTarget(), game); + } else { + discard(); + } + return false; + } +} + +class XantchaSleeperAgentAttackRestrictionEffect extends RestrictionEffect { + + XantchaSleeperAgentAttackRestrictionEffect() { + super(Duration.WhileOnBattlefield); + staticText = "and can't attack its owner or planeswalkers its owner controls."; + } + + XantchaSleeperAgentAttackRestrictionEffect(final XantchaSleeperAgentAttackRestrictionEffect effect) { + super(effect); + } + + @Override + public XantchaSleeperAgentAttackRestrictionEffect copy() { + return new XantchaSleeperAgentAttackRestrictionEffect(this); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return Objects.equals(permanent.getId(), source.getSourceId()); + } + + @Override + public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game) { + + boolean allowAttack = true; + UUID ownerPlayerId = source.getSourcePermanentIfItStillExists(game).getOwnerId(); + + if (defenderId.equals(ownerPlayerId)) { + allowAttack = false; + } + else { + Permanent planeswalker = game.getPermanent(defenderId); + if (planeswalker != null && planeswalker.isControlledBy(ownerPlayerId)) { + allowAttack = false; + } + } + return allowAttack; + } +} diff --git a/Mage.Sets/src/mage/cards/x/XenicPoltergeist.java b/Mage.Sets/src/mage/cards/x/XenicPoltergeist.java index 2b0cbb13875..33d6e8756f5 100644 --- a/Mage.Sets/src/mage/cards/x/XenicPoltergeist.java +++ b/Mage.Sets/src/mage/cards/x/XenicPoltergeist.java @@ -84,7 +84,7 @@ class XenicPoltergeistEffect extends ContinuousEffectImpl { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) { - if (game.getActivePlayerId().equals(source.getControllerId())) { + if (game.isActivePlayer(source.getControllerId())) { return true; } } diff --git a/Mage.Sets/src/mage/cards/y/YawgmothsAgenda.java b/Mage.Sets/src/mage/cards/y/YawgmothsAgenda.java index b03f24343fb..fbf46de1dab 100644 --- a/Mage.Sets/src/mage/cards/y/YawgmothsAgenda.java +++ b/Mage.Sets/src/mage/cards/y/YawgmothsAgenda.java @@ -135,7 +135,7 @@ class YawgmothsAgendaReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(source.getControllerId())) { + if (card != null && card.isOwnedBy(source.getControllerId())) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent == null || !(permanent instanceof PermanentToken)) { return true; diff --git a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java index 385cfdade83..a1d1d16c90b 100644 --- a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java +++ b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java @@ -42,7 +42,7 @@ public final class YawgmothsVileOffering extends CardImpl { this.addAbility(new LegendarySpellAbility()); // Put up to one target creature or planeswalker from a graveyard onto the battlefield under your control. - // Destroy up to one target creature or planeswalker. Exile Yawgmoth’s Vile Offering. + // Destroy up to one target creature or planeswalker. Exile Yawgmoth's Vile Offering. this.getSpellAbility().addEffect(new YawgmothsVileOfferingEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard(0, 1, cardFilter)); this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker(0, 1, new FilterCreatureOrPlaneswalkerPermanent(), false)); diff --git a/Mage.Sets/src/mage/cards/y/YawgmothsWill.java b/Mage.Sets/src/mage/cards/y/YawgmothsWill.java index ada8e06646c..8690dbd141a 100644 --- a/Mage.Sets/src/mage/cards/y/YawgmothsWill.java +++ b/Mage.Sets/src/mage/cards/y/YawgmothsWill.java @@ -125,7 +125,7 @@ class YawgmothsWillReplacementEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(source.getControllerId())) { + if (card != null && card.isOwnedBy(source.getControllerId())) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent == null || !(permanent instanceof PermanentToken)) { return true; diff --git a/Mage.Sets/src/mage/cards/y/YennetCryptSovereign.java b/Mage.Sets/src/mage/cards/y/YennetCryptSovereign.java new file mode 100644 index 00000000000..59b7e84f17f --- /dev/null +++ b/Mage.Sets/src/mage/cards/y/YennetCryptSovereign.java @@ -0,0 +1,101 @@ +package mage.cards.y; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.Card; +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; + +/** + * + * @author TheElk801 + */ +public final class YennetCryptSovereign extends CardImpl { + + public YennetCryptSovereign(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Menace + this.addAbility(new MenaceAbility()); + + // Whenever Yennet, Crypt Sovereign attacks, reveal the top card of your library. If that card's converted mana cost is odd, you may cast it without paying its mana cost. Otherwise, draw a card. + this.addAbility(new AttacksTriggeredAbility( + new YennetCryptSovereignEffect(), false + )); + } + + public YennetCryptSovereign(final YennetCryptSovereign card) { + super(card); + } + + @Override + public YennetCryptSovereign copy() { + return new YennetCryptSovereign(this); + } +} + +class YennetCryptSovereignEffect extends OneShotEffect { + + public YennetCryptSovereignEffect() { + super(Outcome.Benefit); + this.staticText = "reveal the top card of your library. " + + "If that card's converted mana cost is odd, " + + "you may cast it without paying its mana cost. " + + "Otherwise, draw a card"; + } + + public YennetCryptSovereignEffect(final YennetCryptSovereignEffect effect) { + super(effect); + } + + @Override + public YennetCryptSovereignEffect copy() { + return new YennetCryptSovereignEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null || !player.getLibrary().hasCards()) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + player.revealCards(source, new CardsImpl(card), game); + if (card.getConvertedManaCost() % 2 == 1) { + if (player.chooseUse(outcome, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) { + player.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game)); + } + } else { + player.drawCards(1, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/y/YidrisMaelstromWielder.java b/Mage.Sets/src/mage/cards/y/YidrisMaelstromWielder.java index 2d2ccb801c2..2f73bc50243 100644 --- a/Mage.Sets/src/mage/cards/y/YidrisMaelstromWielder.java +++ b/Mage.Sets/src/mage/cards/y/YidrisMaelstromWielder.java @@ -71,7 +71,7 @@ class YidrisMaelstromWielderGainCascadeEffect extends ContinuousEffectImpl { if (controller != null) { for (StackObject stackObject : game.getStack()) { // only spells cast, so no copies of spells - if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; if (spell.getFromZone() == Zone.HAND) { game.getState().addOtherAbility(spell.getCard(), cascadeAbility); diff --git a/Mage.Sets/src/mage/cards/y/YoungPyromancer.java b/Mage.Sets/src/mage/cards/y/YoungPyromancer.java index 0b8a2eaa9b0..6f7b3b631f3 100644 --- a/Mage.Sets/src/mage/cards/y/YoungPyromancer.java +++ b/Mage.Sets/src/mage/cards/y/YoungPyromancer.java @@ -1,4 +1,3 @@ - package mage.cards.y; import java.util.UUID; @@ -27,7 +26,10 @@ public final class YoungPyromancer extends CardImpl { this.toughness = new MageInt(1); // 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_INSTANT_OR_SORCERY_SPELL, false)); + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new YoungPyromancerElementalToken()), + StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false + )); } diff --git a/Mage.Sets/src/mage/cards/y/YurikoTheTigersShadow.java b/Mage.Sets/src/mage/cards/y/YurikoTheTigersShadow.java new file mode 100644 index 00000000000..bec2707e419 --- /dev/null +++ b/Mage.Sets/src/mage/cards/y/YurikoTheTigersShadow.java @@ -0,0 +1,103 @@ +package mage.cards.y; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.keyword.NinjutsuAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author TheElk801 + */ +public final class YurikoTheTigersShadow extends CardImpl { + + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent(SubType.NINJA, "a Ninja you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public YurikoTheTigersShadow(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NINJA); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Commander ninjutsu {U}{B} + this.addAbility(new NinjutsuAbility(new ManaCostsImpl("{U}{B}"), true)); + + // Whenever a Ninja you control deals combat damage to a player, reveal the top card of your library and put that card into your hand. Each opponent loses life equal to that card's converted mana cost. + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( + new YurikoTheTigersShadowEffect(), filter, + false, SetTargetPointer.NONE, true + )); + } + + public YurikoTheTigersShadow(final YurikoTheTigersShadow card) { + super(card); + } + + @Override + public YurikoTheTigersShadow copy() { + return new YurikoTheTigersShadow(this); + } +} + +class YurikoTheTigersShadowEffect extends OneShotEffect { + + public YurikoTheTigersShadowEffect() { + super(Outcome.Benefit); + this.staticText = "reveal the top card of your library " + + "and put that card into your hand. Each opponent loses life " + + "equal to that card's converted mana cost"; + } + + public YurikoTheTigersShadowEffect(final YurikoTheTigersShadowEffect effect) { + super(effect); + } + + @Override + public YurikoTheTigersShadowEffect copy() { + return new YurikoTheTigersShadowEffect(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; + } + player.revealCards(source, new CardsImpl(card), game); + player.moveCards(card, Zone.HAND, source, game); + return new LoseLifeOpponentsEffect( + card.getConvertedManaCost() + ).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java b/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java index c0e0f672c13..700a1e7d460 100644 --- a/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java +++ b/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java @@ -8,7 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -51,7 +51,7 @@ public final class ZacamaPrimalCalamity extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Zacama, Primal Calamity enters the battlefield, if you cast it, untap all lands you control. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new UntapAllLandsControllerEffect(), false), CastFromEverywhereSourceCondition.instance, "When {this} enters the battlefield, if you cast it, untap all lands you control.")); diff --git a/Mage.Sets/src/mage/cards/z/ZadaHedronGrinder.java b/Mage.Sets/src/mage/cards/z/ZadaHedronGrinder.java index 8c7f524cf91..7b76cdcb2f4 100644 --- a/Mage.Sets/src/mage/cards/z/ZadaHedronGrinder.java +++ b/Mage.Sets/src/mage/cards/z/ZadaHedronGrinder.java @@ -100,7 +100,7 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl { private boolean isControlledInstantOrSorcery(Spell spell) { return spell != null - && (spell.getControllerId().equals(this.getControllerId())) + && (spell.isControlledBy(this.getControllerId())) && (spell.isInstant() || spell.isSorcery()); } diff --git a/Mage.Sets/src/mage/cards/z/ZameckGuildmage.java b/Mage.Sets/src/mage/cards/z/ZameckGuildmage.java index 4706cd7ccb6..4c785c41979 100644 --- a/Mage.Sets/src/mage/cards/z/ZameckGuildmage.java +++ b/Mage.Sets/src/mage/cards/z/ZameckGuildmage.java @@ -69,7 +69,7 @@ class ZameckGuildmageEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - return permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.isCreature(); + return permanent != null && permanent.isControlledBy(source.getControllerId()) && permanent.isCreature(); } @Override diff --git a/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java b/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java index d7804a5a6f5..f560e66f98c 100644 --- a/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java +++ b/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -41,7 +41,7 @@ public final class ZealotsEnDal extends CardImpl { this.toughness = new MageInt(4); // At the beginning of your upkeep, if all nonland permanents you control are white, you gain 1 life. - this.addAbility(new ConditionalTriggeredAbility( + this.addAbility(new ConditionalInterveningIfTriggeredAbility( new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1), TargetController.YOU, false), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), "At the beginning of your upkeep, if all nonland permanents you control are white, you gain 1 life." diff --git a/Mage.Sets/src/mage/cards/z/ZombieCannibal.java b/Mage.Sets/src/mage/cards/z/ZombieCannibal.java index 36bc2e950a3..d871dff4fda 100644 --- a/Mage.Sets/src/mage/cards/z/ZombieCannibal.java +++ b/Mage.Sets/src/mage/cards/z/ZombieCannibal.java @@ -1,21 +1,20 @@ - package mage.cards.z; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.ExileTargetEffect; 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.filter.FilterCard; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; -import mage.target.Target; import mage.target.common.TargetCardInGraveyard; /** @@ -25,15 +24,14 @@ import mage.target.common.TargetCardInGraveyard; public final class ZombieCannibal extends CardImpl { public ZombieCannibal(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); // Whenever Zombie Cannibal deals combat damage to a player, you may exile target card from that player's graveyard. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ZombieCannibalEffect(), true, true)); - + this.addAbility(new ZombieCannibalTriggeredAbility()); } public ZombieCannibal(final ZombieCannibal card) { @@ -46,32 +44,46 @@ public final class ZombieCannibal extends CardImpl { } } -class ZombieCannibalEffect extends OneShotEffect { - - public ZombieCannibalEffect() { - super(Outcome.Exile); - staticText = "you may exile target card from that player's graveyard."; +class ZombieCannibalTriggeredAbility extends TriggeredAbilityImpl { + + public ZombieCannibalTriggeredAbility() { + super(Zone.BATTLEFIELD, new ExileTargetEffect(null, "", Zone.GRAVEYARD), true); } - - public ZombieCannibalEffect(final ZombieCannibalEffect effect) { - super(effect); + + public ZombieCannibalTriggeredAbility(final ZombieCannibalTriggeredAbility ability) { + super(ability); } - + @Override - public ZombieCannibalEffect copy() { - return new ZombieCannibalEffect(this); + public ZombieCannibalTriggeredAbility copy() { + return new ZombieCannibalTriggeredAbility(this); } - + @Override - public boolean apply(Game game, Ability source) { - FilterCard filter = new FilterCard(); - Player player = game.getPlayer(source.getTargets().getFirstTarget()); - if (player != null) { - filter.add(new OwnerIdPredicate(player.getId())); - Target target = new TargetCardInGraveyard(filter); - game.getPermanent(target.getFirstTarget()).moveToExile(null, null, source.getSourceId(), game); + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; } - return false; + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterCard("card in " + damagedPlayer.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(damagedPlayer.getId())); + TargetCardInGraveyard target = new TargetCardInGraveyard(filter); + this.getTargets().clear(); + this.addTarget(target); + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may exile target card from that player's graveyard"; } - } diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index a2638ba711b..1553e50b598 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -89,6 +89,7 @@ public final class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Inheritance", 4, Rarity.UNCOMMON, mage.cards.i.Inheritance.class)); cards.add(new SetCardInfo("Insidious Bookworms", "51a", Rarity.COMMON, mage.cards.i.InsidiousBookworms.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Insidious Bookworms", "51b", Rarity.COMMON, mage.cards.i.InsidiousBookworms.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ivory Gargoyle", 5, Rarity.RARE, mage.cards.i.IvoryGargoyle.class)); cards.add(new SetCardInfo("Juniper Order Advocate", 6, Rarity.UNCOMMON, mage.cards.j.JuniperOrderAdvocate.class)); cards.add(new SetCardInfo("Kaysa", 96, Rarity.RARE, mage.cards.k.Kaysa.class)); cards.add(new SetCardInfo("Keeper of Tresserhorn", 52, Rarity.RARE, mage.cards.k.KeeperOfTresserhorn.class)); diff --git a/Mage.Sets/src/mage/sets/ArabianNights.java b/Mage.Sets/src/mage/sets/ArabianNights.java index ce09fa0d56a..7776d5f2bb6 100644 --- a/Mage.Sets/src/mage/sets/ArabianNights.java +++ b/Mage.Sets/src/mage/sets/ArabianNights.java @@ -82,7 +82,7 @@ public final class ArabianNights extends ExpansionSet { cards.add(new SetCardInfo("Jandor's Ring", 64, Rarity.RARE, mage.cards.j.JandorsRing.class)); cards.add(new SetCardInfo("Jandor's Saddlebags", 65, Rarity.RARE, mage.cards.j.JandorsSaddlebags.class)); cards.add(new SetCardInfo("Jihad", 5, Rarity.RARE, mage.cards.j.Jihad.class)); - cards.add(new SetCardInfo("Junún Efreet", 28, Rarity.RARE, mage.cards.j.JununEfreet.class)); + cards.add(new SetCardInfo("Junun Efreet", 28, Rarity.RARE, mage.cards.j.JununEfreet.class)); cards.add(new SetCardInfo("Juzam Djinn", 29, Rarity.RARE, mage.cards.j.JuzamDjinn.class)); cards.add(new SetCardInfo("Khabal Ghoul", 30, Rarity.UNCOMMON, mage.cards.k.KhabalGhoul.class)); cards.add(new SetCardInfo("King Suleiman", 6, Rarity.RARE, mage.cards.k.KingSuleiman.class)); diff --git a/Mage.Sets/src/mage/sets/Battlebond.java b/Mage.Sets/src/mage/sets/Battlebond.java index cc83734d192..3c13280af43 100644 --- a/Mage.Sets/src/mage/sets/Battlebond.java +++ b/Mage.Sets/src/mage/sets/Battlebond.java @@ -1,4 +1,3 @@ - package mage.sets; import mage.cards.ExpansionSet; @@ -10,23 +9,26 @@ import mage.constants.SetType; * @author TheElk801 */ public final class Battlebond extends ExpansionSet { - + private static final Battlebond instance = new Battlebond(); - + public static Battlebond getInstance() { return instance; } - + + private Battlebond() { super("Battlebond", "BBD", ExpansionSet.buildDate(2018, 6, 8), SetType.SUPPLEMENTAL); this.blockName = "Battlebond"; this.hasBasicLands = false; this.hasBoosters = true; + this.hasPartnerMechanic = true; this.numBoosterLands = 0; this.numBoosterCommon = 11; this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; + cards.add(new SetCardInfo("Aim High", 189, Rarity.UNCOMMON, mage.cards.a.AimHigh.class)); cards.add(new SetCardInfo("Angel of Retribution", 86, Rarity.UNCOMMON, mage.cards.a.AngelOfRetribution.class)); cards.add(new SetCardInfo("Angelic Chorus", 87, Rarity.RARE, mage.cards.a.AngelicChorus.class)); @@ -115,6 +117,7 @@ public final class Battlebond extends ExpansionSet { cards.add(new SetCardInfo("Giant Growth", 200, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); cards.add(new SetCardInfo("Goblin Razerunners", 179, Rarity.RARE, mage.cards.g.GoblinRazerunners.class)); cards.add(new SetCardInfo("Gold-Forged Sentinel", 236, Rarity.UNCOMMON, mage.cards.g.GoldForgedSentinel.class)); + cards.add(new SetCardInfo("Gorm the Great", 8, Rarity.RARE, mage.cards.g.GormTheGreat.class)); cards.add(new SetCardInfo("Greater Good", 201, Rarity.RARE, mage.cards.g.GreaterGood.class)); cards.add(new SetCardInfo("Grotesque Mutation", 145, Rarity.COMMON, mage.cards.g.GrotesqueMutation.class)); cards.add(new SetCardInfo("Grothama, All-Devouring", 71, Rarity.MYTHIC, mage.cards.g.GrothamaAllDevouring.class)); @@ -210,6 +213,7 @@ public final class Battlebond extends ExpansionSet { cards.add(new SetCardInfo("Riptide Crab", 228, Rarity.COMMON, mage.cards.r.RiptideCrab.class)); cards.add(new SetCardInfo("Rotfeaster Maggot", 157, Rarity.COMMON, mage.cards.r.RotfeasterMaggot.class)); cards.add(new SetCardInfo("Rowan Kenrith", 2, Rarity.MYTHIC, mage.cards.r.RowanKenrith.class)); + cards.add(new SetCardInfo("Rowan Kenrith", 256, Rarity.MYTHIC, mage.cards.r.RowanKenrith.class)); cards.add(new SetCardInfo("Royal Trooper", 104, Rarity.COMMON, mage.cards.r.RoyalTrooper.class)); cards.add(new SetCardInfo("Rushblade Commander", 77, Rarity.UNCOMMON, mage.cards.r.RushbladeCommander.class)); cards.add(new SetCardInfo("Saddleback Lagac", 211, Rarity.COMMON, mage.cards.s.SaddlebackLagac.class)); @@ -276,9 +280,11 @@ public final class Battlebond extends ExpansionSet { cards.add(new SetCardInfo("War's Toll", 187, Rarity.RARE, mage.cards.w.WarsToll.class)); cards.add(new SetCardInfo("Watercourser", 137, Rarity.COMMON, mage.cards.w.Watercourser.class)); cards.add(new SetCardInfo("Will Kenrith", 1, Rarity.MYTHIC, mage.cards.w.WillKenrith.class)); + cards.add(new SetCardInfo("Will Kenrith", 255, Rarity.MYTHIC, mage.cards.w.WillKenrith.class)); cards.add(new SetCardInfo("Wrap in Flames", 188, Rarity.COMMON, mage.cards.w.WrapInFlames.class)); cards.add(new SetCardInfo("Yotian Soldier", 249, Rarity.COMMON, mage.cards.y.YotianSoldier.class)); cards.add(new SetCardInfo("Zndrsplt's Judgment", 43, Rarity.RARE, mage.cards.z.ZndrspltsJudgment.class)); cards.add(new SetCardInfo("Zndrsplt, Eye of Wisdom", 5, Rarity.RARE, mage.cards.z.ZndrspltEyeOfWisdom.class)); } + } diff --git a/Mage.Sets/src/mage/sets/Coldsnap.java b/Mage.Sets/src/mage/sets/Coldsnap.java index 6fbb6b7f9d4..21790372da1 100644 --- a/Mage.Sets/src/mage/sets/Coldsnap.java +++ b/Mage.Sets/src/mage/sets/Coldsnap.java @@ -35,6 +35,7 @@ public final class Coldsnap extends ExpansionSet { cards.add(new SetCardInfo("Arctic Nishoba", 102, Rarity.UNCOMMON, mage.cards.a.ArcticNishoba.class)); cards.add(new SetCardInfo("Arcum Dagsson", 27, Rarity.RARE, mage.cards.a.ArcumDagsson.class)); cards.add(new SetCardInfo("Aurochs Herd", 103, Rarity.COMMON, mage.cards.a.AurochsHerd.class)); + cards.add(new SetCardInfo("Balduvian Fallen", 51, Rarity.UNCOMMON, mage.cards.b.BalduvianFallen.class)); cards.add(new SetCardInfo("Balduvian Frostwaker", 28, Rarity.UNCOMMON, mage.cards.b.BalduvianFrostwaker.class)); cards.add(new SetCardInfo("Balduvian Rage", 76, Rarity.UNCOMMON, mage.cards.b.BalduvianRage.class)); cards.add(new SetCardInfo("Balduvian Warlord", 77, Rarity.UNCOMMON, mage.cards.b.BalduvianWarlord.class)); @@ -52,6 +53,7 @@ public final class Coldsnap extends ExpansionSet { cards.add(new SetCardInfo("Commandeer", 29, Rarity.RARE, mage.cards.c.Commandeer.class)); cards.add(new SetCardInfo("Controvert", 30, Rarity.UNCOMMON, mage.cards.c.Controvert.class)); cards.add(new SetCardInfo("Counterbalance", 31, Rarity.UNCOMMON, mage.cards.c.Counterbalance.class)); + cards.add(new SetCardInfo("Cover of Winter", 3, Rarity.RARE, mage.cards.c.CoverOfWinter.class)); cards.add(new SetCardInfo("Cryoclasm", 79, Rarity.UNCOMMON, mage.cards.c.Cryoclasm.class)); cards.add(new SetCardInfo("Darien, King of Kjeldor", 4, Rarity.RARE, mage.cards.d.DarienKingOfKjeldor.class)); cards.add(new SetCardInfo("Dark Depths", 145, Rarity.RARE, mage.cards.d.DarkDepths.class)); @@ -141,6 +143,7 @@ public final class Coldsnap extends ExpansionSet { cards.add(new SetCardInfo("Rune Snag", 46, Rarity.COMMON, mage.cards.r.RuneSnag.class)); cards.add(new SetCardInfo("Scrying Sheets", 149, Rarity.RARE, mage.cards.s.ScryingSheets.class)); cards.add(new SetCardInfo("Sek'Kuar, Deathkeeper", 131, Rarity.RARE, mage.cards.s.SekKuarDeathkeeper.class)); + cards.add(new SetCardInfo("Shape of the Wiitigo", 120, Rarity.RARE, mage.cards.s.ShapeOfTheWiitigo.class)); cards.add(new SetCardInfo("Sheltering Ancient", 121, Rarity.UNCOMMON, mage.cards.s.ShelteringAncient.class)); cards.add(new SetCardInfo("Simian Brawler", 122, Rarity.COMMON, mage.cards.s.SimianBrawler.class)); cards.add(new SetCardInfo("Skred", 97, Rarity.COMMON, mage.cards.s.Skred.class)); diff --git a/Mage.Sets/src/mage/sets/Commander2018.java b/Mage.Sets/src/mage/sets/Commander2018.java new file mode 100644 index 00000000000..0958b3ad4e2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/Commander2018.java @@ -0,0 +1,331 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author TheElk801 + */ +public final class Commander2018 extends ExpansionSet { + + private static final Commander2018 instance = new Commander2018(); + + public static Commander2018 getInstance() { + return instance; + } + + private Commander2018() { + super("Commander 2018 Edition", "C18", ExpansionSet.buildDate(2018, 8, 10), SetType.SUPPLEMENTAL); + this.blockName = "Command Zone"; + + cards.add(new SetCardInfo("Acidic Slime", 127, Rarity.UNCOMMON, mage.cards.a.AcidicSlime.class)); + cards.add(new SetCardInfo("Adarkar Valkyrie", 60, Rarity.RARE, mage.cards.a.AdarkarValkyrie.class)); + cards.add(new SetCardInfo("Aether Gale", 80, Rarity.RARE, mage.cards.a.AetherGale.class)); + cards.add(new SetCardInfo("Aethermage's Touch", 168, Rarity.RARE, mage.cards.a.AethermagesTouch.class)); + cards.add(new SetCardInfo("Ajani's Chosen", 61, Rarity.RARE, mage.cards.a.AjanisChosen.class)); + cards.add(new SetCardInfo("Akoum Refuge", 231, Rarity.UNCOMMON, mage.cards.a.AkoumRefuge.class)); + cards.add(new SetCardInfo("Akroma's Vengeance", 62, Rarity.RARE, mage.cards.a.AkromasVengeance.class)); + cards.add(new SetCardInfo("Aminatou's Augury", 6, Rarity.RARE, mage.cards.a.AminatousAugury.class)); + cards.add(new SetCardInfo("Aminatou, the Fateshifter", 37, Rarity.MYTHIC, mage.cards.a.AminatouTheFateShifter.class)); + cards.add(new SetCardInfo("Ancient Stone Idol", 53, Rarity.RARE, mage.cards.a.AncientStoneIdol.class)); + cards.add(new SetCardInfo("Arcane Sanctum", 232, Rarity.UNCOMMON, mage.cards.a.ArcaneSanctum.class)); + cards.add(new SetCardInfo("Archetype of Imagination", 81, Rarity.UNCOMMON, mage.cards.a.ArchetypeOfImagination.class)); + cards.add(new SetCardInfo("Arixmethes, Slumbering Isle", 38, Rarity.RARE, mage.cards.a.ArixmethesSlumberingIsle.class)); + cards.add(new SetCardInfo("Army of the Damned", 113, Rarity.MYTHIC, mage.cards.a.ArmyOfTheDamned.class)); + cards.add(new SetCardInfo("Aura Gnarlid", 128, Rarity.COMMON, mage.cards.a.AuraGnarlid.class)); + cards.add(new SetCardInfo("Avenger of Zendikar", 129, Rarity.MYTHIC, mage.cards.a.AvengerOfZendikar.class)); + cards.add(new SetCardInfo("Azorius Chancery", 233, Rarity.UNCOMMON, mage.cards.a.AzoriusChancery.class)); + cards.add(new SetCardInfo("Azorius Guildgate", 234, Rarity.COMMON, mage.cards.a.AzoriusGuildgate.class)); + cards.add(new SetCardInfo("Azorius Signet", 196, Rarity.COMMON, mage.cards.a.AzoriusSignet.class)); + cards.add(new SetCardInfo("Baloth Woodcrasher", 130, Rarity.UNCOMMON, mage.cards.b.BalothWoodcrasher.class)); + cards.add(new SetCardInfo("Banishing Stroke", 63, Rarity.UNCOMMON, mage.cards.b.BanishingStroke.class)); + cards.add(new SetCardInfo("Bant Charm", 169, Rarity.UNCOMMON, mage.cards.b.BantCharm.class)); + cards.add(new SetCardInfo("Barren Moor", 235, Rarity.COMMON, mage.cards.b.BarrenMoor.class)); + cards.add(new SetCardInfo("Bear Umbra", 131, Rarity.RARE, mage.cards.b.BearUmbra.class)); + cards.add(new SetCardInfo("Blasphemous Act", 120, Rarity.RARE, mage.cards.b.BlasphemousAct.class)); + cards.add(new SetCardInfo("Blighted Woodland", 236, Rarity.UNCOMMON, mage.cards.b.BlightedWoodland.class)); + cards.add(new SetCardInfo("Blinkmoth Urn", 197, Rarity.RARE, mage.cards.b.BlinkmothUrn.class)); + cards.add(new SetCardInfo("Bloodtracker", 14, Rarity.RARE, mage.cards.b.Bloodtracker.class)); + cards.add(new SetCardInfo("Blossoming Sands", 237, Rarity.COMMON, mage.cards.b.BlossomingSands.class)); + cards.add(new SetCardInfo("Bojuka Bog", 238, Rarity.COMMON, mage.cards.b.BojukaBog.class)); + cards.add(new SetCardInfo("Boon Satyr", 132, Rarity.RARE, mage.cards.b.BoonSatyr.class)); + cards.add(new SetCardInfo("Borderland Explorer", 133, Rarity.COMMON, mage.cards.b.BorderlandExplorer.class)); + cards.add(new SetCardInfo("Boreas Charger", 1, Rarity.RARE, mage.cards.b.BoreasCharger.class)); + cards.add(new SetCardInfo("Bosh, Iron Golem", 198, Rarity.RARE, mage.cards.b.BoshIronGolem.class)); + cards.add(new SetCardInfo("Brainstorm", 82, Rarity.UNCOMMON, mage.cards.b.Brainstorm.class)); + cards.add(new SetCardInfo("Brudiclad, Telchor Engineer", 39, Rarity.MYTHIC, mage.cards.b.BrudicladTelchorEngineer.class)); + cards.add(new SetCardInfo("Bruna, Light of Alabaster", 170, Rarity.MYTHIC, mage.cards.b.BrunaLightOfAlabaster.class)); + cards.add(new SetCardInfo("Budoka Gardener", 134, Rarity.RARE, mage.cards.b.BudokaGardener.class)); + cards.add(new SetCardInfo("Buried Ruin", 239, Rarity.UNCOMMON, mage.cards.b.BuriedRuin.class)); + cards.add(new SetCardInfo("Celestial Archon", 64, Rarity.RARE, mage.cards.c.CelestialArchon.class)); + cards.add(new SetCardInfo("Centaur Vinecrasher", 135, Rarity.RARE, mage.cards.c.CentaurVinecrasher.class)); + cards.add(new SetCardInfo("Chain Reaction", 121, Rarity.RARE, mage.cards.c.ChainReaction.class)); + cards.add(new SetCardInfo("Chaos Warp", 122, Rarity.RARE, mage.cards.c.ChaosWarp.class)); + cards.add(new SetCardInfo("Charnelhoard Wurm", 171, Rarity.RARE, mage.cards.c.CharnelhoardWurm.class)); + cards.add(new SetCardInfo("Chief of the Foundry", 199, Rarity.UNCOMMON, mage.cards.c.ChiefOfTheFoundry.class)); + cards.add(new SetCardInfo("Cloudform", 83, Rarity.UNCOMMON, mage.cards.c.Cloudform.class)); + cards.add(new SetCardInfo("Cold-Eyed Selkie", 172, Rarity.RARE, mage.cards.c.ColdEyedSelkie.class)); + cards.add(new SetCardInfo("Command Tower", 240, Rarity.COMMON, mage.cards.c.CommandTower.class)); + cards.add(new SetCardInfo("Commander's Sphere", 200, Rarity.COMMON, mage.cards.c.CommandersSphere.class)); + cards.add(new SetCardInfo("Consign to Dust", 136, Rarity.UNCOMMON, mage.cards.c.ConsignToDust.class)); + cards.add(new SetCardInfo("Conundrum Sphinx", 84, Rarity.RARE, mage.cards.c.ConundrumSphinx.class)); + cards.add(new SetCardInfo("Coveted Jewel", 54, Rarity.RARE, mage.cards.c.CovetedJewel.class)); + cards.add(new SetCardInfo("Crash of Rhino Beetles", 29, Rarity.RARE, mage.cards.c.CrashOfRhinoBeetles.class)); + cards.add(new SetCardInfo("Creeping Renaissance", 137, Rarity.RARE, mage.cards.c.CreepingRenaissance.class)); + cards.add(new SetCardInfo("Crib Swap", 65, Rarity.UNCOMMON, mage.cards.c.CribSwap.class)); + cards.add(new SetCardInfo("Crystal Ball", 201, Rarity.UNCOMMON, mage.cards.c.CrystalBall.class)); + cards.add(new SetCardInfo("Cultivate", 138, Rarity.COMMON, mage.cards.c.Cultivate.class)); + cards.add(new SetCardInfo("Darksteel Citadel", 241, Rarity.UNCOMMON, mage.cards.d.DarksteelCitadel.class)); + cards.add(new SetCardInfo("Darksteel Juggernaut", 202, Rarity.RARE, mage.cards.d.DarksteelJuggernaut.class)); + cards.add(new SetCardInfo("Dawn's Reflection", 139, Rarity.COMMON, mage.cards.d.DawnsReflection.class)); + cards.add(new SetCardInfo("Daxos of Meletis", 173, Rarity.RARE, mage.cards.d.DaxosOfMeletis.class)); + cards.add(new SetCardInfo("Deathreap Ritual", 174, Rarity.UNCOMMON, mage.cards.d.DeathreapRitual.class)); + cards.add(new SetCardInfo("Decimate", 175, Rarity.RARE, mage.cards.d.Decimate.class)); + cards.add(new SetCardInfo("Devastation Tide", 85, Rarity.RARE, mage.cards.d.DevastationTide.class)); + cards.add(new SetCardInfo("Dictate of Kruphix", 86, Rarity.RARE, mage.cards.d.DictateOfKruphix.class)); + cards.add(new SetCardInfo("Dimir Aqueduct", 242, Rarity.UNCOMMON, mage.cards.d.DimirAqueduct.class)); + cards.add(new SetCardInfo("Dimir Guildgate", 243, Rarity.COMMON, mage.cards.d.DimirGuildgate.class)); + cards.add(new SetCardInfo("Dimir Signet", 203, Rarity.COMMON, mage.cards.d.DimirSignet.class)); + cards.add(new SetCardInfo("Dismal Backwater", 244, Rarity.COMMON, mage.cards.d.DismalBackwater.class)); + cards.add(new SetCardInfo("Dismantling Blow", 66, Rarity.COMMON, mage.cards.d.DismantlingBlow.class)); + cards.add(new SetCardInfo("Djinn of Wishes", 87, Rarity.RARE, mage.cards.d.DjinnOfWishes.class)); + cards.add(new SetCardInfo("Dream Cache", 88, Rarity.COMMON, mage.cards.d.DreamCache.class)); + cards.add(new SetCardInfo("Dreamstone Hedron", 204, Rarity.UNCOMMON, mage.cards.d.DreamstoneHedron.class)); + cards.add(new SetCardInfo("Duplicant", 205, Rarity.RARE, mage.cards.d.Duplicant.class)); + cards.add(new SetCardInfo("Duskmantle Seer", 176, Rarity.RARE, mage.cards.d.DuskmantleSeer.class)); + cards.add(new SetCardInfo("Echo Storm", 7, Rarity.RARE, mage.cards.e.EchoStorm.class)); + cards.add(new SetCardInfo("Eel Umbra", 89, Rarity.COMMON, mage.cards.e.EelUmbra.class)); + cards.add(new SetCardInfo("Eidolon of Blossoms", 140, Rarity.RARE, mage.cards.e.EidolonOfBlossoms.class)); + cards.add(new SetCardInfo("Elderwood Scion", 177, Rarity.RARE, mage.cards.e.ElderwoodScion.class)); + cards.add(new SetCardInfo("Emissary of Grudges", 20, Rarity.RARE, mage.cards.e.EmissaryOfGrudges.class)); + cards.add(new SetCardInfo("Empyrial Storm", 2, Rarity.RARE, mage.cards.e.EmpyrialStorm.class)); + cards.add(new SetCardInfo("Enchanter's Bane", 21, Rarity.RARE, mage.cards.e.EnchantersBane.class)); + cards.add(new SetCardInfo("Enchantress's Presence", 141, Rarity.RARE, mage.cards.e.EnchantresssPresence.class)); + cards.add(new SetCardInfo("Endless Atlas", 55, Rarity.RARE, mage.cards.e.EndlessAtlas.class)); + cards.add(new SetCardInfo("Enigma Sphinx", 178, Rarity.RARE, mage.cards.e.EnigmaSphinx.class)); + cards.add(new SetCardInfo("Entreat the Angels", 67, Rarity.MYTHIC, mage.cards.e.EntreatTheAngels.class)); + cards.add(new SetCardInfo("Entreat the Dead", 15, Rarity.RARE, mage.cards.e.EntreatTheDead.class)); + cards.add(new SetCardInfo("Epic Proportions", 142, Rarity.RARE, mage.cards.e.EpicProportions.class)); + cards.add(new SetCardInfo("Esper Charm", 179, Rarity.UNCOMMON, mage.cards.e.EsperCharm.class)); + cards.add(new SetCardInfo("Estrid's Invocation", 8, Rarity.RARE, mage.cards.e.EstridsInvocation.class)); + cards.add(new SetCardInfo("Estrid, the Masked", 40, Rarity.MYTHIC, mage.cards.e.EstridTheMasked.class)); + cards.add(new SetCardInfo("Etherium Sculptor", 90, Rarity.COMMON, mage.cards.e.EtheriumSculptor.class)); + cards.add(new SetCardInfo("Ever-Watching Threshold", 9, Rarity.RARE, mage.cards.e.EverWatchingThreshold.class)); + cards.add(new SetCardInfo("Evolving Wilds", 245, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); + cards.add(new SetCardInfo("Explore", 143, Rarity.COMMON, mage.cards.e.Explore.class)); + cards.add(new SetCardInfo("Explosive Vegetation", 144, Rarity.UNCOMMON, mage.cards.e.ExplosiveVegetation.class)); + cards.add(new SetCardInfo("Far Wanderings", 145, Rarity.COMMON, mage.cards.f.FarWanderings.class)); + cards.add(new SetCardInfo("Farhaven Elf", 146, Rarity.COMMON, mage.cards.f.FarhavenElf.class)); + cards.add(new SetCardInfo("Fertile Ground", 147, Rarity.COMMON, mage.cards.f.FertileGround.class)); + cards.add(new SetCardInfo("Finest Hour", 180, Rarity.RARE, mage.cards.f.FinestHour.class)); + cards.add(new SetCardInfo("Flameblast Dragon", 123, Rarity.RARE, mage.cards.f.FlameblastDragon.class)); + cards.add(new SetCardInfo("Forest", 305, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 306, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 307, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forge of Heroes", 58, Rarity.COMMON, mage.cards.f.ForgeOfHeroes.class)); + cards.add(new SetCardInfo("Forgotten Cave", 246, Rarity.COMMON, mage.cards.f.ForgottenCave.class)); + cards.add(new SetCardInfo("Forsaken Sanctuary", 247, Rarity.UNCOMMON, mage.cards.f.ForsakenSanctuary.class)); + cards.add(new SetCardInfo("Foundry of the Consuls", 248, Rarity.UNCOMMON, mage.cards.f.FoundryOfTheConsuls.class)); + cards.add(new SetCardInfo("Fury Storm", 22, Rarity.RARE, mage.cards.f.FuryStorm.class)); + cards.add(new SetCardInfo("Gaze of Granite", 181, Rarity.RARE, mage.cards.g.GazeOfGranite.class)); + cards.add(new SetCardInfo("Genesis Storm", 30, Rarity.RARE, mage.cards.g.GenesisStorm.class)); + cards.add(new SetCardInfo("Geode Golem", 56, Rarity.UNCOMMON, mage.cards.g.GeodeGolem.class)); + cards.add(new SetCardInfo("Golgari Rot Farm", 249, Rarity.UNCOMMON, mage.cards.g.GolgariRotFarm.class)); + cards.add(new SetCardInfo("Grapple with the Past", 148, Rarity.COMMON, mage.cards.g.GrappleWithThePast.class)); + cards.add(new SetCardInfo("Great Furnace", 250, Rarity.COMMON, mage.cards.g.GreatFurnace.class)); + cards.add(new SetCardInfo("Grim Backwoods", 251, Rarity.RARE, mage.cards.g.GrimBackwoods.class)); + cards.add(new SetCardInfo("Grisly Salvage", 182, Rarity.COMMON, mage.cards.g.GrislySalvage.class)); + cards.add(new SetCardInfo("Ground Seal", 149, Rarity.RARE, mage.cards.g.GroundSeal.class)); + cards.add(new SetCardInfo("Gruul Turf", 252, Rarity.UNCOMMON, mage.cards.g.GruulTurf.class)); + cards.add(new SetCardInfo("Gyrus, Waker of Corpses", 41, Rarity.MYTHIC, mage.cards.g.GyrusWakerOfCorpses.class)); + cards.add(new SetCardInfo("Halimar Depths", 253, Rarity.COMMON, mage.cards.h.HalimarDepths.class)); + cards.add(new SetCardInfo("Harrow", 150, Rarity.COMMON, mage.cards.h.Harrow.class)); + cards.add(new SetCardInfo("Haunted Fengraf", 254, Rarity.COMMON, mage.cards.h.HauntedFengraf.class)); + cards.add(new SetCardInfo("Heavenly Blademaster", 3, Rarity.RARE, mage.cards.h.HeavenlyBlademaster.class)); + cards.add(new SetCardInfo("Hedron Archive", 206, Rarity.UNCOMMON, mage.cards.h.HedronArchive.class)); + cards.add(new SetCardInfo("Hellkite Igniter", 124, Rarity.RARE, mage.cards.h.HellkiteIgniter.class)); + cards.add(new SetCardInfo("Herald of the Pantheon", 151, Rarity.RARE, mage.cards.h.HeraldOfThePantheon.class)); + cards.add(new SetCardInfo("High Priest of Penance", 183, Rarity.RARE, mage.cards.h.HighPriestOfPenance.class)); + cards.add(new SetCardInfo("Highland Lake", 255, Rarity.UNCOMMON, mage.cards.h.HighlandLake.class)); + cards.add(new SetCardInfo("Hunting Wilds", 152, Rarity.UNCOMMON, mage.cards.h.HuntingWilds.class)); + cards.add(new SetCardInfo("Hydra Omnivore", 153, Rarity.MYTHIC, mage.cards.h.HydraOmnivore.class)); + cards.add(new SetCardInfo("Inkwell Leviathan", 91, Rarity.RARE, mage.cards.i.InkwellLeviathan.class)); + cards.add(new SetCardInfo("Into the Roil", 92, Rarity.COMMON, mage.cards.i.IntoTheRoil.class)); + cards.add(new SetCardInfo("Island", 296, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 297, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 298, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Isolated Watchtower", 59, Rarity.RARE, mage.cards.i.IsolatedWatchtower.class)); + cards.add(new SetCardInfo("Izzet Boilerworks", 256, Rarity.UNCOMMON, mage.cards.i.IzzetBoilerworks.class)); + cards.add(new SetCardInfo("Izzet Guildgate", 257, Rarity.COMMON, mage.cards.i.IzzetGuildgate.class)); + cards.add(new SetCardInfo("Izzet Signet", 207, Rarity.COMMON, mage.cards.i.IzzetSignet.class)); + cards.add(new SetCardInfo("Jeskai Infiltrator", 93, Rarity.RARE, mage.cards.j.JeskaiInfiltrator.class)); + cards.add(new SetCardInfo("Jund Panorama", 258, Rarity.COMMON, mage.cards.j.JundPanorama.class)); + cards.add(new SetCardInfo("Jungle Hollow", 259, Rarity.COMMON, mage.cards.j.JungleHollow.class)); + cards.add(new SetCardInfo("Jwar Isle Refuge", 260, Rarity.UNCOMMON, mage.cards.j.JwarIsleRefuge.class)); + cards.add(new SetCardInfo("Kazandu Refuge", 261, Rarity.UNCOMMON, mage.cards.k.KazanduRefuge.class)); + cards.add(new SetCardInfo("Kestia, the Cultivator", 42, Rarity.MYTHIC, mage.cards.k.KestiaTheCultivator.class)); + cards.add(new SetCardInfo("Khalni Garden", 262, Rarity.COMMON, mage.cards.k.KhalniGarden.class)); + cards.add(new SetCardInfo("Khalni Heart Expedition", 154, Rarity.COMMON, mage.cards.k.KhalniHeartExpedition.class)); + cards.add(new SetCardInfo("Krosan Verge", 263, Rarity.UNCOMMON, mage.cards.k.KrosanVerge.class)); + cards.add(new SetCardInfo("Kruphix's Insight", 155, Rarity.COMMON, mage.cards.k.KruphixsInsight.class)); + cards.add(new SetCardInfo("Lavalanche", 184, Rarity.RARE, mage.cards.l.Lavalanche.class)); + cards.add(new SetCardInfo("Lightform", 68, Rarity.UNCOMMON, mage.cards.l.Lightform.class)); + cards.add(new SetCardInfo("Lonely Sandbar", 264, Rarity.COMMON, mage.cards.l.LonelySandbar.class)); + cards.add(new SetCardInfo("Lord Windgrace", 43, Rarity.MYTHIC, mage.cards.l.LordWindgrace.class)); + cards.add(new SetCardInfo("Loyal Apprentice", 23, Rarity.UNCOMMON, mage.cards.l.LoyalApprentice.class)); + cards.add(new SetCardInfo("Loyal Drake", 10, Rarity.UNCOMMON, mage.cards.l.LoyalDrake.class)); + cards.add(new SetCardInfo("Loyal Guardian", 31, Rarity.UNCOMMON, mage.cards.l.LoyalGuardian.class)); + cards.add(new SetCardInfo("Loyal Subordinate", 16, Rarity.UNCOMMON, mage.cards.l.LoyalSubordinate.class)); + cards.add(new SetCardInfo("Loyal Unicorn", 4, Rarity.UNCOMMON, mage.cards.l.LoyalUnicorn.class)); + cards.add(new SetCardInfo("Magmaquake", 125, Rarity.RARE, mage.cards.m.Magmaquake.class)); + cards.add(new SetCardInfo("Magnifying Glass", 208, Rarity.UNCOMMON, mage.cards.m.MagnifyingGlass.class)); + cards.add(new SetCardInfo("Magus of the Balance", 5, Rarity.RARE, mage.cards.m.MagusOfTheBalance.class)); + cards.add(new SetCardInfo("Martial Coup", 69, Rarity.RARE, mage.cards.m.MartialCoup.class)); + cards.add(new SetCardInfo("Maverick Thopterist", 185, Rarity.UNCOMMON, mage.cards.m.MaverickThopterist.class)); + cards.add(new SetCardInfo("Meandering River", 265, Rarity.UNCOMMON, mage.cards.m.MeanderingRiver.class)); + cards.add(new SetCardInfo("Mimic Vat", 209, Rarity.RARE, mage.cards.m.MimicVat.class)); + cards.add(new SetCardInfo("Mind Stone", 210, Rarity.COMMON, mage.cards.m.MindStone.class)); + cards.add(new SetCardInfo("Mirrorworks", 211, Rarity.RARE, mage.cards.m.Mirrorworks.class)); + cards.add(new SetCardInfo("Moldgraf Monstrosity", 156, Rarity.RARE, mage.cards.m.MoldgrafMonstrosity.class)); + cards.add(new SetCardInfo("Moonlight Bargain", 114, Rarity.RARE, mage.cards.m.MoonlightBargain.class)); + cards.add(new SetCardInfo("Mortify", 186, Rarity.UNCOMMON, mage.cards.m.Mortify.class)); + cards.add(new SetCardInfo("Mortuary Mire", 266, Rarity.COMMON, mage.cards.m.MortuaryMire.class)); + cards.add(new SetCardInfo("Mosswort Bridge", 267, Rarity.RARE, mage.cards.m.MosswortBridge.class)); + cards.add(new SetCardInfo("Mountain Valley", 268, Rarity.UNCOMMON, mage.cards.m.MountainValley.class)); + cards.add(new SetCardInfo("Mountain", 302, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 303, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 304, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mulldrifter", 94, Rarity.UNCOMMON, mage.cards.m.Mulldrifter.class)); + cards.add(new SetCardInfo("Myr Battlesphere", 212, Rarity.RARE, mage.cards.m.MyrBattlesphere.class)); + cards.add(new SetCardInfo("Myriad Landscape", 269, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class)); + cards.add(new SetCardInfo("Myth Unbound", 32, Rarity.RARE, mage.cards.m.MythUnbound.class)); + cards.add(new SetCardInfo("Nesting Dragon", 24, Rarity.RARE, mage.cards.n.NestingDragon.class)); + cards.add(new SetCardInfo("New Benalia", 270, Rarity.UNCOMMON, mage.cards.n.NewBenalia.class)); + cards.add(new SetCardInfo("Night Incarnate", 17, Rarity.RARE, mage.cards.n.NightIncarnate.class)); + cards.add(new SetCardInfo("Ninja of the Deep Hours", 95, Rarity.COMMON, mage.cards.n.NinjaOfTheDeepHours.class)); + cards.add(new SetCardInfo("Nylea's Colossus", 33, Rarity.RARE, mage.cards.n.NyleasColossus.class)); + cards.add(new SetCardInfo("Octopus Umbra", 11, Rarity.RARE, mage.cards.o.OctopusUmbra.class)); + cards.add(new SetCardInfo("Orzhov Basilica", 271, Rarity.UNCOMMON, mage.cards.o.OrzhovBasilica.class)); + cards.add(new SetCardInfo("Orzhov Guildgate", 272, Rarity.COMMON, mage.cards.o.OrzhovGuildgate.class)); + cards.add(new SetCardInfo("Orzhov Signet", 213, Rarity.COMMON, mage.cards.o.OrzhovSignet.class)); + cards.add(new SetCardInfo("Overgrowth", 157, Rarity.COMMON, mage.cards.o.Overgrowth.class)); + cards.add(new SetCardInfo("Phyrexian Delver", 115, Rarity.RARE, mage.cards.p.PhyrexianDelver.class)); + cards.add(new SetCardInfo("Phyrexian Rebirth", 70, Rarity.RARE, mage.cards.p.PhyrexianRebirth.class)); + cards.add(new SetCardInfo("Pilgrim's Eye", 214, Rarity.COMMON, mage.cards.p.PilgrimsEye.class)); + cards.add(new SetCardInfo("Plains", 293, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 294, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 295, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ponder", 96, Rarity.COMMON, mage.cards.p.Ponder.class)); + cards.add(new SetCardInfo("Portent", 97, Rarity.COMMON, mage.cards.p.Portent.class)); + cards.add(new SetCardInfo("Predict", 98, Rarity.UNCOMMON, mage.cards.p.Predict.class)); + cards.add(new SetCardInfo("Primordial Mist", 12, Rarity.RARE, mage.cards.p.PrimordialMist.class)); + cards.add(new SetCardInfo("Prismatic Lens", 215, Rarity.UNCOMMON, mage.cards.p.PrismaticLens.class)); + cards.add(new SetCardInfo("Prototype Portal", 216, Rarity.RARE, mage.cards.p.PrototypePortal.class)); + cards.add(new SetCardInfo("Psychosis Crawler", 217, Rarity.RARE, mage.cards.p.PsychosisCrawler.class)); + cards.add(new SetCardInfo("Putrefy", 187, Rarity.UNCOMMON, mage.cards.p.Putrefy.class)); + cards.add(new SetCardInfo("Rakdos Carnarium", 273, Rarity.COMMON, mage.cards.r.RakdosCarnarium.class)); + cards.add(new SetCardInfo("Rampaging Baloths", 158, Rarity.RARE, mage.cards.r.RampagingBaloths.class)); + cards.add(new SetCardInfo("Ravenous Slime", 34, Rarity.RARE, mage.cards.r.RavenousSlime.class)); + cards.add(new SetCardInfo("Reality Scramble", 25, Rarity.RARE, mage.cards.r.RealityScramble.class)); + cards.add(new SetCardInfo("Reclamation Sage", 159, Rarity.UNCOMMON, mage.cards.r.ReclamationSage.class)); + cards.add(new SetCardInfo("Retreat to Hagra", 116, Rarity.UNCOMMON, mage.cards.r.RetreatToHagra.class)); + cards.add(new SetCardInfo("Retrofitter Foundry", 57, Rarity.RARE, mage.cards.r.RetrofitterFoundry.class)); + cards.add(new SetCardInfo("Return to Dust", 71, Rarity.UNCOMMON, mage.cards.r.ReturnToDust.class)); + cards.add(new SetCardInfo("Reverse Engineer", 99, Rarity.UNCOMMON, mage.cards.r.ReverseEngineer.class)); + cards.add(new SetCardInfo("Righteous Authority", 188, Rarity.RARE, mage.cards.r.RighteousAuthority.class)); + cards.add(new SetCardInfo("Rocky Tar Pit", 274, Rarity.UNCOMMON, mage.cards.r.RockyTarPit.class)); + cards.add(new SetCardInfo("Rubblehulk", 189, Rarity.RARE, mage.cards.r.Rubblehulk.class)); + cards.add(new SetCardInfo("Ruinous Path", 117, Rarity.RARE, mage.cards.r.RuinousPath.class)); + cards.add(new SetCardInfo("Sage's Reverie", 72, Rarity.UNCOMMON, mage.cards.s.SagesReverie.class)); + cards.add(new SetCardInfo("Saheeli's Artistry", 100, Rarity.RARE, mage.cards.s.SaheelisArtistry.class)); + cards.add(new SetCardInfo("Saheeli's Directive", 26, Rarity.RARE, mage.cards.s.SaheelisDirective.class)); + cards.add(new SetCardInfo("Saheeli, the Gifted", 44, Rarity.MYTHIC, mage.cards.s.SaheeliTheGifted.class)); + cards.add(new SetCardInfo("Sakura-Tribe Elder", 160, Rarity.COMMON, mage.cards.s.SakuraTribeElder.class)); + cards.add(new SetCardInfo("Savage Lands", 275, Rarity.UNCOMMON, mage.cards.s.SavageLands.class)); + cards.add(new SetCardInfo("Savage Twister", 190, Rarity.UNCOMMON, mage.cards.s.SavageTwister.class)); + cards.add(new SetCardInfo("Scoured Barrens", 276, Rarity.COMMON, mage.cards.s.ScouredBarrens.class)); + cards.add(new SetCardInfo("Scrabbling Claws", 218, Rarity.UNCOMMON, mage.cards.s.ScrabblingClaws.class)); + cards.add(new SetCardInfo("Scute Mob", 161, Rarity.RARE, mage.cards.s.ScuteMob.class)); + cards.add(new SetCardInfo("Scuttling Doom Engine", 219, Rarity.RARE, mage.cards.s.ScuttlingDoomEngine.class)); + cards.add(new SetCardInfo("Seaside Citadel", 277, Rarity.UNCOMMON, mage.cards.s.SeasideCitadel.class)); + cards.add(new SetCardInfo("Seat of the Synod", 278, Rarity.COMMON, mage.cards.s.SeatOfTheSynod.class)); + cards.add(new SetCardInfo("Secluded Steppe", 279, Rarity.COMMON, mage.cards.s.SecludedSteppe.class)); + cards.add(new SetCardInfo("Seer's Lantern", 220, Rarity.COMMON, mage.cards.s.SeersLantern.class)); + cards.add(new SetCardInfo("Seer's Sundial", 221, Rarity.RARE, mage.cards.s.SeersSundial.class)); + cards.add(new SetCardInfo("Sejiri Refuge", 280, Rarity.UNCOMMON, mage.cards.s.SejiriRefuge.class)); + cards.add(new SetCardInfo("Selesnya Sanctuary", 281, Rarity.COMMON, mage.cards.s.SelesnyaSanctuary.class)); + cards.add(new SetCardInfo("Serra Avatar", 73, Rarity.MYTHIC, mage.cards.s.SerraAvatar.class)); + cards.add(new SetCardInfo("Sharding Sphinx", 101, Rarity.RARE, mage.cards.s.ShardingSphinx.class)); + cards.add(new SetCardInfo("Sigil of the Empty Throne", 74, Rarity.RARE, mage.cards.s.SigilOfTheEmptyThrone.class)); + cards.add(new SetCardInfo("Sigiled Starfish", 102, Rarity.COMMON, mage.cards.s.SigiledStarfish.class)); + cards.add(new SetCardInfo("Silent Sentinel", 75, Rarity.RARE, mage.cards.s.SilentSentinel.class)); + cards.add(new SetCardInfo("Silent-Blade Oni", 191, Rarity.RARE, mage.cards.s.SilentBladeOni.class)); + cards.add(new SetCardInfo("Simic Growth Chamber", 282, Rarity.UNCOMMON, mage.cards.s.SimicGrowthChamber.class)); + cards.add(new SetCardInfo("Skull Storm", 18, Rarity.RARE, mage.cards.s.SkullStorm.class)); + cards.add(new SetCardInfo("Snake Umbra", 162, Rarity.COMMON, mage.cards.s.SnakeUmbra.class)); + cards.add(new SetCardInfo("Sol Ring", 222, Rarity.UNCOMMON, mage.cards.s.SolRing.class)); + cards.add(new SetCardInfo("Soul Snare", 76, Rarity.UNCOMMON, mage.cards.s.SoulSnare.class)); + cards.add(new SetCardInfo("Soul of Innistrad", 118, Rarity.MYTHIC, mage.cards.s.SoulOfInnistrad.class)); + cards.add(new SetCardInfo("Soul of New Phyrexia", 223, Rarity.MYTHIC, mage.cards.s.SoulOfNewPhyrexia.class)); + cards.add(new SetCardInfo("Sower of Discord", 19, Rarity.RARE, mage.cards.s.SowerOfDiscord.class)); + cards.add(new SetCardInfo("Spawning Grounds", 163, Rarity.RARE, mage.cards.s.SpawningGrounds.class)); + cards.add(new SetCardInfo("Sphinx of Jwar Isle", 103, Rarity.RARE, mage.cards.s.SphinxOfJwarIsle.class)); + cards.add(new SetCardInfo("Sphinx of Uthuun", 104, Rarity.RARE, mage.cards.s.SphinxOfUthuun.class)); + cards.add(new SetCardInfo("Steel Hellkite", 224, Rarity.RARE, mage.cards.s.SteelHellkite.class)); + cards.add(new SetCardInfo("Stitch Together", 119, Rarity.UNCOMMON, mage.cards.s.StitchTogether.class)); + cards.add(new SetCardInfo("Submerged Boneyard", 283, Rarity.UNCOMMON, mage.cards.s.SubmergedBoneyard.class)); + cards.add(new SetCardInfo("Swamp", 299, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 300, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 301, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swiftfoot Boots", 225, Rarity.UNCOMMON, mage.cards.s.SwiftfootBoots.class)); + cards.add(new SetCardInfo("Swiftwater Cliffs", 284, Rarity.COMMON, mage.cards.s.SwiftwaterCliffs.class)); + cards.add(new SetCardInfo("Tawnos, Urza's Apprentice", 45, Rarity.MYTHIC, mage.cards.t.TawnosUrzasApprentice.class)); + cards.add(new SetCardInfo("Telling Time", 105, Rarity.COMMON, mage.cards.t.TellingTime.class)); + cards.add(new SetCardInfo("Temple of the False God", 285, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class)); + cards.add(new SetCardInfo("Terminus", 77, Rarity.RARE, mage.cards.t.Terminus.class)); + cards.add(new SetCardInfo("Terramorphic Expanse", 286, Rarity.COMMON, mage.cards.t.TerramorphicExpanse.class)); + cards.add(new SetCardInfo("Thantis, the Warweaver", 46, Rarity.MYTHIC, mage.cards.t.ThantisTheWarweaver.class)); + cards.add(new SetCardInfo("Thirst for Knowledge", 106, Rarity.UNCOMMON, mage.cards.t.ThirstForKnowledge.class)); + cards.add(new SetCardInfo("Thopter Assembly", 226, Rarity.RARE, mage.cards.t.ThopterAssembly.class)); + cards.add(new SetCardInfo("Thopter Engineer", 126, Rarity.UNCOMMON, mage.cards.t.ThopterEngineer.class)); + cards.add(new SetCardInfo("Thopter Spy Network", 107, Rarity.RARE, mage.cards.t.ThopterSpyNetwork.class)); + cards.add(new SetCardInfo("Thornwood Falls", 287, Rarity.COMMON, mage.cards.t.ThornwoodFalls.class)); + cards.add(new SetCardInfo("Tidings", 108, Rarity.UNCOMMON, mage.cards.t.Tidings.class)); + cards.add(new SetCardInfo("Tranquil Cove", 288, Rarity.COMMON, mage.cards.t.TranquilCove.class)); + cards.add(new SetCardInfo("Tranquil Expanse", 289, Rarity.UNCOMMON, mage.cards.t.TranquilExpanse.class)); + cards.add(new SetCardInfo("Tranquil Thicket", 290, Rarity.COMMON, mage.cards.t.TranquilThicket.class)); + cards.add(new SetCardInfo("Treasure Hunt", 109, Rarity.COMMON, mage.cards.t.TreasureHunt.class)); + cards.add(new SetCardInfo("Treasure Nabber", 27, Rarity.RARE, mage.cards.t.TreasureNabber.class)); + cards.add(new SetCardInfo("Turntimber Sower", 35, Rarity.RARE, mage.cards.t.TurntimberSower.class)); + cards.add(new SetCardInfo("Tuvasa the Sunlit", 47, Rarity.MYTHIC, mage.cards.t.TuvasaTheSunlit.class)); + cards.add(new SetCardInfo("Unflinching Courage", 192, Rarity.UNCOMMON, mage.cards.u.UnflinchingCourage.class)); + cards.add(new SetCardInfo("Unquestioned Authority", 78, Rarity.UNCOMMON, mage.cards.u.UnquestionedAuthority.class)); + cards.add(new SetCardInfo("Unstable Obelisk", 227, Rarity.UNCOMMON, mage.cards.u.UnstableObelisk.class)); + cards.add(new SetCardInfo("Unwinding Clock", 228, Rarity.RARE, mage.cards.u.UnwindingClock.class)); + cards.add(new SetCardInfo("Utter End", 193, Rarity.RARE, mage.cards.u.UtterEnd.class)); + cards.add(new SetCardInfo("Varchild, Betrayer of Kjeldor", 28, Rarity.RARE, mage.cards.v.VarchildBetrayerOfKjeldor.class)); + cards.add(new SetCardInfo("Varina, Lich Queen", 48, Rarity.MYTHIC, mage.cards.v.VarinaLichQueen.class)); + cards.add(new SetCardInfo("Vedalken Humiliator", 13, Rarity.RARE, mage.cards.v.VedalkenHumiliator.class)); + cards.add(new SetCardInfo("Vessel of Endless Rest", 229, Rarity.UNCOMMON, mage.cards.v.VesselOfEndlessRest.class)); + cards.add(new SetCardInfo("Vow of Flight", 110, Rarity.UNCOMMON, mage.cards.v.VowOfFlight.class)); + cards.add(new SetCardInfo("Vow of Wildness", 164, Rarity.UNCOMMON, mage.cards.v.VowOfWildness.class)); + cards.add(new SetCardInfo("Warped Landscape", 291, Rarity.COMMON, mage.cards.w.WarpedLandscape.class)); + cards.add(new SetCardInfo("Whiptongue Hydra", 36, Rarity.RARE, mage.cards.w.WhiptongueHydra.class)); + cards.add(new SetCardInfo("Whirler Rogue", 111, Rarity.UNCOMMON, mage.cards.w.WhirlerRogue.class)); + cards.add(new SetCardInfo("Whitewater Naiads", 112, Rarity.UNCOMMON, mage.cards.w.WhitewaterNaiads.class)); + cards.add(new SetCardInfo("Wild Growth", 165, Rarity.COMMON, mage.cards.w.WildGrowth.class)); + cards.add(new SetCardInfo("Windgrace's Judgment", 49, Rarity.RARE, mage.cards.w.WindgracesJudgment.class)); + cards.add(new SetCardInfo("Winds of Rath", 79, Rarity.RARE, mage.cards.w.WindsOfRath.class)); + cards.add(new SetCardInfo("Woodland Stream", 292, Rarity.COMMON, mage.cards.w.WoodlandStream.class)); + cards.add(new SetCardInfo("Worm Harvest", 194, Rarity.RARE, mage.cards.w.WormHarvest.class)); + cards.add(new SetCardInfo("Worn Powerstone", 230, Rarity.UNCOMMON, mage.cards.w.WornPowerstone.class)); + cards.add(new SetCardInfo("Xantcha, Sleeper Agent", 50, Rarity.RARE, mage.cards.x.XantchaSleeperAgent.class)); + cards.add(new SetCardInfo("Yavimaya Elder", 166, Rarity.COMMON, mage.cards.y.YavimayaElder.class)); + cards.add(new SetCardInfo("Yavimaya Enchantress", 167, Rarity.COMMON, mage.cards.y.YavimayaEnchantress.class)); + cards.add(new SetCardInfo("Yennett, Cryptic Sovereign", 51, Rarity.MYTHIC, mage.cards.y.YennetCryptSovereign.class)); + cards.add(new SetCardInfo("Yuriko, the Tiger's Shadow", 52, Rarity.RARE, mage.cards.y.YurikoTheTigersShadow.class)); + cards.add(new SetCardInfo("Zendikar Incarnate", 195, Rarity.UNCOMMON, mage.cards.z.ZendikarIncarnate.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/CommanderAnthologyVolumeII.java b/Mage.Sets/src/mage/sets/CommanderAnthologyVolumeII.java new file mode 100644 index 00000000000..eff5498d467 --- /dev/null +++ b/Mage.Sets/src/mage/sets/CommanderAnthologyVolumeII.java @@ -0,0 +1,337 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author rystan + */ +public class CommanderAnthologyVolumeII extends ExpansionSet { + + private static final CommanderAnthologyVolumeII instance = new CommanderAnthologyVolumeII(); + + public static CommanderAnthologyVolumeII getInstance() { + return instance; + } + + private CommanderAnthologyVolumeII() { + super("Commander Anthology 2018", "CM2", ExpansionSet.buildDate(2018, 6, 8), SetType.SUPPLEMENTAL); + this.blockName = "Commander Anthology 2018"; + this.hasBasicLands = false; + + cards.add(new SetCardInfo("Abzan Falconer", 15, Rarity.UNCOMMON, mage.cards.a.AbzanFalconer.class)); + cards.add(new SetCardInfo("Acidic Slime", 132, Rarity.UNCOMMON, mage.cards.a.AcidicSlime.class)); + cards.add(new SetCardInfo("Ancient Amphitheater", 232, Rarity.RARE, mage.cards.a.AncientAmphitheater.class)); + cards.add(new SetCardInfo("Ancient Excavation", 150, Rarity.UNCOMMON, mage.cards.a.AncientExcavation.class)); + cards.add(new SetCardInfo("Angel of Serenity", 16, Rarity.MYTHIC, mage.cards.a.AngelOfSerenity.class)); + cards.add(new SetCardInfo("Anya, Merciless Angel", 8, Rarity.MYTHIC, mage.cards.a.AnyaMercilessAngel.class)); + cards.add(new SetCardInfo("Arbiter of Knollridge", 17, Rarity.RARE, mage.cards.a.ArbiterOfKnollridge.class)); + cards.add(new SetCardInfo("Arcane Lighthouse", 233, Rarity.UNCOMMON, mage.cards.a.ArcaneLighthouse.class)); + cards.add(new SetCardInfo("Arcane Sanctum", 234, Rarity.UNCOMMON, mage.cards.a.ArcaneSanctum.class)); + cards.add(new SetCardInfo("Artisan of Kozilek", 14, Rarity.UNCOMMON, mage.cards.a.ArtisanOfKozilek.class)); + cards.add(new SetCardInfo("Ash Barrens", 235, Rarity.COMMON, mage.cards.a.AshBarrens.class)); + cards.add(new SetCardInfo("Astral Cornucopia", 172, Rarity.RARE, mage.cards.a.AstralCornucopia.class)); + cards.add(new SetCardInfo("Atraxa, Praetors' Voice", 10, Rarity.MYTHIC, mage.cards.a.AtraxaPraetorsVoice.class)); + cards.add(new SetCardInfo("Avatar of Woe", 57, Rarity.RARE, mage.cards.a.AvatarOfWoe.class)); + cards.add(new SetCardInfo("Azorius Chancery", 236, Rarity.UNCOMMON, mage.cards.a.AzoriusChancery.class)); + cards.add(new SetCardInfo("Bane of the Living", 58, Rarity.RARE, mage.cards.b.BaneOfTheLiving.class)); + cards.add(new SetCardInfo("Banishing Light", 18, Rarity.UNCOMMON, mage.cards.b.BanishingLight.class)); + cards.add(new SetCardInfo("Barren Moor", 237, Rarity.COMMON, mage.cards.b.BarrenMoor.class)); + cards.add(new SetCardInfo("Basalt Monolith", 173, Rarity.UNCOMMON, mage.cards.b.BasaltMonolith.class)); + cards.add(new SetCardInfo("Beetleback Chief", 83, Rarity.UNCOMMON, mage.cards.b.BeetlebackChief.class)); + cards.add(new SetCardInfo("Bitter Feud", 84, Rarity.RARE, mage.cards.b.BitterFeud.class)); + cards.add(new SetCardInfo("Blade of Selves", 174, Rarity.RARE, mage.cards.b.BladeOfSelves.class)); + cards.add(new SetCardInfo("Blasphemous Act", 85, Rarity.RARE, mage.cards.b.BlasphemousAct.class)); + cards.add(new SetCardInfo("Blasted Landscape", 238, Rarity.UNCOMMON, mage.cards.b.BlastedLandscape.class)); + cards.add(new SetCardInfo("Bogardan Hellkite", 86, Rarity.MYTHIC, mage.cards.b.BogardanHellkite.class)); + cards.add(new SetCardInfo("Borderland Behemoth", 87, Rarity.RARE, mage.cards.b.BorderlandBehemoth.class)); + cards.add(new SetCardInfo("Boros Cluestone", 175, Rarity.COMMON, mage.cards.b.BorosCluestone.class)); + cards.add(new SetCardInfo("Boros Garrison", 239, Rarity.UNCOMMON, mage.cards.b.BorosGarrison.class)); + cards.add(new SetCardInfo("Boros Guildgate", 240, Rarity.COMMON, mage.cards.b.BorosGuildgate.class)); + cards.add(new SetCardInfo("Boros Signet", 176, Rarity.COMMON, mage.cards.b.BorosSignet.class)); + cards.add(new SetCardInfo("Bosh, Iron Golem", 5, Rarity.RARE, mage.cards.b.BoshIronGolem.class)); + cards.add(new SetCardInfo("Bottle Gnomes", 177, Rarity.UNCOMMON, mage.cards.b.BottleGnomes.class)); + cards.add(new SetCardInfo("Brave the Sands", 19, Rarity.UNCOMMON, mage.cards.b.BraveTheSands.class)); + cards.add(new SetCardInfo("Brawn", 133, Rarity.UNCOMMON, mage.cards.b.Brawn.class)); + cards.add(new SetCardInfo("Breath of Darigaaz", 88, Rarity.UNCOMMON, mage.cards.b.BreathOfDarigaaz.class)); + cards.add(new SetCardInfo("Bred for the Hunt", 151, Rarity.UNCOMMON, mage.cards.b.BredForTheHunt.class)); + cards.add(new SetCardInfo("Buried Alive", 59, Rarity.UNCOMMON, mage.cards.b.BuriedAlive.class)); + cards.add(new SetCardInfo("Buried Ruin", 241, Rarity.UNCOMMON, mage.cards.b.BuriedRuin.class)); + cards.add(new SetCardInfo("Butcher of Malakir", 60, Rarity.RARE, mage.cards.b.ButcherOfMalakir.class)); + cards.add(new SetCardInfo("Caged Sun", 178, Rarity.RARE, mage.cards.c.CagedSun.class)); + cards.add(new SetCardInfo("Cathars' Crusade", 20, Rarity.RARE, mage.cards.c.CatharsCrusade.class)); + cards.add(new SetCardInfo("Cathodion", 179, Rarity.UNCOMMON, mage.cards.c.Cathodion.class)); + cards.add(new SetCardInfo("Cauldron of Souls", 180, Rarity.RARE, mage.cards.c.CauldronOfSouls.class)); + cards.add(new SetCardInfo("Champion of Lambholt", 134, Rarity.RARE, mage.cards.c.ChampionOfLambholt.class)); + cards.add(new SetCardInfo("Chaos Warp", 89, Rarity.RARE, mage.cards.c.ChaosWarp.class)); + cards.add(new SetCardInfo("Citadel Siege", 21, Rarity.RARE, mage.cards.c.CitadelSiege.class)); + cards.add(new SetCardInfo("Coldsteel Heart", 181, Rarity.UNCOMMON, mage.cards.c.ColdsteelHeart.class)); + cards.add(new SetCardInfo("Command Tower", 242, Rarity.COMMON, mage.cards.c.CommandTower.class)); + cards.add(new SetCardInfo("Commander's Sphere", 182, Rarity.COMMON, mage.cards.c.CommandersSphere.class)); + cards.add(new SetCardInfo("Corpsejack Menace", 152, Rarity.RARE, mage.cards.c.CorpsejackMenace.class)); + cards.add(new SetCardInfo("Crib Swap", 22, Rarity.UNCOMMON, mage.cards.c.CribSwap.class)); + cards.add(new SetCardInfo("Crystalline Crawler", 183, Rarity.RARE, mage.cards.c.CrystallineCrawler.class)); + cards.add(new SetCardInfo("Cultivate", 135, Rarity.COMMON, mage.cards.c.Cultivate.class)); + cards.add(new SetCardInfo("Curse of the Nightly Hunt", 90, Rarity.UNCOMMON, mage.cards.c.CurseOfTheNightlyHunt.class)); + cards.add(new SetCardInfo("Custodi Soulbinders", 23, Rarity.RARE, mage.cards.c.CustodiSoulbinders.class)); + cards.add(new SetCardInfo("Damia, Sage of Stone", 2, Rarity.MYTHIC, mage.cards.d.DamiaSageOfStone.class)); + cards.add(new SetCardInfo("Daretti, Scrap Savant", 4, Rarity.MYTHIC, mage.cards.d.DarettiScrapSavant.class)); + cards.add(new SetCardInfo("Dark Hatchling", 61, Rarity.RARE, mage.cards.d.DarkHatchling.class)); + cards.add(new SetCardInfo("Darksteel Citadel", 243, Rarity.UNCOMMON, mage.cards.d.DarksteelCitadel.class)); + cards.add(new SetCardInfo("Darksteel Ingot", 184, Rarity.UNCOMMON, mage.cards.d.DarksteelIngot.class)); + cards.add(new SetCardInfo("Darkwater Catacombs", 244, Rarity.RARE, mage.cards.d.DarkwaterCatacombs.class)); + cards.add(new SetCardInfo("Dawnbreak Reclaimer", 24, Rarity.RARE, mage.cards.d.DawnbreakReclaimer.class)); + cards.add(new SetCardInfo("Dawnglare Invoker", 25, Rarity.COMMON, mage.cards.d.DawnglareInvoker.class)); + cards.add(new SetCardInfo("Deepglow Skate", 39, Rarity.RARE, mage.cards.d.DeepglowSkate.class)); + cards.add(new SetCardInfo("Desecrator Hag", 153, Rarity.COMMON, mage.cards.d.DesecratorHag.class)); + cards.add(new SetCardInfo("Desolation Giant", 91, Rarity.RARE, mage.cards.d.DesolationGiant.class)); + cards.add(new SetCardInfo("Dimir Aqueduct", 245, Rarity.UNCOMMON, mage.cards.d.DimirAqueduct.class)); + cards.add(new SetCardInfo("Dimir Signet", 185, Rarity.COMMON, mage.cards.d.DimirSignet.class)); + cards.add(new SetCardInfo("Disaster Radius", 92, Rarity.RARE, mage.cards.d.DisasterRadius.class)); + cards.add(new SetCardInfo("Disdainful Stroke", 40, Rarity.COMMON, mage.cards.d.DisdainfulStroke.class)); + cards.add(new SetCardInfo("Dormant Volcano", 246, Rarity.UNCOMMON, mage.cards.d.DormantVolcano.class)); + cards.add(new SetCardInfo("Dreadship Reef", 247, Rarity.UNCOMMON, mage.cards.d.DreadshipReef.class)); + cards.add(new SetCardInfo("Dream Pillager", 93, Rarity.RARE, mage.cards.d.DreamPillager.class)); + cards.add(new SetCardInfo("Dreamborn Muse", 41, Rarity.RARE, mage.cards.d.DreambornMuse.class)); + cards.add(new SetCardInfo("Dreamstone Hedron", 186, Rarity.UNCOMMON, mage.cards.d.DreamstoneHedron.class)); + cards.add(new SetCardInfo("Drifting Meadow", 248, Rarity.COMMON, mage.cards.d.DriftingMeadow.class)); + cards.add(new SetCardInfo("Dualcaster Mage", 94, Rarity.RARE, mage.cards.d.DualcasterMage.class)); + cards.add(new SetCardInfo("Duelist's Heritage", 26, Rarity.RARE, mage.cards.d.DuelistsHeritage.class)); + cards.add(new SetCardInfo("Duneblast", 154, Rarity.RARE, mage.cards.d.Duneblast.class)); + cards.add(new SetCardInfo("Earthquake", 95, Rarity.RARE, mage.cards.e.Earthquake.class)); + cards.add(new SetCardInfo("Elite Scaleguard", 27, Rarity.UNCOMMON, mage.cards.e.EliteScaleguard.class)); + cards.add(new SetCardInfo("Enduring Scalelord", 155, Rarity.UNCOMMON, mage.cards.e.EnduringScalelord.class)); + cards.add(new SetCardInfo("Epochrasite", 187, Rarity.RARE, mage.cards.e.Epochrasite.class)); + cards.add(new SetCardInfo("Eternal Witness", 136, Rarity.UNCOMMON, mage.cards.e.EternalWitness.class)); + cards.add(new SetCardInfo("Everflowing Chalice", 188, Rarity.UNCOMMON, mage.cards.e.EverflowingChalice.class)); + cards.add(new SetCardInfo("Evolving Wilds", 249, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); + cards.add(new SetCardInfo("Exotic Orchard", 250, Rarity.RARE, mage.cards.e.ExoticOrchard.class)); + cards.add(new SetCardInfo("Extractor Demon", 62, Rarity.RARE, mage.cards.e.ExtractorDemon.class)); + cards.add(new SetCardInfo("Fact or Fiction", 42, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class)); + cards.add(new SetCardInfo("Faith's Fetters", 28, Rarity.COMMON, mage.cards.f.FaithsFetters.class)); + cards.add(new SetCardInfo("Faithless Looting", 96, Rarity.COMMON, mage.cards.f.FaithlessLooting.class)); + cards.add(new SetCardInfo("Fall of the Hammer", 97, Rarity.COMMON, mage.cards.f.FallOfTheHammer.class)); + cards.add(new SetCardInfo("Fathom Mage", 156, Rarity.RARE, mage.cards.f.FathomMage.class)); + cards.add(new SetCardInfo("Feldon of the Third Path", 6, Rarity.MYTHIC, mage.cards.f.FeldonOfTheThirdPath.class)); + cards.add(new SetCardInfo("Fellwar Stone", 189, Rarity.UNCOMMON, mage.cards.f.FellwarStone.class)); + cards.add(new SetCardInfo("Festercreep", 63, Rarity.COMMON, mage.cards.f.Festercreep.class)); + cards.add(new SetCardInfo("Fiery Confluence", 98, Rarity.RARE, mage.cards.f.FieryConfluence.class)); + cards.add(new SetCardInfo("Fire Diamond", 190, Rarity.UNCOMMON, mage.cards.f.FireDiamond.class)); + cards.add(new SetCardInfo("Flamekin Village", 251, Rarity.RARE, mage.cards.f.FlamekinVillage.class)); + cards.add(new SetCardInfo("Flametongue Kavu", 99, Rarity.UNCOMMON, mage.cards.f.FlametongueKavu.class)); + cards.add(new SetCardInfo("Fleshbag Marauder", 64, Rarity.UNCOMMON, mage.cards.f.FleshbagMarauder.class)); + cards.add(new SetCardInfo("Forest", 306, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 307, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 308, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 309, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 310, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 311, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 312, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forgotten Ancient", 137, Rarity.RARE, mage.cards.f.ForgottenAncient.class)); + cards.add(new SetCardInfo("Forgotten Cave", 252, Rarity.COMMON, mage.cards.f.ForgottenCave.class)); + cards.add(new SetCardInfo("Fumiko the Lowblood", 100, Rarity.RARE, mage.cards.f.FumikoTheLowblood.class)); + cards.add(new SetCardInfo("Ghave, Guru of Spores", 157, Rarity.MYTHIC, mage.cards.g.GhaveGuruOfSpores.class)); + cards.add(new SetCardInfo("Ghost Quarter", 253, Rarity.UNCOMMON, mage.cards.g.GhostQuarter.class)); + cards.add(new SetCardInfo("Gisela, Blade of Goldnight", 9, Rarity.MYTHIC, mage.cards.g.GiselaBladeOfGoldnight.class)); + cards.add(new SetCardInfo("Goblin Welder", 101, Rarity.RARE, mage.cards.g.GoblinWelder.class)); + cards.add(new SetCardInfo("Golgari Rot Farm", 254, Rarity.UNCOMMON, mage.cards.g.GolgariRotFarm.class)); + cards.add(new SetCardInfo("Golgari Signet", 191, Rarity.COMMON, mage.cards.g.GolgariSignet.class)); + cards.add(new SetCardInfo("Golgari Signet", 192, Rarity.COMMON, mage.cards.g.GolgariSignet.class)); + cards.add(new SetCardInfo("Grave Pact", 65, Rarity.RARE, mage.cards.g.GravePact.class)); + cards.add(new SetCardInfo("Gravedigger", 66, Rarity.COMMON, mage.cards.g.Gravedigger.class)); + cards.add(new SetCardInfo("Great Furnace", 255, Rarity.COMMON, mage.cards.g.GreatFurnace.class)); + cards.add(new SetCardInfo("Grip of Phyresis", 43, Rarity.UNCOMMON, mage.cards.g.GripOfPhyresis.class)); + cards.add(new SetCardInfo("Hamletback Goliath", 102, Rarity.RARE, mage.cards.h.HamletbackGoliath.class)); + cards.add(new SetCardInfo("Hammerfist Giant", 103, Rarity.RARE, mage.cards.h.HammerfistGiant.class)); + cards.add(new SetCardInfo("Hardened Scales", 138, Rarity.RARE, mage.cards.h.HardenedScales.class)); + cards.add(new SetCardInfo("Herald of the Host", 29, Rarity.UNCOMMON, mage.cards.h.HeraldOfTheHost.class)); + cards.add(new SetCardInfo("Hoard-Smelter Dragon", 104, Rarity.RARE, mage.cards.h.HoardSmelterDragon.class)); + cards.add(new SetCardInfo("Hostility", 105, Rarity.RARE, mage.cards.h.Hostility.class)); + cards.add(new SetCardInfo("Hunted Dragon", 106, Rarity.RARE, mage.cards.h.HuntedDragon.class)); + cards.add(new SetCardInfo("Ichor Wellspring", 193, Rarity.COMMON, mage.cards.i.IchorWellspring.class)); + cards.add(new SetCardInfo("Ikra Shidiqi, the Usurper", 11, Rarity.MYTHIC, mage.cards.i.IkraShidiqiTheUsurper.class)); + cards.add(new SetCardInfo("Impact Resonance", 107, Rarity.RARE, mage.cards.i.ImpactResonance.class)); + cards.add(new SetCardInfo("Incite Rebellion", 108, Rarity.RARE, mage.cards.i.InciteRebellion.class)); + cards.add(new SetCardInfo("Inferno Titan", 109, Rarity.MYTHIC, mage.cards.i.InfernoTitan.class)); + cards.add(new SetCardInfo("Ingot Chewer", 110, Rarity.COMMON, mage.cards.i.IngotChewer.class)); + cards.add(new SetCardInfo("Inspiring Call", 139, Rarity.UNCOMMON, mage.cards.i.InspiringCall.class)); + cards.add(new SetCardInfo("Ishai, Ojutai Dragonspeaker", 12, Rarity.MYTHIC, mage.cards.i.IshaiOjutaiDragonspeaker.class)); + cards.add(new SetCardInfo("Island", 286, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 287, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 289, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 290, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 291, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 292, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jalum Tome", 194, Rarity.RARE, mage.cards.j.JalumTome.class)); + cards.add(new SetCardInfo("Jareth, Leonine Titan", 30, Rarity.COMMON, mage.cards.j.JarethLeonineTitan.class)); + cards.add(new SetCardInfo("Juniper Order Ranger", 158, Rarity.UNCOMMON, mage.cards.j.JuniperOrderRanger.class)); + cards.add(new SetCardInfo("Junk Diver", 195, Rarity.RARE, mage.cards.j.JunkDiver.class)); + cards.add(new SetCardInfo("Jwar Isle Refuge", 256, Rarity.UNCOMMON, mage.cards.j.JwarIsleRefuge.class)); + cards.add(new SetCardInfo("Kalemne, Disciple of Iroas", 7, Rarity.MYTHIC, mage.cards.k.KalemneDiscipleOfIroas.class)); + cards.add(new SetCardInfo("Kalemne's Captain", 31, Rarity.RARE, mage.cards.k.KalemnesCaptain.class)); + cards.add(new SetCardInfo("Kalonian Hydra", 140, Rarity.MYTHIC, mage.cards.k.KalonianHydra.class)); + cards.add(new SetCardInfo("Languish", 67, Rarity.RARE, mage.cards.l.Languish.class)); + cards.add(new SetCardInfo("Lhurgoyf", 141, Rarity.RARE, mage.cards.l.Lhurgoyf.class)); + cards.add(new SetCardInfo("Lightning Greaves", 196, Rarity.UNCOMMON, mage.cards.l.LightningGreaves.class)); + cards.add(new SetCardInfo("Liquimetal Coating", 197, Rarity.UNCOMMON, mage.cards.l.LiquimetalCoating.class)); + cards.add(new SetCardInfo("Living Death", 68, Rarity.RARE, mage.cards.l.LivingDeath.class)); + cards.add(new SetCardInfo("Lonely Sandbar", 257, Rarity.COMMON, mage.cards.l.LonelySandbar.class)); + cards.add(new SetCardInfo("Loreseeker's Stone", 198, Rarity.UNCOMMON, mage.cards.l.LoreseekersStone.class)); + cards.add(new SetCardInfo("Loxodon Warhammer", 199, Rarity.UNCOMMON, mage.cards.l.LoxodonWarhammer.class)); + cards.add(new SetCardInfo("Magma Giant", 111, Rarity.RARE, mage.cards.m.MagmaGiant.class)); + cards.add(new SetCardInfo("Magmaquake", 112, Rarity.RARE, mage.cards.m.Magmaquake.class)); + cards.add(new SetCardInfo("Magus of the Wheel", 113, Rarity.RARE, mage.cards.m.MagusOfTheWheel.class)); + cards.add(new SetCardInfo("Manifold Insights", 44, Rarity.RARE, mage.cards.m.ManifoldInsights.class)); + cards.add(new SetCardInfo("Master Biomancer", 159, Rarity.MYTHIC, mage.cards.m.MasterBiomancer.class)); + cards.add(new SetCardInfo("Memory Erosion", 45, Rarity.RARE, mage.cards.m.MemoryErosion.class)); + cards.add(new SetCardInfo("Merciless Eviction", 160, Rarity.RARE, mage.cards.m.MercilessEviction.class)); + cards.add(new SetCardInfo("Meteor Blast", 114, Rarity.UNCOMMON, mage.cards.m.MeteorBlast.class)); + cards.add(new SetCardInfo("Migratory Route", 161, Rarity.UNCOMMON, mage.cards.m.MigratoryRoute.class)); + cards.add(new SetCardInfo("Mind Stone", 200, Rarity.UNCOMMON, mage.cards.m.MindStone.class)); + cards.add(new SetCardInfo("Minds Aglow", 46, Rarity.RARE, mage.cards.m.MindsAglow.class)); + cards.add(new SetCardInfo("Mirrorweave", 162, Rarity.RARE, mage.cards.m.Mirrorweave.class)); + cards.add(new SetCardInfo("Mortify", 163, Rarity.UNCOMMON, mage.cards.m.Mortify.class)); + cards.add(new SetCardInfo("Mortivore", 69, Rarity.RARE, mage.cards.m.Mortivore.class)); + cards.add(new SetCardInfo("Mountain", 300, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 301, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 302, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 303, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 304, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 305, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mulldrifter", 47, Rarity.UNCOMMON, mage.cards.m.Mulldrifter.class)); + cards.add(new SetCardInfo("Murmuring Bosk", 258, Rarity.RARE, mage.cards.m.MurmuringBosk.class)); + cards.add(new SetCardInfo("Mycosynth Wellspring", 201, Rarity.COMMON, mage.cards.m.MycosynthWellspring.class)); + cards.add(new SetCardInfo("Myr Battlesphere", 202, Rarity.RARE, mage.cards.m.MyrBattlesphere.class)); + cards.add(new SetCardInfo("Myr Retriever", 203, Rarity.UNCOMMON, mage.cards.m.MyrRetriever.class)); + cards.add(new SetCardInfo("Myr Sire", 204, Rarity.COMMON, mage.cards.m.MyrSire.class)); + cards.add(new SetCardInfo("Necroplasm", 70, Rarity.RARE, mage.cards.n.Necroplasm.class)); + cards.add(new SetCardInfo("Nezumi Graverobber", 71, Rarity.UNCOMMON, mage.cards.n.NezumiGraverobber.class)); + cards.add(new SetCardInfo("Oblivion Stone", 205, Rarity.RARE, mage.cards.o.OblivionStone.class)); + cards.add(new SetCardInfo("Opal Palace", 259, Rarity.COMMON, mage.cards.o.OpalPalace.class)); + cards.add(new SetCardInfo("Opulent Palace", 260, Rarity.UNCOMMON, mage.cards.o.OpulentPalace.class)); + cards.add(new SetCardInfo("Oreskos Explorer", 32, Rarity.UNCOMMON, mage.cards.o.OreskosExplorer.class)); + cards.add(new SetCardInfo("Orim's Thunder", 33, Rarity.COMMON, mage.cards.o.OrimsThunder.class)); + cards.add(new SetCardInfo("Orzhov Advokist", 34, Rarity.UNCOMMON, mage.cards.o.OrzhovAdvokist.class)); + cards.add(new SetCardInfo("Orzhov Signet", 206, Rarity.COMMON, mage.cards.o.OrzhovSignet.class)); + cards.add(new SetCardInfo("Palladium Myr", 207, Rarity.UNCOMMON, mage.cards.p.PalladiumMyr.class)); + cards.add(new SetCardInfo("Panic Spellbomb", 208, Rarity.COMMON, mage.cards.p.PanicSpellbomb.class)); + cards.add(new SetCardInfo("Patron of the Nezumi", 72, Rarity.RARE, mage.cards.p.PatronOfTheNezumi.class)); + cards.add(new SetCardInfo("Pentavus", 209, Rarity.RARE, mage.cards.p.Pentavus.class)); + cards.add(new SetCardInfo("Phyrexia's Core", 261, Rarity.UNCOMMON, mage.cards.p.PhyrexiasCore.class)); + cards.add(new SetCardInfo("Pilgrim's Eye", 210, Rarity.COMMON, mage.cards.p.PilgrimsEye.class)); + cards.add(new SetCardInfo("Plains", 279, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 280, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 281, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 282, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 283, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 284, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 285, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Pristine Talisman", 211, Rarity.COMMON, mage.cards.p.PristineTalisman.class)); + cards.add(new SetCardInfo("Putrefy", 164, Rarity.UNCOMMON, mage.cards.p.Putrefy.class)); + cards.add(new SetCardInfo("Relic Crush", 142, Rarity.COMMON, mage.cards.r.RelicCrush.class)); + cards.add(new SetCardInfo("Reliquary Tower", 262, Rarity.UNCOMMON, mage.cards.r.ReliquaryTower.class)); + cards.add(new SetCardInfo("Reveillark", 35, Rarity.RARE, mage.cards.r.Reveillark.class)); + cards.add(new SetCardInfo("Reyhan, Last of the Abzan", 13, Rarity.RARE, mage.cards.r.ReyhanLastOfTheAbzan.class)); + cards.add(new SetCardInfo("Riddlekeeper", 48, Rarity.RARE, mage.cards.r.Riddlekeeper.class)); + cards.add(new SetCardInfo("Rise from the Grave", 73, Rarity.UNCOMMON, mage.cards.r.RiseFromTheGrave.class)); + cards.add(new SetCardInfo("Rite of the Raging Storm", 115, Rarity.UNCOMMON, mage.cards.r.RiteOfTheRagingStorm.class)); + cards.add(new SetCardInfo("Ruby Medallion", 212, Rarity.RARE, mage.cards.r.RubyMedallion.class)); + cards.add(new SetCardInfo("Rupture Spire", 263, Rarity.COMMON, mage.cards.r.RuptureSpire.class)); + cards.add(new SetCardInfo("Sandsteppe Citadel", 264, Rarity.UNCOMMON, mage.cards.s.SandsteppeCitadel.class)); + cards.add(new SetCardInfo("Sandstone Oracle", 213, Rarity.UNCOMMON, mage.cards.s.SandstoneOracle.class)); + cards.add(new SetCardInfo("Scavenging Ooze", 143, Rarity.RARE, mage.cards.s.ScavengingOoze.class)); + cards.add(new SetCardInfo("Scrap Mastery", 116, Rarity.RARE, mage.cards.s.ScrapMastery.class)); + cards.add(new SetCardInfo("Scythe Specter", 74, Rarity.RARE, mage.cards.s.ScytheSpecter.class)); + cards.add(new SetCardInfo("Seaside Citadel", 265, Rarity.UNCOMMON, mage.cards.s.SeasideCitadel.class)); + cards.add(new SetCardInfo("Secluded Steppe", 266, Rarity.COMMON, mage.cards.s.SecludedSteppe.class)); + cards.add(new SetCardInfo("Seer's Sundial", 214, Rarity.RARE, mage.cards.s.SeersSundial.class)); + cards.add(new SetCardInfo("Sewer Nemesis", 75, Rarity.RARE, mage.cards.s.SewerNemesis.class)); + cards.add(new SetCardInfo("Shared Trauma", 76, Rarity.RARE, mage.cards.s.SharedTrauma.class)); + cards.add(new SetCardInfo("Sign in Blood", 77, Rarity.COMMON, mage.cards.s.SignInBlood.class)); + cards.add(new SetCardInfo("Simic Growth Chamber", 267, Rarity.UNCOMMON, mage.cards.s.SimicGrowthChamber.class)); + cards.add(new SetCardInfo("Simic Signet", 215, Rarity.COMMON, mage.cards.s.SimicSignet.class)); + cards.add(new SetCardInfo("Simic Signet", 216, Rarity.COMMON, mage.cards.s.SimicSignet.class)); + cards.add(new SetCardInfo("Skullbriar, the Walking Grave", 165, Rarity.RARE, mage.cards.s.SkullbriarTheWalkingGrave.class)); + cards.add(new SetCardInfo("Slipstream Eel", 49, Rarity.COMMON, mage.cards.s.SlipstreamEel.class)); + cards.add(new SetCardInfo("Smoldering Crater", 268, Rarity.COMMON, mage.cards.s.SmolderingCrater.class)); + cards.add(new SetCardInfo("Sol Ring", 217, Rarity.UNCOMMON, mage.cards.s.SolRing.class)); + cards.add(new SetCardInfo("Solemn Simulacrum", 218, Rarity.RARE, mage.cards.s.SolemnSimulacrum.class)); + cards.add(new SetCardInfo("Solemn Simulacrum", 219, Rarity.RARE, mage.cards.s.SolemnSimulacrum.class)); + cards.add(new SetCardInfo("Solidarity of Heroes", 144, Rarity.UNCOMMON, mage.cards.s.SolidarityOfHeroes.class)); + cards.add(new SetCardInfo("Spell Crumple", 50, Rarity.UNCOMMON, mage.cards.s.SpellCrumple.class)); + cards.add(new SetCardInfo("Spine of Ish Sah", 220, Rarity.RARE, mage.cards.s.SpineOfIshSah.class)); + cards.add(new SetCardInfo("Spitebellows", 117, Rarity.UNCOMMON, mage.cards.s.Spitebellows.class)); + cards.add(new SetCardInfo("Spitting Image", 166, Rarity.RARE, mage.cards.s.SpittingImage.class)); + cards.add(new SetCardInfo("Staff of Nin", 221, Rarity.RARE, mage.cards.s.StaffOfNin.class)); + cards.add(new SetCardInfo("Starstorm", 118, Rarity.RARE, mage.cards.s.Starstorm.class)); + cards.add(new SetCardInfo("Steel Hellkite", 222, Rarity.RARE, mage.cards.s.SteelHellkite.class)); + cards.add(new SetCardInfo("Stinkdrinker Daredevil", 119, Rarity.COMMON, mage.cards.s.StinkdrinkerDaredevil.class)); + cards.add(new SetCardInfo("Stitch Together", 78, Rarity.UNCOMMON, mage.cards.s.StitchTogether.class)); + cards.add(new SetCardInfo("Stoneshock Giant", 120, Rarity.UNCOMMON, mage.cards.s.StoneshockGiant.class)); + cards.add(new SetCardInfo("Sublime Exhalation", 36, Rarity.RARE, mage.cards.s.SublimeExhalation.class)); + cards.add(new SetCardInfo("Sun Titan", 37, Rarity.MYTHIC, mage.cards.s.SunTitan.class)); + cards.add(new SetCardInfo("Sungrass Prairie", 269, Rarity.RARE, mage.cards.s.SungrassPrairie.class)); + cards.add(new SetCardInfo("Sunrise Sovereign", 121, Rarity.RARE, mage.cards.s.SunriseSovereign.class)); + cards.add(new SetCardInfo("Svogthos, the Restless Tomb", 270, Rarity.UNCOMMON, mage.cards.s.SvogthosTheRestlessTomb.class)); + cards.add(new SetCardInfo("Swamp", 293, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 295, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 296, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 297, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 298, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 299, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swiftfoot Boots", 223, Rarity.UNCOMMON, mage.cards.s.SwiftfootBoots.class)); + cards.add(new SetCardInfo("Sylvan Reclamation", 167, Rarity.UNCOMMON, mage.cards.s.SylvanReclamation.class)); + cards.add(new SetCardInfo("Syphon Flesh", 79, Rarity.UNCOMMON, mage.cards.s.SyphonFlesh.class)); + cards.add(new SetCardInfo("Syphon Mind", 80, Rarity.COMMON, mage.cards.s.SyphonMind.class)); + cards.add(new SetCardInfo("Szadek, Lord of Secrets", 168, Rarity.RARE, mage.cards.s.SzadekLordOfSecrets.class)); + cards.add(new SetCardInfo("Taurean Mauler", 122, Rarity.RARE, mage.cards.t.TaureanMauler.class)); + cards.add(new SetCardInfo("Temple of the False God", 271, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class)); + cards.add(new SetCardInfo("Temple of the False God", 272, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class)); + cards.add(new SetCardInfo("Terramorphic Expanse", 273, Rarity.COMMON, mage.cards.t.TerramorphicExpanse.class)); + cards.add(new SetCardInfo("Tezzeret's Gambit", 51, Rarity.UNCOMMON, mage.cards.t.TezzeretsGambit.class)); + cards.add(new SetCardInfo("The Mimeoplasm", 1, Rarity.MYTHIC, mage.cards.t.TheMimeoplasm.class)); + cards.add(new SetCardInfo("Thought Vessel", 224, Rarity.COMMON, mage.cards.t.ThoughtVessel.class)); + cards.add(new SetCardInfo("Thrummingbird", 52, Rarity.UNCOMMON, mage.cards.t.Thrummingbird.class)); + cards.add(new SetCardInfo("Thundercloud Shaman", 123, Rarity.UNCOMMON, mage.cards.t.ThundercloudShaman.class)); + cards.add(new SetCardInfo("Trading Post", 225, Rarity.RARE, mage.cards.t.TradingPost.class)); + cards.add(new SetCardInfo("Tranquil Thicket", 274, Rarity.COMMON, mage.cards.t.TranquilThicket.class)); + cards.add(new SetCardInfo("Treasure Cruise", 53, Rarity.COMMON, mage.cards.t.TreasureCruise.class)); + cards.add(new SetCardInfo("Tribute to the Wild", 145, Rarity.UNCOMMON, mage.cards.t.TributeToTheWild.class)); + cards.add(new SetCardInfo("Triskelavus", 226, Rarity.RARE, mage.cards.t.Triskelavus.class)); + cards.add(new SetCardInfo("Troll Ascetic", 146, Rarity.RARE, mage.cards.t.TrollAscetic.class)); + cards.add(new SetCardInfo("Tuktuk the Explorer", 124, Rarity.RARE, mage.cards.t.TuktukTheExplorer.class)); + cards.add(new SetCardInfo("Tuskguard Captain", 147, Rarity.UNCOMMON, mage.cards.t.TuskguardCaptain.class)); + cards.add(new SetCardInfo("Tyrant's Familiar", 125, Rarity.RARE, mage.cards.t.TyrantsFamiliar.class)); + cards.add(new SetCardInfo("Underground River", 275, Rarity.RARE, mage.cards.u.UndergroundRiver.class)); + cards.add(new SetCardInfo("Unnerve", 81, Rarity.COMMON, mage.cards.u.Unnerve.class)); + cards.add(new SetCardInfo("Unstable Obelisk", 227, Rarity.UNCOMMON, mage.cards.u.UnstableObelisk.class)); + cards.add(new SetCardInfo("Urza's Incubator", 228, Rarity.RARE, mage.cards.u.UrzasIncubator.class)); + cards.add(new SetCardInfo("Victory's Herald", 38, Rarity.RARE, mage.cards.v.VictorysHerald.class)); + cards.add(new SetCardInfo("Vivid Crag", 276, Rarity.UNCOMMON, mage.cards.v.VividCrag.class)); + cards.add(new SetCardInfo("Vivid Meadow", 277, Rarity.UNCOMMON, mage.cards.v.VividMeadow.class)); + cards.add(new SetCardInfo("Volcanic Offering", 126, Rarity.RARE, mage.cards.v.VolcanicOffering.class)); + cards.add(new SetCardInfo("Vorel of the Hull Clade", 169, Rarity.RARE, mage.cards.v.VorelOfTheHullClade.class)); + cards.add(new SetCardInfo("Vorosh, the Hunter", 3, Rarity.RARE, mage.cards.v.VoroshTheHunter.class)); + cards.add(new SetCardInfo("Vow of Flight", 54, Rarity.UNCOMMON, mage.cards.v.VowOfFlight.class)); + cards.add(new SetCardInfo("Vow of Malice", 82, Rarity.UNCOMMON, mage.cards.v.VowOfMalice.class)); + cards.add(new SetCardInfo("Vow of Wildness", 148, Rarity.UNCOMMON, mage.cards.v.VowOfWildness.class)); + cards.add(new SetCardInfo("Vulturous Zombie", 170, Rarity.RARE, mage.cards.v.VulturousZombie.class)); + cards.add(new SetCardInfo("Warchief Giant", 127, Rarity.UNCOMMON, mage.cards.w.WarchiefGiant.class)); + cards.add(new SetCardInfo("Warmonger Hellkite", 128, Rarity.RARE, mage.cards.w.WarmongerHellkite.class)); + cards.add(new SetCardInfo("Warstorm Surge", 129, Rarity.RARE, mage.cards.w.WarstormSurge.class)); + cards.add(new SetCardInfo("Wayfarer's Bauble", 229, Rarity.COMMON, mage.cards.w.WayfarersBauble.class)); + cards.add(new SetCardInfo("Whipflare", 130, Rarity.UNCOMMON, mage.cards.w.Whipflare.class)); + cards.add(new SetCardInfo("Wind-Scarred Crag", 278, Rarity.COMMON, mage.cards.w.WindScarredCrag.class)); + cards.add(new SetCardInfo("Windfall", 55, Rarity.UNCOMMON, mage.cards.w.Windfall.class)); + cards.add(new SetCardInfo("Wonder", 56, Rarity.UNCOMMON, mage.cards.w.Wonder.class)); + cards.add(new SetCardInfo("Word of Seizing", 131, Rarity.RARE, mage.cards.w.WordOfSeizing.class)); + cards.add(new SetCardInfo("Worn Powerstone", 230, Rarity.UNCOMMON, mage.cards.w.WornPowerstone.class)); + cards.add(new SetCardInfo("Wrexial, the Risen Deep", 171, Rarity.MYTHIC, mage.cards.w.WrexialTheRisenDeep.class)); + cards.add(new SetCardInfo("Wurmcoil Engine", 231, Rarity.MYTHIC, mage.cards.w.WurmcoilEngine.class)); + cards.add(new SetCardInfo("Yavimaya Elder", 149, Rarity.COMMON, mage.cards.y.YavimayaElder.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/CoreSet2019.java b/Mage.Sets/src/mage/sets/CoreSet2019.java index 8ad48668f8f..132743ef002 100644 --- a/Mage.Sets/src/mage/sets/CoreSet2019.java +++ b/Mage.Sets/src/mage/sets/CoreSet2019.java @@ -1,7 +1,14 @@ - package mage.sets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import mage.cards.Card; import mage.cards.ExpansionSet; +import mage.cards.repository.CardCriteria; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; +import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.SetType; @@ -16,51 +23,382 @@ public final class CoreSet2019 extends ExpansionSet { public static CoreSet2019 getInstance() { return instance; } + List savedSpecialCommon = new ArrayList<>(); + protected final List savedSpecialLand = new ArrayList<>(); private CoreSet2019() { super("Core Set 2019", "M19", ExpansionSet.buildDate(2018, 7, 13), SetType.CORE); this.hasBoosters = true; + this.hasBasicLands = true; + this.numBoosterSpecial = 0; this.numBoosterLands = 1; this.numBoosterCommon = 10; this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; + this.numBoosterDoubleFaced = -1; this.maxCardNumberInBooster = 280; + + // Core 2019 boosters have a 5/12 chance of basic land being replaced + // with the common taplands, which DO NOT appear in the common slot. + this.ratioBoosterSpecialLand = 12; + this.ratioBoosterSpecialLandNumerator = 5; + + cards.add(new SetCardInfo("Abnormal Endurance", 85, Rarity.COMMON, mage.cards.a.AbnormalEndurance.class)); cards.add(new SetCardInfo("Act of Treason", 127, Rarity.COMMON, mage.cards.a.ActOfTreason.class)); + cards.add(new SetCardInfo("Aegis of the Heavens", 1, Rarity.UNCOMMON, mage.cards.a.AegisOfTheHeavens.class)); + cards.add(new SetCardInfo("Aerial Engineer", 211, Rarity.UNCOMMON, mage.cards.a.AerialEngineer.class)); + cards.add(new SetCardInfo("Aether Tunnel", 43, Rarity.UNCOMMON, mage.cards.a.AetherTunnel.class)); + cards.add(new SetCardInfo("Aethershield Artificer", 2, Rarity.UNCOMMON, mage.cards.a.AethershieldArtificer.class)); + cards.add(new SetCardInfo("Aggressive Mammoth", 302, Rarity.RARE, mage.cards.a.AggressiveMammoth.class)); + cards.add(new SetCardInfo("Air Elemental", 308, Rarity.UNCOMMON, mage.cards.a.AirElemental.class)); + cards.add(new SetCardInfo("Ajani's Influence", 282, Rarity.RARE, mage.cards.a.AjanisInfluence.class)); + cards.add(new SetCardInfo("Ajani's Last Stand", 4, Rarity.RARE, mage.cards.a.AjanisLastStand.class)); + cards.add(new SetCardInfo("Ajani's Pridemate", 5, Rarity.UNCOMMON, mage.cards.a.AjanisPridemate.class)); + cards.add(new SetCardInfo("Ajani's Welcome", 6, Rarity.UNCOMMON, mage.cards.a.AjanisWelcome.class)); + cards.add(new SetCardInfo("Ajani, Adversary of Tyrants", 3, Rarity.MYTHIC, mage.cards.a.AjaniAdversaryOfTyrants.class)); + cards.add(new SetCardInfo("Ajani, Wise Counselor", 281, Rarity.MYTHIC, mage.cards.a.AjaniWiseCounselor.class)); + cards.add(new SetCardInfo("Alpine Moon", 128, Rarity.RARE, mage.cards.a.AlpineMoon.class)); + cards.add(new SetCardInfo("Amulet of Safekeeping", 226, Rarity.RARE, mage.cards.a.AmuletOfSafekeeping.class)); + cards.add(new SetCardInfo("Angel of the Dawn", 7, Rarity.COMMON, mage.cards.a.AngelOfTheDawn.class)); cards.add(new SetCardInfo("Anticipate", 44, Rarity.COMMON, mage.cards.a.Anticipate.class)); + cards.add(new SetCardInfo("Apex of Power", 129, Rarity.MYTHIC, mage.cards.a.ApexOfPower.class)); + cards.add(new SetCardInfo("Arcades, the Strategist", 212, Rarity.MYTHIC, mage.cards.a.ArcadesTheStrategist.class)); + cards.add(new SetCardInfo("Arcane Encyclopedia", 227, Rarity.UNCOMMON, mage.cards.a.ArcaneEncyclopedia.class)); + cards.add(new SetCardInfo("Arisen Gorgon", 292, Rarity.UNCOMMON, mage.cards.a.ArisenGorgon.class)); + cards.add(new SetCardInfo("Aven Wind Mage", 45, Rarity.COMMON, mage.cards.a.AvenWindMage.class)); + cards.add(new SetCardInfo("Aviation Pioneer", 46, Rarity.COMMON, mage.cards.a.AviationPioneer.class)); + cards.add(new SetCardInfo("Banefire", 130, Rarity.RARE, mage.cards.b.Banefire.class)); + cards.add(new SetCardInfo("Befuddle", 309, Rarity.COMMON, mage.cards.b.Befuddle.class)); + cards.add(new SetCardInfo("Blanchwood Armor", 169, Rarity.UNCOMMON, mage.cards.b.BlanchwoodArmor.class)); + cards.add(new SetCardInfo("Blood Divination", 86, Rarity.UNCOMMON, mage.cards.b.BloodDivination.class)); + cards.add(new SetCardInfo("Boggart Brute", 131, Rarity.COMMON, mage.cards.b.BoggartBrute.class)); + cards.add(new SetCardInfo("Bogstomper", 87, Rarity.COMMON, mage.cards.b.Bogstomper.class)); + cards.add(new SetCardInfo("Bone Dragon", 88, Rarity.MYTHIC, mage.cards.b.BoneDragon.class)); + cards.add(new SetCardInfo("Bone to Ash", 47, Rarity.UNCOMMON, mage.cards.b.BoneToAsh.class)); + cards.add(new SetCardInfo("Brawl-Bash Ogre", 213, Rarity.UNCOMMON, mage.cards.b.BrawlBashOgre.class)); + cards.add(new SetCardInfo("Bristling Boar", 170, Rarity.COMMON, mage.cards.b.BristlingBoar.class)); cards.add(new SetCardInfo("Cancel", 48, Rarity.COMMON, mage.cards.c.Cancel.class)); cards.add(new SetCardInfo("Catalyst Elemental", 132, Rarity.COMMON, mage.cards.c.CatalystElemental.class)); + cards.add(new SetCardInfo("Cavalry Drillmaster", 8, Rarity.COMMON, mage.cards.c.CavalryDrillmaster.class)); + cards.add(new SetCardInfo("Centaur Courser", 171, Rarity.COMMON, mage.cards.c.CentaurCourser.class)); + cards.add(new SetCardInfo("Chaos Wand", 228, Rarity.RARE, mage.cards.c.ChaosWand.class)); + cards.add(new SetCardInfo("Child of Night", 89, Rarity.COMMON, mage.cards.c.ChildOfNight.class)); + cards.add(new SetCardInfo("Chromium, the Mutable", 214, Rarity.MYTHIC, mage.cards.c.ChromiumTheMutable.class)); + cards.add(new SetCardInfo("Cinder Barrens", 248, Rarity.COMMON, mage.cards.c.CinderBarrens.class)); + cards.add(new SetCardInfo("Cleansing Nova", 9, Rarity.RARE, mage.cards.c.CleansingNova.class)); + cards.add(new SetCardInfo("Colossal Dreadmaw", 172, Rarity.COMMON, mage.cards.c.ColossalDreadmaw.class)); + cards.add(new SetCardInfo("Colossal Majesty", 173, Rarity.UNCOMMON, mage.cards.c.ColossalMajesty.class)); + cards.add(new SetCardInfo("Court Cleric", 283, Rarity.UNCOMMON, mage.cards.c.CourtCleric.class)); + cards.add(new SetCardInfo("Crash Through", 133, Rarity.COMMON, mage.cards.c.CrashThrough.class)); + cards.add(new SetCardInfo("Crucible of Worlds", 229, Rarity.MYTHIC, mage.cards.c.CrucibleOfWorlds.class)); + cards.add(new SetCardInfo("Daggerback Basilisk", 174, Rarity.COMMON, mage.cards.d.DaggerbackBasilisk.class)); + cards.add(new SetCardInfo("Dark-Dweller Oracle", 134, Rarity.RARE, mage.cards.d.DarkDwellerOracle.class)); cards.add(new SetCardInfo("Daybreak Chaplain", 10, Rarity.COMMON, mage.cards.d.DaybreakChaplain.class)); + cards.add(new SetCardInfo("Death Baron", 90, Rarity.RARE, mage.cards.d.DeathBaron.class)); + cards.add(new SetCardInfo("Declare Dominance", 175, Rarity.UNCOMMON, mage.cards.d.DeclareDominance.class)); + cards.add(new SetCardInfo("Demanding Dragon", 135, Rarity.RARE, mage.cards.d.DemandingDragon.class)); + cards.add(new SetCardInfo("Demon of Catastrophes", 91, Rarity.RARE, mage.cards.d.DemonOfCatastrophes.class)); + cards.add(new SetCardInfo("Departed Deckhand", 49, Rarity.UNCOMMON, mage.cards.d.DepartedDeckhand.class)); + cards.add(new SetCardInfo("Desecrated Tomb", 230, Rarity.RARE, mage.cards.d.DesecratedTomb.class)); + cards.add(new SetCardInfo("Detection Tower", 249, Rarity.RARE, mage.cards.d.DetectionTower.class)); + cards.add(new SetCardInfo("Diamond Mare", 231, Rarity.UNCOMMON, mage.cards.d.DiamondMare.class)); + cards.add(new SetCardInfo("Diregraf Ghoul", 92, Rarity.UNCOMMON, mage.cards.d.DiregrafGhoul.class)); + cards.add(new SetCardInfo("Dismissive Pyromancer", 136, Rarity.RARE, mage.cards.d.DismissivePyromancer.class)); cards.add(new SetCardInfo("Disperse", 50, Rarity.COMMON, mage.cards.d.Disperse.class)); + cards.add(new SetCardInfo("Divination", 51, Rarity.COMMON, mage.cards.d.Divination.class)); + cards.add(new SetCardInfo("Djinn of Wishes", 52, Rarity.RARE, mage.cards.d.DjinnOfWishes.class)); + cards.add(new SetCardInfo("Doomed Dissenter", 93, Rarity.COMMON, mage.cards.d.DoomedDissenter.class)); + cards.add(new SetCardInfo("Doublecast", 137, Rarity.UNCOMMON, mage.cards.d.Doublecast.class)); + cards.add(new SetCardInfo("Draconic Disciple", 215, Rarity.UNCOMMON, mage.cards.d.DraconicDisciple.class)); + cards.add(new SetCardInfo("Dragon Egg", 138, Rarity.UNCOMMON, mage.cards.d.DragonEgg.class)); + cards.add(new SetCardInfo("Dragon's Hoard", 232, Rarity.RARE, mage.cards.d.DragonsHoard.class)); + cards.add(new SetCardInfo("Druid of Horns", 176, Rarity.UNCOMMON, mage.cards.d.DruidOfHorns.class)); + cards.add(new SetCardInfo("Druid of the Cowl", 177, Rarity.COMMON, mage.cards.d.DruidOfTheCowl.class)); + cards.add(new SetCardInfo("Dryad Greenseeker", 178, Rarity.UNCOMMON, mage.cards.d.DryadGreenseeker.class)); + cards.add(new SetCardInfo("Duress", 94, Rarity.COMMON, mage.cards.d.Duress.class)); cards.add(new SetCardInfo("Dwarven Priest", 11, Rarity.COMMON, mage.cards.d.DwarvenPriest.class)); cards.add(new SetCardInfo("Dwindle", 53, Rarity.COMMON, mage.cards.d.Dwindle.class)); + cards.add(new SetCardInfo("Electrify", 139, Rarity.COMMON, mage.cards.e.Electrify.class)); + cards.add(new SetCardInfo("Elvish Clancaller", 179, Rarity.RARE, mage.cards.e.ElvishClancaller.class)); + cards.add(new SetCardInfo("Elvish Rejuvenator", 180, Rarity.COMMON, mage.cards.e.ElvishRejuvenator.class)); + cards.add(new SetCardInfo("Enigma Drake", 216, Rarity.UNCOMMON, mage.cards.e.EnigmaDrake.class)); + cards.add(new SetCardInfo("Epicure of Blood", 95, Rarity.COMMON, mage.cards.e.EpicureOfBlood.class)); + cards.add(new SetCardInfo("Essence Scatter", 54, Rarity.COMMON, mage.cards.e.EssenceScatter.class)); + cards.add(new SetCardInfo("Exclusion Mage", 55, Rarity.UNCOMMON, mage.cards.e.ExclusionMage.class)); + cards.add(new SetCardInfo("Explosive Apparatus", 233, Rarity.COMMON, mage.cards.e.ExplosiveApparatus.class)); + cards.add(new SetCardInfo("Fell Specter", 96, Rarity.UNCOMMON, mage.cards.f.FellSpecter.class)); + cards.add(new SetCardInfo("Field Creeper", 234, Rarity.COMMON, mage.cards.f.FieldCreeper.class)); + cards.add(new SetCardInfo("Fiery Finish", 140, Rarity.UNCOMMON, mage.cards.f.FieryFinish.class)); cards.add(new SetCardInfo("Fire Elemental", 141, Rarity.COMMON, mage.cards.f.FireElemental.class)); + cards.add(new SetCardInfo("Forest", 277, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 278, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 279, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 280, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forsaken Sanctuary", 250, Rarity.COMMON, mage.cards.f.ForsakenSanctuary.class)); + cards.add(new SetCardInfo("Foul Orchard", 251, Rarity.COMMON, mage.cards.f.FoulOrchard.class)); + cards.add(new SetCardInfo("Fountain of Renewal", 235, Rarity.UNCOMMON, mage.cards.f.FountainOfRenewal.class)); + cards.add(new SetCardInfo("Fraying Omnipotence", 97, Rarity.RARE, mage.cards.f.FrayingOmnipotence.class)); cards.add(new SetCardInfo("Frilled Sea Serpent", 56, Rarity.COMMON, mage.cards.f.FrilledSeaSerpent.class)); + cards.add(new SetCardInfo("Gallant Cavalry", 12, Rarity.COMMON, mage.cards.g.GallantCavalry.class)); + cards.add(new SetCardInfo("Gargoyle Sentinel", 236, Rarity.UNCOMMON, mage.cards.g.GargoyleSentinel.class)); + cards.add(new SetCardInfo("Gearsmith Guardian", 237, Rarity.COMMON, mage.cards.g.GearsmithGuardian.class)); cards.add(new SetCardInfo("Gearsmith Prodigy", 57, Rarity.COMMON, mage.cards.g.GearsmithProdigy.class)); + cards.add(new SetCardInfo("Ghastbark Twins", 181, Rarity.UNCOMMON, mage.cards.g.GhastbarkTwins.class)); + cards.add(new SetCardInfo("Ghirapur Guide", 182, Rarity.UNCOMMON, mage.cards.g.GhirapurGuide.class)); + cards.add(new SetCardInfo("Ghostform", 58, Rarity.COMMON, mage.cards.g.Ghostform.class)); + cards.add(new SetCardInfo("Giant Spider", 183, Rarity.COMMON, mage.cards.g.GiantSpider.class)); + cards.add(new SetCardInfo("Gift of Paradise", 184, Rarity.UNCOMMON, mage.cards.g.GiftOfParadise.class)); + cards.add(new SetCardInfo("Gigantosaurus", 185, Rarity.RARE, mage.cards.g.Gigantosaurus.class)); cards.add(new SetCardInfo("Goblin Instigator", 142, Rarity.COMMON, mage.cards.g.GoblinInstigator.class)); cards.add(new SetCardInfo("Goblin Motivator", 143, Rarity.COMMON, mage.cards.g.GoblinMotivator.class)); + cards.add(new SetCardInfo("Goblin Trashmaster", 144, Rarity.RARE, mage.cards.g.GoblinTrashmaster.class)); + cards.add(new SetCardInfo("Goreclaw, Terror of Qal Sisma", 186, Rarity.RARE, mage.cards.g.GoreclawTerrorOfQalSisma.class)); + cards.add(new SetCardInfo("Grasping Scoundrel", 312, Rarity.COMMON, mage.cards.g.GraspingScoundrel.class)); + cards.add(new SetCardInfo("Gravedigger", 98, Rarity.UNCOMMON, mage.cards.g.Gravedigger.class)); + cards.add(new SetCardInfo("Gravewaker", 293, Rarity.RARE, mage.cards.g.Gravewaker.class)); + cards.add(new SetCardInfo("Graveyard Marshal", 99, Rarity.RARE, mage.cards.g.GraveyardMarshal.class)); + cards.add(new SetCardInfo("Greenwood Sentinel", 187, Rarity.COMMON, mage.cards.g.GreenwoodSentinel.class)); + cards.add(new SetCardInfo("Guttersnipe", 145, Rarity.UNCOMMON, mage.cards.g.Guttersnipe.class)); + cards.add(new SetCardInfo("Havoc Devils", 146, Rarity.COMMON, mage.cards.h.HavocDevils.class)); + cards.add(new SetCardInfo("Herald of Faith", 13, Rarity.UNCOMMON, mage.cards.h.HeraldOfFaith.class)); + cards.add(new SetCardInfo("Heroic Reinforcements", 217, Rarity.UNCOMMON, mage.cards.h.HeroicReinforcements.class)); + cards.add(new SetCardInfo("Hieromancer's Cage", 14, Rarity.UNCOMMON, mage.cards.h.HieromancersCage.class)); + cards.add(new SetCardInfo("Highland Game", 188, Rarity.COMMON, mage.cards.h.HighlandGame.class)); + cards.add(new SetCardInfo("Highland Lake", 252, Rarity.COMMON, mage.cards.h.HighlandLake.class)); + cards.add(new SetCardInfo("Hired Blade", 100, Rarity.COMMON, mage.cards.h.HiredBlade.class)); + cards.add(new SetCardInfo("Horizon Scholar", 59, Rarity.UNCOMMON, mage.cards.h.HorizonScholar.class)); cards.add(new SetCardInfo("Hostile Minotaur", 147, Rarity.COMMON, mage.cards.h.HostileMinotaur.class)); + cards.add(new SetCardInfo("Hungering Hydra", 189, Rarity.RARE, mage.cards.h.HungeringHydra.class)); + cards.add(new SetCardInfo("Infectious Horror", 101, Rarity.COMMON, mage.cards.i.InfectiousHorror.class)); + cards.add(new SetCardInfo("Infernal Reckoning", 102, Rarity.RARE, mage.cards.i.InfernalReckoning.class)); + cards.add(new SetCardInfo("Infernal Scarring", 103, Rarity.COMMON, mage.cards.i.InfernalScarring.class)); + cards.add(new SetCardInfo("Inferno Hellion", 148, Rarity.UNCOMMON, mage.cards.i.InfernoHellion.class)); cards.add(new SetCardInfo("Inspired Charge", 15, Rarity.COMMON, mage.cards.i.InspiredCharge.class)); + cards.add(new SetCardInfo("Invoke the Divine", 16, Rarity.COMMON, mage.cards.i.InvokeTheDivine.class)); + cards.add(new SetCardInfo("Isareth the Awakener", 104, Rarity.RARE, mage.cards.i.IsarethTheAwakener.class)); + cards.add(new SetCardInfo("Island", 265, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 266, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 267, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 268, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Isolate", 17, Rarity.RARE, mage.cards.i.Isolate.class)); + cards.add(new SetCardInfo("Kargan Dragonrider", 297, Rarity.COMMON, mage.cards.k.KarganDragonrider.class)); cards.add(new SetCardInfo("Knight of the Tusk", 18, Rarity.COMMON, mage.cards.k.KnightOfTheTusk.class)); cards.add(new SetCardInfo("Knight's Pledge", 19, Rarity.COMMON, mage.cards.k.KnightsPledge.class)); + cards.add(new SetCardInfo("Knightly Valor", 20, Rarity.UNCOMMON, mage.cards.k.KnightlyValor.class)); + cards.add(new SetCardInfo("Lathliss, Dragon Queen", 149, Rarity.RARE, mage.cards.l.LathlissDragonQueen.class)); cards.add(new SetCardInfo("Lava Axe", 150, Rarity.COMMON, mage.cards.l.LavaAxe.class)); + cards.add(new SetCardInfo("Lena, Selfless Champion", 21, Rarity.RARE, mage.cards.l.LenaSelflessChampion.class)); + cards.add(new SetCardInfo("Leonin Vanguard", 22, Rarity.UNCOMMON, mage.cards.l.LeoninVanguard.class)); + cards.add(new SetCardInfo("Leonin Warleader", 23, Rarity.RARE, mage.cards.l.LeoninWarleader.class)); + cards.add(new SetCardInfo("Lich's Caress", 105, Rarity.COMMON, mage.cards.l.LichsCaress.class)); + cards.add(new SetCardInfo("Lightning Mare", 151, Rarity.UNCOMMON, mage.cards.l.LightningMare.class)); + cards.add(new SetCardInfo("Lightning Strike", 152, Rarity.UNCOMMON, mage.cards.l.LightningStrike.class)); + cards.add(new SetCardInfo("Liliana's Contract", 107, Rarity.RARE, mage.cards.l.LilianasContract.class)); + cards.add(new SetCardInfo("Liliana's Spoils", 294, Rarity.RARE, mage.cards.l.LilianasSpoils.class)); + cards.add(new SetCardInfo("Liliana, Untouched by Death", 106, Rarity.MYTHIC, mage.cards.l.LilianaUntouchedByDeath.class)); + cards.add(new SetCardInfo("Liliana, the Necromancer", 291, Rarity.MYTHIC, mage.cards.l.LilianaTheNecromancer.class)); + cards.add(new SetCardInfo("Llanowar Elves", 314, Rarity.COMMON, mage.cards.l.LlanowarElves.class)); cards.add(new SetCardInfo("Loxodon Line Breaker", 24, Rarity.COMMON, mage.cards.l.LoxodonLineBreaker.class)); + cards.add(new SetCardInfo("Luminous Bonds", 25, Rarity.COMMON, mage.cards.l.LuminousBonds.class)); + cards.add(new SetCardInfo("Macabre Waltz", 108, Rarity.COMMON, mage.cards.m.MacabreWaltz.class)); + cards.add(new SetCardInfo("Magistrate's Scepter", 238, Rarity.RARE, mage.cards.m.MagistratesScepter.class)); + cards.add(new SetCardInfo("Make a Stand", 26, Rarity.UNCOMMON, mage.cards.m.MakeAStand.class)); + cards.add(new SetCardInfo("Manalith", 239, Rarity.COMMON, mage.cards.m.Manalith.class)); + cards.add(new SetCardInfo("Marauder's Axe", 240, Rarity.COMMON, mage.cards.m.MaraudersAxe.class)); + cards.add(new SetCardInfo("Meandering River", 253, Rarity.COMMON, mage.cards.m.MeanderingRiver.class)); + cards.add(new SetCardInfo("Mentor of the Meek", 27, Rarity.RARE, mage.cards.m.MentorOfTheMeek.class)); + cards.add(new SetCardInfo("Metamorphic Alteration", 60, Rarity.RARE, mage.cards.m.MetamorphicAlteration.class)); + cards.add(new SetCardInfo("Meteor Golem", 241, Rarity.UNCOMMON, mage.cards.m.MeteorGolem.class)); cards.add(new SetCardInfo("Mighty Leap", 28, Rarity.COMMON, mage.cards.m.MightyLeap.class)); + cards.add(new SetCardInfo("Militia Bugler", 29, Rarity.UNCOMMON, mage.cards.m.MilitiaBugler.class)); + cards.add(new SetCardInfo("Millstone", 242, Rarity.UNCOMMON, mage.cards.m.Millstone.class)); + cards.add(new SetCardInfo("Mind Rot", 109, Rarity.COMMON, mage.cards.m.MindRot.class)); + cards.add(new SetCardInfo("Mirror Image", 61, Rarity.UNCOMMON, mage.cards.m.MirrorImage.class)); + cards.add(new SetCardInfo("Mist-Cloaked Herald", 310, Rarity.COMMON, mage.cards.m.MistCloakedHerald.class)); + cards.add(new SetCardInfo("Mistcaller", 62, Rarity.RARE, mage.cards.m.Mistcaller.class)); + cards.add(new SetCardInfo("Mountain", 273, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 274, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 275, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 276, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Murder", 110, Rarity.UNCOMMON, mage.cards.m.Murder.class)); + cards.add(new SetCardInfo("Mystic Archaeologist", 63, Rarity.RARE, mage.cards.m.MysticArchaeologist.class)); + cards.add(new SetCardInfo("Naturalize", 190, Rarity.COMMON, mage.cards.n.Naturalize.class)); + cards.add(new SetCardInfo("Nexus of Fate", 306, Rarity.MYTHIC, mage.cards.n.NexusOfFate.class)); + cards.add(new SetCardInfo("Nicol Bolas, the Arisen", 218, Rarity.MYTHIC, mage.cards.n.NicolBolasTheArisen.class)); + cards.add(new SetCardInfo("Nicol Bolas, the Ravager", 218, Rarity.MYTHIC, mage.cards.n.NicolBolasTheRavager.class)); + cards.add(new SetCardInfo("Nightmare's Thirst", 111, Rarity.UNCOMMON, mage.cards.n.NightmaresThirst.class)); + cards.add(new SetCardInfo("Novice Knight", 30, Rarity.UNCOMMON, mage.cards.n.NoviceKnight.class)); + cards.add(new SetCardInfo("Oakenform", 191, Rarity.COMMON, mage.cards.o.Oakenform.class)); cards.add(new SetCardInfo("Omenspeaker", 64, Rarity.COMMON, mage.cards.o.Omenspeaker.class)); + cards.add(new SetCardInfo("Omniscience", 65, Rarity.MYTHIC, mage.cards.o.Omniscience.class)); cards.add(new SetCardInfo("Onakke Ogre", 153, Rarity.COMMON, mage.cards.o.OnakkeOgre.class)); + cards.add(new SetCardInfo("One with the Machine", 66, Rarity.RARE, mage.cards.o.OneWithTheMachine.class)); + cards.add(new SetCardInfo("Open the Graves", 112, Rarity.RARE, mage.cards.o.OpenTheGraves.class)); cards.add(new SetCardInfo("Oreskos Swiftclaw", 31, Rarity.COMMON, mage.cards.o.OreskosSwiftclaw.class)); + cards.add(new SetCardInfo("Palladia-Mors, the Ruiner", 219, Rarity.MYTHIC, mage.cards.p.PalladiaMorsTheRuiner.class)); + cards.add(new SetCardInfo("Patient Rebuilding", 67, Rarity.RARE, mage.cards.p.PatientRebuilding.class)); + cards.add(new SetCardInfo("Pegasus Courser", 32, Rarity.COMMON, mage.cards.p.PegasusCourser.class)); + cards.add(new SetCardInfo("Pelakka Wurm", 192, Rarity.RARE, mage.cards.p.PelakkaWurm.class)); + cards.add(new SetCardInfo("Pendulum of Patterns", 288, Rarity.COMMON, mage.cards.p.PendulumOfPatterns.class)); + cards.add(new SetCardInfo("Phylactery Lich", 113, Rarity.RARE, mage.cards.p.PhylacteryLich.class)); + cards.add(new SetCardInfo("Plague Mare", 114, Rarity.UNCOMMON, mage.cards.p.PlagueMare.class)); + cards.add(new SetCardInfo("Plains", 261, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 262, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 263, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 264, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plummet", 193, Rarity.COMMON, mage.cards.p.Plummet.class)); + cards.add(new SetCardInfo("Poison-Tip Archer", 220, Rarity.UNCOMMON, mage.cards.p.PoisonTipArcher.class)); + cards.add(new SetCardInfo("Prodigious Growth", 194, Rarity.RARE, mage.cards.p.ProdigiousGrowth.class)); + cards.add(new SetCardInfo("Psychic Corrosion", 68, Rarity.UNCOMMON, mage.cards.p.PsychicCorrosion.class)); + cards.add(new SetCardInfo("Psychic Symbiont", 221, Rarity.UNCOMMON, mage.cards.p.PsychicSymbiont.class)); + cards.add(new SetCardInfo("Rabid Bite", 195, Rarity.COMMON, mage.cards.r.RabidBite.class)); + cards.add(new SetCardInfo("Radiating Lightning", 313, Rarity.COMMON, mage.cards.r.RadiatingLightning.class)); + cards.add(new SetCardInfo("Ravenous Harpy", 115, Rarity.UNCOMMON, mage.cards.r.RavenousHarpy.class)); + cards.add(new SetCardInfo("Reassembling Skeleton", 116, Rarity.UNCOMMON, mage.cards.r.ReassemblingSkeleton.class)); + cards.add(new SetCardInfo("Reclamation Sage", 196, Rarity.UNCOMMON, mage.cards.r.ReclamationSage.class)); + cards.add(new SetCardInfo("Recollect", 197, Rarity.UNCOMMON, mage.cards.r.Recollect.class)); + cards.add(new SetCardInfo("Regal Bloodlord", 222, Rarity.UNCOMMON, mage.cards.r.RegalBloodlord.class)); + cards.add(new SetCardInfo("Reliquary Tower", 254, Rarity.UNCOMMON, mage.cards.r.ReliquaryTower.class)); + cards.add(new SetCardInfo("Remorseful Cleric", 33, Rarity.RARE, mage.cards.r.RemorsefulCleric.class)); + cards.add(new SetCardInfo("Resplendent Angel", 34, Rarity.MYTHIC, mage.cards.r.ResplendentAngel.class)); cards.add(new SetCardInfo("Revitalize", 35, Rarity.COMMON, mage.cards.r.Revitalize.class)); + cards.add(new SetCardInfo("Rhox Oracle", 198, Rarity.COMMON, mage.cards.r.RhoxOracle.class)); + cards.add(new SetCardInfo("Riddlemaster Sphinx", 287, Rarity.RARE, mage.cards.r.RiddlemasterSphinx.class)); + cards.add(new SetCardInfo("Rise from the Grave", 117, Rarity.UNCOMMON, mage.cards.r.RiseFromTheGrave.class)); + cards.add(new SetCardInfo("Rogue's Gloves", 243, Rarity.UNCOMMON, mage.cards.r.RoguesGloves.class)); + cards.add(new SetCardInfo("Root Snare", 199, Rarity.COMMON, mage.cards.r.RootSnare.class)); + cards.add(new SetCardInfo("Runic Armasaur", 200, Rarity.RARE, mage.cards.r.RunicArmasaur.class)); + cards.add(new SetCardInfo("Rupture Spire", 255, Rarity.UNCOMMON, mage.cards.r.RuptureSpire.class)); cards.add(new SetCardInfo("Rustwing Falcon", 36, Rarity.COMMON, mage.cards.r.RustwingFalcon.class)); + cards.add(new SetCardInfo("Sai, Master Thopterist", 69, Rarity.RARE, mage.cards.s.SaiMasterThopterist.class)); cards.add(new SetCardInfo("Salvager of Secrets", 70, Rarity.COMMON, mage.cards.s.SalvagerOfSecrets.class)); + cards.add(new SetCardInfo("Sarkhan's Dragonfire", 298, Rarity.RARE, mage.cards.s.SarkhansDragonfire.class)); + cards.add(new SetCardInfo("Sarkhan's Unsealing", 155, Rarity.RARE, mage.cards.s.SarkhansUnsealing.class)); + cards.add(new SetCardInfo("Sarkhan's Whelp", 299, Rarity.UNCOMMON, mage.cards.s.SarkhansWhelp.class)); + cards.add(new SetCardInfo("Sarkhan, Dragonsoul", 296, Rarity.MYTHIC, mage.cards.s.SarkhanDragonsoul.class)); + cards.add(new SetCardInfo("Sarkhan, Fireblood", 154, Rarity.MYTHIC, mage.cards.s.SarkhanFireblood.class)); + cards.add(new SetCardInfo("Satyr Enchanter", 223, Rarity.UNCOMMON, mage.cards.s.SatyrEnchanter.class)); + cards.add(new SetCardInfo("Scapeshift", 201, Rarity.MYTHIC, mage.cards.s.Scapeshift.class)); cards.add(new SetCardInfo("Scholar of Stars", 71, Rarity.COMMON, mage.cards.s.ScholarOfStars.class)); + cards.add(new SetCardInfo("Serra's Guardian", 284, Rarity.RARE, mage.cards.s.SerrasGuardian.class)); + cards.add(new SetCardInfo("Shield Mare", 37, Rarity.UNCOMMON, mage.cards.s.ShieldMare.class)); + cards.add(new SetCardInfo("Shivan Dragon", 300, Rarity.RARE, mage.cards.s.ShivanDragon.class)); + cards.add(new SetCardInfo("Shock", 156, Rarity.COMMON, mage.cards.s.Shock.class)); + cards.add(new SetCardInfo("Siegebreaker Giant", 157, Rarity.UNCOMMON, mage.cards.s.SiegebreakerGiant.class)); + cards.add(new SetCardInfo("Sift", 72, Rarity.UNCOMMON, mage.cards.s.Sift.class)); + cards.add(new SetCardInfo("Sigiled Sword of Valeron", 244, Rarity.RARE, mage.cards.s.SigiledSwordOfValeron.class)); + cards.add(new SetCardInfo("Silverbeak Griffin", 285, Rarity.COMMON, mage.cards.s.SilverbeakGriffin.class)); + cards.add(new SetCardInfo("Skalla Wolf", 303, Rarity.RARE, mage.cards.s.SkallaWolf.class)); + cards.add(new SetCardInfo("Skeleton Archer", 118, Rarity.COMMON, mage.cards.s.SkeletonArcher.class)); + cards.add(new SetCardInfo("Skilled Animator", 73, Rarity.UNCOMMON, mage.cards.s.SkilledAnimator.class)); + cards.add(new SetCardInfo("Skymarch Bloodletter", 119, Rarity.COMMON, mage.cards.s.SkymarchBloodletter.class)); + cards.add(new SetCardInfo("Skyrider Patrol", 224, Rarity.UNCOMMON, mage.cards.s.SkyriderPatrol.class)); cards.add(new SetCardInfo("Skyscanner", 245, Rarity.COMMON, mage.cards.s.Skyscanner.class)); + cards.add(new SetCardInfo("Sleep", 74, Rarity.UNCOMMON, mage.cards.s.Sleep.class)); + cards.add(new SetCardInfo("Smelt", 158, Rarity.COMMON, mage.cards.s.Smelt.class)); + cards.add(new SetCardInfo("Snapping Drake", 75, Rarity.COMMON, mage.cards.s.SnappingDrake.class)); cards.add(new SetCardInfo("Sovereign's Bite", 120, Rarity.COMMON, mage.cards.s.SovereignsBite.class)); + cards.add(new SetCardInfo("Sparktongue Dragon", 159, Rarity.COMMON, mage.cards.s.SparktongueDragon.class)); + cards.add(new SetCardInfo("Spit Flame", 160, Rarity.RARE, mage.cards.s.SpitFlame.class)); + cards.add(new SetCardInfo("Star-Crowned Stag", 38, Rarity.COMMON, mage.cards.s.StarCrownedStag.class)); + cards.add(new SetCardInfo("Stitcher's Supplier", 121, Rarity.UNCOMMON, mage.cards.s.StitchersSupplier.class)); + cards.add(new SetCardInfo("Stone Quarry", 256, Rarity.COMMON, mage.cards.s.StoneQuarry.class)); + cards.add(new SetCardInfo("Strangling Spores", 122, Rarity.COMMON, mage.cards.s.StranglingSpores.class)); + cards.add(new SetCardInfo("Submerged Boneyard", 257, Rarity.COMMON, mage.cards.s.SubmergedBoneyard.class)); + cards.add(new SetCardInfo("Sun Sentinel", 307, Rarity.COMMON, mage.cards.s.SunSentinel.class)); + cards.add(new SetCardInfo("Suncleanser", 39, Rarity.RARE, mage.cards.s.Suncleanser.class)); + cards.add(new SetCardInfo("Supreme Phantom", 76, Rarity.RARE, mage.cards.s.SupremePhantom.class)); cards.add(new SetCardInfo("Sure Strike", 161, Rarity.COMMON, mage.cards.s.SureStrike.class)); + cards.add(new SetCardInfo("Surge Mare", 77, Rarity.UNCOMMON, mage.cards.s.SurgeMare.class)); + cards.add(new SetCardInfo("Suspicious Bookcase", 246, Rarity.UNCOMMON, mage.cards.s.SuspiciousBookcase.class)); + cards.add(new SetCardInfo("Swamp", 269, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 270, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 271, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 272, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Switcheroo", 78, Rarity.UNCOMMON, mage.cards.s.Switcheroo.class)); + cards.add(new SetCardInfo("Take Vengeance", 40, Rarity.COMMON, mage.cards.t.TakeVengeance.class)); + cards.add(new SetCardInfo("Talons of Wildwood", 202, Rarity.COMMON, mage.cards.t.TalonsOfWildwood.class)); + cards.add(new SetCardInfo("Tattered Mummy", 295, Rarity.COMMON, mage.cards.t.TatteredMummy.class)); + cards.add(new SetCardInfo("Tectonic Rift", 162, Rarity.UNCOMMON, mage.cards.t.TectonicRift.class)); + cards.add(new SetCardInfo("Tezzeret's Gatebreaker", 289, Rarity.RARE, mage.cards.t.TezzeretsGatebreaker.class)); + cards.add(new SetCardInfo("Tezzeret's Strider", 290, Rarity.UNCOMMON, mage.cards.t.TezzeretsStrider.class)); + cards.add(new SetCardInfo("Tezzeret, Artifice Master", 79, Rarity.MYTHIC, mage.cards.t.TezzeretArtificeMaster.class)); + cards.add(new SetCardInfo("Tezzeret, Cruel Machinist", 286, Rarity.MYTHIC, mage.cards.t.TezzeretCruelMachinist.class)); + cards.add(new SetCardInfo("Thorn Lieutenant", 203, Rarity.RARE, mage.cards.t.ThornLieutenant.class)); + cards.add(new SetCardInfo("Thornhide Wolves", 204, Rarity.COMMON, mage.cards.t.ThornhideWolves.class)); + cards.add(new SetCardInfo("Thud", 163, Rarity.UNCOMMON, mage.cards.t.Thud.class)); + cards.add(new SetCardInfo("Timber Gorge", 258, Rarity.COMMON, mage.cards.t.TimberGorge.class)); + cards.add(new SetCardInfo("Titanic Growth", 205, Rarity.COMMON, mage.cards.t.TitanicGrowth.class)); cards.add(new SetCardInfo("Tolarian Scholar", 80, Rarity.COMMON, mage.cards.t.TolarianScholar.class)); cards.add(new SetCardInfo("Tormenting Voice", 164, Rarity.COMMON, mage.cards.t.TormentingVoice.class)); + cards.add(new SetCardInfo("Totally Lost", 81, Rarity.COMMON, mage.cards.t.TotallyLost.class)); + cards.add(new SetCardInfo("Tranquil Expanse", 259, Rarity.COMMON, mage.cards.t.TranquilExpanse.class)); + cards.add(new SetCardInfo("Transmogrifying Wand", 247, Rarity.RARE, mage.cards.t.TransmogrifyingWand.class)); cards.add(new SetCardInfo("Trumpet Blast", 165, Rarity.COMMON, mage.cards.t.TrumpetBlast.class)); cards.add(new SetCardInfo("Trusty Packbeast", 41, Rarity.COMMON, mage.cards.t.TrustyPackbeast.class)); + cards.add(new SetCardInfo("Two-Headed Zombie", 123, Rarity.COMMON, mage.cards.t.TwoHeadedZombie.class)); cards.add(new SetCardInfo("Uncomfortable Chill", 82, Rarity.COMMON, mage.cards.u.UncomfortableChill.class)); + cards.add(new SetCardInfo("Ursine Champion", 304, Rarity.COMMON, mage.cards.u.UrsineChampion.class)); + cards.add(new SetCardInfo("Vaevictis Asmadi, the Dire", 225, Rarity.MYTHIC, mage.cards.v.VaevictisAsmadiTheDire.class)); + cards.add(new SetCardInfo("Valiant Knight", 42, Rarity.RARE, mage.cards.v.ValiantKnight.class)); + cards.add(new SetCardInfo("Vampire Neonate", 124, Rarity.COMMON, mage.cards.v.VampireNeonate.class)); + cards.add(new SetCardInfo("Vampire Sovereign", 125, Rarity.UNCOMMON, mage.cards.v.VampireSovereign.class)); + cards.add(new SetCardInfo("Viashino Pyromancer", 166, Rarity.COMMON, mage.cards.v.ViashinoPyromancer.class)); + cards.add(new SetCardInfo("Vigilant Baloth", 206, Rarity.UNCOMMON, mage.cards.v.VigilantBaloth.class)); + cards.add(new SetCardInfo("Vine Mare", 207, Rarity.UNCOMMON, mage.cards.v.VineMare.class)); + cards.add(new SetCardInfo("Vivien Reid", 208, Rarity.MYTHIC, mage.cards.v.VivienReid.class)); + cards.add(new SetCardInfo("Vivien of the Arkbow", 301, Rarity.MYTHIC, mage.cards.v.VivienOfTheArkbow.class)); + cards.add(new SetCardInfo("Vivien's Invocation", 209, Rarity.RARE, mage.cards.v.ViviensInvocation.class)); + cards.add(new SetCardInfo("Vivien's Jaguar", 305, Rarity.UNCOMMON, mage.cards.v.ViviensJaguar.class)); + cards.add(new SetCardInfo("Volcanic Dragon", 167, Rarity.UNCOMMON, mage.cards.v.VolcanicDragon.class)); + cards.add(new SetCardInfo("Volley Veteran", 168, Rarity.UNCOMMON, mage.cards.v.VolleyVeteran.class)); + cards.add(new SetCardInfo("Walking Corpse", 126, Rarity.COMMON, mage.cards.w.WalkingCorpse.class)); cards.add(new SetCardInfo("Wall of Mist", 83, Rarity.COMMON, mage.cards.w.WallOfMist.class)); + cards.add(new SetCardInfo("Wall of Vines", 210, Rarity.COMMON, mage.cards.w.WallOfVines.class)); + cards.add(new SetCardInfo("Waterknot", 311, Rarity.COMMON, mage.cards.w.Waterknot.class)); + cards.add(new SetCardInfo("Windreader Sphinx", 84, Rarity.RARE, mage.cards.w.WindreaderSphinx.class)); + cards.add(new SetCardInfo("Woodland Stream", 260, Rarity.COMMON, mage.cards.w.WoodlandStream.class)); } + + @Override + public List getCardsByRarity(Rarity rarity) { + // Common cards retrievement of Core Set 2019 boosters - prevent the retrievement of the common lands (e.g. Meandering River) + if (rarity == Rarity.COMMON) { + List savedCardsInfos = savedCards.get(rarity); + if (savedCardsInfos == null) { + CardCriteria criteria = new CardCriteria(); + criteria.rarities(Rarity.COMMON); + criteria.setCodes(this.code).notTypes(CardType.LAND); + savedCardsInfos = CardRepository.instance.findCards(criteria); + if (maxCardNumberInBooster != Integer.MAX_VALUE) { + savedCardsInfos.removeIf(next -> next.getCardNumberAsInt() > maxCardNumberInBooster && rarity != Rarity.LAND); + } + savedCards.put(rarity, savedCardsInfos); + } + // Return a copy of the saved cards information, as not to let modify the original. + return new ArrayList<>(savedCardsInfos); + } else { + return super.getCardsByRarity(rarity); + } + } + + @Override + // the common taplands replacing the basic land + public List getSpecialLand() + { + if (savedSpecialLand.isEmpty()) + { + CardCriteria criteria = new CardCriteria(); + criteria.setCodes(this.code); + criteria.rarities(Rarity.COMMON); + criteria.types(CardType.LAND); + savedSpecialLand.addAll(CardRepository.instance.findCards(criteria)); + } + + return new ArrayList<>(savedSpecialLand); + } + + + } diff --git a/Mage.Sets/src/mage/sets/Darksteel.java b/Mage.Sets/src/mage/sets/Darksteel.java index 7624752521b..c5cdc1d0dd3 100644 --- a/Mage.Sets/src/mage/sets/Darksteel.java +++ b/Mage.Sets/src/mage/sets/Darksteel.java @@ -114,6 +114,7 @@ public final class Darksteel extends ExpansionSet { cards.add(new SetCardInfo("Myr Moonvessel", 133, Rarity.COMMON, mage.cards.m.MyrMoonvessel.class)); cards.add(new SetCardInfo("Nemesis Mask", 134, Rarity.UNCOMMON, mage.cards.n.NemesisMask.class)); cards.add(new SetCardInfo("Neurok Prodigy", 26, Rarity.COMMON, mage.cards.n.NeurokProdigy.class)); + cards.add(new SetCardInfo("Neurok Transmuter", 27, Rarity.UNCOMMON, mage.cards.n.NeurokTransmuter.class)); cards.add(new SetCardInfo("Nim Abomination", 49, Rarity.UNCOMMON, mage.cards.n.NimAbomination.class)); cards.add(new SetCardInfo("Nourish", 78, Rarity.COMMON, mage.cards.n.Nourish.class)); cards.add(new SetCardInfo("Oxidda Golem", 135, Rarity.COMMON, mage.cards.o.OxiddaGolem.class)); @@ -169,6 +170,7 @@ public final class Darksteel extends ExpansionSet { cards.add(new SetCardInfo("Tel-Jilad Outrider", 87, Rarity.COMMON, mage.cards.t.TelJiladOutrider.class)); cards.add(new SetCardInfo("Tel-Jilad Wolf", 88, Rarity.COMMON, mage.cards.t.TelJiladWolf.class)); cards.add(new SetCardInfo("Test of Faith", 17, Rarity.UNCOMMON, mage.cards.t.TestOfFaith.class)); + cards.add(new SetCardInfo("Thought Dissector", 152, Rarity.RARE, mage.cards.t.ThoughtDissector.class)); cards.add(new SetCardInfo("Thunderstaff", 153, Rarity.UNCOMMON, mage.cards.t.Thunderstaff.class)); cards.add(new SetCardInfo("Trinisphere", 154, Rarity.RARE, mage.cards.t.Trinisphere.class)); cards.add(new SetCardInfo("Turn the Tables", 18, Rarity.RARE, mage.cards.t.TurnTheTables.class)); diff --git a/Mage.Sets/src/mage/sets/Dissension.java b/Mage.Sets/src/mage/sets/Dissension.java index 796ac237363..3aabb0d2cee 100644 --- a/Mage.Sets/src/mage/sets/Dissension.java +++ b/Mage.Sets/src/mage/sets/Dissension.java @@ -38,6 +38,7 @@ public final class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Azorius First-Wing", 105, Rarity.COMMON, mage.cards.a.AzoriusFirstWing.class)); cards.add(new SetCardInfo("Azorius Guildmage", 141, Rarity.UNCOMMON, mage.cards.a.AzoriusGuildmage.class)); cards.add(new SetCardInfo("Azorius Herald", 2, Rarity.UNCOMMON, mage.cards.a.AzoriusHerald.class)); + cards.add(new SetCardInfo("Azorius Ploy", 106, Rarity.UNCOMMON, mage.cards.a.AzoriusPloy.class)); cards.add(new SetCardInfo("Azorius Signet", 159, Rarity.COMMON, mage.cards.a.AzoriusSignet.class)); cards.add(new SetCardInfo("Beacon Hawk", 3, Rarity.COMMON, mage.cards.b.BeaconHawk.class)); cards.add(new SetCardInfo("Biomantic Mastery", 142, Rarity.RARE, mage.cards.b.BiomanticMastery.class)); @@ -73,8 +74,10 @@ public final class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Entropic Eidolon", 45, Rarity.COMMON, mage.cards.e.EntropicEidolon.class)); cards.add(new SetCardInfo("Evolution Vat", 161, Rarity.RARE, mage.cards.e.EvolutionVat.class)); cards.add(new SetCardInfo("Experiment Kraj", 110, Rarity.RARE, mage.cards.e.ExperimentKraj.class)); + cards.add(new SetCardInfo("Fertile Imagination", 84, Rarity.UNCOMMON, mage.cards.f.FertileImagination.class)); cards.add(new SetCardInfo("Flame-Kin War Scout", 61, Rarity.UNCOMMON, mage.cards.f.FlameKinWarScout.class)); cards.add(new SetCardInfo("Flaring Flame-Kin", 62, Rarity.UNCOMMON, mage.cards.f.FlaringFlameKin.class)); + cards.add(new SetCardInfo("Flash Foliage", 85, Rarity.UNCOMMON, mage.cards.f.FlashFoliage.class)); cards.add(new SetCardInfo("Freewind Equenaut", 9, Rarity.COMMON, mage.cards.f.FreewindEquenaut.class)); cards.add(new SetCardInfo("Ghost Quarter", 173, Rarity.UNCOMMON, mage.cards.g.GhostQuarter.class)); cards.add(new SetCardInfo("Gnat Alley Creeper", 63, Rarity.UNCOMMON, mage.cards.g.GnatAlleyCreeper.class)); @@ -105,6 +108,9 @@ public final class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Minister of Impediments", 144, Rarity.COMMON, mage.cards.m.MinisterOfImpediments.class)); cards.add(new SetCardInfo("Mistral Charger", 13, Rarity.UNCOMMON, mage.cards.m.MistralCharger.class)); cards.add(new SetCardInfo("Momir Vig, Simic Visionary", 118, Rarity.RARE, mage.cards.m.MomirVigSimicVisionary.class)); + cards.add(new SetCardInfo("Muse Vessel", 163, Rarity.RARE, mage.cards.m.MuseVessel.class)); + cards.add(new SetCardInfo("Nettling Curse", 48, Rarity.COMMON, mage.cards.n.NettlingCurse.class)); + cards.add(new SetCardInfo("Nightcreep", 49, Rarity.UNCOMMON, mage.cards.n.Nightcreep.class)); cards.add(new SetCardInfo("Nihilistic Glee", 50, Rarity.RARE, mage.cards.n.NihilisticGlee.class)); cards.add(new SetCardInfo("Novijen, Heart of Progress", 175, Rarity.UNCOMMON, mage.cards.n.NovijenHeartOfProgress.class)); cards.add(new SetCardInfo("Novijen Sages", 27, Rarity.RARE, mage.cards.n.NovijenSages.class)); @@ -131,10 +137,12 @@ public final class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Pure // Simple", 154, Rarity.UNCOMMON, mage.cards.p.PureSimple.class)); cards.add(new SetCardInfo("Ragamuffyn", 51, Rarity.UNCOMMON, mage.cards.r.Ragamuffyn.class)); cards.add(new SetCardInfo("Rain of Gore", 126, Rarity.RARE, mage.cards.r.RainOfGore.class)); + cards.add(new SetCardInfo("Rakdos Augermage", 127, Rarity.RARE, mage.cards.r.RakdosAugermage.class)); cards.add(new SetCardInfo("Rakdos Carnarium", 178, Rarity.COMMON, mage.cards.r.RakdosCarnarium.class)); cards.add(new SetCardInfo("Rakdos Guildmage", 145, Rarity.UNCOMMON, mage.cards.r.RakdosGuildmage.class)); cards.add(new SetCardInfo("Rakdos Ickspitter", 128, Rarity.COMMON, mage.cards.r.RakdosIckspitter.class)); cards.add(new SetCardInfo("Rakdos Pit Dragon", 69, Rarity.RARE, mage.cards.r.RakdosPitDragon.class)); + cards.add(new SetCardInfo("Rakdos Riteknife", 164, Rarity.RARE, mage.cards.r.RakdosRiteknife.class)); cards.add(new SetCardInfo("Rakdos Signet", 165, Rarity.COMMON, mage.cards.r.RakdosSignet.class)); cards.add(new SetCardInfo("Rakdos the Defiler", 129, Rarity.RARE, mage.cards.r.RakdosTheDefiler.class)); cards.add(new SetCardInfo("Ratcatcher", 52, Rarity.RARE, mage.cards.r.Ratcatcher.class)); @@ -168,7 +176,10 @@ public final class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Steeling Stance", 18, Rarity.COMMON, mage.cards.s.SteelingStance.class)); cards.add(new SetCardInfo("Stoic Ephemera", 19, Rarity.UNCOMMON, mage.cards.s.StoicEphemera.class)); cards.add(new SetCardInfo("Stomp and Howl", 96, Rarity.UNCOMMON, mage.cards.s.StompAndHowl.class)); + cards.add(new SetCardInfo("Stormscale Anarch", 74, Rarity.RARE, mage.cards.s.StormscaleAnarch.class)); + cards.add(new SetCardInfo("Street Savvy", 97, Rarity.COMMON, mage.cards.s.StreetSavvy.class)); cards.add(new SetCardInfo("Supply // Demand", 157, Rarity.UNCOMMON, mage.cards.s.SupplyDemand.class)); + cards.add(new SetCardInfo("Swift Silence", 132, Rarity.RARE, mage.cards.s.SwiftSilence.class)); cards.add(new SetCardInfo("Taste for Mayhem", 75, Rarity.COMMON, mage.cards.t.TasteForMayhem.class)); cards.add(new SetCardInfo("Thrive", 98, Rarity.COMMON, mage.cards.t.Thrive.class)); cards.add(new SetCardInfo("Tidespout Tyrant", 34, Rarity.RARE, mage.cards.t.TidespoutTyrant.class)); @@ -184,6 +195,7 @@ public final class Dissension extends ExpansionSet { cards.add(new SetCardInfo("Vesper Ghoul", 57, Rarity.COMMON, mage.cards.v.VesperGhoul.class)); cards.add(new SetCardInfo("Vigean Graftmage", 35, Rarity.UNCOMMON, mage.cards.v.VigeanGraftmage.class)); cards.add(new SetCardInfo("Vigean Hydropon", 135, Rarity.COMMON, mage.cards.v.VigeanHydropon.class)); + cards.add(new SetCardInfo("Vigean Intuition", 136, Rarity.UNCOMMON, mage.cards.v.VigeanIntuition.class)); cards.add(new SetCardInfo("Vision Skeins", 36, Rarity.COMMON, mage.cards.v.VisionSkeins.class)); cards.add(new SetCardInfo("Voidslime", 137, Rarity.RARE, mage.cards.v.Voidslime.class)); cards.add(new SetCardInfo("Wakestone Gargoyle", 21, Rarity.RARE, mage.cards.w.WakestoneGargoyle.class)); diff --git a/Mage.Sets/src/mage/sets/Dominaria.java b/Mage.Sets/src/mage/sets/Dominaria.java index 4fd36ededd6..98d533f1954 100644 --- a/Mage.Sets/src/mage/sets/Dominaria.java +++ b/Mage.Sets/src/mage/sets/Dominaria.java @@ -26,7 +26,7 @@ public final class Dominaria extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; - this.needsLegends = true; + this.needsLegendCreature = true; this.maxCardNumberInBooster = 269; cards.add(new SetCardInfo("Academy Drake", 40, Rarity.COMMON, mage.cards.a.AcademyDrake.class)); @@ -117,7 +117,7 @@ public final class Dominaria extends ExpansionSet { cards.add(new SetCardInfo("Ghitu Journeymage", 126, Rarity.COMMON, mage.cards.g.GhituJourneymage.class)); cards.add(new SetCardInfo("Ghitu Lavarunner", 127, Rarity.COMMON, mage.cards.g.GhituLavarunner.class)); cards.add(new SetCardInfo("Gideon's Reproach", 19, Rarity.COMMON, mage.cards.g.GideonsReproach.class)); - cards.add(new SetCardInfo("Gift of Growth", 163, Rarity.COMMON, mage.cards.g.GiftofGrowth.class)); + cards.add(new SetCardInfo("Gift of Growth", 163, Rarity.COMMON, mage.cards.g.GiftOfGrowth.class)); cards.add(new SetCardInfo("Gilded Lotus", 215, Rarity.RARE, mage.cards.g.GildedLotus.class)); cards.add(new SetCardInfo("Goblin Barrage", 128, Rarity.UNCOMMON, mage.cards.g.GoblinBarrage.class)); cards.add(new SetCardInfo("Goblin Chainwhirler", 129, Rarity.RARE, mage.cards.g.GoblinChainwhirler.class)); diff --git a/Mage.Sets/src/mage/sets/DragonsMaze.java b/Mage.Sets/src/mage/sets/DragonsMaze.java index d9e10a58ea8..8e01820b2a5 100644 --- a/Mage.Sets/src/mage/sets/DragonsMaze.java +++ b/Mage.Sets/src/mage/sets/DragonsMaze.java @@ -202,10 +202,10 @@ public final class DragonsMaze extends ExpansionSet { CardCriteria criteria = new CardCriteria(); criteria.setCodes(this.code).notTypes(CardType.LAND); criteria.rarities(rarity).doubleFaced(false); - if (maxCardNumberInBooster != Integer.MAX_VALUE) { - criteria.maxCardNumber(maxCardNumberInBooster); - } savedCardsInfos = CardRepository.instance.findCards(criteria); + if (maxCardNumberInBooster != Integer.MAX_VALUE) { + savedCardsInfos.removeIf(next -> next.getCardNumberAsInt() > maxCardNumberInBooster && rarity != Rarity.LAND); + } savedCards.put(rarity, savedCardsInfos); } // Return a copy of the saved cards information, as not to modify the original. diff --git a/Mage.Sets/src/mage/sets/Exodus.java b/Mage.Sets/src/mage/sets/Exodus.java index 03228018197..d1091318d43 100644 --- a/Mage.Sets/src/mage/sets/Exodus.java +++ b/Mage.Sets/src/mage/sets/Exodus.java @@ -68,8 +68,10 @@ public final class Exodus extends ExpansionSet { cards.add(new SetCardInfo("Hatred", 64, Rarity.RARE, mage.cards.h.Hatred.class)); cards.add(new SetCardInfo("High Ground", 7, Rarity.UNCOMMON, mage.cards.h.HighGround.class)); cards.add(new SetCardInfo("Jackalope Herd", 111, Rarity.COMMON, mage.cards.j.JackalopeHerd.class)); + cards.add(new SetCardInfo("Keeper of the Beasts", 112, Rarity.UNCOMMON, mage.cards.k.KeeperOfTheBeasts.class)); cards.add(new SetCardInfo("Keeper of the Dead", 65, Rarity.UNCOMMON, mage.cards.k.KeeperOfTheDead.class)); cards.add(new SetCardInfo("Keeper of the Light", 8, Rarity.UNCOMMON, mage.cards.k.KeeperOfTheLight.class)); + cards.add(new SetCardInfo("Keeper of the Mind", 36, Rarity.UNCOMMON, mage.cards.k.KeeperOfTheMind.class)); cards.add(new SetCardInfo("Killer Whale", 37, Rarity.UNCOMMON, mage.cards.k.KillerWhale.class)); cards.add(new SetCardInfo("Kor Chant", 9, Rarity.COMMON, mage.cards.k.KorChant.class)); cards.add(new SetCardInfo("Mage il-Vec", 86, Rarity.COMMON, mage.cards.m.MageIlVec.class)); diff --git a/Mage.Sets/src/mage/sets/FateReforged.java b/Mage.Sets/src/mage/sets/FateReforged.java index e500a7f1bf2..0cc077d3ed3 100644 --- a/Mage.Sets/src/mage/sets/FateReforged.java +++ b/Mage.Sets/src/mage/sets/FateReforged.java @@ -236,10 +236,10 @@ public final class FateReforged extends ExpansionSet { CardCriteria criteria = new CardCriteria(); criteria.rarities(Rarity.COMMON); criteria.setCodes(this.code).notTypes(CardType.LAND); - if (maxCardNumberInBooster != Integer.MAX_VALUE) { - criteria.maxCardNumber(maxCardNumberInBooster); - } savedCardsInfos = CardRepository.instance.findCards(criteria); + if (maxCardNumberInBooster != Integer.MAX_VALUE) { + savedCardsInfos.removeIf(next -> next.getCardNumberAsInt() > maxCardNumberInBooster && rarity != Rarity.LAND); + } savedCards.put(rarity, savedCardsInfos); } // Return a copy of the saved cards information, as not to let modify the original. diff --git a/Mage.Sets/src/mage/sets/FourthEdition.java b/Mage.Sets/src/mage/sets/FourthEdition.java index d4609ac9519..45b19500756 100644 --- a/Mage.Sets/src/mage/sets/FourthEdition.java +++ b/Mage.Sets/src/mage/sets/FourthEdition.java @@ -27,378 +27,379 @@ public final class FourthEdition extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abomination", 117, Rarity.UNCOMMON, mage.cards.a.Abomination.class)); - cards.add(new SetCardInfo("Animate Dead", 118, Rarity.UNCOMMON, mage.cards.a.AnimateDead.class)); - cards.add(new SetCardInfo("Ashes to Ashes", 119, Rarity.UNCOMMON, mage.cards.a.AshesToAshes.class)); - cards.add(new SetCardInfo("Bad Moon", 120, Rarity.RARE, mage.cards.b.BadMoon.class)); - cards.add(new SetCardInfo("Black Knight", 121, Rarity.UNCOMMON, mage.cards.b.BlackKnight.class)); - cards.add(new SetCardInfo("Blight", 122, Rarity.UNCOMMON, mage.cards.b.Blight.class)); - cards.add(new SetCardInfo("Bog Imp", 123, Rarity.COMMON, mage.cards.b.BogImp.class)); - cards.add(new SetCardInfo("Bog Wraith", 124, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); - cards.add(new SetCardInfo("Carrion Ants", 125, Rarity.UNCOMMON, mage.cards.c.CarrionAnts.class)); - cards.add(new SetCardInfo("Cosmic Horror", 126, Rarity.RARE, mage.cards.c.CosmicHorror.class)); - cards.add(new SetCardInfo("Cursed Land", 127, Rarity.UNCOMMON, mage.cards.c.CursedLand.class)); - cards.add(new SetCardInfo("Cyclopean Mummy", 128, Rarity.COMMON, mage.cards.c.CyclopeanMummy.class)); - cards.add(new SetCardInfo("Dark Ritual", 129, Rarity.COMMON, mage.cards.d.DarkRitual.class)); - cards.add(new SetCardInfo("Deathgrip", 130, Rarity.UNCOMMON, mage.cards.d.Deathgrip.class)); - cards.add(new SetCardInfo("Deathlace", 131, Rarity.RARE, mage.cards.d.Deathlace.class)); - cards.add(new SetCardInfo("Drain Life", 132, Rarity.COMMON, mage.cards.d.DrainLife.class)); - cards.add(new SetCardInfo("Drudge Skeletons", 133, Rarity.COMMON, mage.cards.d.DrudgeSkeletons.class)); - cards.add(new SetCardInfo("El-Hajjaj", 134, Rarity.RARE, mage.cards.e.ElHajjaj.class)); - cards.add(new SetCardInfo("Erg Raiders", 135, Rarity.COMMON, mage.cards.e.ErgRaiders.class)); - cards.add(new SetCardInfo("Evil Presence", 136, Rarity.UNCOMMON, mage.cards.e.EvilPresence.class)); - cards.add(new SetCardInfo("Fear", 137, Rarity.COMMON, mage.cards.f.Fear.class)); - cards.add(new SetCardInfo("Frozen Shade", 138, Rarity.COMMON, mage.cards.f.FrozenShade.class)); - cards.add(new SetCardInfo("Gloom", 139, Rarity.UNCOMMON, mage.cards.g.Gloom.class)); - cards.add(new SetCardInfo("Greed", 140, Rarity.RARE, mage.cards.g.Greed.class)); - cards.add(new SetCardInfo("Howl from Beyond", 141, Rarity.COMMON, mage.cards.h.HowlFromBeyond.class)); - cards.add(new SetCardInfo("Hypnotic Specter", 142, Rarity.UNCOMMON, mage.cards.h.HypnoticSpecter.class)); - cards.add(new SetCardInfo("Junún Efreet", 143, Rarity.UNCOMMON, mage.cards.j.JununEfreet.class)); - cards.add(new SetCardInfo("Lord of the Pit", 144, Rarity.RARE, mage.cards.l.LordOfThePit.class)); - cards.add(new SetCardInfo("Lost Soul", 145, Rarity.COMMON, mage.cards.l.LostSoul.class)); - cards.add(new SetCardInfo("Marsh Gas", 146, Rarity.COMMON, mage.cards.m.MarshGas.class)); - cards.add(new SetCardInfo("Mind Twist", 147, Rarity.RARE, mage.cards.m.MindTwist.class)); - cards.add(new SetCardInfo("Murk Dwellers", 148, Rarity.COMMON, mage.cards.m.MurkDwellers.class)); - cards.add(new SetCardInfo("Nether Shadow", 149, Rarity.RARE, mage.cards.n.NetherShadow.class)); - cards.add(new SetCardInfo("Nightmare", 150, Rarity.RARE, mage.cards.n.Nightmare.class)); - cards.add(new SetCardInfo("Paralyze", 151, Rarity.COMMON, mage.cards.p.Paralyze.class)); - cards.add(new SetCardInfo("Pestilence", 152, Rarity.COMMON, mage.cards.p.Pestilence.class)); - cards.add(new SetCardInfo("Pit Scorpion", 153, Rarity.COMMON, mage.cards.p.PitScorpion.class)); - cards.add(new SetCardInfo("Plague Rats", 154, Rarity.COMMON, mage.cards.p.PlagueRats.class)); - cards.add(new SetCardInfo("Rag Man", 155, Rarity.RARE, mage.cards.r.RagMan.class)); - cards.add(new SetCardInfo("Raise Dead", 156, Rarity.COMMON, mage.cards.r.RaiseDead.class)); - cards.add(new SetCardInfo("Royal Assassin", 157, Rarity.RARE, mage.cards.r.RoyalAssassin.class)); - cards.add(new SetCardInfo("Scathe Zombies", 158, Rarity.COMMON, mage.cards.s.ScatheZombies.class)); - cards.add(new SetCardInfo("Scavenging Ghoul", 159, Rarity.UNCOMMON, mage.cards.s.ScavengingGhoul.class)); - cards.add(new SetCardInfo("Sengir Vampire", 160, Rarity.UNCOMMON, mage.cards.s.SengirVampire.class)); - cards.add(new SetCardInfo("Simulacrum", 161, Rarity.UNCOMMON, mage.cards.s.Simulacrum.class)); - cards.add(new SetCardInfo("Sorceress Queen", 162, Rarity.RARE, mage.cards.s.SorceressQueen.class)); - cards.add(new SetCardInfo("Spirit Shackle", 163, Rarity.UNCOMMON, mage.cards.s.SpiritShackle.class)); - cards.add(new SetCardInfo("Terror", 164, Rarity.COMMON, mage.cards.t.Terror.class)); - cards.add(new SetCardInfo("Uncle Istvan", 165, Rarity.UNCOMMON, mage.cards.u.UncleIstvan.class)); - cards.add(new SetCardInfo("Unholy Strength", 166, Rarity.COMMON, mage.cards.u.UnholyStrength.class)); - cards.add(new SetCardInfo("Vampire Bats", 167, Rarity.COMMON, mage.cards.v.VampireBats.class)); - cards.add(new SetCardInfo("Wall of Bone", 168, Rarity.UNCOMMON, mage.cards.w.WallOfBone.class)); - cards.add(new SetCardInfo("Warp Artifact", 169, Rarity.RARE, mage.cards.w.WarpArtifact.class)); - cards.add(new SetCardInfo("Weakness", 170, Rarity.COMMON, mage.cards.w.Weakness.class)); - cards.add(new SetCardInfo("Will-o'-the-Wisp", 171, Rarity.RARE, mage.cards.w.WillOTheWisp.class)); - cards.add(new SetCardInfo("Word of Binding", 172, Rarity.COMMON, mage.cards.w.WordOfBinding.class)); - cards.add(new SetCardInfo("Xenic Poltergeist", 173, Rarity.RARE, mage.cards.x.XenicPoltergeist.class)); - cards.add(new SetCardInfo("Zombie Master", 174, Rarity.RARE, mage.cards.z.ZombieMaster.class)); cards.add(new SetCardInfo("Air Elemental", 59, Rarity.UNCOMMON, mage.cards.a.AirElemental.class)); - cards.add(new SetCardInfo("Animate Artifact", 60, Rarity.UNCOMMON, mage.cards.a.AnimateArtifact.class)); - cards.add(new SetCardInfo("Apprentice Wizard", 61, Rarity.COMMON, mage.cards.a.ApprenticeWizard.class)); - cards.add(new SetCardInfo("Backfire", 62, Rarity.UNCOMMON, mage.cards.b.Backfire.class)); - cards.add(new SetCardInfo("Blue Elemental Blast", 63, Rarity.COMMON, mage.cards.b.BlueElementalBlast.class)); - cards.add(new SetCardInfo("Control Magic", 64, Rarity.UNCOMMON, mage.cards.c.ControlMagic.class)); - cards.add(new SetCardInfo("Counterspell", 65, Rarity.UNCOMMON, mage.cards.c.Counterspell.class)); - cards.add(new SetCardInfo("Creature Bond", 66, Rarity.COMMON, mage.cards.c.CreatureBond.class)); - cards.add(new SetCardInfo("Drain Power", 67, Rarity.RARE, mage.cards.d.DrainPower.class)); - cards.add(new SetCardInfo("Energy Flux", 68, Rarity.UNCOMMON, mage.cards.e.EnergyFlux.class)); - cards.add(new SetCardInfo("Energy Tap", 69, Rarity.COMMON, mage.cards.e.EnergyTap.class)); - cards.add(new SetCardInfo("Erosion", 70, Rarity.COMMON, mage.cards.e.Erosion.class)); - cards.add(new SetCardInfo("Feedback", 71, Rarity.UNCOMMON, mage.cards.f.Feedback.class)); - cards.add(new SetCardInfo("Flight", 72, Rarity.COMMON, mage.cards.f.Flight.class)); - cards.add(new SetCardInfo("Flood", 73, Rarity.COMMON, mage.cards.f.Flood.class)); - cards.add(new SetCardInfo("Gaseous Form", 74, Rarity.COMMON, mage.cards.g.GaseousForm.class)); - cards.add(new SetCardInfo("Ghost Ship", 75, Rarity.UNCOMMON, mage.cards.g.GhostShip.class)); - cards.add(new SetCardInfo("Giant Tortoise", 76, Rarity.COMMON, mage.cards.g.GiantTortoise.class)); - cards.add(new SetCardInfo("Hurkyl's Recall", 77, Rarity.RARE, mage.cards.h.HurkylsRecall.class)); - cards.add(new SetCardInfo("Island Fish Jasconius", 78, Rarity.RARE, mage.cards.i.IslandFishJasconius.class)); - cards.add(new SetCardInfo("Jump", 79, Rarity.COMMON, mage.cards.j.Jump.class)); - cards.add(new SetCardInfo("Leviathan", 80, Rarity.RARE, mage.cards.l.Leviathan.class)); - cards.add(new SetCardInfo("Lifetap", 81, Rarity.UNCOMMON, mage.cards.l.Lifetap.class)); - cards.add(new SetCardInfo("Lord of Atlantis", 82, Rarity.RARE, mage.cards.l.LordOfAtlantis.class)); - cards.add(new SetCardInfo("Mahamoti Djinn", 84, Rarity.RARE, mage.cards.m.MahamotiDjinn.class)); - cards.add(new SetCardInfo("Mana Short", 85, Rarity.RARE, mage.cards.m.ManaShort.class)); - cards.add(new SetCardInfo("Merfolk of the Pearl Trident", 86, Rarity.COMMON, mage.cards.m.MerfolkOfThePearlTrident.class)); - cards.add(new SetCardInfo("Mind Bomb", 87, Rarity.UNCOMMON, mage.cards.m.MindBomb.class)); - cards.add(new SetCardInfo("Phantasmal Forces", 88, Rarity.UNCOMMON, mage.cards.p.PhantasmalForces.class)); - cards.add(new SetCardInfo("Phantasmal Terrain", 89, Rarity.COMMON, mage.cards.p.PhantasmalTerrain.class)); - cards.add(new SetCardInfo("Phantom Monster", 90, Rarity.UNCOMMON, mage.cards.p.PhantomMonster.class)); - cards.add(new SetCardInfo("Pirate Ship", 91, Rarity.RARE, mage.cards.p.PirateShip.class)); - cards.add(new SetCardInfo("Power Leak", 92, Rarity.COMMON, mage.cards.p.PowerLeak.class)); - cards.add(new SetCardInfo("Power Sink", 93, Rarity.COMMON, mage.cards.p.PowerSink.class)); - cards.add(new SetCardInfo("Prodigal Sorcerer", 94, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class)); - cards.add(new SetCardInfo("Psionic Entity", 95, Rarity.RARE, mage.cards.p.PsionicEntity.class)); - cards.add(new SetCardInfo("Psychic Venom", 96, Rarity.COMMON, mage.cards.p.PsychicVenom.class)); - cards.add(new SetCardInfo("Relic Bind", 97, Rarity.RARE, mage.cards.r.RelicBind.class)); - cards.add(new SetCardInfo("Sea Serpent", 98, Rarity.COMMON, mage.cards.s.SeaSerpent.class)); - cards.add(new SetCardInfo("Segovian Leviathan", 99, Rarity.UNCOMMON, mage.cards.s.SegovianLeviathan.class)); - cards.add(new SetCardInfo("Sindbad", 100, Rarity.UNCOMMON, mage.cards.s.Sindbad.class)); - cards.add(new SetCardInfo("Siren's Call", 101, Rarity.UNCOMMON, mage.cards.s.SirensCall.class)); - cards.add(new SetCardInfo("Spell Blast", 103, Rarity.COMMON, mage.cards.s.SpellBlast.class)); - cards.add(new SetCardInfo("Stasis", 104, Rarity.RARE, mage.cards.s.Stasis.class)); - cards.add(new SetCardInfo("Steal Artifact", 105, Rarity.UNCOMMON, mage.cards.s.StealArtifact.class)); - cards.add(new SetCardInfo("Sunken City", 106, Rarity.COMMON, mage.cards.s.SunkenCity.class)); - cards.add(new SetCardInfo("Thoughtlace", 107, Rarity.RARE, mage.cards.t.Thoughtlace.class)); - cards.add(new SetCardInfo("Time Elemental", 108, Rarity.RARE, mage.cards.t.TimeElemental.class)); - cards.add(new SetCardInfo("Twiddle", 109, Rarity.COMMON, mage.cards.t.Twiddle.class)); - cards.add(new SetCardInfo("Unstable Mutation", 110, Rarity.COMMON, mage.cards.u.UnstableMutation.class)); - cards.add(new SetCardInfo("Unsummon", 111, Rarity.COMMON, mage.cards.u.Unsummon.class)); - cards.add(new SetCardInfo("Volcanic Eruption", 112, Rarity.RARE, mage.cards.v.VolcanicEruption.class)); - cards.add(new SetCardInfo("Wall of Air", 113, Rarity.UNCOMMON, mage.cards.w.WallOfAir.class)); - cards.add(new SetCardInfo("Wall of Water", 114, Rarity.UNCOMMON, mage.cards.w.WallOfWater.class)); - cards.add(new SetCardInfo("Water Elemental", 115, Rarity.UNCOMMON, mage.cards.w.WaterElemental.class)); - cards.add(new SetCardInfo("Zephyr Falcon", 116, Rarity.COMMON, mage.cards.z.ZephyrFalcon.class)); - cards.add(new SetCardInfo("Aspect of Wolf", 233, Rarity.RARE, mage.cards.a.AspectOfWolf.class)); - cards.add(new SetCardInfo("Birds of Paradise", 234, Rarity.RARE, mage.cards.b.BirdsOfParadise.class)); - cards.add(new SetCardInfo("Carnivorous Plant", 235, Rarity.COMMON, mage.cards.c.CarnivorousPlant.class)); - cards.add(new SetCardInfo("Channel", 236, Rarity.UNCOMMON, mage.cards.c.Channel.class)); - cards.add(new SetCardInfo("Cockatrice", 237, Rarity.RARE, mage.cards.c.Cockatrice.class)); - cards.add(new SetCardInfo("Craw Wurm", 238, Rarity.COMMON, mage.cards.c.CrawWurm.class)); - cards.add(new SetCardInfo("Crumble", 239, Rarity.UNCOMMON, mage.cards.c.Crumble.class)); - cards.add(new SetCardInfo("Desert Twister", 240, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class)); - cards.add(new SetCardInfo("Durkwood Boars", 241, Rarity.COMMON, mage.cards.d.DurkwoodBoars.class)); - cards.add(new SetCardInfo("Elven Riders", 242, Rarity.UNCOMMON, mage.cards.e.ElvenRiders.class)); - cards.add(new SetCardInfo("Elvish Archers", 243, Rarity.RARE, mage.cards.e.ElvishArchers.class)); - cards.add(new SetCardInfo("Fog", 244, Rarity.COMMON, mage.cards.f.Fog.class)); - cards.add(new SetCardInfo("Force of Nature", 245, Rarity.RARE, mage.cards.f.ForceOfNature.class)); - cards.add(new SetCardInfo("Fungusaur", 246, Rarity.RARE, mage.cards.f.Fungusaur.class)); - cards.add(new SetCardInfo("Gaea's Liege", 247, Rarity.RARE, mage.cards.g.GaeasLiege.class)); - cards.add(new SetCardInfo("Giant Growth", 248, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); - cards.add(new SetCardInfo("Giant Spider", 249, Rarity.COMMON, mage.cards.g.GiantSpider.class)); - cards.add(new SetCardInfo("Grizzly Bears", 250, Rarity.COMMON, mage.cards.g.GrizzlyBears.class)); - cards.add(new SetCardInfo("Hurricane", 251, Rarity.UNCOMMON, mage.cards.h.Hurricane.class)); - cards.add(new SetCardInfo("Instill Energy", 252, Rarity.UNCOMMON, mage.cards.i.InstillEnergy.class)); - cards.add(new SetCardInfo("Ironroot Treefolk", 253, Rarity.COMMON, mage.cards.i.IronrootTreefolk.class)); - cards.add(new SetCardInfo("Killer Bees", 254, Rarity.UNCOMMON, mage.cards.k.KillerBees.class)); - cards.add(new SetCardInfo("Land Leeches", 255, Rarity.COMMON, mage.cards.l.LandLeeches.class)); - cards.add(new SetCardInfo("Ley Druid", 256, Rarity.UNCOMMON, mage.cards.l.LeyDruid.class)); - cards.add(new SetCardInfo("Lifeforce", 257, Rarity.UNCOMMON, mage.cards.l.Lifeforce.class)); - cards.add(new SetCardInfo("Lifelace", 258, Rarity.RARE, mage.cards.l.Lifelace.class)); - cards.add(new SetCardInfo("Living Artifact", 259, Rarity.RARE, mage.cards.l.LivingArtifact.class)); - cards.add(new SetCardInfo("Living Lands", 260, Rarity.RARE, mage.cards.l.LivingLands.class)); - cards.add(new SetCardInfo("Llanowar Elves", 261, Rarity.COMMON, mage.cards.l.LlanowarElves.class)); - cards.add(new SetCardInfo("Lure", 262, Rarity.UNCOMMON, mage.cards.l.Lure.class)); - cards.add(new SetCardInfo("Marsh Viper", 263, Rarity.COMMON, mage.cards.m.MarshViper.class)); - cards.add(new SetCardInfo("Nafs Asp", 264, Rarity.COMMON, NafsAsp.class)); - cards.add(new SetCardInfo("Pradesh Gypsies", 265, Rarity.COMMON, mage.cards.p.PradeshGypsies.class)); - cards.add(new SetCardInfo("Radjan Spirit", 266, Rarity.UNCOMMON, mage.cards.r.RadjanSpirit.class)); - cards.add(new SetCardInfo("Regeneration", 268, Rarity.COMMON, mage.cards.r.Regeneration.class)); - cards.add(new SetCardInfo("Sandstorm", 269, Rarity.COMMON, mage.cards.s.Sandstorm.class)); - cards.add(new SetCardInfo("Scryb Sprites", 270, Rarity.COMMON, mage.cards.s.ScrybSprites.class)); - cards.add(new SetCardInfo("Shanodin Dryads", 271, Rarity.COMMON, mage.cards.s.ShanodinDryads.class)); - cards.add(new SetCardInfo("Stream of Life", 272, Rarity.COMMON, mage.cards.s.StreamOfLife.class)); - cards.add(new SetCardInfo("Sylvan Library", 273, Rarity.RARE, mage.cards.s.SylvanLibrary.class)); - cards.add(new SetCardInfo("Thicket Basilisk", 274, Rarity.UNCOMMON, mage.cards.t.ThicketBasilisk.class)); - cards.add(new SetCardInfo("Timber Wolves", 275, Rarity.RARE, mage.cards.t.TimberWolves.class)); - cards.add(new SetCardInfo("Titania's Song", 276, Rarity.RARE, mage.cards.t.TitaniasSong.class)); - cards.add(new SetCardInfo("Tranquility", 277, Rarity.COMMON, mage.cards.t.Tranquility.class)); - cards.add(new SetCardInfo("Tsunami", 278, Rarity.UNCOMMON, mage.cards.t.Tsunami.class)); - cards.add(new SetCardInfo("Untamed Wilds", 279, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); - cards.add(new SetCardInfo("Venom", 280, Rarity.COMMON, mage.cards.v.Venom.class)); - cards.add(new SetCardInfo("Verduran Enchantress", 281, Rarity.RARE, mage.cards.v.VerduranEnchantress.class)); - cards.add(new SetCardInfo("Wall of Brambles", 282, Rarity.UNCOMMON, mage.cards.w.WallOfBrambles.class)); - cards.add(new SetCardInfo("Wall of Ice", 283, Rarity.UNCOMMON, mage.cards.w.WallOfIce.class)); - cards.add(new SetCardInfo("Wall of Wood", 284, Rarity.COMMON, mage.cards.w.WallOfWood.class)); - cards.add(new SetCardInfo("Wanderlust", 285, Rarity.UNCOMMON, mage.cards.w.Wanderlust.class)); - cards.add(new SetCardInfo("War Mammoth", 286, Rarity.COMMON, mage.cards.w.WarMammoth.class)); - cards.add(new SetCardInfo("Web", 287, Rarity.RARE, mage.cards.w.Web.class)); - cards.add(new SetCardInfo("Whirling Dervish", 288, Rarity.UNCOMMON, mage.cards.w.WhirlingDervish.class)); - cards.add(new SetCardInfo("Wild Growth", 289, Rarity.COMMON, mage.cards.w.WildGrowth.class)); - cards.add(new SetCardInfo("Winter Blast", 290, Rarity.UNCOMMON, mage.cards.w.WinterBlast.class)); - cards.add(new SetCardInfo("Forest", 376, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 377, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 378, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 367, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 368, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 369, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mishra's Factory", 361, Rarity.UNCOMMON, mage.cards.m.MishrasFactory.class)); - cards.add(new SetCardInfo("Mountain", 373, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 374, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 375, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Oasis", 362, Rarity.UNCOMMON, mage.cards.o.Oasis.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)); - cards.add(new SetCardInfo("Plains", 366, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Strip Mine", 363, Rarity.UNCOMMON, mage.cards.s.StripMine.class)); - cards.add(new SetCardInfo("Swamp", 370, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 371, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 372, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ali Baba", 175, Rarity.UNCOMMON, mage.cards.a.AliBaba.class)); - cards.add(new SetCardInfo("Ball Lightning", 176, Rarity.RARE, mage.cards.b.BallLightning.class)); - cards.add(new SetCardInfo("Bird Maiden", 177, Rarity.COMMON, mage.cards.b.BirdMaiden.class)); - cards.add(new SetCardInfo("Blood Lust", 178, Rarity.COMMON, mage.cards.b.BloodLust.class)); - cards.add(new SetCardInfo("Brothers of Fire", 179, Rarity.COMMON, mage.cards.b.BrothersOfFire.class)); - cards.add(new SetCardInfo("Burrowing", 180, Rarity.UNCOMMON, mage.cards.b.Burrowing.class)); - cards.add(new SetCardInfo("Cave People", 181, Rarity.UNCOMMON, mage.cards.c.CavePeople.class)); - cards.add(new SetCardInfo("Chaoslace", 182, Rarity.RARE, mage.cards.c.Chaoslace.class)); - cards.add(new SetCardInfo("Crimson Manticore", 183, Rarity.RARE, mage.cards.c.CrimsonManticore.class)); - cards.add(new SetCardInfo("Detonate", 184, Rarity.UNCOMMON, mage.cards.d.Detonate.class)); - cards.add(new SetCardInfo("Disintegrate", 185, Rarity.COMMON, mage.cards.d.Disintegrate.class)); - cards.add(new SetCardInfo("Dragon Whelp", 186, Rarity.UNCOMMON, mage.cards.d.DragonWhelp.class)); - cards.add(new SetCardInfo("Dwarven Warriors", 187, Rarity.COMMON, mage.cards.d.DwarvenWarriors.class)); - cards.add(new SetCardInfo("Earth Elemental", 188, Rarity.UNCOMMON, mage.cards.e.EarthElemental.class)); - cards.add(new SetCardInfo("Earthquake", 189, Rarity.RARE, mage.cards.e.Earthquake.class)); - cards.add(new SetCardInfo("Eternal Warrior", 190, Rarity.COMMON, mage.cards.e.EternalWarrior.class)); - cards.add(new SetCardInfo("Fire Elemental", 191, Rarity.UNCOMMON, mage.cards.f.FireElemental.class)); - cards.add(new SetCardInfo("Fireball", 192, Rarity.COMMON, mage.cards.f.Fireball.class)); - cards.add(new SetCardInfo("Firebreathing", 193, Rarity.COMMON, mage.cards.f.Firebreathing.class)); - cards.add(new SetCardInfo("Fissure", 194, Rarity.COMMON, mage.cards.f.Fissure.class)); - cards.add(new SetCardInfo("Flashfires", 195, Rarity.UNCOMMON, mage.cards.f.Flashfires.class)); - cards.add(new SetCardInfo("Giant Strength", 196, Rarity.COMMON, mage.cards.g.GiantStrength.class)); - cards.add(new SetCardInfo("Goblin Balloon Brigade", 197, Rarity.UNCOMMON, mage.cards.g.GoblinBalloonBrigade.class)); - cards.add(new SetCardInfo("Goblin King", 198, Rarity.RARE, mage.cards.g.GoblinKing.class)); - cards.add(new SetCardInfo("Goblin Rock Sled", 199, Rarity.COMMON, mage.cards.g.GoblinRockSled.class)); - cards.add(new SetCardInfo("Gray Ogre", 200, Rarity.COMMON, mage.cards.g.GrayOgre.class)); - cards.add(new SetCardInfo("Hill Giant", 201, Rarity.COMMON, mage.cards.h.HillGiant.class)); - cards.add(new SetCardInfo("Hurloon Minotaur", 202, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class)); - cards.add(new SetCardInfo("Hurr Jackal", 203, Rarity.RARE, mage.cards.h.HurrJackal.class)); - cards.add(new SetCardInfo("Immolation", 204, Rarity.COMMON, mage.cards.i.Immolation.class)); - cards.add(new SetCardInfo("Inferno", 205, Rarity.RARE, mage.cards.i.Inferno.class)); - cards.add(new SetCardInfo("Ironclaw Orcs", 206, Rarity.COMMON, mage.cards.i.IronclawOrcs.class)); - cards.add(new SetCardInfo("Keldon Warlord", 207, Rarity.UNCOMMON, mage.cards.k.KeldonWarlord.class)); - cards.add(new SetCardInfo("Lightning Bolt", 208, Rarity.COMMON, mage.cards.l.LightningBolt.class)); - cards.add(new SetCardInfo("Magnetic Mountain", 209, Rarity.RARE, mage.cards.m.MagneticMountain.class)); - cards.add(new SetCardInfo("Mana Clash", 210, Rarity.RARE, mage.cards.m.ManaClash.class)); - cards.add(new SetCardInfo("Mana Flare", 211, Rarity.RARE, mage.cards.m.ManaFlare.class)); - cards.add(new SetCardInfo("Manabarbs", 212, Rarity.RARE, mage.cards.m.Manabarbs.class)); - cards.add(new SetCardInfo("Mons's Goblin Raiders", 213, Rarity.COMMON, mage.cards.m.MonssGoblinRaiders.class)); - cards.add(new SetCardInfo("Orcish Artillery", 214, Rarity.UNCOMMON, mage.cards.o.OrcishArtillery.class)); - cards.add(new SetCardInfo("Orcish Oriflamme", 215, Rarity.UNCOMMON, mage.cards.o.OrcishOriflamme.class)); - cards.add(new SetCardInfo("Power Surge", 216, Rarity.RARE, mage.cards.p.PowerSurge.class)); - cards.add(new SetCardInfo("Pyrotechnics", 217, Rarity.UNCOMMON, mage.cards.p.Pyrotechnics.class)); - cards.add(new SetCardInfo("Red Elemental Blast", 218, Rarity.COMMON, mage.cards.r.RedElementalBlast.class)); - cards.add(new SetCardInfo("Shatter", 219, Rarity.COMMON, mage.cards.s.Shatter.class)); - cards.add(new SetCardInfo("Shivan Dragon", 220, Rarity.RARE, mage.cards.s.ShivanDragon.class)); - cards.add(new SetCardInfo("Sisters of the Flame", 221, Rarity.COMMON, mage.cards.s.SistersOfTheFlame.class)); - cards.add(new SetCardInfo("Smoke", 222, Rarity.RARE, mage.cards.s.Smoke.class)); - cards.add(new SetCardInfo("Stone Giant", 223, Rarity.UNCOMMON, mage.cards.s.StoneGiant.class)); - cards.add(new SetCardInfo("Stone Rain", 224, Rarity.COMMON, mage.cards.s.StoneRain.class)); - cards.add(new SetCardInfo("The Brute", 226, Rarity.COMMON, mage.cards.t.TheBrute.class)); - cards.add(new SetCardInfo("Tunnel", 227, Rarity.UNCOMMON, mage.cards.t.Tunnel.class)); - cards.add(new SetCardInfo("Uthden Troll", 228, Rarity.UNCOMMON, mage.cards.u.UthdenTroll.class)); - cards.add(new SetCardInfo("Wall of Dust", 229, Rarity.UNCOMMON, mage.cards.w.WallOfDust.class)); - cards.add(new SetCardInfo("Wall of Fire", 230, Rarity.UNCOMMON, mage.cards.w.WallOfFire.class)); - cards.add(new SetCardInfo("Wall of Stone", 231, Rarity.UNCOMMON, mage.cards.w.WallOfStone.class)); - cards.add(new SetCardInfo("Winds of Change", 232, Rarity.RARE, mage.cards.w.WindsOfChange.class)); cards.add(new SetCardInfo("Alabaster Potion", 1, Rarity.COMMON, mage.cards.a.AlabasterPotion.class)); + cards.add(new SetCardInfo("Aladdin's Lamp", 291, Rarity.RARE, mage.cards.a.AladdinsLamp.class)); + cards.add(new SetCardInfo("Aladdin's Ring", 292, Rarity.RARE, mage.cards.a.AladdinsRing.class)); + cards.add(new SetCardInfo("Ali Baba", 175, Rarity.UNCOMMON, mage.cards.a.AliBaba.class)); cards.add(new SetCardInfo("Amrou Kithkin", 2, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); + cards.add(new SetCardInfo("Amulet of Kroog", 293, Rarity.COMMON, mage.cards.a.AmuletOfKroog.class)); cards.add(new SetCardInfo("Angry Mob", 3, Rarity.UNCOMMON, mage.cards.a.AngryMob.class)); + cards.add(new SetCardInfo("Animate Artifact", 60, Rarity.UNCOMMON, mage.cards.a.AnimateArtifact.class)); + cards.add(new SetCardInfo("Animate Dead", 118, Rarity.UNCOMMON, mage.cards.a.AnimateDead.class)); cards.add(new SetCardInfo("Animate Wall", 4, Rarity.RARE, mage.cards.a.AnimateWall.class)); + cards.add(new SetCardInfo("Ankh of Mishra", 294, Rarity.RARE, mage.cards.a.AnkhOfMishra.class)); + cards.add(new SetCardInfo("Apprentice Wizard", 61, Rarity.COMMON, mage.cards.a.ApprenticeWizard.class)); + cards.add(new SetCardInfo("Armageddon Clock", 295, Rarity.RARE, mage.cards.a.ArmageddonClock.class)); cards.add(new SetCardInfo("Armageddon", 5, Rarity.RARE, mage.cards.a.Armageddon.class)); + cards.add(new SetCardInfo("Ashes to Ashes", 119, Rarity.UNCOMMON, mage.cards.a.AshesToAshes.class)); + cards.add(new SetCardInfo("Ashnod's Battle Gear", 296, Rarity.UNCOMMON, mage.cards.a.AshnodsBattleGear.class)); + cards.add(new SetCardInfo("Aspect of Wolf", 233, Rarity.RARE, mage.cards.a.AspectOfWolf.class)); + cards.add(new SetCardInfo("Backfire", 62, Rarity.UNCOMMON, mage.cards.b.Backfire.class)); + cards.add(new SetCardInfo("Bad Moon", 120, Rarity.RARE, mage.cards.b.BadMoon.class)); cards.add(new SetCardInfo("Balance", 6, Rarity.RARE, mage.cards.b.Balance.class)); + cards.add(new SetCardInfo("Ball Lightning", 176, Rarity.RARE, mage.cards.b.BallLightning.class)); + cards.add(new SetCardInfo("Battering Ram", 297, Rarity.COMMON, mage.cards.b.BatteringRam.class)); cards.add(new SetCardInfo("Benalish Hero", 7, Rarity.COMMON, mage.cards.b.BenalishHero.class)); + cards.add(new SetCardInfo("Bird Maiden", 177, Rarity.COMMON, mage.cards.b.BirdMaiden.class)); + cards.add(new SetCardInfo("Birds of Paradise", 234, Rarity.RARE, mage.cards.b.BirdsOfParadise.class)); + cards.add(new SetCardInfo("Black Knight", 121, Rarity.UNCOMMON, mage.cards.b.BlackKnight.class)); + cards.add(new SetCardInfo("Black Mana Battery", 298, Rarity.RARE, mage.cards.b.BlackManaBattery.class)); + cards.add(new SetCardInfo("Black Vise", 299, Rarity.UNCOMMON, mage.cards.b.BlackVise.class)); cards.add(new SetCardInfo("Black Ward", 8, Rarity.UNCOMMON, mage.cards.b.BlackWard.class)); cards.add(new SetCardInfo("Blessing", 9, Rarity.RARE, mage.cards.b.Blessing.class)); + cards.add(new SetCardInfo("Blight", 122, Rarity.UNCOMMON, mage.cards.b.Blight.class)); + cards.add(new SetCardInfo("Blood Lust", 178, Rarity.COMMON, mage.cards.b.BloodLust.class)); + cards.add(new SetCardInfo("Blue Elemental Blast", 63, Rarity.COMMON, mage.cards.b.BlueElementalBlast.class)); + cards.add(new SetCardInfo("Blue Mana Battery", 300, Rarity.RARE, mage.cards.b.BlueManaBattery.class)); cards.add(new SetCardInfo("Blue Ward", 10, Rarity.UNCOMMON, mage.cards.b.BlueWard.class)); + cards.add(new SetCardInfo("Bog Imp", 123, Rarity.COMMON, mage.cards.b.BogImp.class)); + cards.add(new SetCardInfo("Bog Wraith", 124, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); + cards.add(new SetCardInfo("Bottle of Suleiman", 301, Rarity.RARE, mage.cards.b.BottleOfSuleiman.class)); cards.add(new SetCardInfo("Brainwash", 11, Rarity.COMMON, mage.cards.b.Brainwash.class)); + cards.add(new SetCardInfo("Brass Man", 302, Rarity.UNCOMMON, mage.cards.b.BrassMan.class)); + cards.add(new SetCardInfo("Brothers of Fire", 179, Rarity.COMMON, mage.cards.b.BrothersOfFire.class)); + cards.add(new SetCardInfo("Burrowing", 180, Rarity.UNCOMMON, mage.cards.b.Burrowing.class)); + cards.add(new SetCardInfo("Carnivorous Plant", 235, Rarity.COMMON, mage.cards.c.CarnivorousPlant.class)); + cards.add(new SetCardInfo("Carrion Ants", 125, Rarity.UNCOMMON, mage.cards.c.CarrionAnts.class)); cards.add(new SetCardInfo("Castle", 12, Rarity.UNCOMMON, mage.cards.c.Castle.class)); + cards.add(new SetCardInfo("Cave People", 181, Rarity.UNCOMMON, mage.cards.c.CavePeople.class)); + cards.add(new SetCardInfo("Celestial Prism", 304, Rarity.UNCOMMON, mage.cards.c.CelestialPrism.class)); + cards.add(new SetCardInfo("Channel", 236, Rarity.UNCOMMON, mage.cards.c.Channel.class)); + cards.add(new SetCardInfo("Chaoslace", 182, Rarity.RARE, mage.cards.c.Chaoslace.class)); cards.add(new SetCardInfo("Circle of Protection: Artifacts", 13, Rarity.COMMON, mage.cards.c.CircleOfProtectionArtifacts.class)); cards.add(new SetCardInfo("Circle of Protection: Black", 14, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlack.class)); cards.add(new SetCardInfo("Circle of Protection: Blue", 15, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlue.class)); cards.add(new SetCardInfo("Circle of Protection: Green", 16, Rarity.COMMON, mage.cards.c.CircleOfProtectionGreen.class)); cards.add(new SetCardInfo("Circle of Protection: Red", 17, Rarity.COMMON, mage.cards.c.CircleOfProtectionRed.class)); cards.add(new SetCardInfo("Circle of Protection: White", 18, Rarity.COMMON, mage.cards.c.CircleOfProtectionWhite.class)); - cards.add(new SetCardInfo("Conversion", 19, Rarity.UNCOMMON, mage.cards.c.Conversion.class)); - cards.add(new SetCardInfo("Crusade", 20, Rarity.RARE, mage.cards.c.Crusade.class)); - cards.add(new SetCardInfo("Death Ward", 21, Rarity.COMMON, mage.cards.d.DeathWard.class)); - cards.add(new SetCardInfo("Disenchant", 22, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Divine Transformation", 23, Rarity.UNCOMMON, mage.cards.d.DivineTransformation.class)); - cards.add(new SetCardInfo("Elder Land Wurm", 24, Rarity.RARE, mage.cards.e.ElderLandWurm.class)); - cards.add(new SetCardInfo("Eye for an Eye", 25, Rarity.RARE, mage.cards.e.EyeForAnEye.class)); - cards.add(new SetCardInfo("Fortified Area", 26, Rarity.COMMON, mage.cards.f.FortifiedArea.class)); - cards.add(new SetCardInfo("Green Ward", 27, Rarity.UNCOMMON, mage.cards.g.GreenWard.class)); - cards.add(new SetCardInfo("Healing Salve", 28, Rarity.COMMON, mage.cards.h.HealingSalve.class)); - cards.add(new SetCardInfo("Holy Armor", 29, Rarity.COMMON, mage.cards.h.HolyArmor.class)); - cards.add(new SetCardInfo("Holy Strength", 30, Rarity.COMMON, mage.cards.h.HolyStrength.class)); - cards.add(new SetCardInfo("Island Sanctuary", 31, Rarity.RARE, mage.cards.i.IslandSanctuary.class)); - cards.add(new SetCardInfo("Karma", 32, Rarity.UNCOMMON, mage.cards.k.Karma.class)); - cards.add(new SetCardInfo("Kismet", 33, Rarity.UNCOMMON, mage.cards.k.Kismet.class)); - cards.add(new SetCardInfo("Land Tax", 34, Rarity.RARE, mage.cards.l.LandTax.class)); - cards.add(new SetCardInfo("Mesa Pegasus", 35, Rarity.COMMON, mage.cards.m.MesaPegasus.class)); - cards.add(new SetCardInfo("Morale", 36, Rarity.COMMON, mage.cards.m.Morale.class)); - cards.add(new SetCardInfo("Northern Paladin", 37, Rarity.RARE, mage.cards.n.NorthernPaladin.class)); - cards.add(new SetCardInfo("Osai Vultures", 38, Rarity.UNCOMMON, mage.cards.o.OsaiVultures.class)); - cards.add(new SetCardInfo("Pearled Unicorn", 39, Rarity.COMMON, mage.cards.p.PearledUnicorn.class)); - cards.add(new SetCardInfo("Personal Incarnation", 40, Rarity.RARE, mage.cards.p.PersonalIncarnation.class)); - cards.add(new SetCardInfo("Piety", 41, Rarity.COMMON, Piety.class)); - cards.add(new SetCardInfo("Pikemen", 42, Rarity.COMMON, mage.cards.p.Pikemen.class)); - cards.add(new SetCardInfo("Purelace", 43, Rarity.RARE, mage.cards.p.Purelace.class)); - cards.add(new SetCardInfo("Red Ward", 44, Rarity.UNCOMMON, mage.cards.r.RedWard.class)); - cards.add(new SetCardInfo("Reverse Damage", 45, Rarity.RARE, mage.cards.r.ReverseDamage.class)); - cards.add(new SetCardInfo("Righteousness", 46, Rarity.RARE, mage.cards.r.Righteousness.class)); - cards.add(new SetCardInfo("Samite Healer", 47, Rarity.COMMON, mage.cards.s.SamiteHealer.class)); - cards.add(new SetCardInfo("Savannah Lions", 48, Rarity.RARE, mage.cards.s.SavannahLions.class)); - cards.add(new SetCardInfo("Seeker", 49, Rarity.COMMON, mage.cards.s.Seeker.class)); - cards.add(new SetCardInfo("Serra Angel", 50, Rarity.UNCOMMON, mage.cards.s.SerraAngel.class)); - cards.add(new SetCardInfo("Spirit Link", 51, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); - cards.add(new SetCardInfo("Swords to Plowshares", 52, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class)); - cards.add(new SetCardInfo("Tundra Wolves", 53, Rarity.COMMON, mage.cards.t.TundraWolves.class)); - cards.add(new SetCardInfo("Visions", 54, Rarity.UNCOMMON, mage.cards.v.Visions.class)); - cards.add(new SetCardInfo("Wall of Swords", 55, Rarity.UNCOMMON, mage.cards.w.WallOfSwords.class)); - cards.add(new SetCardInfo("White Knight", 56, Rarity.UNCOMMON, mage.cards.w.WhiteKnight.class)); - cards.add(new SetCardInfo("White Ward", 57, Rarity.UNCOMMON, mage.cards.w.WhiteWard.class)); - cards.add(new SetCardInfo("Wrath of God", 58, Rarity.RARE, mage.cards.w.WrathOfGod.class)); - cards.add(new SetCardInfo("Aladdin's Lamp", 291, Rarity.RARE, mage.cards.a.AladdinsLamp.class)); - cards.add(new SetCardInfo("Aladdin's Ring", 292, Rarity.RARE, mage.cards.a.AladdinsRing.class)); - cards.add(new SetCardInfo("Amulet of Kroog", 293, Rarity.COMMON, mage.cards.a.AmuletOfKroog.class)); - cards.add(new SetCardInfo("Ankh of Mishra", 294, Rarity.RARE, mage.cards.a.AnkhOfMishra.class)); - cards.add(new SetCardInfo("Armageddon Clock", 295, Rarity.RARE, mage.cards.a.ArmageddonClock.class)); - cards.add(new SetCardInfo("Ashnod's Battle Gear", 296, Rarity.UNCOMMON, mage.cards.a.AshnodsBattleGear.class)); - cards.add(new SetCardInfo("Battering Ram", 297, Rarity.COMMON, mage.cards.b.BatteringRam.class)); - cards.add(new SetCardInfo("Black Mana Battery", 298, Rarity.RARE, mage.cards.b.BlackManaBattery.class)); - cards.add(new SetCardInfo("Black Vise", 299, Rarity.UNCOMMON, mage.cards.b.BlackVise.class)); - cards.add(new SetCardInfo("Blue Mana Battery", 300, Rarity.RARE, mage.cards.b.BlueManaBattery.class)); - cards.add(new SetCardInfo("Bottle of Suleiman", 301, Rarity.RARE, mage.cards.b.BottleOfSuleiman.class)); - cards.add(new SetCardInfo("Brass Man", 302, Rarity.UNCOMMON, mage.cards.b.BrassMan.class)); - cards.add(new SetCardInfo("Celestial Prism", 304, Rarity.UNCOMMON, mage.cards.c.CelestialPrism.class)); cards.add(new SetCardInfo("Clay Statue", 305, Rarity.COMMON, mage.cards.c.ClayStatue.class)); cards.add(new SetCardInfo("Clockwork Avian", 306, Rarity.RARE, mage.cards.c.ClockworkAvian.class)); cards.add(new SetCardInfo("Clockwork Beast", 307, Rarity.RARE, mage.cards.c.ClockworkBeast.class)); + cards.add(new SetCardInfo("Cockatrice", 237, Rarity.RARE, mage.cards.c.Cockatrice.class)); cards.add(new SetCardInfo("Colossus of Sardia", 308, Rarity.RARE, mage.cards.c.ColossusOfSardia.class)); cards.add(new SetCardInfo("Conservator", 309, Rarity.UNCOMMON, mage.cards.c.Conservator.class)); + cards.add(new SetCardInfo("Control Magic", 64, Rarity.UNCOMMON, mage.cards.c.ControlMagic.class)); + cards.add(new SetCardInfo("Conversion", 19, Rarity.UNCOMMON, mage.cards.c.Conversion.class)); cards.add(new SetCardInfo("Coral Helm", 310, Rarity.RARE, mage.cards.c.CoralHelm.class)); + cards.add(new SetCardInfo("Cosmic Horror", 126, Rarity.RARE, mage.cards.c.CosmicHorror.class)); + cards.add(new SetCardInfo("Counterspell", 65, Rarity.UNCOMMON, mage.cards.c.Counterspell.class)); + cards.add(new SetCardInfo("Craw Wurm", 238, Rarity.COMMON, mage.cards.c.CrawWurm.class)); + cards.add(new SetCardInfo("Creature Bond", 66, Rarity.COMMON, mage.cards.c.CreatureBond.class)); + cards.add(new SetCardInfo("Crimson Manticore", 183, Rarity.RARE, mage.cards.c.CrimsonManticore.class)); + cards.add(new SetCardInfo("Crumble", 239, Rarity.UNCOMMON, mage.cards.c.Crumble.class)); + cards.add(new SetCardInfo("Crusade", 20, Rarity.RARE, mage.cards.c.Crusade.class)); cards.add(new SetCardInfo("Crystal Rod", 311, Rarity.UNCOMMON, mage.cards.c.CrystalRod.class)); + cards.add(new SetCardInfo("Cursed Land", 127, Rarity.UNCOMMON, mage.cards.c.CursedLand.class)); cards.add(new SetCardInfo("Cursed Rack", 312, Rarity.UNCOMMON, mage.cards.c.CursedRack.class)); + cards.add(new SetCardInfo("Cyclopean Mummy", 128, Rarity.COMMON, mage.cards.c.CyclopeanMummy.class)); cards.add(new SetCardInfo("Dancing Scimitar", 313, Rarity.RARE, mage.cards.d.DancingScimitar.class)); + cards.add(new SetCardInfo("Dark Ritual", 129, Rarity.COMMON, mage.cards.d.DarkRitual.class)); + cards.add(new SetCardInfo("Death Ward", 21, Rarity.COMMON, mage.cards.d.DeathWard.class)); + cards.add(new SetCardInfo("Deathgrip", 130, Rarity.UNCOMMON, mage.cards.d.Deathgrip.class)); + cards.add(new SetCardInfo("Deathlace", 131, Rarity.RARE, mage.cards.d.Deathlace.class)); + cards.add(new SetCardInfo("Desert Twister", 240, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class)); + cards.add(new SetCardInfo("Detonate", 184, Rarity.UNCOMMON, mage.cards.d.Detonate.class)); cards.add(new SetCardInfo("Diabolic Machine", 314, Rarity.UNCOMMON, mage.cards.d.DiabolicMachine.class)); cards.add(new SetCardInfo("Dingus Egg", 315, Rarity.RARE, mage.cards.d.DingusEgg.class)); + cards.add(new SetCardInfo("Disenchant", 22, Rarity.COMMON, mage.cards.d.Disenchant.class)); + cards.add(new SetCardInfo("Disintegrate", 185, Rarity.COMMON, mage.cards.d.Disintegrate.class)); cards.add(new SetCardInfo("Disrupting Scepter", 316, Rarity.RARE, mage.cards.d.DisruptingScepter.class)); + cards.add(new SetCardInfo("Divine Transformation", 23, Rarity.UNCOMMON, mage.cards.d.DivineTransformation.class)); cards.add(new SetCardInfo("Dragon Engine", 317, Rarity.RARE, mage.cards.d.DragonEngine.class)); + cards.add(new SetCardInfo("Dragon Whelp", 186, Rarity.UNCOMMON, mage.cards.d.DragonWhelp.class)); + cards.add(new SetCardInfo("Drain Life", 132, Rarity.COMMON, mage.cards.d.DrainLife.class)); + cards.add(new SetCardInfo("Drain Power", 67, Rarity.RARE, mage.cards.d.DrainPower.class)); + cards.add(new SetCardInfo("Drudge Skeletons", 133, Rarity.COMMON, mage.cards.d.DrudgeSkeletons.class)); + cards.add(new SetCardInfo("Durkwood Boars", 241, Rarity.COMMON, mage.cards.d.DurkwoodBoars.class)); + cards.add(new SetCardInfo("Dwarven Warriors", 187, Rarity.COMMON, mage.cards.d.DwarvenWarriors.class)); + cards.add(new SetCardInfo("Earth Elemental", 188, Rarity.UNCOMMON, mage.cards.e.EarthElemental.class)); + cards.add(new SetCardInfo("Earthquake", 189, Rarity.RARE, mage.cards.e.Earthquake.class)); cards.add(new SetCardInfo("Ebony Horse", 318, Rarity.RARE, mage.cards.e.EbonyHorse.class)); + cards.add(new SetCardInfo("El-Hajjaj", 134, Rarity.RARE, mage.cards.e.ElHajjaj.class)); + cards.add(new SetCardInfo("Elder Land Wurm", 24, Rarity.RARE, mage.cards.e.ElderLandWurm.class)); + cards.add(new SetCardInfo("Elven Riders", 242, Rarity.UNCOMMON, mage.cards.e.ElvenRiders.class)); + cards.add(new SetCardInfo("Elvish Archers", 243, Rarity.RARE, mage.cards.e.ElvishArchers.class)); + cards.add(new SetCardInfo("Energy Flux", 68, Rarity.UNCOMMON, mage.cards.e.EnergyFlux.class)); + cards.add(new SetCardInfo("Energy Tap", 69, Rarity.COMMON, mage.cards.e.EnergyTap.class)); + cards.add(new SetCardInfo("Erg Raiders", 135, Rarity.COMMON, mage.cards.e.ErgRaiders.class)); + cards.add(new SetCardInfo("Erosion", 70, Rarity.COMMON, mage.cards.e.Erosion.class)); + cards.add(new SetCardInfo("Eternal Warrior", 190, Rarity.COMMON, mage.cards.e.EternalWarrior.class)); + cards.add(new SetCardInfo("Evil Presence", 136, Rarity.UNCOMMON, mage.cards.e.EvilPresence.class)); + cards.add(new SetCardInfo("Eye for an Eye", 25, Rarity.RARE, mage.cards.e.EyeForAnEye.class)); + cards.add(new SetCardInfo("Fear", 137, Rarity.COMMON, mage.cards.f.Fear.class)); + cards.add(new SetCardInfo("Feedback", 71, Rarity.UNCOMMON, mage.cards.f.Feedback.class)); cards.add(new SetCardInfo("Fellwar Stone", 319, Rarity.UNCOMMON, mage.cards.f.FellwarStone.class)); + cards.add(new SetCardInfo("Fire Elemental", 191, Rarity.UNCOMMON, mage.cards.f.FireElemental.class)); + cards.add(new SetCardInfo("Fireball", 192, Rarity.COMMON, mage.cards.f.Fireball.class)); + cards.add(new SetCardInfo("Firebreathing", 193, Rarity.COMMON, mage.cards.f.Firebreathing.class)); + cards.add(new SetCardInfo("Fissure", 194, Rarity.COMMON, mage.cards.f.Fissure.class)); + cards.add(new SetCardInfo("Flashfires", 195, Rarity.UNCOMMON, mage.cards.f.Flashfires.class)); + cards.add(new SetCardInfo("Flight", 72, Rarity.COMMON, mage.cards.f.Flight.class)); + cards.add(new SetCardInfo("Flood", 73, Rarity.COMMON, mage.cards.f.Flood.class)); cards.add(new SetCardInfo("Flying Carpet", 320, Rarity.RARE, mage.cards.f.FlyingCarpet.class)); + cards.add(new SetCardInfo("Fog", 244, Rarity.COMMON, mage.cards.f.Fog.class)); + cards.add(new SetCardInfo("Force of Nature", 245, Rarity.RARE, mage.cards.f.ForceOfNature.class)); + cards.add(new SetCardInfo("Forest", 376, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 377, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 378, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fortified Area", 26, Rarity.COMMON, mage.cards.f.FortifiedArea.class)); + cards.add(new SetCardInfo("Frozen Shade", 138, Rarity.COMMON, mage.cards.f.FrozenShade.class)); + cards.add(new SetCardInfo("Fungusaur", 246, Rarity.RARE, mage.cards.f.Fungusaur.class)); + cards.add(new SetCardInfo("Gaea's Liege", 247, Rarity.RARE, mage.cards.g.GaeasLiege.class)); + cards.add(new SetCardInfo("Gaseous Form", 74, Rarity.COMMON, mage.cards.g.GaseousForm.class)); + cards.add(new SetCardInfo("Ghost Ship", 75, Rarity.UNCOMMON, mage.cards.g.GhostShip.class)); + cards.add(new SetCardInfo("Giant Growth", 248, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); + cards.add(new SetCardInfo("Giant Spider", 249, Rarity.COMMON, mage.cards.g.GiantSpider.class)); + cards.add(new SetCardInfo("Giant Strength", 196, Rarity.COMMON, mage.cards.g.GiantStrength.class)); + cards.add(new SetCardInfo("Giant Tortoise", 76, Rarity.COMMON, mage.cards.g.GiantTortoise.class)); cards.add(new SetCardInfo("Glasses of Urza", 321, Rarity.UNCOMMON, mage.cards.g.GlassesOfUrza.class)); + cards.add(new SetCardInfo("Gloom", 139, Rarity.UNCOMMON, mage.cards.g.Gloom.class)); + cards.add(new SetCardInfo("Goblin Balloon Brigade", 197, Rarity.UNCOMMON, mage.cards.g.GoblinBalloonBrigade.class)); + cards.add(new SetCardInfo("Goblin King", 198, Rarity.RARE, mage.cards.g.GoblinKing.class)); + cards.add(new SetCardInfo("Goblin Rock Sled", 199, Rarity.COMMON, mage.cards.g.GoblinRockSled.class)); cards.add(new SetCardInfo("Grapeshot Catapult", 322, Rarity.COMMON, mage.cards.g.GrapeshotCatapult.class)); + cards.add(new SetCardInfo("Gray Ogre", 200, Rarity.COMMON, mage.cards.g.GrayOgre.class)); + cards.add(new SetCardInfo("Greed", 140, Rarity.RARE, mage.cards.g.Greed.class)); cards.add(new SetCardInfo("Green Mana Battery", 323, Rarity.RARE, mage.cards.g.GreenManaBattery.class)); + cards.add(new SetCardInfo("Green Ward", 27, Rarity.UNCOMMON, mage.cards.g.GreenWard.class)); + cards.add(new SetCardInfo("Grizzly Bears", 250, Rarity.COMMON, mage.cards.g.GrizzlyBears.class)); + cards.add(new SetCardInfo("Healing Salve", 28, Rarity.COMMON, mage.cards.h.HealingSalve.class)); cards.add(new SetCardInfo("Helm of Chatzuk", 324, Rarity.RARE, mage.cards.h.HelmOfChatzuk.class)); + cards.add(new SetCardInfo("Hill Giant", 201, Rarity.COMMON, mage.cards.h.HillGiant.class)); + cards.add(new SetCardInfo("Holy Armor", 29, Rarity.COMMON, mage.cards.h.HolyArmor.class)); + cards.add(new SetCardInfo("Holy Strength", 30, Rarity.COMMON, mage.cards.h.HolyStrength.class)); + cards.add(new SetCardInfo("Howl from Beyond", 141, Rarity.COMMON, mage.cards.h.HowlFromBeyond.class)); cards.add(new SetCardInfo("Howling Mine", 325, Rarity.RARE, mage.cards.h.HowlingMine.class)); + cards.add(new SetCardInfo("Hurkyl's Recall", 77, Rarity.RARE, mage.cards.h.HurkylsRecall.class)); + cards.add(new SetCardInfo("Hurloon Minotaur", 202, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class)); + cards.add(new SetCardInfo("Hurr Jackal", 203, Rarity.RARE, mage.cards.h.HurrJackal.class)); + cards.add(new SetCardInfo("Hurricane", 251, Rarity.UNCOMMON, mage.cards.h.Hurricane.class)); + cards.add(new SetCardInfo("Hypnotic Specter", 142, Rarity.UNCOMMON, mage.cards.h.HypnoticSpecter.class)); + cards.add(new SetCardInfo("Immolation", 204, Rarity.COMMON, mage.cards.i.Immolation.class)); + cards.add(new SetCardInfo("Inferno", 205, Rarity.RARE, mage.cards.i.Inferno.class)); + cards.add(new SetCardInfo("Instill Energy", 252, Rarity.UNCOMMON, mage.cards.i.InstillEnergy.class)); cards.add(new SetCardInfo("Iron Star", 326, Rarity.UNCOMMON, mage.cards.i.IronStar.class)); + cards.add(new SetCardInfo("Ironclaw Orcs", 206, Rarity.COMMON, mage.cards.i.IronclawOrcs.class)); + cards.add(new SetCardInfo("Ironroot Treefolk", 253, Rarity.COMMON, mage.cards.i.IronrootTreefolk.class)); + cards.add(new SetCardInfo("Island Fish Jasconius", 78, Rarity.RARE, mage.cards.i.IslandFishJasconius.class)); + cards.add(new SetCardInfo("Island Sanctuary", 31, Rarity.RARE, mage.cards.i.IslandSanctuary.class)); + cards.add(new SetCardInfo("Island", 367, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 368, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 369, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ivory Cup", 327, Rarity.UNCOMMON, mage.cards.i.IvoryCup.class)); cards.add(new SetCardInfo("Ivory Tower", 328, Rarity.RARE, mage.cards.i.IvoryTower.class)); cards.add(new SetCardInfo("Jade Monolith", 329, Rarity.RARE, mage.cards.j.JadeMonolith.class)); cards.add(new SetCardInfo("Jandor's Saddlebags", 330, Rarity.RARE, mage.cards.j.JandorsSaddlebags.class)); cards.add(new SetCardInfo("Jayemdae Tome", 331, Rarity.RARE, mage.cards.j.JayemdaeTome.class)); + cards.add(new SetCardInfo("Jump", 79, Rarity.COMMON, mage.cards.j.Jump.class)); + cards.add(new SetCardInfo("Junun Efreet", 143, Rarity.UNCOMMON, mage.cards.j.JununEfreet.class)); + cards.add(new SetCardInfo("Karma", 32, Rarity.UNCOMMON, mage.cards.k.Karma.class)); + cards.add(new SetCardInfo("Keldon Warlord", 207, Rarity.UNCOMMON, mage.cards.k.KeldonWarlord.class)); + cards.add(new SetCardInfo("Killer Bees", 254, Rarity.UNCOMMON, mage.cards.k.KillerBees.class)); + cards.add(new SetCardInfo("Kismet", 33, Rarity.UNCOMMON, mage.cards.k.Kismet.class)); cards.add(new SetCardInfo("Kormus Bell", 332, Rarity.RARE, mage.cards.k.KormusBell.class)); + cards.add(new SetCardInfo("Land Leeches", 255, Rarity.COMMON, mage.cards.l.LandLeeches.class)); + cards.add(new SetCardInfo("Land Tax", 34, Rarity.RARE, mage.cards.l.LandTax.class)); + cards.add(new SetCardInfo("Leviathan", 80, Rarity.RARE, mage.cards.l.Leviathan.class)); + cards.add(new SetCardInfo("Ley Druid", 256, Rarity.UNCOMMON, mage.cards.l.LeyDruid.class)); cards.add(new SetCardInfo("Library of Leng", 333, Rarity.UNCOMMON, mage.cards.l.LibraryOfLeng.class)); + cards.add(new SetCardInfo("Lifeforce", 257, Rarity.UNCOMMON, mage.cards.l.Lifeforce.class)); + cards.add(new SetCardInfo("Lifelace", 258, Rarity.RARE, mage.cards.l.Lifelace.class)); + cards.add(new SetCardInfo("Lifetap", 81, Rarity.UNCOMMON, mage.cards.l.Lifetap.class)); + cards.add(new SetCardInfo("Lightning Bolt", 208, Rarity.COMMON, mage.cards.l.LightningBolt.class)); + cards.add(new SetCardInfo("Living Artifact", 259, Rarity.RARE, mage.cards.l.LivingArtifact.class)); + cards.add(new SetCardInfo("Living Lands", 260, Rarity.RARE, mage.cards.l.LivingLands.class)); + cards.add(new SetCardInfo("Llanowar Elves", 261, Rarity.COMMON, mage.cards.l.LlanowarElves.class)); + cards.add(new SetCardInfo("Lord of Atlantis", 82, Rarity.RARE, mage.cards.l.LordOfAtlantis.class)); + cards.add(new SetCardInfo("Lord of the Pit", 144, Rarity.RARE, mage.cards.l.LordOfThePit.class)); + cards.add(new SetCardInfo("Lost Soul", 145, Rarity.COMMON, mage.cards.l.LostSoul.class)); + cards.add(new SetCardInfo("Lure", 262, Rarity.UNCOMMON, mage.cards.l.Lure.class)); + cards.add(new SetCardInfo("Magnetic Mountain", 209, Rarity.RARE, mage.cards.m.MagneticMountain.class)); + cards.add(new SetCardInfo("Mahamoti Djinn", 84, Rarity.RARE, mage.cards.m.MahamotiDjinn.class)); + cards.add(new SetCardInfo("Mana Clash", 210, Rarity.RARE, mage.cards.m.ManaClash.class)); + cards.add(new SetCardInfo("Mana Flare", 211, Rarity.RARE, mage.cards.m.ManaFlare.class)); + cards.add(new SetCardInfo("Mana Short", 85, Rarity.RARE, mage.cards.m.ManaShort.class)); cards.add(new SetCardInfo("Mana Vault", 334, Rarity.RARE, mage.cards.m.ManaVault.class)); + cards.add(new SetCardInfo("Manabarbs", 212, Rarity.RARE, mage.cards.m.Manabarbs.class)); + cards.add(new SetCardInfo("Marsh Gas", 146, Rarity.COMMON, mage.cards.m.MarshGas.class)); + cards.add(new SetCardInfo("Marsh Viper", 263, Rarity.COMMON, mage.cards.m.MarshViper.class)); cards.add(new SetCardInfo("Meekstone", 335, Rarity.RARE, mage.cards.m.Meekstone.class)); + cards.add(new SetCardInfo("Merfolk of the Pearl Trident", 86, Rarity.COMMON, mage.cards.m.MerfolkOfThePearlTrident.class)); + cards.add(new SetCardInfo("Mesa Pegasus", 35, Rarity.COMMON, mage.cards.m.MesaPegasus.class)); cards.add(new SetCardInfo("Millstone", 336, Rarity.RARE, mage.cards.m.Millstone.class)); + cards.add(new SetCardInfo("Mind Bomb", 87, Rarity.UNCOMMON, mage.cards.m.MindBomb.class)); + cards.add(new SetCardInfo("Mind Twist", 147, Rarity.RARE, mage.cards.m.MindTwist.class)); + cards.add(new SetCardInfo("Mishra's Factory", 361, Rarity.UNCOMMON, mage.cards.m.MishrasFactory.class)); cards.add(new SetCardInfo("Mishra's War Machine", 337, Rarity.RARE, mage.cards.m.MishrasWarMachine.class)); + cards.add(new SetCardInfo("Mons's Goblin Raiders", 213, Rarity.COMMON, mage.cards.m.MonssGoblinRaiders.class)); + cards.add(new SetCardInfo("Morale", 36, Rarity.COMMON, mage.cards.m.Morale.class)); + cards.add(new SetCardInfo("Mountain", 373, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 374, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 375, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Murk Dwellers", 148, Rarity.COMMON, mage.cards.m.MurkDwellers.class)); + cards.add(new SetCardInfo("Nafs Asp", 264, Rarity.COMMON, NafsAsp.class)); + cards.add(new SetCardInfo("Nether Shadow", 149, Rarity.RARE, mage.cards.n.NetherShadow.class)); cards.add(new SetCardInfo("Nevinyrral's Disk", 338, Rarity.RARE, mage.cards.n.NevinyrralsDisk.class)); + cards.add(new SetCardInfo("Nightmare", 150, Rarity.RARE, mage.cards.n.Nightmare.class)); + cards.add(new SetCardInfo("Northern Paladin", 37, Rarity.RARE, mage.cards.n.NorthernPaladin.class)); + cards.add(new SetCardInfo("Oasis", 362, Rarity.UNCOMMON, mage.cards.o.Oasis.class)); cards.add(new SetCardInfo("Obsianus Golem", 339, Rarity.UNCOMMON, mage.cards.o.ObsianusGolem.class)); cards.add(new SetCardInfo("Onulet", 340, Rarity.RARE, mage.cards.o.Onulet.class)); + cards.add(new SetCardInfo("Orcish Artillery", 214, Rarity.UNCOMMON, mage.cards.o.OrcishArtillery.class)); + cards.add(new SetCardInfo("Orcish Oriflamme", 215, Rarity.UNCOMMON, mage.cards.o.OrcishOriflamme.class)); cards.add(new SetCardInfo("Ornithopter", 341, Rarity.UNCOMMON, mage.cards.o.Ornithopter.class)); + cards.add(new SetCardInfo("Osai Vultures", 38, Rarity.UNCOMMON, mage.cards.o.OsaiVultures.class)); + cards.add(new SetCardInfo("Paralyze", 151, Rarity.COMMON, mage.cards.p.Paralyze.class)); + cards.add(new SetCardInfo("Pearled Unicorn", 39, Rarity.COMMON, mage.cards.p.PearledUnicorn.class)); + cards.add(new SetCardInfo("Personal Incarnation", 40, Rarity.RARE, mage.cards.p.PersonalIncarnation.class)); + cards.add(new SetCardInfo("Pestilence", 152, Rarity.COMMON, mage.cards.p.Pestilence.class)); + cards.add(new SetCardInfo("Phantasmal Forces", 88, Rarity.UNCOMMON, mage.cards.p.PhantasmalForces.class)); + cards.add(new SetCardInfo("Phantasmal Terrain", 89, Rarity.COMMON, mage.cards.p.PhantasmalTerrain.class)); + cards.add(new SetCardInfo("Phantom Monster", 90, Rarity.UNCOMMON, mage.cards.p.PhantomMonster.class)); + cards.add(new SetCardInfo("Piety", 41, Rarity.COMMON, Piety.class)); + cards.add(new SetCardInfo("Pikemen", 42, Rarity.COMMON, mage.cards.p.Pikemen.class)); + cards.add(new SetCardInfo("Pirate Ship", 91, Rarity.RARE, mage.cards.p.PirateShip.class)); + cards.add(new SetCardInfo("Pit Scorpion", 153, Rarity.COMMON, mage.cards.p.PitScorpion.class)); + cards.add(new SetCardInfo("Plague Rats", 154, Rarity.COMMON, mage.cards.p.PlagueRats.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)); + cards.add(new SetCardInfo("Plains", 366, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Power Leak", 92, Rarity.COMMON, mage.cards.p.PowerLeak.class)); + cards.add(new SetCardInfo("Power Sink", 93, Rarity.COMMON, mage.cards.p.PowerSink.class)); + cards.add(new SetCardInfo("Power Surge", 216, Rarity.RARE, mage.cards.p.PowerSurge.class)); + cards.add(new SetCardInfo("Pradesh Gypsies", 265, Rarity.COMMON, mage.cards.p.PradeshGypsies.class)); cards.add(new SetCardInfo("Primal Clay", 342, Rarity.RARE, mage.cards.p.PrimalClay.class)); + cards.add(new SetCardInfo("Prodigal Sorcerer", 94, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class)); + cards.add(new SetCardInfo("Psionic Entity", 95, Rarity.RARE, mage.cards.p.PsionicEntity.class)); + cards.add(new SetCardInfo("Psychic Venom", 96, Rarity.COMMON, mage.cards.p.PsychicVenom.class)); + cards.add(new SetCardInfo("Purelace", 43, Rarity.RARE, mage.cards.p.Purelace.class)); + cards.add(new SetCardInfo("Pyrotechnics", 217, Rarity.UNCOMMON, mage.cards.p.Pyrotechnics.class)); + cards.add(new SetCardInfo("Radjan Spirit", 266, Rarity.UNCOMMON, mage.cards.r.RadjanSpirit.class)); + cards.add(new SetCardInfo("Rag Man", 155, Rarity.RARE, mage.cards.r.RagMan.class)); + cards.add(new SetCardInfo("Raise Dead", 156, Rarity.COMMON, mage.cards.r.RaiseDead.class)); + cards.add(new SetCardInfo("Red Elemental Blast", 218, Rarity.COMMON, mage.cards.r.RedElementalBlast.class)); cards.add(new SetCardInfo("Red Mana Battery", 343, Rarity.RARE, mage.cards.r.RedManaBattery.class)); + cards.add(new SetCardInfo("Red Ward", 44, Rarity.UNCOMMON, mage.cards.r.RedWard.class)); + cards.add(new SetCardInfo("Regeneration", 268, Rarity.COMMON, mage.cards.r.Regeneration.class)); + cards.add(new SetCardInfo("Relic Bind", 97, Rarity.RARE, mage.cards.r.RelicBind.class)); + cards.add(new SetCardInfo("Reverse Damage", 45, Rarity.RARE, mage.cards.r.ReverseDamage.class)); + cards.add(new SetCardInfo("Righteousness", 46, Rarity.RARE, mage.cards.r.Righteousness.class)); cards.add(new SetCardInfo("Rod of Ruin", 344, Rarity.UNCOMMON, mage.cards.r.RodOfRuin.class)); + cards.add(new SetCardInfo("Royal Assassin", 157, Rarity.RARE, mage.cards.r.RoyalAssassin.class)); + cards.add(new SetCardInfo("Samite Healer", 47, Rarity.COMMON, mage.cards.s.SamiteHealer.class)); + cards.add(new SetCardInfo("Sandstorm", 269, Rarity.COMMON, mage.cards.s.Sandstorm.class)); + cards.add(new SetCardInfo("Savannah Lions", 48, Rarity.RARE, mage.cards.s.SavannahLions.class)); + cards.add(new SetCardInfo("Scathe Zombies", 158, Rarity.COMMON, mage.cards.s.ScatheZombies.class)); + cards.add(new SetCardInfo("Scavenging Ghoul", 159, Rarity.UNCOMMON, mage.cards.s.ScavengingGhoul.class)); + cards.add(new SetCardInfo("Scryb Sprites", 270, Rarity.COMMON, mage.cards.s.ScrybSprites.class)); + cards.add(new SetCardInfo("Sea Serpent", 98, Rarity.COMMON, mage.cards.s.SeaSerpent.class)); + cards.add(new SetCardInfo("Seeker", 49, Rarity.COMMON, mage.cards.s.Seeker.class)); + cards.add(new SetCardInfo("Segovian Leviathan", 99, Rarity.UNCOMMON, mage.cards.s.SegovianLeviathan.class)); + cards.add(new SetCardInfo("Sengir Vampire", 160, Rarity.UNCOMMON, mage.cards.s.SengirVampire.class)); + cards.add(new SetCardInfo("Serra Angel", 50, Rarity.UNCOMMON, mage.cards.s.SerraAngel.class)); + cards.add(new SetCardInfo("Shanodin Dryads", 271, Rarity.COMMON, mage.cards.s.ShanodinDryads.class)); cards.add(new SetCardInfo("Shapeshifter", 345, Rarity.UNCOMMON, mage.cards.s.Shapeshifter.class)); + cards.add(new SetCardInfo("Shatter", 219, Rarity.COMMON, mage.cards.s.Shatter.class)); + cards.add(new SetCardInfo("Shivan Dragon", 220, Rarity.RARE, mage.cards.s.ShivanDragon.class)); + cards.add(new SetCardInfo("Simulacrum", 161, Rarity.UNCOMMON, mage.cards.s.Simulacrum.class)); + cards.add(new SetCardInfo("Sindbad", 100, Rarity.UNCOMMON, mage.cards.s.Sindbad.class)); + cards.add(new SetCardInfo("Siren's Call", 101, Rarity.UNCOMMON, mage.cards.s.SirensCall.class)); + cards.add(new SetCardInfo("Sisters of the Flame", 221, Rarity.COMMON, mage.cards.s.SistersOfTheFlame.class)); + cards.add(new SetCardInfo("Smoke", 222, Rarity.RARE, mage.cards.s.Smoke.class)); + cards.add(new SetCardInfo("Sorceress Queen", 162, Rarity.RARE, mage.cards.s.SorceressQueen.class)); cards.add(new SetCardInfo("Soul Net", 346, Rarity.UNCOMMON, mage.cards.s.SoulNet.class)); + cards.add(new SetCardInfo("Spell Blast", 103, Rarity.COMMON, mage.cards.s.SpellBlast.class)); + cards.add(new SetCardInfo("Spirit Link", 51, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); + cards.add(new SetCardInfo("Spirit Shackle", 163, Rarity.UNCOMMON, mage.cards.s.SpiritShackle.class)); + cards.add(new SetCardInfo("Stasis", 104, Rarity.RARE, mage.cards.s.Stasis.class)); + cards.add(new SetCardInfo("Steal Artifact", 105, Rarity.UNCOMMON, mage.cards.s.StealArtifact.class)); + cards.add(new SetCardInfo("Stone Giant", 223, Rarity.UNCOMMON, mage.cards.s.StoneGiant.class)); + cards.add(new SetCardInfo("Stone Rain", 224, Rarity.COMMON, mage.cards.s.StoneRain.class)); + cards.add(new SetCardInfo("Stream of Life", 272, Rarity.COMMON, mage.cards.s.StreamOfLife.class)); + cards.add(new SetCardInfo("Strip Mine", 363, Rarity.UNCOMMON, mage.cards.s.StripMine.class)); cards.add(new SetCardInfo("Sunglasses of Urza", 347, Rarity.RARE, mage.cards.s.SunglassesOfUrza.class)); + cards.add(new SetCardInfo("Sunken City", 106, Rarity.COMMON, mage.cards.s.SunkenCity.class)); + cards.add(new SetCardInfo("Swamp", 370, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 371, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 372, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swords to Plowshares", 52, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class)); + cards.add(new SetCardInfo("Sylvan Library", 273, Rarity.RARE, mage.cards.s.SylvanLibrary.class)); cards.add(new SetCardInfo("Tawnos's Wand", 348, Rarity.UNCOMMON, mage.cards.t.TawnossWand.class)); cards.add(new SetCardInfo("Tawnos's Weaponry", 349, Rarity.UNCOMMON, mage.cards.t.TawnossWeaponry.class)); + cards.add(new SetCardInfo("Terror", 164, Rarity.COMMON, mage.cards.t.Terror.class)); cards.add(new SetCardInfo("Tetravus", 350, Rarity.RARE, mage.cards.t.Tetravus.class)); + cards.add(new SetCardInfo("The Brute", 226, Rarity.COMMON, mage.cards.t.TheBrute.class)); cards.add(new SetCardInfo("The Hive", 351, Rarity.RARE, mage.cards.t.TheHive.class)); cards.add(new SetCardInfo("The Rack", 352, Rarity.UNCOMMON, mage.cards.t.TheRack.class)); + cards.add(new SetCardInfo("Thicket Basilisk", 274, Rarity.UNCOMMON, mage.cards.t.ThicketBasilisk.class)); + cards.add(new SetCardInfo("Thoughtlace", 107, Rarity.RARE, mage.cards.t.Thoughtlace.class)); cards.add(new SetCardInfo("Throne of Bone", 353, Rarity.UNCOMMON, mage.cards.t.ThroneOfBone.class)); + cards.add(new SetCardInfo("Timber Wolves", 275, Rarity.RARE, mage.cards.t.TimberWolves.class)); + cards.add(new SetCardInfo("Time Elemental", 108, Rarity.RARE, mage.cards.t.TimeElemental.class)); + cards.add(new SetCardInfo("Titania's Song", 276, Rarity.RARE, mage.cards.t.TitaniasSong.class)); + cards.add(new SetCardInfo("Tranquility", 277, Rarity.COMMON, mage.cards.t.Tranquility.class)); cards.add(new SetCardInfo("Triskelion", 354, Rarity.RARE, mage.cards.t.Triskelion.class)); + cards.add(new SetCardInfo("Tsunami", 278, Rarity.UNCOMMON, mage.cards.t.Tsunami.class)); + cards.add(new SetCardInfo("Tundra Wolves", 53, Rarity.COMMON, mage.cards.t.TundraWolves.class)); + cards.add(new SetCardInfo("Tunnel", 227, Rarity.UNCOMMON, mage.cards.t.Tunnel.class)); + cards.add(new SetCardInfo("Twiddle", 109, Rarity.COMMON, mage.cards.t.Twiddle.class)); + cards.add(new SetCardInfo("Uncle Istvan", 165, Rarity.UNCOMMON, mage.cards.u.UncleIstvan.class)); + cards.add(new SetCardInfo("Unholy Strength", 166, Rarity.COMMON, mage.cards.u.UnholyStrength.class)); + cards.add(new SetCardInfo("Unstable Mutation", 110, Rarity.COMMON, mage.cards.u.UnstableMutation.class)); + cards.add(new SetCardInfo("Unsummon", 111, Rarity.COMMON, mage.cards.u.Unsummon.class)); + cards.add(new SetCardInfo("Untamed Wilds", 279, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); cards.add(new SetCardInfo("Urza's Avenger", 355, Rarity.RARE, mage.cards.u.UrzasAvenger.class)); + cards.add(new SetCardInfo("Uthden Troll", 228, Rarity.UNCOMMON, mage.cards.u.UthdenTroll.class)); + cards.add(new SetCardInfo("Vampire Bats", 167, Rarity.COMMON, mage.cards.v.VampireBats.class)); + cards.add(new SetCardInfo("Venom", 280, Rarity.COMMON, mage.cards.v.Venom.class)); + cards.add(new SetCardInfo("Verduran Enchantress", 281, Rarity.RARE, mage.cards.v.VerduranEnchantress.class)); + cards.add(new SetCardInfo("Visions", 54, Rarity.UNCOMMON, mage.cards.v.Visions.class)); + cards.add(new SetCardInfo("Volcanic Eruption", 112, Rarity.RARE, mage.cards.v.VolcanicEruption.class)); + cards.add(new SetCardInfo("Wall of Air", 113, Rarity.UNCOMMON, mage.cards.w.WallOfAir.class)); + cards.add(new SetCardInfo("Wall of Bone", 168, Rarity.UNCOMMON, mage.cards.w.WallOfBone.class)); + cards.add(new SetCardInfo("Wall of Brambles", 282, Rarity.UNCOMMON, mage.cards.w.WallOfBrambles.class)); + cards.add(new SetCardInfo("Wall of Dust", 229, Rarity.UNCOMMON, mage.cards.w.WallOfDust.class)); + cards.add(new SetCardInfo("Wall of Fire", 230, Rarity.UNCOMMON, mage.cards.w.WallOfFire.class)); + cards.add(new SetCardInfo("Wall of Ice", 283, Rarity.UNCOMMON, mage.cards.w.WallOfIce.class)); cards.add(new SetCardInfo("Wall of Spears", 356, Rarity.COMMON, mage.cards.w.WallOfSpears.class)); + cards.add(new SetCardInfo("Wall of Stone", 231, Rarity.UNCOMMON, mage.cards.w.WallOfStone.class)); + cards.add(new SetCardInfo("Wall of Swords", 55, Rarity.UNCOMMON, mage.cards.w.WallOfSwords.class)); + cards.add(new SetCardInfo("Wall of Water", 114, Rarity.UNCOMMON, mage.cards.w.WallOfWater.class)); + cards.add(new SetCardInfo("Wall of Wood", 284, Rarity.COMMON, mage.cards.w.WallOfWood.class)); + cards.add(new SetCardInfo("Wanderlust", 285, Rarity.UNCOMMON, mage.cards.w.Wanderlust.class)); + cards.add(new SetCardInfo("War Mammoth", 286, Rarity.COMMON, mage.cards.w.WarMammoth.class)); + cards.add(new SetCardInfo("Warp Artifact", 169, Rarity.RARE, mage.cards.w.WarpArtifact.class)); + cards.add(new SetCardInfo("Water Elemental", 115, Rarity.UNCOMMON, mage.cards.w.WaterElemental.class)); + cards.add(new SetCardInfo("Weakness", 170, Rarity.COMMON, mage.cards.w.Weakness.class)); + cards.add(new SetCardInfo("Web", 287, Rarity.RARE, mage.cards.w.Web.class)); + cards.add(new SetCardInfo("Whirling Dervish", 288, Rarity.UNCOMMON, mage.cards.w.WhirlingDervish.class)); + cards.add(new SetCardInfo("White Knight", 56, Rarity.UNCOMMON, mage.cards.w.WhiteKnight.class)); cards.add(new SetCardInfo("White Mana Battery", 357, Rarity.RARE, mage.cards.w.WhiteManaBattery.class)); + cards.add(new SetCardInfo("White Ward", 57, Rarity.UNCOMMON, mage.cards.w.WhiteWard.class)); + cards.add(new SetCardInfo("Wild Growth", 289, Rarity.COMMON, mage.cards.w.WildGrowth.class)); + cards.add(new SetCardInfo("Will-o'-the-Wisp", 171, Rarity.RARE, mage.cards.w.WillOTheWisp.class)); + cards.add(new SetCardInfo("Winds of Change", 232, Rarity.RARE, mage.cards.w.WindsOfChange.class)); + cards.add(new SetCardInfo("Winter Blast", 290, Rarity.UNCOMMON, mage.cards.w.WinterBlast.class)); cards.add(new SetCardInfo("Winter Orb", 358, Rarity.RARE, mage.cards.w.WinterOrb.class)); cards.add(new SetCardInfo("Wooden Sphere", 359, Rarity.UNCOMMON, mage.cards.w.WoodenSphere.class)); + cards.add(new SetCardInfo("Word of Binding", 172, Rarity.COMMON, mage.cards.w.WordOfBinding.class)); + cards.add(new SetCardInfo("Wrath of God", 58, Rarity.RARE, mage.cards.w.WrathOfGod.class)); + cards.add(new SetCardInfo("Xenic Poltergeist", 173, Rarity.RARE, mage.cards.x.XenicPoltergeist.class)); cards.add(new SetCardInfo("Yotian Soldier", 360, Rarity.COMMON, mage.cards.y.YotianSoldier.class)); + cards.add(new SetCardInfo("Zephyr Falcon", 116, Rarity.COMMON, mage.cards.z.ZephyrFalcon.class)); + cards.add(new SetCardInfo("Zombie Master", 174, Rarity.RARE, mage.cards.z.ZombieMaster.class)); } } diff --git a/Mage.Sets/src/mage/sets/Guildpact.java b/Mage.Sets/src/mage/sets/Guildpact.java index 5eadbe6723e..1e3a1611318 100644 --- a/Mage.Sets/src/mage/sets/Guildpact.java +++ b/Mage.Sets/src/mage/sets/Guildpact.java @@ -29,6 +29,7 @@ public final class Guildpact extends ExpansionSet { this.ratioBoosterMythic = 0; cards.add(new SetCardInfo("Absolver Thrull", 1, Rarity.COMMON, mage.cards.a.AbsolverThrull.class)); cards.add(new SetCardInfo("Abyssal Nocturnus", 43, Rarity.RARE, mage.cards.a.AbyssalNocturnus.class)); + cards.add(new SetCardInfo("Aetherplasm", 22, Rarity.UNCOMMON, mage.cards.a.Aetherplasm.class)); cards.add(new SetCardInfo("Agent of Masks", 100, Rarity.UNCOMMON, mage.cards.a.AgentOfMasks.class)); cards.add(new SetCardInfo("Angel of Despair", 101, Rarity.RARE, mage.cards.a.AngelOfDespair.class)); cards.add(new SetCardInfo("Battering Wurm", 79, Rarity.UNCOMMON, mage.cards.b.BatteringWurm.class)); @@ -44,6 +45,7 @@ public final class Guildpact extends ExpansionSet { cards.add(new SetCardInfo("Castigate", 106, Rarity.COMMON, mage.cards.c.Castigate.class)); cards.add(new SetCardInfo("Caustic Rain", 44, Rarity.UNCOMMON, mage.cards.c.CausticRain.class)); cards.add(new SetCardInfo("Cerebral Vortex", 107, Rarity.RARE, mage.cards.c.CerebralVortex.class)); + cards.add(new SetCardInfo("Conjurer's Ban", 108, Rarity.UNCOMMON, mage.cards.c.ConjurersBan.class)); cards.add(new SetCardInfo("Crash Landing", 82, Rarity.UNCOMMON, mage.cards.c.CrashLanding.class)); cards.add(new SetCardInfo("Cremate", 45, Rarity.COMMON, mage.cards.c.Cremate.class)); cards.add(new SetCardInfo("Cry of Contrition", 46, Rarity.COMMON, mage.cards.c.CryOfContrition.class)); @@ -129,6 +131,7 @@ public final class Guildpact extends ExpansionSet { cards.add(new SetCardInfo("Pillory of the Sleepless", 125, Rarity.COMMON, mage.cards.p.PilloryOfTheSleepless.class)); cards.add(new SetCardInfo("Plagued Rusalka", 56, Rarity.UNCOMMON, mage.cards.p.PlaguedRusalka.class)); cards.add(new SetCardInfo("Poisonbelly Ogre", 57, Rarity.COMMON, mage.cards.p.PoisonbellyOgre.class)); + cards.add(new SetCardInfo("Predatory Focus", 92, Rarity.UNCOMMON, mage.cards.p.PredatoryFocus.class)); cards.add(new SetCardInfo("Primeval Light", 93, Rarity.UNCOMMON, mage.cards.p.PrimevalLight.class)); cards.add(new SetCardInfo("Pyromatics", 72, Rarity.COMMON, mage.cards.p.Pyromatics.class)); cards.add(new SetCardInfo("Quicken", 31, Rarity.RARE, mage.cards.q.Quicken.class)); diff --git a/Mage.Sets/src/mage/sets/Homelands.java b/Mage.Sets/src/mage/sets/Homelands.java index 195df34bc10..52e35f67724 100644 --- a/Mage.Sets/src/mage/sets/Homelands.java +++ b/Mage.Sets/src/mage/sets/Homelands.java @@ -1,4 +1,3 @@ - package mage.sets; import mage.cards.ExpansionSet; @@ -89,6 +88,7 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Dry Spell", "46a", Rarity.COMMON, DrySpell.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dry Spell", "46b", Rarity.COMMON, DrySpell.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dwarven Pony", 70, Rarity.RARE, mage.cards.d.DwarvenPony.class)); + cards.add(new SetCardInfo("Dwarven Sea Clan", 71, Rarity.RARE, mage.cards.d.DwarvenSeaClan.class)); cards.add(new SetCardInfo("Dwarven Trader", "72a", Rarity.COMMON, DwarvenTrader.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dwarven Trader", "72b", Rarity.COMMON, DwarvenTrader.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ebony Rhino", 106, Rarity.COMMON, mage.cards.e.EbonyRhino.class)); @@ -103,10 +103,14 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Forget", 26, Rarity.RARE, mage.cards.f.Forget.class)); cards.add(new SetCardInfo("Funeral March", 48, Rarity.UNCOMMON, mage.cards.f.FuneralMarch.class)); cards.add(new SetCardInfo("Ghost Hounds", 49, Rarity.UNCOMMON, mage.cards.g.GhostHounds.class)); + cards.add(new SetCardInfo("Giant Oyster", 28, Rarity.UNCOMMON, mage.cards.g.GiantOyster.class)); + cards.add(new SetCardInfo("Giant Albatross", "27a", Rarity.COMMON, mage.cards.g.GiantAlbatross.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Giant Albatross", "27b", Rarity.COMMON, mage.cards.g.GiantAlbatross.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grandmother Sengir", 50, Rarity.RARE, mage.cards.g.GrandmotherSengir.class)); cards.add(new SetCardInfo("Greater Werewolf", 51, Rarity.UNCOMMON, mage.cards.g.GreaterWerewolf.class)); cards.add(new SetCardInfo("Hazduhr the Abbot", 8, Rarity.RARE, mage.cards.h.HazduhrTheAbbot.class)); cards.add(new SetCardInfo("Headstone", 52, Rarity.COMMON, mage.cards.h.Headstone.class)); + cards.add(new SetCardInfo("Heart Wolf", 75, Rarity.RARE, mage.cards.h.HeartWolf.class)); cards.add(new SetCardInfo("Hungry Mist", "88a", Rarity.COMMON, mage.cards.h.HungryMist.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Hungry Mist", "88b", Rarity.COMMON, mage.cards.h.HungryMist.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ihsan's Shade", 53, Rarity.UNCOMMON, mage.cards.i.IhsansShade.class)); @@ -114,6 +118,7 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Ironclaw Curse", 76, Rarity.RARE, mage.cards.i.IronclawCurse.class)); cards.add(new SetCardInfo("Jinx", 29, Rarity.COMMON, mage.cards.j.Jinx.class)); cards.add(new SetCardInfo("Joven", 77, Rarity.COMMON, mage.cards.j.Joven.class)); + cards.add(new SetCardInfo("Joven's Ferrets", 89, Rarity.COMMON, mage.cards.j.JovensFerrets.class)); cards.add(new SetCardInfo("Joven's Tools", 108, Rarity.UNCOMMON, mage.cards.j.JovensTools.class)); cards.add(new SetCardInfo("Koskun Falls", 55, Rarity.RARE, mage.cards.k.KoskunFalls.class)); cards.add(new SetCardInfo("Koskun Keep", 114, Rarity.UNCOMMON, mage.cards.k.KoskunKeep.class)); @@ -129,7 +134,9 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Mesa Falcon", "10b", Rarity.COMMON, MesaFalcon.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mystic Decree", 34, Rarity.RARE, mage.cards.m.MysticDecree.class)); cards.add(new SetCardInfo("Narwhal", 35, Rarity.RARE, mage.cards.n.Narwhal.class)); + cards.add(new SetCardInfo("Orcish Mine", 78, Rarity.UNCOMMON, mage.cards.o.OrcishMine.class)); cards.add(new SetCardInfo("Primal Order", 92, Rarity.RARE, mage.cards.p.PrimalOrder.class)); + cards.add(new SetCardInfo("Prophecy", 11, Rarity.COMMON, mage.cards.p.Prophecy.class)); cards.add(new SetCardInfo("Rashka the Slayer", 12, Rarity.RARE, mage.cards.r.RashkaTheSlayer.class)); cards.add(new SetCardInfo("Reef Pirates", "36a", Rarity.COMMON, ReefPirates.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Reef Pirates", "36b", Rarity.COMMON, ReefPirates.class, NON_FULL_USE_VARIOUS)); @@ -139,12 +146,16 @@ public final class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Root Spider", 94, Rarity.UNCOMMON, mage.cards.r.RootSpider.class)); 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("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)); cards.add(new SetCardInfo("Sengir Bats", "57a", Rarity.COMMON, SengirBats.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sengir Bats", "57b", Rarity.COMMON, SengirBats.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Serra Aviary", 14, Rarity.RARE, mage.cards.s.SerraAviary.class)); cards.add(new SetCardInfo("Serra Bestiary", 15, Rarity.UNCOMMON, mage.cards.s.SerraBestiary.class)); + cards.add(new SetCardInfo("Serra Inquisitors", 16, Rarity.UNCOMMON, mage.cards.s.SerraInquisitors.class)); cards.add(new SetCardInfo("Serra Paladin", 17, Rarity.COMMON, mage.cards.s.SerraPaladin.class)); cards.add(new SetCardInfo("Serrated Arrows", 110, Rarity.COMMON, mage.cards.s.SerratedArrows.class)); cards.add(new SetCardInfo("Shrink", "97a", Rarity.COMMON, mage.cards.s.Shrink.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index fc91128ae47..fc2e781f9c6 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -1,4 +1,3 @@ - package mage.sets; import mage.cards.ExpansionSet; @@ -191,6 +190,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Kjeldoran Skyknight", 40, Rarity.COMMON, mage.cards.k.KjeldoranSkyknight.class)); cards.add(new SetCardInfo("Kjeldoran Warrior", 41, Rarity.COMMON, mage.cards.k.KjeldoranWarrior.class)); cards.add(new SetCardInfo("Knight of Stromgald", 138, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class)); + cards.add(new SetCardInfo("Krovikan Elementalist", 139, Rarity.UNCOMMON, mage.cards.k.KrovikanElementalist.class)); cards.add(new SetCardInfo("Krovikan Fetish", 140, Rarity.COMMON, mage.cards.k.KrovikanFetish.class)); cards.add(new SetCardInfo("Krovikan Sorcerer", 81, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class)); cards.add(new SetCardInfo("Land Cap", 357, Rarity.RARE, mage.cards.l.LandCap.class)); diff --git a/Mage.Sets/src/mage/sets/Innistrad.java b/Mage.Sets/src/mage/sets/Innistrad.java index 62ea025a4ef..b32374439f6 100644 --- a/Mage.Sets/src/mage/sets/Innistrad.java +++ b/Mage.Sets/src/mage/sets/Innistrad.java @@ -309,7 +309,7 @@ public final class Innistrad extends ExpansionSet { cards.add(new SetCardInfo("Wooden Stake", 237, Rarity.COMMON, mage.cards.w.WoodenStake.class)); cards.add(new SetCardInfo("Woodland Cemetery", 249, Rarity.RARE, mage.cards.w.WoodlandCemetery.class)); cards.add(new SetCardInfo("Woodland Sleuth", 210, Rarity.COMMON, mage.cards.w.WoodlandSleuth.class)); - cards.add(new SetCardInfo("Wreath of Geists", 211, Rarity.UNCOMMON, mage.cards.w.WreathofGeists.class)); + cards.add(new SetCardInfo("Wreath of Geists", 211, Rarity.UNCOMMON, mage.cards.w.WreathOfGeists.class)); } } diff --git a/Mage.Sets/src/mage/sets/Invasion.java b/Mage.Sets/src/mage/sets/Invasion.java index 65a342d2e12..f5fb547f149 100644 --- a/Mage.Sets/src/mage/sets/Invasion.java +++ b/Mage.Sets/src/mage/sets/Invasion.java @@ -88,6 +88,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Darigaaz's Attendant", 301, Rarity.UNCOMMON, mage.cards.d.DarigaazsAttendant.class)); cards.add(new SetCardInfo("Darigaaz, the Igniter", 243, Rarity.RARE, mage.cards.d.DarigaazTheIgniter.class)); cards.add(new SetCardInfo("Defiling Tears", 99, Rarity.UNCOMMON, mage.cards.d.DefilingTears.class)); + cards.add(new SetCardInfo("Desperate Research", 100, Rarity.RARE, mage.cards.d.DesperateResearch.class)); cards.add(new SetCardInfo("Devouring Strossus", 101, Rarity.RARE, mage.cards.d.DevouringStrossus.class)); cards.add(new SetCardInfo("Dismantling Blow", 14, Rarity.COMMON, mage.cards.d.DismantlingBlow.class)); cards.add(new SetCardInfo("Disrupt", 51, Rarity.UNCOMMON, mage.cards.d.Disrupt.class)); @@ -105,6 +106,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Elfhame Sanctuary", 185, Rarity.UNCOMMON, mage.cards.e.ElfhameSanctuary.class)); cards.add(new SetCardInfo("Elvish Champion", 186, Rarity.RARE, mage.cards.e.ElvishChampion.class)); cards.add(new SetCardInfo("Empress Galina", 54, Rarity.RARE, mage.cards.e.EmpressGalina.class)); + cards.add(new SetCardInfo("Essence Leak", 55, Rarity.UNCOMMON, mage.cards.e.EssenceLeak.class)); cards.add(new SetCardInfo("Exclude", 56, Rarity.COMMON, mage.cards.e.Exclude.class)); cards.add(new SetCardInfo("Exotic Curse", 105, Rarity.COMMON, mage.cards.e.ExoticCurse.class)); cards.add(new SetCardInfo("Explosive Growth", 187, Rarity.COMMON, mage.cards.e.ExplosiveGrowth.class)); @@ -160,6 +162,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Llanowar Elite", 196, Rarity.COMMON, mage.cards.l.LlanowarElite.class)); cards.add(new SetCardInfo("Llanowar Knight", 254, Rarity.COMMON, mage.cards.l.LlanowarKnight.class)); cards.add(new SetCardInfo("Llanowar Vanguard", 197, Rarity.COMMON, mage.cards.l.LlanowarVanguard.class)); + cards.add(new SetCardInfo("Loafing Giant", 153, Rarity.RARE, mage.cards.l.LoafingGiant.class)); cards.add(new SetCardInfo("Lobotomy", 255, Rarity.UNCOMMON, mage.cards.l.Lobotomy.class)); cards.add(new SetCardInfo("Lotus Guardian", 305, Rarity.RARE, mage.cards.l.LotusGuardian.class)); cards.add(new SetCardInfo("Mana Maze", 59, Rarity.RARE, mage.cards.m.ManaMaze.class)); @@ -205,6 +208,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Planar Portal", 308, Rarity.RARE, mage.cards.p.PlanarPortal.class)); + cards.add(new SetCardInfo("Pledge of Loyalty", 24, Rarity.UNCOMMON, mage.cards.p.PledgeOfLoyalty.class)); cards.add(new SetCardInfo("Pouncing Kavu", 158, Rarity.COMMON, mage.cards.p.PouncingKavu.class)); cards.add(new SetCardInfo("Power Armor", 309, Rarity.UNCOMMON, mage.cards.p.PowerArmor.class)); cards.add(new SetCardInfo("Prison Barricade", 25, Rarity.COMMON, mage.cards.p.PrisonBarricade.class)); @@ -246,12 +250,14 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Salt Marsh", 326, Rarity.UNCOMMON, mage.cards.s.SaltMarsh.class)); cards.add(new SetCardInfo("Samite Archer", 269, Rarity.UNCOMMON, mage.cards.s.SamiteArcher.class)); cards.add(new SetCardInfo("Sapphire Leech", 71, Rarity.RARE, mage.cards.s.SapphireLeech.class)); + cards.add(new SetCardInfo("Saproling Infestation", 208, Rarity.RARE, mage.cards.s.SaprolingInfestation.class)); cards.add(new SetCardInfo("Saproling Symbiosis", 209, Rarity.RARE, mage.cards.s.SaprolingSymbiosis.class)); cards.add(new SetCardInfo("Savage Offensive", 162, Rarity.COMMON, mage.cards.s.SavageOffensive.class)); cards.add(new SetCardInfo("Scarred Puma", 163, Rarity.COMMON, mage.cards.s.ScarredPuma.class)); cards.add(new SetCardInfo("Scavenged Weaponry", 123, Rarity.COMMON, mage.cards.s.ScavengedWeaponry.class)); cards.add(new SetCardInfo("Scorching Lava", 164, Rarity.COMMON, mage.cards.s.ScorchingLava.class)); cards.add(new SetCardInfo("Scouting Trek", 210, Rarity.UNCOMMON, mage.cards.s.ScoutingTrek.class)); + cards.add(new SetCardInfo("Searing Rays", 165, Rarity.UNCOMMON, mage.cards.s.SearingRays.class)); cards.add(new SetCardInfo("Seashell Cameo", 311, Rarity.UNCOMMON, mage.cards.s.SeashellCameo.class)); cards.add(new SetCardInfo("Seer's Vision", 270, Rarity.UNCOMMON, mage.cards.s.SeersVision.class)); cards.add(new SetCardInfo("Serpentine Kavu", 211, Rarity.COMMON, mage.cards.s.SerpentineKavu.class)); diff --git a/Mage.Sets/src/mage/sets/JiangYangguMuYanling.java b/Mage.Sets/src/mage/sets/JiangYangguMuYanling.java index 327bfad93ff..1121e75f8c1 100644 --- a/Mage.Sets/src/mage/sets/JiangYangguMuYanling.java +++ b/Mage.Sets/src/mage/sets/JiangYangguMuYanling.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package mage.sets; import mage.cards.ExpansionSet; @@ -22,10 +17,48 @@ public final class JiangYangguMuYanling extends ExpansionSet { } private JiangYangguMuYanling() { - super("Global Series: Jiang Yanggu & Mu Yanling", "GS1", ExpansionSet.buildDate(2018, 6, 22), SetType.SUPPLEMENTAL); + super("Global Series: Jiang Yanggu & Mu Yanling", "GS1", ExpansionSet.buildDate(2018, 6, 22), SetType.SUPPLEMENTAL_STANDARD_LEGAL); this.blockName = "Global Series"; - this.hasBasicLands = false; + this.hasBasicLands = true; + cards.add(new SetCardInfo("Aggressive Instinct", 34, Rarity.COMMON, mage.cards.a.AggressiveInstinct.class)); + cards.add(new SetCardInfo("Ancestor Dragon", 12, Rarity.RARE, mage.cards.a.AncestorDragon.class)); + cards.add(new SetCardInfo("Armored Whirl Turtle", 7, Rarity.COMMON, mage.cards.a.ArmoredWhirlTurtle.class)); + cards.add(new SetCardInfo("Breath of Fire", 33, Rarity.COMMON, mage.cards.b.BreathOfFire.class)); + cards.add(new SetCardInfo("Brilliant Plan", 17, Rarity.UNCOMMON, mage.cards.b.BrilliantPlan.class)); + cards.add(new SetCardInfo("Cleansing Screech", 37, Rarity.COMMON, mage.cards.c.CleansingScreech.class)); + cards.add(new SetCardInfo("Cloak of Mists", 13, Rarity.COMMON, mage.cards.c.CloakOfMists.class)); + cards.add(new SetCardInfo("Colorful Feiyi Sparrow", 2, Rarity.COMMON, mage.cards.c.ColorfulFeiyiSparrow.class)); + cards.add(new SetCardInfo("Confidence from Strength", 35, Rarity.COMMON, mage.cards.c.ConfidenceFromStrength.class)); + cards.add(new SetCardInfo("Dragon's Presence", 16, Rarity.COMMON, mage.cards.d.DragonsPresence.class)); + cards.add(new SetCardInfo("Drown in Shapelessness", 15, Rarity.COMMON, mage.cards.d.DrownInShapelessness.class)); + cards.add(new SetCardInfo("Earth-Origin Yak", 9, Rarity.COMMON, mage.cards.e.EarthOriginYak.class)); + cards.add(new SetCardInfo("Earthshaking Si", 31, Rarity.COMMON, mage.cards.e.EarthshakingSi.class)); + cards.add(new SetCardInfo("Feiyi Snake", 24, Rarity.COMMON, mage.cards.f.FeiyiSnake.class)); + cards.add(new SetCardInfo("Ferocious Zheng", 28, Rarity.COMMON, mage.cards.f.FerociousZheng.class)); + cards.add(new SetCardInfo("Fire-Omen Crane", 29, Rarity.UNCOMMON, mage.cards.f.FireOmenCrane.class)); + cards.add(new SetCardInfo("Forest", 40, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Giant Spider", 27, Rarity.COMMON, mage.cards.g.GiantSpider.class)); + cards.add(new SetCardInfo("Hardened-Scale Armor", 32, Rarity.COMMON, mage.cards.h.HardenedScaleArmor.class)); + cards.add(new SetCardInfo("Heavenly Qilin", 6, Rarity.COMMON, mage.cards.h.HeavenlyQilin.class)); + cards.add(new SetCardInfo("Island", 21, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jiang Yanggu", 22, Rarity.MYTHIC, mage.cards.j.JiangYanggu.class)); + cards.add(new SetCardInfo("Journey for the Elixir", 36, Rarity.RARE, mage.cards.j.JourneyForTheElixir.class)); + cards.add(new SetCardInfo("Leopard-Spotted Jiao", 23, Rarity.COMMON, mage.cards.l.LeopardSpottedJiao.class)); + cards.add(new SetCardInfo("Meandering River", 19, Rarity.COMMON, mage.cards.m.MeanderingRiver.class)); + cards.add(new SetCardInfo("Moon-Eating Dog", 10, Rarity.UNCOMMON, mage.cards.m.MoonEatingDog.class)); + cards.add(new SetCardInfo("Mountain", 39, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mu Yanling", 1, Rarity.MYTHIC, mage.cards.m.MuYanling.class)); + cards.add(new SetCardInfo("Nine-Tail White Fox", 8, Rarity.COMMON, mage.cards.n.NineTailWhiteFox.class)); + cards.add(new SetCardInfo("Plains", 20, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Purple-Crystal Crab", 3, Rarity.COMMON, mage.cards.p.PurpleCrystalCrab.class)); + cards.add(new SetCardInfo("Qilin's Blessing", 14, Rarity.COMMON, mage.cards.q.QilinsBlessing.class)); + cards.add(new SetCardInfo("Reckless Pangolin", 26, Rarity.COMMON, mage.cards.r.RecklessPangolin.class)); + cards.add(new SetCardInfo("Rhythmic Water Vortex", 18, Rarity.RARE, mage.cards.r.RhythmicWaterVortex.class)); + cards.add(new SetCardInfo("Sacred White Deer", 25, Rarity.UNCOMMON, mage.cards.s.SacredWhiteDeer.class)); + cards.add(new SetCardInfo("Screeching Phoenix", 30, Rarity.RARE, mage.cards.s.ScreechingPhoenix.class)); + cards.add(new SetCardInfo("Stormcloud Spirit", 11, Rarity.UNCOMMON, mage.cards.s.StormcloudSpirit.class)); + cards.add(new SetCardInfo("Timber Gorge", 38, Rarity.COMMON, mage.cards.t.TimberGorge.class)); + cards.add(new SetCardInfo("Vivid Flying Fish", 4, Rarity.COMMON, mage.cards.v.VividFlyingFish.class)); + cards.add(new SetCardInfo("Welkin Tern", 5, Rarity.COMMON, mage.cards.w.WelkinTern.class)); } } diff --git a/Mage.Sets/src/mage/sets/Judgment.java b/Mage.Sets/src/mage/sets/Judgment.java index 30d2c7c1e4e..2acb1d73d71 100644 --- a/Mage.Sets/src/mage/sets/Judgment.java +++ b/Mage.Sets/src/mage/sets/Judgment.java @@ -37,6 +37,7 @@ public final class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Aven Fogbringer", 34, Rarity.COMMON, mage.cards.a.AvenFogbringer.class)); cards.add(new SetCardInfo("Aven Warcraft", 2, Rarity.UNCOMMON, mage.cards.a.AvenWarcraft.class)); cards.add(new SetCardInfo("Balthor the Defiled", 61, Rarity.RARE, mage.cards.b.BalthorTheDefiled.class)); + cards.add(new SetCardInfo("Barbarian Bully", 79, Rarity.COMMON, mage.cards.b.BarbarianBully.class)); cards.add(new SetCardInfo("Battle Screech", 3, Rarity.UNCOMMON, mage.cards.b.BattleScreech.class)); cards.add(new SetCardInfo("Battlefield Scrounger", 106, Rarity.COMMON, mage.cards.b.BattlefieldScrounger.class)); cards.add(new SetCardInfo("Battlewise Aven", 4, Rarity.COMMON, mage.cards.b.BattlewiseAven.class)); diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index 9bfe6843a20..987bc827ddd 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -1,4 +1,3 @@ - package mage.sets; import mage.cards.ExpansionSet; @@ -173,6 +172,7 @@ public final class Legends extends ExpansionSet { cards.add(new SetCardInfo("Lost Soul", 111, Rarity.COMMON, mage.cards.l.LostSoul.class)); cards.add(new SetCardInfo("Mana Drain", 65, Rarity.UNCOMMON, mage.cards.m.ManaDrain.class)); cards.add(new SetCardInfo("Mana Matrix", 285, Rarity.RARE, mage.cards.m.ManaMatrix.class)); + cards.add(new SetCardInfo("Marble Priest", 286, Rarity.UNCOMMON, mage.cards.m.MarblePriest.class)); cards.add(new SetCardInfo("Marhault Elsdragon", 244, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); cards.add(new SetCardInfo("Mirror Universe", 287, Rarity.RARE, mage.cards.m.MirrorUniverse.class)); cards.add(new SetCardInfo("Moat", 28, Rarity.RARE, mage.cards.m.Moat.class)); diff --git a/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java b/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java index 16384462e2a..3175d24d207 100644 --- a/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java +++ b/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java @@ -309,6 +309,7 @@ public final class LimitedEditionAlpha extends ExpansionSet { cards.add(new SetCardInfo("Will-o'-the-Wisp", 135, Rarity.RARE, mage.cards.w.WillOTheWisp.class)); cards.add(new SetCardInfo("Winter Orb", 275, Rarity.RARE, mage.cards.w.WinterOrb.class)); cards.add(new SetCardInfo("Wooden Sphere", 276, Rarity.UNCOMMON, mage.cards.w.WoodenSphere.class)); + cards.add(new SetCardInfo("Word of Command", 136, Rarity.RARE, mage.cards.w.WordOfCommand.class)); cards.add(new SetCardInfo("Wrath of God", 45, Rarity.RARE, mage.cards.w.WrathOfGod.class)); cards.add(new SetCardInfo("Zombie Master", 137, Rarity.RARE, mage.cards.z.ZombieMaster.class)); } diff --git a/Mage.Sets/src/mage/sets/LimitedEditionBeta.java b/Mage.Sets/src/mage/sets/LimitedEditionBeta.java index 4046a234975..a67c9d45eeb 100644 --- a/Mage.Sets/src/mage/sets/LimitedEditionBeta.java +++ b/Mage.Sets/src/mage/sets/LimitedEditionBeta.java @@ -316,6 +316,7 @@ public final class LimitedEditionBeta extends ExpansionSet { cards.add(new SetCardInfo("Will-o'-the-Wisp", 136, Rarity.RARE, mage.cards.w.WillOTheWisp.class)); cards.add(new SetCardInfo("Winter Orb", 276, Rarity.RARE, mage.cards.w.WinterOrb.class)); cards.add(new SetCardInfo("Wooden Sphere", 277, Rarity.UNCOMMON, mage.cards.w.WoodenSphere.class)); + cards.add(new SetCardInfo("Word of Command", 137, Rarity.RARE, mage.cards.w.WordOfCommand.class)); cards.add(new SetCardInfo("Wrath of God", 46, Rarity.RARE, mage.cards.w.WrathOfGod.class)); cards.add(new SetCardInfo("Zombie Master", 138, Rarity.RARE, mage.cards.z.ZombieMaster.class)); } diff --git a/Mage.Sets/src/mage/sets/MasterpieceSeries.java b/Mage.Sets/src/mage/sets/MasterpieceSeries.java index 94987ed7006..a338aff7875 100644 --- a/Mage.Sets/src/mage/sets/MasterpieceSeries.java +++ b/Mage.Sets/src/mage/sets/MasterpieceSeries.java @@ -34,7 +34,7 @@ public final class MasterpieceSeries extends ExpansionSet { cards.add(new SetCardInfo("Chromatic Lantern", 8, Rarity.MYTHIC, mage.cards.c.ChromaticLantern.class, cardGraphicInfo)); cards.add(new SetCardInfo("Chrome Mox", 9, Rarity.MYTHIC, mage.cards.c.ChromeMox.class, cardGraphicInfo)); cards.add(new SetCardInfo("Cloudstone Curio", 10, Rarity.MYTHIC, mage.cards.c.CloudstoneCurio.class, cardGraphicInfo)); - cards.add(new SetCardInfo("Combustible Gearhulk", 2, Rarity.MYTHIC, mage.cards.c.CombustibleGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Combustible Gearhulk", 4, Rarity.MYTHIC, mage.cards.c.CombustibleGearhulk.class, cardGraphicInfo)); cards.add(new SetCardInfo("Crucible of Worlds", 11, Rarity.MYTHIC, mage.cards.c.CrucibleOfWorlds.class, cardGraphicInfo)); cards.add(new SetCardInfo("Defense Grid", 34, Rarity.MYTHIC, mage.cards.d.DefenseGrid.class, cardGraphicInfo)); cards.add(new SetCardInfo("Duplicant", 35, Rarity.MYTHIC, mage.cards.d.Duplicant.class, cardGraphicInfo)); @@ -62,8 +62,8 @@ public final class MasterpieceSeries extends ExpansionSet { cards.add(new SetCardInfo("Rings of Brighthearth", 21, Rarity.MYTHIC, mage.cards.r.RingsOfBrighthearth.class, cardGraphicInfo)); cards.add(new SetCardInfo("Scroll Rack", 22, Rarity.MYTHIC, mage.cards.s.ScrollRack.class, cardGraphicInfo)); cards.add(new SetCardInfo("Sculpting Steel", 23, Rarity.MYTHIC, mage.cards.s.SculptingSteel.class, cardGraphicInfo)); - cards.add(new SetCardInfo("Solemn Simulacrum", 25, Rarity.MYTHIC, mage.cards.s.SolemnSimulacrum.class, cardGraphicInfo)); cards.add(new SetCardInfo("Sol Ring", 24, Rarity.MYTHIC, mage.cards.s.SolRing.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Solemn Simulacrum", 25, Rarity.MYTHIC, mage.cards.s.SolemnSimulacrum.class, cardGraphicInfo)); cards.add(new SetCardInfo("Sphere of Resistance", 47, Rarity.MYTHIC, mage.cards.s.SphereOfResistance.class, cardGraphicInfo)); cards.add(new SetCardInfo("Staff of Domination", 48, Rarity.MYTHIC, mage.cards.s.StaffOfDomination.class, cardGraphicInfo)); cards.add(new SetCardInfo("Static Orb", 26, Rarity.MYTHIC, mage.cards.s.StaticOrb.class, cardGraphicInfo)); @@ -74,7 +74,7 @@ public final class MasterpieceSeries extends ExpansionSet { cards.add(new SetCardInfo("Sword of Fire and Ice", 29, Rarity.MYTHIC, mage.cards.s.SwordOfFireAndIce.class, cardGraphicInfo)); cards.add(new SetCardInfo("Sword of Light and Shadow", 30, Rarity.MYTHIC, mage.cards.s.SwordOfLightAndShadow.class, cardGraphicInfo)); cards.add(new SetCardInfo("Sword of War and Peace", 51, Rarity.MYTHIC, mage.cards.s.SwordOfWarAndPeace.class, cardGraphicInfo)); - cards.add(new SetCardInfo("Torrential Gearhulk", 4, Rarity.MYTHIC, mage.cards.t.TorrentialGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Torrential Gearhulk", 2, Rarity.MYTHIC, mage.cards.t.TorrentialGearhulk.class, cardGraphicInfo)); cards.add(new SetCardInfo("Trinisphere", 52, Rarity.MYTHIC, mage.cards.t.Trinisphere.class, cardGraphicInfo)); cards.add(new SetCardInfo("Vedalken Shackles", 53, Rarity.MYTHIC, mage.cards.v.VedalkenShackles.class, cardGraphicInfo)); cards.add(new SetCardInfo("Verdurous Gearhulk", 5, Rarity.MYTHIC, mage.cards.v.VerdurousGearhulk.class, cardGraphicInfo)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index d466ec8914b..c3f9f8ffbf1 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -141,9 +141,11 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Infernal Darkness", 97, Rarity.RARE, mage.cards.i.InfernalDarkness.class)); cards.add(new SetCardInfo("Inheritance", 18, Rarity.UNCOMMON, mage.cards.i.Inheritance.class)); cards.add(new SetCardInfo("Ironclaw Orcs", 132, Rarity.COMMON, mage.cards.i.IronclawOrcs.class)); + cards.add(new SetCardInfo("Ivory Gargoyle", 19, Rarity.RARE, mage.cards.i.IvoryGargoyle.class)); cards.add(new SetCardInfo("Jester's Mask", 211, Rarity.RARE, mage.cards.j.JestersMask.class)); cards.add(new SetCardInfo("Jeweled Amulet", 212, Rarity.UNCOMMON, mage.cards.j.JeweledAmulet.class)); cards.add(new SetCardInfo("Johtull Wurm", 168, Rarity.UNCOMMON, mage.cards.j.JohtullWurm.class)); + cards.add(new SetCardInfo("Joven's Ferrets", 169, Rarity.UNCOMMON, mage.cards.j.JovensFerrets.class)); cards.add(new SetCardInfo("Juniper Order Advocate", 20, Rarity.UNCOMMON, mage.cards.j.JuniperOrderAdvocate.class)); cards.add(new SetCardInfo("Karplusan Giant", 133, Rarity.UNCOMMON, mage.cards.k.KarplusanGiant.class)); cards.add(new SetCardInfo("Kaysa", 170, Rarity.RARE, mage.cards.k.Kaysa.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionIV.java b/Mage.Sets/src/mage/sets/MastersEditionIV.java index 4ba79ba3ed6..8658d66d9b5 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionIV.java +++ b/Mage.Sets/src/mage/sets/MastersEditionIV.java @@ -158,7 +158,7 @@ public final class MastersEditionIV extends ExpansionSet { cards.add(new SetCardInfo("Island Sanctuary", 15, Rarity.RARE, mage.cards.i.IslandSanctuary.class)); cards.add(new SetCardInfo("Jade Monolith", 208, Rarity.RARE, mage.cards.j.JadeMonolith.class)); cards.add(new SetCardInfo("Juggernaut", 209, Rarity.UNCOMMON, mage.cards.j.Juggernaut.class)); - cards.add(new SetCardInfo("Junún Efreet", 88, Rarity.UNCOMMON, mage.cards.j.JununEfreet.class)); + cards.add(new SetCardInfo("Junun Efreet", 88, Rarity.UNCOMMON, mage.cards.j.JununEfreet.class)); cards.add(new SetCardInfo("Just Fate", 16, Rarity.COMMON, mage.cards.j.JustFate.class)); cards.add(new SetCardInfo("Kismet", 17, Rarity.RARE, mage.cards.k.Kismet.class)); cards.add(new SetCardInfo("Kormus Bell", 210, Rarity.RARE, mage.cards.k.KormusBell.class)); @@ -298,6 +298,7 @@ public final class MastersEditionIV extends ExpansionSet { cards.add(new SetCardInfo("Wild Griffin", 35, Rarity.COMMON, mage.cards.w.WildGriffin.class)); cards.add(new SetCardInfo("Wild Ox", 174, Rarity.UNCOMMON, mage.cards.w.WildOx.class)); cards.add(new SetCardInfo("Wood Elemental", 175, Rarity.RARE, mage.cards.w.WoodElemental.class)); + cards.add(new SetCardInfo("Word of Command", 103, Rarity.RARE, mage.cards.w.WordOfCommand.class)); cards.add(new SetCardInfo("Xenic Poltergeist", 104, Rarity.UNCOMMON, mage.cards.x.XenicPoltergeist.class)); cards.add(new SetCardInfo("Yotian Soldier", 240, Rarity.COMMON, mage.cards.y.YotianSoldier.class)); cards.add(new SetCardInfo("Zombie Master", 105, Rarity.UNCOMMON, mage.cards.z.ZombieMaster.class)); diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index a4d10d4350f..73f52e99038 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -33,6 +33,7 @@ public final class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Armistice", 3, Rarity.RARE, mage.cards.a.Armistice.class)); cards.add(new SetCardInfo("Arms Dealer", 172, Rarity.UNCOMMON, mage.cards.a.ArmsDealer.class)); cards.add(new SetCardInfo("Arrest", 4, Rarity.UNCOMMON, mage.cards.a.Arrest.class)); + cards.add(new SetCardInfo("Assembly Hall", 286, Rarity.RARE, mage.cards.a.AssemblyHall.class)); cards.add(new SetCardInfo("Ballista Squad", 5, Rarity.UNCOMMON, mage.cards.b.BallistaSquad.class)); cards.add(new SetCardInfo("Balloon Peddler", 59, Rarity.COMMON, mage.cards.b.BalloonPeddler.class)); cards.add(new SetCardInfo("Battle Rampart", 173, Rarity.COMMON, mage.cards.b.BattleRampart.class)); @@ -118,8 +119,10 @@ public final class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Energy Flux", 78, Rarity.UNCOMMON, mage.cards.e.EnergyFlux.class)); cards.add(new SetCardInfo("Enslaved Horror", 134, Rarity.UNCOMMON, mage.cards.e.EnslavedHorror.class)); cards.add(new SetCardInfo("Extortion", 135, Rarity.RARE, mage.cards.e.Extortion.class)); + cards.add(new SetCardInfo("Extravagant Spirit", 79, Rarity.RARE, mage.cards.e.ExtravagantSpirit.class)); cards.add(new SetCardInfo("Eye of Ramos", 294, Rarity.RARE, mage.cards.e.EyeOfRamos.class)); cards.add(new SetCardInfo("False Demise", 80, Rarity.UNCOMMON, mage.cards.f.FalseDemise.class)); + cards.add(new SetCardInfo("Ferocity", 245, Rarity.COMMON, mage.cards.f.Ferocity.class)); cards.add(new SetCardInfo("Flailing Manticore", 187, Rarity.RARE, mage.cards.f.FlailingManticore.class)); cards.add(new SetCardInfo("Flailing Ogre", 188, Rarity.UNCOMMON, mage.cards.f.FlailingOgre.class)); cards.add(new SetCardInfo("Flailing Soldier", 189, Rarity.COMMON, mage.cards.f.FlailingSoldier.class)); diff --git a/Mage.Sets/src/mage/sets/Mirage.java b/Mage.Sets/src/mage/sets/Mirage.java index e001805c06b..845414da3a6 100644 --- a/Mage.Sets/src/mage/sets/Mirage.java +++ b/Mage.Sets/src/mage/sets/Mirage.java @@ -1,6 +1,7 @@ package mage.sets; import mage.cards.ExpansionSet; +import mage.cards.d.Delirium; import mage.constants.Rarity; import mage.constants.SetType; @@ -44,6 +45,7 @@ public final class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Barbed Foliage", 207, Rarity.UNCOMMON, mage.cards.b.BarbedFoliage.class)); cards.add(new SetCardInfo("Barbed-Back Wurm", 105, Rarity.UNCOMMON, mage.cards.b.BarbedBackWurm.class)); cards.add(new SetCardInfo("Bay Falcon", 54, Rarity.COMMON, mage.cards.b.BayFalcon.class)); + cards.add(new SetCardInfo("Bazaar of Wonders", 55, Rarity.RARE, mage.cards.b.BazaarOfWonders.class)); cards.add(new SetCardInfo("Benthic Djinn", 257, Rarity.RARE, mage.cards.b.BenthicDjinn.class)); cards.add(new SetCardInfo("Binding Agony", 106, Rarity.COMMON, mage.cards.b.BindingAgony.class)); cards.add(new SetCardInfo("Blighted Shaman", 107, Rarity.UNCOMMON, mage.cards.b.BlightedShaman.class)); @@ -65,6 +67,7 @@ public final class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Chaos Charm", 163, Rarity.COMMON, mage.cards.c.ChaosCharm.class)); cards.add(new SetCardInfo("Chaosphere", 164, Rarity.RARE, mage.cards.c.Chaosphere.class)); cards.add(new SetCardInfo("Charcoal Diamond", 296, Rarity.UNCOMMON, mage.cards.c.CharcoalDiamond.class)); + cards.add(new SetCardInfo("Chariot of the Sun", 262, Rarity.UNCOMMON, mage.cards.c.ChariotOfTheSun.class)); cards.add(new SetCardInfo("Choking Sands", 113, Rarity.COMMON, mage.cards.c.ChokingSands.class)); cards.add(new SetCardInfo("Cinder Cloud", 165, Rarity.UNCOMMON, mage.cards.c.CinderCloud.class)); cards.add(new SetCardInfo("Civic Guildmage", 7, Rarity.COMMON, mage.cards.c.CivicGuildmage.class)); @@ -81,6 +84,7 @@ public final class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Dark Banishing", 115, Rarity.COMMON, mage.cards.d.DarkBanishing.class)); cards.add(new SetCardInfo("Dark Ritual", 116, Rarity.COMMON, mage.cards.d.DarkRitual.class)); cards.add(new SetCardInfo("Dazzling Beauty", 8, Rarity.COMMON, mage.cards.d.DazzlingBeauty.class)); + cards.add(new SetCardInfo("Delirium", 260, Rarity.UNCOMMON, Delirium.class)); cards.add(new SetCardInfo("Dirtwater Wraith", 117, Rarity.COMMON, mage.cards.d.DirtwaterWraith.class)); cards.add(new SetCardInfo("Disempower", 9, Rarity.COMMON, mage.cards.d.Disempower.class)); cards.add(new SetCardInfo("Disenchant", 10, Rarity.COMMON, mage.cards.d.Disenchant.class)); @@ -137,6 +141,7 @@ public final class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Grasslands", 327, Rarity.UNCOMMON, mage.cards.g.Grasslands.class)); cards.add(new SetCardInfo("Grave Servitude", 126, Rarity.COMMON, mage.cards.g.GraveServitude.class)); cards.add(new SetCardInfo("Gravebane Zombie", 127, Rarity.COMMON, mage.cards.g.GravebaneZombie.class)); + cards.add(new SetCardInfo("Grim Feast", 265, Rarity.RARE, mage.cards.g.GrimFeast.class)); cards.add(new SetCardInfo("Grinning Totem", 303, Rarity.RARE, mage.cards.g.GrinningTotem.class)); cards.add(new SetCardInfo("Hakim, Loreweaver", 68, Rarity.RARE, mage.cards.h.HakimLoreweaver.class)); cards.add(new SetCardInfo("Hall of Gemstone", 221, Rarity.RARE, mage.cards.h.HallOfGemstone.class)); @@ -175,6 +180,7 @@ public final class Mirage extends ExpansionSet { cards.add(new SetCardInfo("Lightning Reflexes", 186, Rarity.COMMON, mage.cards.l.LightningReflexes.class)); cards.add(new SetCardInfo("Lion's Eye Diamond", 307, Rarity.RARE, mage.cards.l.LionsEyeDiamond.class)); cards.add(new SetCardInfo("Locust Swarm", 226, Rarity.UNCOMMON, mage.cards.l.LocustSwarm.class)); + cards.add(new SetCardInfo("Lure of Prey", 227, Rarity.RARE, mage.cards.l.LureOfPrey.class)); cards.add(new SetCardInfo("Mana Prism", 308, Rarity.UNCOMMON, mage.cards.m.ManaPrism.class)); cards.add(new SetCardInfo("Mangara's Tome", 309, Rarity.RARE, mage.cards.m.MangarasTome.class)); cards.add(new SetCardInfo("Marble Diamond", 310, Rarity.UNCOMMON, mage.cards.m.MarbleDiamond.class)); diff --git a/Mage.Sets/src/mage/sets/Mirrodin.java b/Mage.Sets/src/mage/sets/Mirrodin.java index a494c80176f..27b48ee4f84 100644 --- a/Mage.Sets/src/mage/sets/Mirrodin.java +++ b/Mage.Sets/src/mage/sets/Mirrodin.java @@ -169,6 +169,7 @@ public final class Mirrodin extends ExpansionSet { cards.add(new SetCardInfo("Mind's Eye", 205, Rarity.RARE, mage.cards.m.MindsEye.class)); cards.add(new SetCardInfo("Mindslaver", 206, Rarity.RARE, mage.cards.m.Mindslaver.class)); cards.add(new SetCardInfo("Mindstorm Crown", 207, Rarity.UNCOMMON, mage.cards.m.MindstormCrown.class)); + cards.add(new SetCardInfo("Mirror Golem", 208, Rarity.UNCOMMON, mage.cards.m.MirrorGolem.class)); cards.add(new SetCardInfo("Molder Slug", 125, Rarity.RARE, mage.cards.m.MolderSlug.class)); cards.add(new SetCardInfo("Molten Rain", 101, Rarity.COMMON, mage.cards.m.MoltenRain.class)); cards.add(new SetCardInfo("Moriok Scavenger", 68, Rarity.COMMON, mage.cards.m.MoriokScavenger.class)); @@ -176,6 +177,7 @@ public final class Mirrodin extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 300, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 301, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 302, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mourner's Shield", 209, Rarity.UNCOMMON, mage.cards.m.MournersShield.class)); cards.add(new SetCardInfo("Myr Adapter", 210, Rarity.COMMON, mage.cards.m.MyrAdapter.class)); cards.add(new SetCardInfo("Myr Enforcer", 211, Rarity.COMMON, mage.cards.m.MyrEnforcer.class)); cards.add(new SetCardInfo("Myr Incubator", 212, Rarity.RARE, mage.cards.m.MyrIncubator.class)); diff --git a/Mage.Sets/src/mage/sets/MirrodinBesieged.java b/Mage.Sets/src/mage/sets/MirrodinBesieged.java index cd5df52cafb..31c5cc90a67 100644 --- a/Mage.Sets/src/mage/sets/MirrodinBesieged.java +++ b/Mage.Sets/src/mage/sets/MirrodinBesieged.java @@ -38,7 +38,7 @@ public final class MirrodinBesieged extends ExpansionSet { cards.add(new SetCardInfo("Blue Sun's Zenith", 20, Rarity.RARE, mage.cards.b.BlueSunsZenith.class)); cards.add(new SetCardInfo("Bonehoard", 100, Rarity.RARE, mage.cards.b.Bonehoard.class)); cards.add(new SetCardInfo("Brass Squire", 101, Rarity.UNCOMMON, mage.cards.b.BrassSquire.class)); - cards.add(new SetCardInfo("Burn the Impure", 59, Rarity.COMMON, mage.cards.b.BurntheImpure.class)); + cards.add(new SetCardInfo("Burn the Impure", 59, Rarity.COMMON, mage.cards.b.BurnTheImpure.class)); cards.add(new SetCardInfo("Caustic Hound", 40, Rarity.COMMON, mage.cards.c.CausticHound.class)); cards.add(new SetCardInfo("Choking Fumes", 4, Rarity.UNCOMMON, mage.cards.c.ChokingFumes.class)); cards.add(new SetCardInfo("Concussive Bolt", 60, Rarity.COMMON, mage.cards.c.ConcussiveBolt.class)); diff --git a/Mage.Sets/src/mage/sets/NinthEdition.java b/Mage.Sets/src/mage/sets/NinthEdition.java index eac43b9eba0..2996fb9c077 100644 --- a/Mage.Sets/src/mage/sets/NinthEdition.java +++ b/Mage.Sets/src/mage/sets/NinthEdition.java @@ -57,6 +57,7 @@ public final class NinthEdition extends ExpansionSet { cards.add(new SetCardInfo("Bog Imp", 116, Rarity.COMMON, mage.cards.b.BogImp.class)); cards.add(new SetCardInfo("Bog Wraith", 117, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); cards.add(new SetCardInfo("Boiling Seas", 178, Rarity.UNCOMMON, mage.cards.b.BoilingSeas.class)); + cards.add(new SetCardInfo("Booby Trap", 289, Rarity.RARE, mage.cards.b.BoobyTrap.class)); cards.add(new SetCardInfo("Boomerang", 66, Rarity.COMMON, mage.cards.b.Boomerang.class)); cards.add(new SetCardInfo("Bottle Gnomes", 290, Rarity.UNCOMMON, mage.cards.b.BottleGnomes.class)); cards.add(new SetCardInfo("Brushland", 319, Rarity.RARE, mage.cards.b.Brushland.class)); diff --git a/Mage.Sets/src/mage/sets/NissaVsObNixilis.java b/Mage.Sets/src/mage/sets/NissaVsObNixilis.java index a28a95ef015..9a814fd36de 100644 --- a/Mage.Sets/src/mage/sets/NissaVsObNixilis.java +++ b/Mage.Sets/src/mage/sets/NissaVsObNixilis.java @@ -1,4 +1,3 @@ - package mage.sets; import mage.cards.ExpansionSet; @@ -39,7 +38,7 @@ public final class NissaVsObNixilis extends ExpansionSet { cards.add(new SetCardInfo("Despoiler of Souls", 45, Rarity.RARE, mage.cards.d.DespoilerOfSouls.class)); cards.add(new SetCardInfo("Disfigure", 46, Rarity.COMMON, mage.cards.d.Disfigure.class)); cards.add(new SetCardInfo("Doom Blade", 47, Rarity.COMMON, mage.cards.d.DoomBlade.class)); - cards.add(new SetCardInfo("Elvish Visionary", 8, Rarity.UNCOMMON, mage.cards.e.ElvishVisionary.class)); + cards.add(new SetCardInfo("Elvish Visionary", 8, Rarity.COMMON, mage.cards.e.ElvishVisionary.class)); cards.add(new SetCardInfo("Fertile Thicket", 27, Rarity.COMMON, mage.cards.f.FertileThicket.class)); cards.add(new SetCardInfo("Fertilid", 9, Rarity.COMMON, mage.cards.f.Fertilid.class)); cards.add(new SetCardInfo("Fetid Imp", 48, Rarity.COMMON, mage.cards.f.FetidImp.class)); diff --git a/Mage.Sets/src/mage/sets/Onslaught.java b/Mage.Sets/src/mage/sets/Onslaught.java index 0fe924fb02d..4f6bfaebab0 100644 --- a/Mage.Sets/src/mage/sets/Onslaught.java +++ b/Mage.Sets/src/mage/sets/Onslaught.java @@ -79,6 +79,7 @@ public final class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("Charging Slateback", 194, Rarity.COMMON, mage.cards.c.ChargingSlateback.class)); cards.add(new SetCardInfo("Choking Tethers", 74, Rarity.COMMON, mage.cards.c.ChokingTethers.class)); cards.add(new SetCardInfo("Clone", 75, Rarity.RARE, mage.cards.c.Clone.class)); + cards.add(new SetCardInfo("Commando Raid", 195, Rarity.UNCOMMON, mage.cards.c.CommandoRaid.class)); cards.add(new SetCardInfo("Complicate", 76, Rarity.UNCOMMON, mage.cards.c.Complicate.class)); cards.add(new SetCardInfo("Contested Cliffs", 314, Rarity.RARE, mage.cards.c.ContestedCliffs.class)); cards.add(new SetCardInfo("Convalescent Care", 14, Rarity.RARE, mage.cards.c.ConvalescentCare.class)); diff --git a/Mage.Sets/src/mage/sets/PlanarChaos.java b/Mage.Sets/src/mage/sets/PlanarChaos.java index dc3ca252a1b..6856533d5cf 100644 --- a/Mage.Sets/src/mage/sets/PlanarChaos.java +++ b/Mage.Sets/src/mage/sets/PlanarChaos.java @@ -61,6 +61,7 @@ public final class PlanarChaos extends ExpansionSet { cards.add(new SetCardInfo("Deadly Grub", 69, Rarity.COMMON, mage.cards.d.DeadlyGrub.class)); cards.add(new SetCardInfo("Deadwood Treefolk", 126, Rarity.UNCOMMON, mage.cards.d.DeadwoodTreefolk.class)); cards.add(new SetCardInfo("Detritivore", 96, Rarity.RARE, mage.cards.d.Detritivore.class)); + cards.add(new SetCardInfo("Dichotomancy", 38, Rarity.RARE, mage.cards.d.Dichotomancy.class)); cards.add(new SetCardInfo("Dismal Failure", 39, Rarity.UNCOMMON, mage.cards.d.DismalFailure.class)); cards.add(new SetCardInfo("Dormant Sliver", 156, Rarity.UNCOMMON, mage.cards.d.DormantSliver.class)); cards.add(new SetCardInfo("Dreamscape Artist", 40, Rarity.COMMON, mage.cards.d.DreamscapeArtist.class)); @@ -114,6 +115,7 @@ public final class PlanarChaos extends ExpansionSet { cards.add(new SetCardInfo("Midnight Charm", 74, Rarity.COMMON, mage.cards.m.MidnightCharm.class)); cards.add(new SetCardInfo("Mire Boa", 135, Rarity.COMMON, mage.cards.m.MireBoa.class)); cards.add(new SetCardInfo("Mirri the Cursed", 75, Rarity.RARE, mage.cards.m.MirriTheCursed.class)); + cards.add(new SetCardInfo("Molten Firebird", 117, Rarity.RARE, mage.cards.m.MoltenFirebird.class)); cards.add(new SetCardInfo("Muck Drubb", 76, Rarity.UNCOMMON, mage.cards.m.MuckDrubb.class)); cards.add(new SetCardInfo("Mycologist", 27, Rarity.UNCOMMON, mage.cards.m.Mycologist.class)); cards.add(new SetCardInfo("Necrotic Sliver", 159, Rarity.UNCOMMON, mage.cards.n.NecroticSliver.class)); diff --git a/Mage.Sets/src/mage/sets/Portal.java b/Mage.Sets/src/mage/sets/Portal.java index 81b744f91e3..81162ed77cf 100644 --- a/Mage.Sets/src/mage/sets/Portal.java +++ b/Mage.Sets/src/mage/sets/Portal.java @@ -34,226 +34,226 @@ public final class Portal extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Alabaster Dragon", 163, Rarity.RARE, mage.cards.a.AlabasterDragon.class)); - cards.add(new SetCardInfo("Alluring Scent", 80, Rarity.RARE, mage.cards.a.AlluringScent.class)); - cards.add(new SetCardInfo("Anaconda", 81, Rarity.UNCOMMON, mage.cards.a.Anaconda.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Anaconda", 82, Rarity.UNCOMMON, mage.cards.a.Anaconda.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ancestral Memories", 41, Rarity.RARE, mage.cards.a.AncestralMemories.class)); - cards.add(new SetCardInfo("Angelic Blessing", 164, Rarity.COMMON, mage.cards.a.AngelicBlessing.class)); - cards.add(new SetCardInfo("Archangel", 165, Rarity.RARE, mage.cards.a.Archangel.class)); - cards.add(new SetCardInfo("Ardent Militia", 166, Rarity.UNCOMMON, mage.cards.a.ArdentMilitia.class)); - cards.add(new SetCardInfo("Armageddon", 167, Rarity.RARE, mage.cards.a.Armageddon.class)); - cards.add(new SetCardInfo("Armored Pegasus", 168, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class)); - cards.add(new SetCardInfo("Arrogant Vampire", 1, Rarity.UNCOMMON, mage.cards.a.ArrogantVampire.class)); - cards.add(new SetCardInfo("Assassin's Blade", 2, Rarity.UNCOMMON, mage.cards.a.AssassinsBlade.class)); - cards.add(new SetCardInfo("Balance of Power", 42, Rarity.RARE, mage.cards.b.BalanceOfPower.class)); - cards.add(new SetCardInfo("Baleful Stare", 43, Rarity.UNCOMMON, mage.cards.b.BalefulStare.class)); - cards.add(new SetCardInfo("Bee Sting", 83, Rarity.UNCOMMON, mage.cards.b.BeeSting.class)); - cards.add(new SetCardInfo("Blaze", 122, Rarity.UNCOMMON, mage.cards.b.Blaze.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Blaze", 123, Rarity.UNCOMMON, mage.cards.b.Blaze.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Blessed Reversal", 169, Rarity.RARE, mage.cards.b.BlessedReversal.class)); - cards.add(new SetCardInfo("Blinding Light", 170, Rarity.RARE, mage.cards.b.BlindingLight.class)); - cards.add(new SetCardInfo("Bog Imp", 3, Rarity.COMMON, mage.cards.b.BogImp.class)); - cards.add(new SetCardInfo("Bog Raiders", 4, Rarity.COMMON, mage.cards.b.BogRaiders.class)); - cards.add(new SetCardInfo("Bog Wraith", 5, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); - cards.add(new SetCardInfo("Boiling Seas", 124, Rarity.UNCOMMON, mage.cards.b.BoilingSeas.class)); - cards.add(new SetCardInfo("Border Guard", 171, Rarity.COMMON, mage.cards.b.BorderGuard.class)); - cards.add(new SetCardInfo("Breath of Life", 172, Rarity.COMMON, mage.cards.b.BreathOfLife.class)); - cards.add(new SetCardInfo("Bull Hippo", 84, Rarity.UNCOMMON, mage.cards.b.BullHippo.class)); - cards.add(new SetCardInfo("Burning Cloak", 125, Rarity.COMMON, mage.cards.b.BurningCloak.class)); - cards.add(new SetCardInfo("Capricious Sorcerer", 44, Rarity.RARE, mage.cards.c.CapriciousSorcerer.class)); - cards.add(new SetCardInfo("Charging Bandits", 6, Rarity.UNCOMMON, mage.cards.c.ChargingBandits.class)); - cards.add(new SetCardInfo("Charging Paladin", 173, Rarity.UNCOMMON, mage.cards.c.ChargingPaladin.class)); - cards.add(new SetCardInfo("Charging Rhino", 85, Rarity.RARE, mage.cards.c.ChargingRhino.class)); - cards.add(new SetCardInfo("Cloak of Feathers", 45, Rarity.COMMON, mage.cards.c.CloakOfFeathers.class)); - cards.add(new SetCardInfo("Cloud Dragon", 46, Rarity.RARE, mage.cards.c.CloudDragon.class)); - cards.add(new SetCardInfo("Cloud Pirates", 47, Rarity.COMMON, mage.cards.c.CloudPirates.class)); - cards.add(new SetCardInfo("Cloud Spirit", 48, Rarity.UNCOMMON, mage.cards.c.CloudSpirit.class)); - cards.add(new SetCardInfo("Command of Unsummoning", 49, Rarity.UNCOMMON, mage.cards.c.CommandOfUnsummoning.class)); - cards.add(new SetCardInfo("Coral Eel", 50, Rarity.COMMON, mage.cards.c.CoralEel.class)); - cards.add(new SetCardInfo("Craven Giant", 126, Rarity.COMMON, mage.cards.c.CravenGiant.class)); - cards.add(new SetCardInfo("Craven Knight", 7, Rarity.COMMON, mage.cards.c.CravenKnight.class)); - cards.add(new SetCardInfo("Cruel Bargain", 8, Rarity.RARE, mage.cards.c.CruelBargain.class)); - cards.add(new SetCardInfo("Cruel Fate", 51, Rarity.RARE, mage.cards.c.CruelFate.class)); - cards.add(new SetCardInfo("Cruel Tutor", 9, Rarity.RARE, mage.cards.c.CruelTutor.class)); - cards.add(new SetCardInfo("Deep-Sea Serpent", 52, Rarity.UNCOMMON, mage.cards.d.DeepSeaSerpent.class)); - cards.add(new SetCardInfo("Deep Wood", 86, Rarity.UNCOMMON, mage.cards.d.DeepWood.class)); - cards.add(new SetCardInfo("Defiant Stand", 174, Rarity.UNCOMMON, mage.cards.d.DefiantStand.class)); + cards.add(new SetCardInfo("Alabaster Dragon", 1, Rarity.RARE, mage.cards.a.AlabasterDragon.class)); + cards.add(new SetCardInfo("Alluring Scent", 157, Rarity.RARE, mage.cards.a.AlluringScent.class)); + cards.add(new SetCardInfo("Anaconda", "158a", Rarity.UNCOMMON, mage.cards.a.Anaconda.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Anaconda", "158b", Rarity.UNCOMMON, mage.cards.a.Anaconda.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ancestral Memories", 40, Rarity.RARE, mage.cards.a.AncestralMemories.class)); + cards.add(new SetCardInfo("Angelic Blessing", 2, Rarity.COMMON, mage.cards.a.AngelicBlessing.class)); + cards.add(new SetCardInfo("Archangel", 3, Rarity.RARE, mage.cards.a.Archangel.class)); + cards.add(new SetCardInfo("Ardent Militia", 4, Rarity.UNCOMMON, mage.cards.a.ArdentMilitia.class)); + cards.add(new SetCardInfo("Armageddon", 5, Rarity.RARE, mage.cards.a.Armageddon.class)); + cards.add(new SetCardInfo("Armored Pegasus", 6, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class)); + cards.add(new SetCardInfo("Arrogant Vampire", 79, Rarity.UNCOMMON, mage.cards.a.ArrogantVampire.class)); + cards.add(new SetCardInfo("Assassin's Blade", 80, Rarity.UNCOMMON, mage.cards.a.AssassinsBlade.class)); + cards.add(new SetCardInfo("Balance of Power", 41, Rarity.RARE, mage.cards.b.BalanceOfPower.class)); + cards.add(new SetCardInfo("Baleful Stare", 42, Rarity.UNCOMMON, mage.cards.b.BalefulStare.class)); + cards.add(new SetCardInfo("Bee Sting", 159, Rarity.UNCOMMON, mage.cards.b.BeeSting.class)); + cards.add(new SetCardInfo("Blaze", "118a", Rarity.UNCOMMON, mage.cards.b.Blaze.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Blaze", "118b", Rarity.UNCOMMON, mage.cards.b.Blaze.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Blessed Reversal", 7, Rarity.RARE, mage.cards.b.BlessedReversal.class)); + cards.add(new SetCardInfo("Blinding Light", 8, Rarity.RARE, mage.cards.b.BlindingLight.class)); + cards.add(new SetCardInfo("Bog Imp", 81, Rarity.COMMON, mage.cards.b.BogImp.class)); + cards.add(new SetCardInfo("Bog Raiders", 82, Rarity.COMMON, mage.cards.b.BogRaiders.class)); + cards.add(new SetCardInfo("Bog Wraith", 83, Rarity.UNCOMMON, mage.cards.b.BogWraith.class)); + cards.add(new SetCardInfo("Boiling Seas", 119, Rarity.UNCOMMON, mage.cards.b.BoilingSeas.class)); + cards.add(new SetCardInfo("Border Guard", 9, Rarity.COMMON, mage.cards.b.BorderGuard.class)); + cards.add(new SetCardInfo("Breath of Life", 10, Rarity.COMMON, mage.cards.b.BreathOfLife.class)); + cards.add(new SetCardInfo("Bull Hippo", 160, Rarity.UNCOMMON, mage.cards.b.BullHippo.class)); + cards.add(new SetCardInfo("Burning Cloak", 120, Rarity.COMMON, mage.cards.b.BurningCloak.class)); + cards.add(new SetCardInfo("Capricious Sorcerer", 43, Rarity.RARE, mage.cards.c.CapriciousSorcerer.class)); + cards.add(new SetCardInfo("Charging Bandits", 84, Rarity.UNCOMMON, mage.cards.c.ChargingBandits.class)); + cards.add(new SetCardInfo("Charging Paladin", 11, Rarity.UNCOMMON, mage.cards.c.ChargingPaladin.class)); + cards.add(new SetCardInfo("Charging Rhino", 161, Rarity.RARE, mage.cards.c.ChargingRhino.class)); + cards.add(new SetCardInfo("Cloak of Feathers", 44, Rarity.COMMON, mage.cards.c.CloakOfFeathers.class)); + cards.add(new SetCardInfo("Cloud Dragon", 45, Rarity.RARE, mage.cards.c.CloudDragon.class)); + cards.add(new SetCardInfo("Cloud Pirates", 46, Rarity.COMMON, mage.cards.c.CloudPirates.class)); + cards.add(new SetCardInfo("Cloud Spirit", 47, Rarity.UNCOMMON, mage.cards.c.CloudSpirit.class)); + cards.add(new SetCardInfo("Command of Unsummoning", 48, Rarity.UNCOMMON, mage.cards.c.CommandOfUnsummoning.class)); + cards.add(new SetCardInfo("Coral Eel", 49, Rarity.COMMON, mage.cards.c.CoralEel.class)); + cards.add(new SetCardInfo("Craven Giant", 121, Rarity.COMMON, mage.cards.c.CravenGiant.class)); + cards.add(new SetCardInfo("Craven Knight", 85, Rarity.COMMON, mage.cards.c.CravenKnight.class)); + cards.add(new SetCardInfo("Cruel Bargain", 86, Rarity.RARE, mage.cards.c.CruelBargain.class)); + cards.add(new SetCardInfo("Cruel Fate", 50, Rarity.RARE, mage.cards.c.CruelFate.class)); + cards.add(new SetCardInfo("Cruel Tutor", 87, Rarity.RARE, mage.cards.c.CruelTutor.class)); + cards.add(new SetCardInfo("Deep Wood", 162, Rarity.UNCOMMON, mage.cards.d.DeepWood.class)); + cards.add(new SetCardInfo("Deep-Sea Serpent", 51, Rarity.UNCOMMON, mage.cards.d.DeepSeaSerpent.class)); + cards.add(new SetCardInfo("Defiant Stand", 12, Rarity.UNCOMMON, mage.cards.d.DefiantStand.class)); cards.add(new SetCardInfo("Deja Vu", 53, Rarity.COMMON, mage.cards.d.DejaVu.class)); - cards.add(new SetCardInfo("Desert Drake", 127, Rarity.UNCOMMON, mage.cards.d.DesertDrake.class)); - cards.add(new SetCardInfo("Devastation", 128, Rarity.RARE, mage.cards.d.Devastation.class)); - cards.add(new SetCardInfo("Devoted Hero", 175, Rarity.COMMON, mage.cards.d.DevotedHero.class)); - cards.add(new SetCardInfo("Djinn of the Lamp", 54, Rarity.RARE, mage.cards.d.DjinnOfTheLamp.class)); - cards.add(new SetCardInfo("Dread Charge", 10, Rarity.RARE, mage.cards.d.DreadCharge.class)); - cards.add(new SetCardInfo("Dread Reaper", 11, Rarity.RARE, mage.cards.d.DreadReaper.class)); - cards.add(new SetCardInfo("Dry Spell", 12, Rarity.UNCOMMON, DrySpell.class)); - cards.add(new SetCardInfo("Earthquake", 129, Rarity.RARE, mage.cards.e.Earthquake.class)); - cards.add(new SetCardInfo("Ebon Dragon", 13, Rarity.RARE, mage.cards.e.EbonDragon.class)); - cards.add(new SetCardInfo("Elite Cat Warrior", 87, Rarity.COMMON, EliteCatWarrior.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Elite Cat Warrior", 88, Rarity.COMMON, EliteCatWarrior.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Elven Cache", 89, Rarity.COMMON, mage.cards.e.ElvenCache.class)); - cards.add(new SetCardInfo("Elvish Ranger", 90, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); - cards.add(new SetCardInfo("Endless Cockroaches", 14, Rarity.RARE, mage.cards.e.EndlessCockroaches.class)); - cards.add(new SetCardInfo("Exhaustion", 55, Rarity.RARE, mage.cards.e.Exhaustion.class)); - cards.add(new SetCardInfo("False Peace", 176, Rarity.COMMON, mage.cards.f.FalsePeace.class)); - cards.add(new SetCardInfo("Feral Shadow", 15, Rarity.COMMON, mage.cards.f.FeralShadow.class)); - cards.add(new SetCardInfo("Final Strike", 16, Rarity.RARE, mage.cards.f.FinalStrike.class)); - cards.add(new SetCardInfo("Fire Dragon", 130, Rarity.RARE, mage.cards.f.FireDragon.class)); - cards.add(new SetCardInfo("Fire Imp", 131, Rarity.UNCOMMON, mage.cards.f.FireImp.class)); - cards.add(new SetCardInfo("Fire Snake", 132, Rarity.COMMON, mage.cards.f.FireSnake.class)); - cards.add(new SetCardInfo("Fire Tempest", 133, Rarity.RARE, mage.cards.f.FireTempest.class)); - cards.add(new SetCardInfo("Flashfires", 134, Rarity.UNCOMMON, mage.cards.f.Flashfires.class)); - cards.add(new SetCardInfo("Fleet-Footed Monk", 177, Rarity.COMMON, mage.cards.f.FleetFootedMonk.class)); - cards.add(new SetCardInfo("Flux", 56, Rarity.UNCOMMON, mage.cards.f.Flux.class)); - cards.add(new SetCardInfo("Foot Soldiers", 178, Rarity.COMMON, mage.cards.f.FootSoldiers.class)); - cards.add(new SetCardInfo("Forest", 203, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 204, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 205, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 206, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Fruition", 91, Rarity.COMMON, mage.cards.f.Fruition.class)); - cards.add(new SetCardInfo("Giant Octopus", 57, Rarity.COMMON, mage.cards.g.GiantOctopus.class)); - cards.add(new SetCardInfo("Giant Spider", 92, Rarity.COMMON, mage.cards.g.GiantSpider.class)); - cards.add(new SetCardInfo("Gift of Estates", 179, Rarity.RARE, mage.cards.g.GiftOfEstates.class)); - cards.add(new SetCardInfo("Goblin Bully", 136, Rarity.COMMON, mage.cards.g.GoblinBully.class)); - cards.add(new SetCardInfo("Gorilla Warrior", 93, Rarity.COMMON, mage.cards.g.GorillaWarrior.class)); - cards.add(new SetCardInfo("Gravedigger", 17, Rarity.UNCOMMON, mage.cards.g.Gravedigger.class)); - cards.add(new SetCardInfo("Grizzly Bears", 94, Rarity.COMMON, mage.cards.g.GrizzlyBears.class)); - cards.add(new SetCardInfo("Hand of Death", 18, Rarity.COMMON, mage.cards.h.HandOfDeath.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Hand of Death", 19, Rarity.COMMON, mage.cards.h.HandOfDeath.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Harsh Justice", 180, Rarity.RARE, mage.cards.h.HarshJustice.class)); - cards.add(new SetCardInfo("Highland Giant", 137, Rarity.COMMON, mage.cards.h.HighlandGiant.class)); - cards.add(new SetCardInfo("Hill Giant", 138, Rarity.COMMON, mage.cards.h.HillGiant.class)); - cards.add(new SetCardInfo("Horned Turtle", 58, Rarity.COMMON, mage.cards.h.HornedTurtle.class)); - cards.add(new SetCardInfo("Howling Fury", 20, Rarity.COMMON, mage.cards.h.HowlingFury.class)); - cards.add(new SetCardInfo("Hulking Cyclops", 139, Rarity.UNCOMMON, mage.cards.h.HulkingCyclops.class)); - cards.add(new SetCardInfo("Hulking Goblin", 140, Rarity.COMMON, mage.cards.h.HulkingGoblin.class)); - cards.add(new SetCardInfo("Hurricane", 95, Rarity.RARE, mage.cards.h.Hurricane.class)); - cards.add(new SetCardInfo("Ingenious Thief", 59, Rarity.UNCOMMON, mage.cards.i.IngeniousThief.class)); - cards.add(new SetCardInfo("Island", 207, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 208, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 209, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 210, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jungle Lion", 96, Rarity.COMMON, mage.cards.j.JungleLion.class)); - cards.add(new SetCardInfo("Keen-Eyed Archers", 181, Rarity.COMMON, mage.cards.k.KeenEyedArchers.class)); - cards.add(new SetCardInfo("King's Assassin", 21, Rarity.RARE, mage.cards.k.KingsAssassin.class)); - cards.add(new SetCardInfo("Knight Errant", 182, Rarity.COMMON, mage.cards.k.KnightErrant.class)); - cards.add(new SetCardInfo("Last Chance", 141, Rarity.RARE, mage.cards.l.LastChance.class)); - cards.add(new SetCardInfo("Lava Axe", 142, Rarity.COMMON, mage.cards.l.LavaAxe.class)); - cards.add(new SetCardInfo("Lava Flow", 143, Rarity.UNCOMMON, mage.cards.l.LavaFlow.class)); - cards.add(new SetCardInfo("Lizard Warrior", 144, Rarity.COMMON, mage.cards.l.LizardWarrior.class)); - cards.add(new SetCardInfo("Man-o'-War", 60, Rarity.UNCOMMON, mage.cards.m.ManOWar.class)); - cards.add(new SetCardInfo("Mercenary Knight", 22, Rarity.RARE, mage.cards.m.MercenaryKnight.class)); - cards.add(new SetCardInfo("Merfolk of the Pearl Trident", 61, Rarity.COMMON, mage.cards.m.MerfolkOfThePearlTrident.class)); - cards.add(new SetCardInfo("Mind Knives", 23, Rarity.COMMON, mage.cards.m.MindKnives.class)); - cards.add(new SetCardInfo("Mind Rot", 24, Rarity.COMMON, mage.cards.m.MindRot.class)); - cards.add(new SetCardInfo("Minotaur Warrior", 145, Rarity.COMMON, mage.cards.m.MinotaurWarrior.class)); - cards.add(new SetCardInfo("Mobilize", 97, Rarity.COMMON, mage.cards.m.Mobilize.class)); - cards.add(new SetCardInfo("Monstrous Growth", 98, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Monstrous Growth", 99, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Moon Sprite", 100, Rarity.UNCOMMON, mage.cards.m.MoonSprite.class)); + cards.add(new SetCardInfo("Desert Drake", 122, Rarity.UNCOMMON, mage.cards.d.DesertDrake.class)); + cards.add(new SetCardInfo("Devastation", 123, Rarity.RARE, mage.cards.d.Devastation.class)); + cards.add(new SetCardInfo("Devoted Hero", 13, Rarity.COMMON, mage.cards.d.DevotedHero.class)); + cards.add(new SetCardInfo("Djinn of the Lamp", 52, Rarity.RARE, mage.cards.d.DjinnOfTheLamp.class)); + cards.add(new SetCardInfo("Dread Charge", 88, Rarity.RARE, mage.cards.d.DreadCharge.class)); + cards.add(new SetCardInfo("Dread Reaper", 89, Rarity.RARE, mage.cards.d.DreadReaper.class)); + cards.add(new SetCardInfo("Dry Spell", 90, Rarity.UNCOMMON, DrySpell.class)); + cards.add(new SetCardInfo("Earthquake", 124, Rarity.RARE, mage.cards.e.Earthquake.class)); + cards.add(new SetCardInfo("Ebon Dragon", 91, Rarity.RARE, mage.cards.e.EbonDragon.class)); + cards.add(new SetCardInfo("Elite Cat Warrior", "163a", Rarity.COMMON, EliteCatWarrior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Elite Cat Warrior", "163b", Rarity.COMMON, EliteCatWarrior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Elven Cache", 164, Rarity.COMMON, mage.cards.e.ElvenCache.class)); + cards.add(new SetCardInfo("Elvish Ranger", 165, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); + cards.add(new SetCardInfo("Endless Cockroaches", 92, Rarity.RARE, mage.cards.e.EndlessCockroaches.class)); + cards.add(new SetCardInfo("Exhaustion", 54, Rarity.RARE, mage.cards.e.Exhaustion.class)); + cards.add(new SetCardInfo("False Peace", 14, Rarity.COMMON, mage.cards.f.FalsePeace.class)); + cards.add(new SetCardInfo("Feral Shadow", 93, Rarity.COMMON, mage.cards.f.FeralShadow.class)); + cards.add(new SetCardInfo("Final Strike", 94, Rarity.RARE, mage.cards.f.FinalStrike.class)); + cards.add(new SetCardInfo("Fire Dragon", 125, Rarity.RARE, mage.cards.f.FireDragon.class)); + cards.add(new SetCardInfo("Fire Imp", 126, Rarity.UNCOMMON, mage.cards.f.FireImp.class)); + cards.add(new SetCardInfo("Fire Snake", 127, Rarity.COMMON, mage.cards.f.FireSnake.class)); + cards.add(new SetCardInfo("Fire Tempest", 128, Rarity.RARE, mage.cards.f.FireTempest.class)); + cards.add(new SetCardInfo("Flashfires", 129, Rarity.UNCOMMON, mage.cards.f.Flashfires.class)); + cards.add(new SetCardInfo("Fleet-Footed Monk", 15, Rarity.COMMON, mage.cards.f.FleetFootedMonk.class)); + cards.add(new SetCardInfo("Flux", 55, Rarity.UNCOMMON, mage.cards.f.Flux.class)); + cards.add(new SetCardInfo("Foot Soldiers", 16, Rarity.COMMON, mage.cards.f.FootSoldiers.class)); + cards.add(new SetCardInfo("Forest", 212, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 213, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 214, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 215, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fruition", 166, Rarity.COMMON, mage.cards.f.Fruition.class)); + cards.add(new SetCardInfo("Giant Octopus", 56, Rarity.COMMON, mage.cards.g.GiantOctopus.class)); + cards.add(new SetCardInfo("Giant Spider", 167, Rarity.COMMON, mage.cards.g.GiantSpider.class)); + cards.add(new SetCardInfo("Gift of Estates", 17, Rarity.RARE, mage.cards.g.GiftOfEstates.class)); + cards.add(new SetCardInfo("Goblin Bully", 131, Rarity.COMMON, mage.cards.g.GoblinBully.class)); + cards.add(new SetCardInfo("Gorilla Warrior", 168, Rarity.COMMON, mage.cards.g.GorillaWarrior.class)); + cards.add(new SetCardInfo("Gravedigger", 95, Rarity.UNCOMMON, mage.cards.g.Gravedigger.class)); + cards.add(new SetCardInfo("Grizzly Bears", 169, Rarity.COMMON, mage.cards.g.GrizzlyBears.class)); + cards.add(new SetCardInfo("Hand of Death", "96a", Rarity.COMMON, mage.cards.h.HandOfDeath.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Hand of Death", "96b", Rarity.COMMON, mage.cards.h.HandOfDeath.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Harsh Justice", 18, Rarity.RARE, mage.cards.h.HarshJustice.class)); + cards.add(new SetCardInfo("Highland Giant", 132, Rarity.COMMON, mage.cards.h.HighlandGiant.class)); + cards.add(new SetCardInfo("Hill Giant", 133, Rarity.COMMON, mage.cards.h.HillGiant.class)); + cards.add(new SetCardInfo("Horned Turtle", 57, Rarity.COMMON, mage.cards.h.HornedTurtle.class)); + cards.add(new SetCardInfo("Howling Fury", 97, Rarity.COMMON, mage.cards.h.HowlingFury.class)); + cards.add(new SetCardInfo("Hulking Cyclops", 134, Rarity.UNCOMMON, mage.cards.h.HulkingCyclops.class)); + cards.add(new SetCardInfo("Hulking Goblin", 135, Rarity.COMMON, mage.cards.h.HulkingGoblin.class)); + cards.add(new SetCardInfo("Hurricane", 170, Rarity.RARE, mage.cards.h.Hurricane.class)); + cards.add(new SetCardInfo("Ingenious Thief", 58, Rarity.UNCOMMON, mage.cards.i.IngeniousThief.class)); + cards.add(new SetCardInfo("Island", 200, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 201, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 202, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 203, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jungle Lion", 171, Rarity.COMMON, mage.cards.j.JungleLion.class)); + cards.add(new SetCardInfo("Keen-Eyed Archers", 19, Rarity.COMMON, mage.cards.k.KeenEyedArchers.class)); + cards.add(new SetCardInfo("King's Assassin", 98, Rarity.RARE, mage.cards.k.KingsAssassin.class)); + cards.add(new SetCardInfo("Knight Errant", 20, Rarity.COMMON, mage.cards.k.KnightErrant.class)); + cards.add(new SetCardInfo("Last Chance", 136, Rarity.RARE, mage.cards.l.LastChance.class)); + cards.add(new SetCardInfo("Lava Axe", 137, Rarity.COMMON, mage.cards.l.LavaAxe.class)); + cards.add(new SetCardInfo("Lava Flow", 138, Rarity.UNCOMMON, mage.cards.l.LavaFlow.class)); + cards.add(new SetCardInfo("Lizard Warrior", 139, Rarity.COMMON, mage.cards.l.LizardWarrior.class)); + cards.add(new SetCardInfo("Man-o'-War", 59, Rarity.UNCOMMON, mage.cards.m.ManOWar.class)); + cards.add(new SetCardInfo("Mercenary Knight", 99, Rarity.RARE, mage.cards.m.MercenaryKnight.class)); + cards.add(new SetCardInfo("Merfolk of the Pearl Trident", 60, Rarity.COMMON, mage.cards.m.MerfolkOfThePearlTrident.class)); + cards.add(new SetCardInfo("Mind Knives", 100, Rarity.COMMON, mage.cards.m.MindKnives.class)); + cards.add(new SetCardInfo("Mind Rot", 101, Rarity.COMMON, mage.cards.m.MindRot.class)); + cards.add(new SetCardInfo("Minotaur Warrior", 140, Rarity.COMMON, mage.cards.m.MinotaurWarrior.class)); + cards.add(new SetCardInfo("Mobilize", 172, Rarity.COMMON, mage.cards.m.Mobilize.class)); + cards.add(new SetCardInfo("Monstrous Growth", "173a", Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Monstrous Growth", "173b", Rarity.COMMON, mage.cards.m.MonstrousGrowth.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Moon Sprite", 174, Rarity.UNCOMMON, mage.cards.m.MoonSprite.class)); + cards.add(new SetCardInfo("Mountain Goat", 141, Rarity.UNCOMMON, mage.cards.m.MountainGoat.class)); + cards.add(new SetCardInfo("Mountain", 208, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 209, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 210, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 211, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 212, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 213, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 214, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain Goat", 146, Rarity.UNCOMMON, mage.cards.m.MountainGoat.class)); - cards.add(new SetCardInfo("Muck Rats", 25, Rarity.COMMON, mage.cards.m.MuckRats.class)); - cards.add(new SetCardInfo("Mystic Denial", 62, Rarity.UNCOMMON, mage.cards.m.MysticDenial.class)); - cards.add(new SetCardInfo("Natural Order", 101, Rarity.RARE, mage.cards.n.NaturalOrder.class)); - cards.add(new SetCardInfo("Natural Spring", 102, Rarity.UNCOMMON, mage.cards.n.NaturalSpring.class)); - cards.add(new SetCardInfo("Nature's Cloak", 103, Rarity.RARE, mage.cards.n.NaturesCloak.class)); - cards.add(new SetCardInfo("Nature's Lore", 104, Rarity.COMMON, mage.cards.n.NaturesLore.class)); - cards.add(new SetCardInfo("Nature's Ruin", 26, Rarity.UNCOMMON, mage.cards.n.NaturesRuin.class)); - cards.add(new SetCardInfo("Needle Storm", 105, Rarity.UNCOMMON, mage.cards.n.NeedleStorm.class)); - cards.add(new SetCardInfo("Noxious Toad", 27, Rarity.UNCOMMON, mage.cards.n.NoxiousToad.class)); - cards.add(new SetCardInfo("Omen", 63, Rarity.COMMON, mage.cards.o.Omen.class)); - cards.add(new SetCardInfo("Owl Familiar", 64, Rarity.COMMON, mage.cards.o.OwlFamiliar.class)); - cards.add(new SetCardInfo("Panther Warriors", 106, Rarity.COMMON, mage.cards.p.PantherWarriors.class)); - cards.add(new SetCardInfo("Path of Peace", 183, Rarity.COMMON, mage.cards.p.PathOfPeace.class)); - cards.add(new SetCardInfo("Personal Tutor", 65, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); - cards.add(new SetCardInfo("Phantom Warrior", 66, Rarity.RARE, mage.cards.p.PhantomWarrior.class)); - cards.add(new SetCardInfo("Pillaging Horde", 147, Rarity.RARE, mage.cards.p.PillagingHorde.class)); - cards.add(new SetCardInfo("Plains", 215, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - 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("Plant Elemental", 107, Rarity.UNCOMMON, mage.cards.p.PlantElemental.class)); - cards.add(new SetCardInfo("Primeval Force", 108, Rarity.RARE, mage.cards.p.PrimevalForce.class)); - cards.add(new SetCardInfo("Prosperity", 67, Rarity.RARE, mage.cards.p.Prosperity.class)); - cards.add(new SetCardInfo("Pyroclasm", 148, Rarity.RARE, mage.cards.p.Pyroclasm.class)); - cards.add(new SetCardInfo("Python", 28, Rarity.COMMON, mage.cards.p.Python.class)); - cards.add(new SetCardInfo("Raging Cougar", 149, Rarity.COMMON, mage.cards.r.RagingCougar.class)); - cards.add(new SetCardInfo("Raging Goblin", 150, Rarity.COMMON, mage.cards.r.RagingGoblin.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Raging Goblin", 151, Rarity.COMMON, mage.cards.r.RagingGoblin.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Raging Minotaur", 152, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); - cards.add(new SetCardInfo("Rain of Salt", 153, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); - cards.add(new SetCardInfo("Rain of Tears", 29, Rarity.UNCOMMON, mage.cards.r.RainOfTears.class)); - cards.add(new SetCardInfo("Raise Dead", 30, Rarity.COMMON, mage.cards.r.RaiseDead.class)); - cards.add(new SetCardInfo("Redwood Treefolk", 109, Rarity.COMMON, mage.cards.r.RedwoodTreefolk.class)); - cards.add(new SetCardInfo("Regal Unicorn", 184, Rarity.COMMON, mage.cards.r.RegalUnicorn.class)); - cards.add(new SetCardInfo("Renewing Dawn", 185, Rarity.UNCOMMON, mage.cards.r.RenewingDawn.class)); - cards.add(new SetCardInfo("Rowan Treefolk", 110, Rarity.COMMON, mage.cards.r.RowanTreefolk.class)); - cards.add(new SetCardInfo("Sacred Knight", 186, Rarity.COMMON, mage.cards.s.SacredKnight.class)); - cards.add(new SetCardInfo("Sacred Nectar", 187, Rarity.COMMON, mage.cards.s.SacredNectar.class)); - cards.add(new SetCardInfo("Scorching Spear", 154, Rarity.COMMON, mage.cards.s.ScorchingSpear.class)); - cards.add(new SetCardInfo("Scorching Winds", 155, Rarity.UNCOMMON, mage.cards.s.ScorchingWinds.class)); - cards.add(new SetCardInfo("Seasoned Marshal", 188, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); - cards.add(new SetCardInfo("Serpent Assassin", 31, Rarity.RARE, mage.cards.s.SerpentAssassin.class)); - cards.add(new SetCardInfo("Serpent Warrior", 32, Rarity.COMMON, mage.cards.s.SerpentWarrior.class)); - cards.add(new SetCardInfo("Skeletal Crocodile", 33, Rarity.COMMON, mage.cards.s.SkeletalCrocodile.class)); - cards.add(new SetCardInfo("Skeletal Snake", 34, Rarity.COMMON, mage.cards.s.SkeletalSnake.class)); - cards.add(new SetCardInfo("Snapping Drake", 68, Rarity.COMMON, mage.cards.s.SnappingDrake.class)); - cards.add(new SetCardInfo("Sorcerous Sight", 69, Rarity.COMMON, mage.cards.s.SorcerousSight.class)); - cards.add(new SetCardInfo("Soul Shred", 35, Rarity.COMMON, mage.cards.s.SoulShred.class)); - cards.add(new SetCardInfo("Spined Wurm", 111, Rarity.COMMON, mage.cards.s.SpinedWurm.class)); - cards.add(new SetCardInfo("Spiritual Guardian", 189, Rarity.RARE, mage.cards.s.SpiritualGuardian.class)); - cards.add(new SetCardInfo("Spitting Earth", 156, Rarity.COMMON, mage.cards.s.SpittingEarth.class)); - cards.add(new SetCardInfo("Spotted Griffin", 190, Rarity.COMMON, mage.cards.s.SpottedGriffin.class)); - cards.add(new SetCardInfo("Stalking Tiger", 112, Rarity.COMMON, mage.cards.s.StalkingTiger.class)); - cards.add(new SetCardInfo("Starlight", 191, Rarity.UNCOMMON, mage.cards.s.Starlight.class)); - cards.add(new SetCardInfo("Starlit Angel", 192, Rarity.UNCOMMON, mage.cards.s.StarlitAngel.class)); - cards.add(new SetCardInfo("Steadfastness", 193, Rarity.COMMON, mage.cards.s.Steadfastness.class)); - cards.add(new SetCardInfo("Stern Marshal", 194, Rarity.RARE, mage.cards.s.SternMarshal.class)); - cards.add(new SetCardInfo("Stone Rain", 157, Rarity.COMMON, mage.cards.s.StoneRain.class)); - cards.add(new SetCardInfo("Storm Crow", 70, Rarity.COMMON, mage.cards.s.StormCrow.class)); - cards.add(new SetCardInfo("Summer Bloom", 113, Rarity.RARE, mage.cards.s.SummerBloom.class)); - cards.add(new SetCardInfo("Swamp", 219, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 220, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 221, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sylvan Tutor", 114, Rarity.RARE, mage.cards.s.SylvanTutor.class)); - cards.add(new SetCardInfo("Symbol of Unsummoning", 71, Rarity.COMMON, mage.cards.s.SymbolOfUnsummoning.class)); - cards.add(new SetCardInfo("Taunt", 72, Rarity.RARE, mage.cards.t.Taunt.class)); - cards.add(new SetCardInfo("Temporary Truce", 195, Rarity.RARE, mage.cards.t.TemporaryTruce.class)); - cards.add(new SetCardInfo("Theft of Dreams", 73, Rarity.UNCOMMON, mage.cards.t.TheftOfDreams.class)); - cards.add(new SetCardInfo("Thing from the Deep", 74, Rarity.RARE, mage.cards.t.ThingFromTheDeep.class)); - cards.add(new SetCardInfo("Thundering Wurm", 115, Rarity.RARE, mage.cards.t.ThunderingWurm.class)); - cards.add(new SetCardInfo("Thundermare", 158, Rarity.RARE, mage.cards.t.Thundermare.class)); - cards.add(new SetCardInfo("Tidal Surge", 75, Rarity.COMMON, mage.cards.t.TidalSurge.class)); - cards.add(new SetCardInfo("Time Ebb", 76, Rarity.COMMON, mage.cards.t.TimeEbb.class)); - cards.add(new SetCardInfo("Touch of Brilliance", 77, Rarity.COMMON, mage.cards.t.TouchOfBrilliance.class)); - cards.add(new SetCardInfo("Treetop Defense", 116, Rarity.RARE, mage.cards.t.TreetopDefense.class)); - cards.add(new SetCardInfo("Undying Beast", 36, Rarity.COMMON, mage.cards.u.UndyingBeast.class)); - cards.add(new SetCardInfo("Untamed Wilds", 117, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); - cards.add(new SetCardInfo("Valorous Charge", 196, Rarity.UNCOMMON, mage.cards.v.ValorousCharge.class)); - cards.add(new SetCardInfo("Vampiric Feast", 37, Rarity.UNCOMMON, mage.cards.v.VampiricFeast.class)); - cards.add(new SetCardInfo("Vampiric Touch", 38, Rarity.COMMON, mage.cards.v.VampiricTouch.class)); - cards.add(new SetCardInfo("Venerable Monk", 197, Rarity.UNCOMMON, mage.cards.v.VenerableMonk.class)); - cards.add(new SetCardInfo("Vengeance", 198, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); - cards.add(new SetCardInfo("Virtue's Ruin", 39, Rarity.UNCOMMON, mage.cards.v.VirtuesRuin.class)); - cards.add(new SetCardInfo("Volcanic Dragon", 159, Rarity.RARE, mage.cards.v.VolcanicDragon.class)); - cards.add(new SetCardInfo("Volcanic Hammer", 160, Rarity.COMMON, mage.cards.v.VolcanicHammer.class)); - cards.add(new SetCardInfo("Wall of Granite", 161, Rarity.UNCOMMON, mage.cards.w.WallOfGranite.class)); - cards.add(new SetCardInfo("Wall of Swords", 199, Rarity.UNCOMMON, mage.cards.w.WallOfSwords.class)); - cards.add(new SetCardInfo("Warrior's Charge", 200, Rarity.COMMON, WarriorsCharge.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Warrior's Charge", 201, Rarity.COMMON, WarriorsCharge.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Whiptail Wurm", 118, Rarity.UNCOMMON, mage.cards.w.WhiptailWurm.class)); - cards.add(new SetCardInfo("Wicked Pact", 40, Rarity.RARE, mage.cards.w.WickedPact.class)); - cards.add(new SetCardInfo("Willow Dryad", 119, Rarity.COMMON, mage.cards.w.WillowDryad.class)); - cards.add(new SetCardInfo("Wind Drake", 78, Rarity.COMMON, mage.cards.w.WindDrake.class)); - cards.add(new SetCardInfo("Winds of Change", 162, Rarity.RARE, mage.cards.w.WindsOfChange.class)); - cards.add(new SetCardInfo("Winter's Grasp", 120, Rarity.UNCOMMON, mage.cards.w.WintersGrasp.class)); - cards.add(new SetCardInfo("Withering Gaze", 79, Rarity.UNCOMMON, mage.cards.w.WitheringGaze.class)); - cards.add(new SetCardInfo("Wood Elves", 121, Rarity.RARE, mage.cards.w.WoodElves.class)); - cards.add(new SetCardInfo("Wrath of God", 202, Rarity.RARE, mage.cards.w.WrathOfGod.class)); + cards.add(new SetCardInfo("Muck Rats", 102, Rarity.COMMON, mage.cards.m.MuckRats.class)); + cards.add(new SetCardInfo("Mystic Denial", 61, Rarity.UNCOMMON, mage.cards.m.MysticDenial.class)); + cards.add(new SetCardInfo("Natural Order", 175, Rarity.RARE, mage.cards.n.NaturalOrder.class)); + cards.add(new SetCardInfo("Natural Spring", 176, Rarity.UNCOMMON, mage.cards.n.NaturalSpring.class)); + cards.add(new SetCardInfo("Nature's Cloak", 177, Rarity.RARE, mage.cards.n.NaturesCloak.class)); + cards.add(new SetCardInfo("Nature's Lore", 178, Rarity.COMMON, mage.cards.n.NaturesLore.class)); + cards.add(new SetCardInfo("Nature's Ruin", 103, Rarity.UNCOMMON, mage.cards.n.NaturesRuin.class)); + cards.add(new SetCardInfo("Needle Storm", 179, Rarity.UNCOMMON, mage.cards.n.NeedleStorm.class)); + cards.add(new SetCardInfo("Noxious Toad", 104, Rarity.UNCOMMON, mage.cards.n.NoxiousToad.class)); + cards.add(new SetCardInfo("Omen", 62, Rarity.COMMON, mage.cards.o.Omen.class)); + cards.add(new SetCardInfo("Owl Familiar", 63, Rarity.COMMON, mage.cards.o.OwlFamiliar.class)); + cards.add(new SetCardInfo("Panther Warriors", 180, Rarity.COMMON, mage.cards.p.PantherWarriors.class)); + cards.add(new SetCardInfo("Path of Peace", 21, Rarity.COMMON, mage.cards.p.PathOfPeace.class)); + cards.add(new SetCardInfo("Personal Tutor", 64, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); + cards.add(new SetCardInfo("Phantom Warrior", 65, Rarity.RARE, mage.cards.p.PhantomWarrior.class)); + cards.add(new SetCardInfo("Pillaging Horde", 142, Rarity.RARE, mage.cards.p.PillagingHorde.class)); + cards.add(new SetCardInfo("Plains", 196, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 197, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 198, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 199, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plant Elemental", 181, Rarity.UNCOMMON, mage.cards.p.PlantElemental.class)); + cards.add(new SetCardInfo("Primeval Force", 182, Rarity.RARE, mage.cards.p.PrimevalForce.class)); + cards.add(new SetCardInfo("Prosperity", 66, Rarity.RARE, mage.cards.p.Prosperity.class)); + cards.add(new SetCardInfo("Pyroclasm", 143, Rarity.RARE, mage.cards.p.Pyroclasm.class)); + cards.add(new SetCardInfo("Python", 105, Rarity.COMMON, mage.cards.p.Python.class)); + cards.add(new SetCardInfo("Raging Cougar", 144, Rarity.COMMON, mage.cards.r.RagingCougar.class)); + cards.add(new SetCardInfo("Raging Goblin", "145a", Rarity.COMMON, mage.cards.r.RagingGoblin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Raging Goblin", "145b", Rarity.COMMON, mage.cards.r.RagingGoblin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Raging Minotaur", 146, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); + cards.add(new SetCardInfo("Rain of Salt", 147, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); + cards.add(new SetCardInfo("Rain of Tears", 106, Rarity.UNCOMMON, mage.cards.r.RainOfTears.class)); + cards.add(new SetCardInfo("Raise Dead", 107, Rarity.COMMON, mage.cards.r.RaiseDead.class)); + cards.add(new SetCardInfo("Redwood Treefolk", 183, Rarity.COMMON, mage.cards.r.RedwoodTreefolk.class)); + cards.add(new SetCardInfo("Regal Unicorn", 22, Rarity.COMMON, mage.cards.r.RegalUnicorn.class)); + cards.add(new SetCardInfo("Renewing Dawn", 23, Rarity.UNCOMMON, mage.cards.r.RenewingDawn.class)); + cards.add(new SetCardInfo("Rowan Treefolk", 184, Rarity.COMMON, mage.cards.r.RowanTreefolk.class)); + cards.add(new SetCardInfo("Sacred Knight", 24, Rarity.COMMON, mage.cards.s.SacredKnight.class)); + cards.add(new SetCardInfo("Sacred Nectar", 25, Rarity.COMMON, mage.cards.s.SacredNectar.class)); + cards.add(new SetCardInfo("Scorching Spear", 148, Rarity.COMMON, mage.cards.s.ScorchingSpear.class)); + cards.add(new SetCardInfo("Scorching Winds", 149, Rarity.UNCOMMON, mage.cards.s.ScorchingWinds.class)); + cards.add(new SetCardInfo("Seasoned Marshal", 26, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); + cards.add(new SetCardInfo("Serpent Assassin", 108, Rarity.RARE, mage.cards.s.SerpentAssassin.class)); + cards.add(new SetCardInfo("Serpent Warrior", 109, Rarity.COMMON, mage.cards.s.SerpentWarrior.class)); + cards.add(new SetCardInfo("Skeletal Crocodile", 110, Rarity.COMMON, mage.cards.s.SkeletalCrocodile.class)); + cards.add(new SetCardInfo("Skeletal Snake", 111, Rarity.COMMON, mage.cards.s.SkeletalSnake.class)); + cards.add(new SetCardInfo("Snapping Drake", 67, Rarity.COMMON, mage.cards.s.SnappingDrake.class)); + cards.add(new SetCardInfo("Sorcerous Sight", 68, Rarity.COMMON, mage.cards.s.SorcerousSight.class)); + cards.add(new SetCardInfo("Soul Shred", 112, Rarity.COMMON, mage.cards.s.SoulShred.class)); + cards.add(new SetCardInfo("Spined Wurm", 185, Rarity.COMMON, mage.cards.s.SpinedWurm.class)); + cards.add(new SetCardInfo("Spiritual Guardian", 27, Rarity.RARE, mage.cards.s.SpiritualGuardian.class)); + cards.add(new SetCardInfo("Spitting Earth", 150, Rarity.COMMON, mage.cards.s.SpittingEarth.class)); + cards.add(new SetCardInfo("Spotted Griffin", 28, Rarity.COMMON, mage.cards.s.SpottedGriffin.class)); + cards.add(new SetCardInfo("Stalking Tiger", 186, Rarity.COMMON, mage.cards.s.StalkingTiger.class)); + cards.add(new SetCardInfo("Starlight", 29, Rarity.UNCOMMON, mage.cards.s.Starlight.class)); + cards.add(new SetCardInfo("Starlit Angel", 30, Rarity.UNCOMMON, mage.cards.s.StarlitAngel.class)); + cards.add(new SetCardInfo("Steadfastness", 31, Rarity.COMMON, mage.cards.s.Steadfastness.class)); + cards.add(new SetCardInfo("Stern Marshal", 32, Rarity.RARE, mage.cards.s.SternMarshal.class)); + cards.add(new SetCardInfo("Stone Rain", 151, Rarity.COMMON, mage.cards.s.StoneRain.class)); + cards.add(new SetCardInfo("Storm Crow", 69, Rarity.COMMON, mage.cards.s.StormCrow.class)); + cards.add(new SetCardInfo("Summer Bloom", 187, Rarity.RARE, mage.cards.s.SummerBloom.class)); + cards.add(new SetCardInfo("Swamp", 204, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 205, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 206, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 207, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sylvan Tutor", 188, Rarity.RARE, mage.cards.s.SylvanTutor.class)); + cards.add(new SetCardInfo("Symbol of Unsummoning", 70, Rarity.COMMON, mage.cards.s.SymbolOfUnsummoning.class)); + cards.add(new SetCardInfo("Taunt", 71, Rarity.RARE, mage.cards.t.Taunt.class)); + cards.add(new SetCardInfo("Temporary Truce", 33, Rarity.RARE, mage.cards.t.TemporaryTruce.class)); + cards.add(new SetCardInfo("Theft of Dreams", 72, Rarity.UNCOMMON, mage.cards.t.TheftOfDreams.class)); + cards.add(new SetCardInfo("Thing from the Deep", 73, Rarity.RARE, mage.cards.t.ThingFromTheDeep.class)); + cards.add(new SetCardInfo("Thundering Wurm", 189, Rarity.RARE, mage.cards.t.ThunderingWurm.class)); + cards.add(new SetCardInfo("Thundermare", 152, Rarity.RARE, mage.cards.t.Thundermare.class)); + cards.add(new SetCardInfo("Tidal Surge", 74, Rarity.COMMON, mage.cards.t.TidalSurge.class)); + cards.add(new SetCardInfo("Time Ebb", 75, Rarity.COMMON, mage.cards.t.TimeEbb.class)); + cards.add(new SetCardInfo("Touch of Brilliance", 76, Rarity.COMMON, mage.cards.t.TouchOfBrilliance.class)); + cards.add(new SetCardInfo("Treetop Defense", 190, Rarity.RARE, mage.cards.t.TreetopDefense.class)); + cards.add(new SetCardInfo("Undying Beast", 113, Rarity.COMMON, mage.cards.u.UndyingBeast.class)); + cards.add(new SetCardInfo("Untamed Wilds", 191, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); + cards.add(new SetCardInfo("Valorous Charge", 34, Rarity.UNCOMMON, mage.cards.v.ValorousCharge.class)); + cards.add(new SetCardInfo("Vampiric Feast", 114, Rarity.UNCOMMON, mage.cards.v.VampiricFeast.class)); + cards.add(new SetCardInfo("Vampiric Touch", 115, Rarity.COMMON, mage.cards.v.VampiricTouch.class)); + cards.add(new SetCardInfo("Venerable Monk", 35, Rarity.UNCOMMON, mage.cards.v.VenerableMonk.class)); + cards.add(new SetCardInfo("Vengeance", 36, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); + cards.add(new SetCardInfo("Virtue's Ruin", 116, Rarity.UNCOMMON, mage.cards.v.VirtuesRuin.class)); + cards.add(new SetCardInfo("Volcanic Dragon", 153, Rarity.RARE, mage.cards.v.VolcanicDragon.class)); + cards.add(new SetCardInfo("Volcanic Hammer", 154, Rarity.COMMON, mage.cards.v.VolcanicHammer.class)); + cards.add(new SetCardInfo("Wall of Granite", 155, Rarity.UNCOMMON, mage.cards.w.WallOfGranite.class)); + cards.add(new SetCardInfo("Wall of Swords", 37, Rarity.UNCOMMON, mage.cards.w.WallOfSwords.class)); + cards.add(new SetCardInfo("Warrior's Charge", "38a", Rarity.COMMON, WarriorsCharge.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Warrior's Charge", "38b", Rarity.COMMON, WarriorsCharge.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Whiptail Wurm", 192, Rarity.UNCOMMON, mage.cards.w.WhiptailWurm.class)); + cards.add(new SetCardInfo("Wicked Pact", 117, Rarity.RARE, mage.cards.w.WickedPact.class)); + cards.add(new SetCardInfo("Willow Dryad", 193, Rarity.COMMON, mage.cards.w.WillowDryad.class)); + cards.add(new SetCardInfo("Wind Drake", 77, Rarity.COMMON, mage.cards.w.WindDrake.class)); + cards.add(new SetCardInfo("Winds of Change", 156, Rarity.RARE, mage.cards.w.WindsOfChange.class)); + cards.add(new SetCardInfo("Winter's Grasp", 194, Rarity.UNCOMMON, mage.cards.w.WintersGrasp.class)); + cards.add(new SetCardInfo("Withering Gaze", 78, Rarity.UNCOMMON, mage.cards.w.WitheringGaze.class)); + cards.add(new SetCardInfo("Wood Elves", 195, Rarity.RARE, mage.cards.w.WoodElves.class)); + cards.add(new SetCardInfo("Wrath of God", 39, Rarity.RARE, mage.cards.w.WrathOfGod.class)); } } diff --git a/Mage.Sets/src/mage/sets/PortalSecondAge.java b/Mage.Sets/src/mage/sets/PortalSecondAge.java index bb316e198fe..1efd4d74214 100644 --- a/Mage.Sets/src/mage/sets/PortalSecondAge.java +++ b/Mage.Sets/src/mage/sets/PortalSecondAge.java @@ -31,57 +31,57 @@ public final class PortalSecondAge extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abyssal Nightstalker", 1, Rarity.UNCOMMON, mage.cards.a.AbyssalNightstalker.class)); + cards.add(new SetCardInfo("Abyssal Nightstalker", 61, Rarity.UNCOMMON, mage.cards.a.AbyssalNightstalker.class)); cards.add(new SetCardInfo("Air Elemental", 31, Rarity.UNCOMMON, mage.cards.a.AirElemental.class)); - cards.add(new SetCardInfo("Alaborn Cavalier", 121, Rarity.UNCOMMON, mage.cards.a.AlabornCavalier.class)); - cards.add(new SetCardInfo("Alaborn Grenadier", 122, Rarity.COMMON, mage.cards.a.AlabornGrenadier.class)); - cards.add(new SetCardInfo("Alaborn Musketeer", 123, Rarity.COMMON, mage.cards.a.AlabornMusketeer.class)); - cards.add(new SetCardInfo("Alaborn Trooper", 124, Rarity.COMMON, mage.cards.a.AlabornTrooper.class)); - cards.add(new SetCardInfo("Alaborn Veteran", 125, Rarity.RARE, mage.cards.a.AlabornVeteran.class)); - cards.add(new SetCardInfo("Alaborn Zealot", 126, Rarity.UNCOMMON, mage.cards.a.AlabornZealot.class)); - cards.add(new SetCardInfo("Alluring Scent", 61, Rarity.RARE, mage.cards.a.AlluringScent.class)); - cards.add(new SetCardInfo("Ancient Craving", 2, Rarity.RARE, mage.cards.a.AncientCraving.class)); - cards.add(new SetCardInfo("Angelic Blessing", 129, Rarity.COMMON, mage.cards.a.AngelicBlessing.class)); - cards.add(new SetCardInfo("Angelic Wall", 130, Rarity.COMMON, mage.cards.a.AngelicWall.class)); - cards.add(new SetCardInfo("Angel of Fury", 127, Rarity.RARE, mage.cards.a.AngelOfFury.class)); - cards.add(new SetCardInfo("Angel of Mercy", 128, Rarity.UNCOMMON, mage.cards.a.AngelOfMercy.class)); + cards.add(new SetCardInfo("Alaborn Cavalier", 1, Rarity.UNCOMMON, mage.cards.a.AlabornCavalier.class)); + cards.add(new SetCardInfo("Alaborn Grenadier", 2, Rarity.COMMON, mage.cards.a.AlabornGrenadier.class)); + cards.add(new SetCardInfo("Alaborn Musketeer", 3, Rarity.COMMON, mage.cards.a.AlabornMusketeer.class)); + cards.add(new SetCardInfo("Alaborn Trooper", 4, Rarity.COMMON, mage.cards.a.AlabornTrooper.class)); + cards.add(new SetCardInfo("Alaborn Veteran", 5, Rarity.RARE, mage.cards.a.AlabornVeteran.class)); + cards.add(new SetCardInfo("Alaborn Zealot", 6, Rarity.UNCOMMON, mage.cards.a.AlabornZealot.class)); + cards.add(new SetCardInfo("Alluring Scent", 121, Rarity.RARE, mage.cards.a.AlluringScent.class)); + cards.add(new SetCardInfo("Ancient Craving", 62, Rarity.RARE, mage.cards.a.AncientCraving.class)); + cards.add(new SetCardInfo("Angel of Fury", 7, Rarity.RARE, mage.cards.a.AngelOfFury.class)); + cards.add(new SetCardInfo("Angel of Mercy", 8, Rarity.UNCOMMON, mage.cards.a.AngelOfMercy.class)); + cards.add(new SetCardInfo("Angelic Blessing", 9, Rarity.COMMON, mage.cards.a.AngelicBlessing.class)); + cards.add(new SetCardInfo("Angelic Wall", 10, Rarity.COMMON, mage.cards.a.AngelicWall.class)); cards.add(new SetCardInfo("Apprentice Sorcerer", 32, Rarity.UNCOMMON, mage.cards.a.ApprenticeSorcerer.class)); - cards.add(new SetCardInfo("Archangel", 131, Rarity.RARE, mage.cards.a.Archangel.class)); - cards.add(new SetCardInfo("Armageddon", 132, Rarity.RARE, mage.cards.a.Armageddon.class)); + cards.add(new SetCardInfo("Archangel", 11, Rarity.RARE, mage.cards.a.Archangel.class)); + cards.add(new SetCardInfo("Armageddon", 12, Rarity.RARE, mage.cards.a.Armageddon.class)); cards.add(new SetCardInfo("Armored Galleon", 33, Rarity.UNCOMMON, mage.cards.a.ArmoredGalleon.class)); - cards.add(new SetCardInfo("Armored Griffin", 133, Rarity.UNCOMMON, mage.cards.a.ArmoredGriffin.class)); - cards.add(new SetCardInfo("Barbtooth Wurm", 62, Rarity.COMMON, mage.cards.b.BarbtoothWurm.class)); - cards.add(new SetCardInfo("Bargain", 134, Rarity.UNCOMMON, mage.cards.b.Bargain.class)); - cards.add(new SetCardInfo("Bear Cub", 63, Rarity.COMMON, mage.cards.b.BearCub.class)); - cards.add(new SetCardInfo("Bee Sting", 64, Rarity.UNCOMMON, mage.cards.b.BeeSting.class)); + cards.add(new SetCardInfo("Armored Griffin", 13, Rarity.UNCOMMON, mage.cards.a.ArmoredGriffin.class)); + cards.add(new SetCardInfo("Barbtooth Wurm", 122, Rarity.COMMON, mage.cards.b.BarbtoothWurm.class)); + cards.add(new SetCardInfo("Bargain", 14, Rarity.UNCOMMON, mage.cards.b.Bargain.class)); + cards.add(new SetCardInfo("Bear Cub", 123, Rarity.COMMON, mage.cards.b.BearCub.class)); + cards.add(new SetCardInfo("Bee Sting", 124, Rarity.UNCOMMON, mage.cards.b.BeeSting.class)); cards.add(new SetCardInfo("Blaze", 91, Rarity.UNCOMMON, mage.cards.b.Blaze.class)); - cards.add(new SetCardInfo("Bloodcurdling Scream", 3, Rarity.UNCOMMON, mage.cards.b.BloodcurdlingScream.class)); - cards.add(new SetCardInfo("Breath of Life", 135, Rarity.COMMON, mage.cards.b.BreathOfLife.class)); + cards.add(new SetCardInfo("Bloodcurdling Scream", 63, Rarity.UNCOMMON, mage.cards.b.BloodcurdlingScream.class)); + cards.add(new SetCardInfo("Breath of Life", 15, Rarity.COMMON, mage.cards.b.BreathOfLife.class)); cards.add(new SetCardInfo("Brimstone Dragon", 92, Rarity.RARE, mage.cards.b.BrimstoneDragon.class)); - cards.add(new SetCardInfo("Brutal Nightstalker", 4, Rarity.UNCOMMON, mage.cards.b.BrutalNightstalker.class)); - cards.add(new SetCardInfo("Chorus of Woe", 5, Rarity.COMMON, mage.cards.c.ChorusOfWoe.class)); + cards.add(new SetCardInfo("Brutal Nightstalker", 64, Rarity.UNCOMMON, mage.cards.b.BrutalNightstalker.class)); + cards.add(new SetCardInfo("Chorus of Woe", 65, Rarity.COMMON, mage.cards.c.ChorusOfWoe.class)); cards.add(new SetCardInfo("Coastal Wizard", 34, Rarity.RARE, mage.cards.c.CoastalWizard.class)); - cards.add(new SetCardInfo("Coercion", 6, Rarity.UNCOMMON, mage.cards.c.Coercion.class)); - cards.add(new SetCardInfo("Cruel Edict", 7, Rarity.COMMON, mage.cards.c.CruelEdict.class)); - cards.add(new SetCardInfo("Dakmor Bat", 8, Rarity.COMMON, mage.cards.d.DakmorBat.class)); - cards.add(new SetCardInfo("Dakmor Plague", 9, Rarity.UNCOMMON, mage.cards.d.DakmorPlague.class)); - cards.add(new SetCardInfo("Dakmor Scorpion", 10, Rarity.COMMON, mage.cards.d.DakmorScorpion.class)); - cards.add(new SetCardInfo("Dakmor Sorceress", 11, Rarity.RARE, mage.cards.d.DakmorSorceress.class)); - cards.add(new SetCardInfo("Dark Offering", 12, Rarity.UNCOMMON, mage.cards.d.DarkOffering.class)); - cards.add(new SetCardInfo("Deathcoil Wurm", 65, Rarity.RARE, mage.cards.d.DeathcoilWurm.class)); - cards.add(new SetCardInfo("Deep Wood", 66, Rarity.UNCOMMON, mage.cards.d.DeepWood.class)); - cards.add(new SetCardInfo("Deja Vu", 35, Rarity.COMMON, mage.cards.d.DejaVu.class)); - cards.add(new SetCardInfo("Denizen of the Deep", 36, Rarity.RARE, mage.cards.d.DenizenOfTheDeep.class)); + cards.add(new SetCardInfo("Coercion", 66, Rarity.UNCOMMON, mage.cards.c.Coercion.class)); + cards.add(new SetCardInfo("Cruel Edict", 67, Rarity.COMMON, mage.cards.c.CruelEdict.class)); + cards.add(new SetCardInfo("Dakmor Bat", 68, Rarity.COMMON, mage.cards.d.DakmorBat.class)); + cards.add(new SetCardInfo("Dakmor Plague", 69, Rarity.UNCOMMON, mage.cards.d.DakmorPlague.class)); + cards.add(new SetCardInfo("Dakmor Scorpion", 70, Rarity.COMMON, mage.cards.d.DakmorScorpion.class)); + cards.add(new SetCardInfo("Dakmor Sorceress", 71, Rarity.RARE, mage.cards.d.DakmorSorceress.class)); + cards.add(new SetCardInfo("Dark Offering", 72, Rarity.UNCOMMON, mage.cards.d.DarkOffering.class)); + cards.add(new SetCardInfo("Deathcoil Wurm", 125, Rarity.RARE, mage.cards.d.DeathcoilWurm.class)); + cards.add(new SetCardInfo("Deep Wood", 126, Rarity.UNCOMMON, mage.cards.d.DeepWood.class)); + cards.add(new SetCardInfo("Deja Vu", 36, Rarity.COMMON, mage.cards.d.DejaVu.class)); + cards.add(new SetCardInfo("Denizen of the Deep", 35, Rarity.RARE, mage.cards.d.DenizenOfTheDeep.class)); cards.add(new SetCardInfo("Earthquake", 94, Rarity.RARE, mage.cards.e.Earthquake.class)); cards.add(new SetCardInfo("Exhaustion", 37, Rarity.RARE, mage.cards.e.Exhaustion.class)); cards.add(new SetCardInfo("Extinguish", 38, Rarity.COMMON, mage.cards.e.Extinguish.class)); cards.add(new SetCardInfo("Eye Spy", 39, Rarity.UNCOMMON, mage.cards.e.EyeSpy.class)); cards.add(new SetCardInfo("False Summoning", 40, Rarity.COMMON, mage.cards.f.FalseSummoning.class)); - cards.add(new SetCardInfo("Festival of Trokin", 136, Rarity.COMMON, mage.cards.f.FestivalOfTrokin.class)); - cards.add(new SetCardInfo("Forest", 151, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 152, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 153, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Foul Spirit", 13, Rarity.UNCOMMON, mage.cards.f.FoulSpirit.class)); + cards.add(new SetCardInfo("Festival of Trokin", 16, Rarity.COMMON, mage.cards.f.FestivalOfTrokin.class)); + cards.add(new SetCardInfo("Forest", 163, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 164, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 165, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Foul Spirit", 73, Rarity.UNCOMMON, mage.cards.f.FoulSpirit.class)); cards.add(new SetCardInfo("Goblin Cavaliers", 95, Rarity.COMMON, mage.cards.g.GoblinCavaliers.class)); cards.add(new SetCardInfo("Goblin Firestarter", 96, Rarity.UNCOMMON, mage.cards.g.GoblinFirestarter.class)); cards.add(new SetCardInfo("Goblin General", 97, Rarity.RARE, mage.cards.g.GoblinGeneral.class)); @@ -93,106 +93,106 @@ public final class PortalSecondAge extends ExpansionSet { cards.add(new SetCardInfo("Goblin Raider", 103, Rarity.COMMON, mage.cards.g.GoblinRaider.class)); cards.add(new SetCardInfo("Goblin War Cry", 104, Rarity.UNCOMMON, mage.cards.g.GoblinWarCry.class)); cards.add(new SetCardInfo("Goblin War Strike", 105, Rarity.COMMON, mage.cards.g.GoblinWarStrike.class)); - cards.add(new SetCardInfo("Golden Bear", 67, Rarity.COMMON, mage.cards.g.GoldenBear.class)); - cards.add(new SetCardInfo("Hand of Death", 14, Rarity.COMMON, mage.cards.h.HandOfDeath.class)); - cards.add(new SetCardInfo("Harmony of Nature", 68, Rarity.UNCOMMON, mage.cards.h.HarmonyOfNature.class)); - cards.add(new SetCardInfo("Hidden Horror", 15, Rarity.RARE, mage.cards.h.HiddenHorror.class)); - cards.add(new SetCardInfo("Hurricane", 69, Rarity.RARE, mage.cards.h.Hurricane.class)); - cards.add(new SetCardInfo("Ironhoof Ox", 70, Rarity.UNCOMMON, mage.cards.i.IronhoofOx.class)); + cards.add(new SetCardInfo("Golden Bear", 127, Rarity.COMMON, mage.cards.g.GoldenBear.class)); + cards.add(new SetCardInfo("Hand of Death", 74, Rarity.COMMON, mage.cards.h.HandOfDeath.class)); + cards.add(new SetCardInfo("Harmony of Nature", 128, Rarity.UNCOMMON, mage.cards.h.HarmonyOfNature.class)); + cards.add(new SetCardInfo("Hidden Horror", 75, Rarity.RARE, mage.cards.h.HiddenHorror.class)); + cards.add(new SetCardInfo("Hurricane", 129, Rarity.RARE, mage.cards.h.Hurricane.class)); + cards.add(new SetCardInfo("Ironhoof Ox", 130, Rarity.UNCOMMON, mage.cards.i.IronhoofOx.class)); cards.add(new SetCardInfo("Island", 154, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 155, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 156, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jagged Lightning", 106, Rarity.UNCOMMON, mage.cards.j.JaggedLightning.class)); - cards.add(new SetCardInfo("Just Fate", 137, Rarity.RARE, mage.cards.j.JustFate.class)); - cards.add(new SetCardInfo("Kiss of Death", 16, Rarity.UNCOMMON, mage.cards.k.KissOfDeath.class)); + cards.add(new SetCardInfo("Just Fate", 17, Rarity.RARE, mage.cards.j.JustFate.class)); + cards.add(new SetCardInfo("Kiss of Death", 76, Rarity.UNCOMMON, mage.cards.k.KissOfDeath.class)); cards.add(new SetCardInfo("Lava Axe", 107, Rarity.COMMON, mage.cards.l.LavaAxe.class)); - cards.add(new SetCardInfo("Lone Wolf", 71, Rarity.UNCOMMON, mage.cards.l.LoneWolf.class)); - cards.add(new SetCardInfo("Lurking Nightstalker", 17, Rarity.COMMON, mage.cards.l.LurkingNightstalker.class)); - cards.add(new SetCardInfo("Lynx", 72, Rarity.COMMON, mage.cards.l.Lynx.class)); + cards.add(new SetCardInfo("Lone Wolf", 131, Rarity.UNCOMMON, mage.cards.l.LoneWolf.class)); + cards.add(new SetCardInfo("Lurking Nightstalker", 77, Rarity.COMMON, mage.cards.l.LurkingNightstalker.class)); + cards.add(new SetCardInfo("Lynx", 132, Rarity.COMMON, mage.cards.l.Lynx.class)); cards.add(new SetCardInfo("Magma Giant", 108, Rarity.RARE, mage.cards.m.MagmaGiant.class)); - cards.add(new SetCardInfo("Mind Rot", 18, Rarity.COMMON, mage.cards.m.MindRot.class)); - cards.add(new SetCardInfo("Moaning Spirit", 19, Rarity.COMMON, mage.cards.m.MoaningSpirit.class)); - cards.add(new SetCardInfo("Monstrous Growth", 73, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class)); - cards.add(new SetCardInfo("Mountain", 157, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 158, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 159, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Muck Rats", 20, Rarity.COMMON, mage.cards.m.MuckRats.class)); + cards.add(new SetCardInfo("Mind Rot", 78, Rarity.COMMON, mage.cards.m.MindRot.class)); + cards.add(new SetCardInfo("Moaning Spirit", 79, Rarity.COMMON, mage.cards.m.MoaningSpirit.class)); + cards.add(new SetCardInfo("Monstrous Growth", 133, Rarity.COMMON, mage.cards.m.MonstrousGrowth.class)); + cards.add(new SetCardInfo("Mountain", 160, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 161, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 162, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Muck Rats", 80, Rarity.COMMON, mage.cards.m.MuckRats.class)); cards.add(new SetCardInfo("Mystic Denial", 41, Rarity.UNCOMMON, mage.cards.m.MysticDenial.class)); - cards.add(new SetCardInfo("Natural Spring", 74, Rarity.COMMON, mage.cards.n.NaturalSpring.class)); - cards.add(new SetCardInfo("Nature's Lore", 75, Rarity.COMMON, mage.cards.n.NaturesLore.class)); - cards.add(new SetCardInfo("Nightstalker Engine", 21, Rarity.RARE, mage.cards.n.NightstalkerEngine.class)); - cards.add(new SetCardInfo("Norwood Archers", 76, Rarity.COMMON, mage.cards.n.NorwoodArchers.class)); - cards.add(new SetCardInfo("Norwood Priestess", 77, Rarity.RARE, mage.cards.n.NorwoodPriestess.class)); - cards.add(new SetCardInfo("Norwood Ranger", 78, Rarity.COMMON, mage.cards.n.NorwoodRanger.class)); - cards.add(new SetCardInfo("Norwood Riders", 79, Rarity.COMMON, mage.cards.n.NorwoodRiders.class)); - cards.add(new SetCardInfo("Norwood Warrior", 80, Rarity.COMMON, mage.cards.n.NorwoodWarrior.class)); + cards.add(new SetCardInfo("Natural Spring", 134, Rarity.COMMON, mage.cards.n.NaturalSpring.class)); + cards.add(new SetCardInfo("Nature's Lore", 135, Rarity.COMMON, mage.cards.n.NaturesLore.class)); + cards.add(new SetCardInfo("Nightstalker Engine", 81, Rarity.RARE, mage.cards.n.NightstalkerEngine.class)); + cards.add(new SetCardInfo("Norwood Archers", 136, Rarity.COMMON, mage.cards.n.NorwoodArchers.class)); + cards.add(new SetCardInfo("Norwood Priestess", 137, Rarity.RARE, mage.cards.n.NorwoodPriestess.class)); + cards.add(new SetCardInfo("Norwood Ranger", 138, Rarity.COMMON, mage.cards.n.NorwoodRanger.class)); + cards.add(new SetCardInfo("Norwood Riders", 139, Rarity.COMMON, mage.cards.n.NorwoodRiders.class)); + cards.add(new SetCardInfo("Norwood Warrior", 140, Rarity.COMMON, mage.cards.n.NorwoodWarrior.class)); cards.add(new SetCardInfo("Obsidian Giant", 109, Rarity.UNCOMMON, mage.cards.o.ObsidianGiant.class)); cards.add(new SetCardInfo("Ogre Arsonist", 110, Rarity.UNCOMMON, mage.cards.o.OgreArsonist.class)); cards.add(new SetCardInfo("Ogre Berserker", 111, Rarity.COMMON, mage.cards.o.OgreBerserker.class)); cards.add(new SetCardInfo("Ogre Taskmaster", 112, Rarity.UNCOMMON, mage.cards.o.OgreTaskmaster.class)); cards.add(new SetCardInfo("Ogre Warrior", 113, Rarity.COMMON, mage.cards.o.OgreWarrior.class)); - cards.add(new SetCardInfo("Path of Peace", 138, Rarity.COMMON, mage.cards.p.PathOfPeace.class)); - cards.add(new SetCardInfo("Plains", 160, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 161, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 162, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plated Wurm", 81, Rarity.COMMON, mage.cards.p.PlatedWurm.class)); - cards.add(new SetCardInfo("Predatory Nightstalker", 22, Rarity.UNCOMMON, mage.cards.p.PredatoryNightstalker.class)); - cards.add(new SetCardInfo("Prowling Nightstalker", 23, Rarity.COMMON, mage.cards.p.ProwlingNightstalker.class)); + cards.add(new SetCardInfo("Path of Peace", 18, Rarity.COMMON, mage.cards.p.PathOfPeace.class)); + cards.add(new SetCardInfo("Plains", 151, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 152, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 153, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plated Wurm", 141, Rarity.COMMON, mage.cards.p.PlatedWurm.class)); + cards.add(new SetCardInfo("Predatory Nightstalker", 82, Rarity.UNCOMMON, mage.cards.p.PredatoryNightstalker.class)); + cards.add(new SetCardInfo("Prowling Nightstalker", 83, Rarity.COMMON, mage.cards.p.ProwlingNightstalker.class)); cards.add(new SetCardInfo("Raging Goblin", 114, Rarity.COMMON, mage.cards.r.RagingGoblin.class)); - cards.add(new SetCardInfo("Raiding Nightstalker", 24, Rarity.COMMON, mage.cards.r.RaidingNightstalker.class)); - cards.add(new SetCardInfo("Rain of Daggers", 25, Rarity.RARE, mage.cards.r.RainOfDaggers.class)); - cards.add(new SetCardInfo("Raise Dead", 26, Rarity.COMMON, mage.cards.r.RaiseDead.class)); - cards.add(new SetCardInfo("Rally the Troops", 139, Rarity.UNCOMMON, mage.cards.r.RallyTheTroops.class)); - cards.add(new SetCardInfo("Ravenous Rats", 27, Rarity.COMMON, mage.cards.r.RavenousRats.class)); - cards.add(new SetCardInfo("Razorclaw Bear", 82, Rarity.RARE, mage.cards.r.RazorclawBear.class)); + cards.add(new SetCardInfo("Raiding Nightstalker", 84, Rarity.COMMON, mage.cards.r.RaidingNightstalker.class)); + cards.add(new SetCardInfo("Rain of Daggers", 85, Rarity.RARE, mage.cards.r.RainOfDaggers.class)); + cards.add(new SetCardInfo("Raise Dead", 86, Rarity.COMMON, mage.cards.r.RaiseDead.class)); + cards.add(new SetCardInfo("Rally the Troops", 19, Rarity.UNCOMMON, mage.cards.r.RallyTheTroops.class)); + cards.add(new SetCardInfo("Ravenous Rats", 87, Rarity.COMMON, mage.cards.r.RavenousRats.class)); + cards.add(new SetCardInfo("Razorclaw Bear", 142, Rarity.RARE, mage.cards.r.RazorclawBear.class)); cards.add(new SetCardInfo("Relentless Assault", 115, Rarity.RARE, mage.cards.r.RelentlessAssault.class)); cards.add(new SetCardInfo("Remove", 43, Rarity.UNCOMMON, mage.cards.r.Remove.class)); - cards.add(new SetCardInfo("Renewing Touch", 83, Rarity.UNCOMMON, mage.cards.r.RenewingTouch.class)); - cards.add(new SetCardInfo("Return of the Nightstalkers", 28, Rarity.RARE, mage.cards.r.ReturnOfTheNightstalkers.class)); - cards.add(new SetCardInfo("Righteous Charge", 140, Rarity.COMMON, mage.cards.r.RighteousCharge.class)); - cards.add(new SetCardInfo("Righteous Fury", 141, Rarity.RARE, mage.cards.r.RighteousFury.class)); - cards.add(new SetCardInfo("River Bear", 84, Rarity.UNCOMMON, mage.cards.r.RiverBear.class)); - cards.add(new SetCardInfo("Salvage", 85, Rarity.COMMON, mage.cards.s.Salvage.class)); + cards.add(new SetCardInfo("Renewing Touch", 143, Rarity.UNCOMMON, mage.cards.r.RenewingTouch.class)); + cards.add(new SetCardInfo("Return of the Nightstalkers", 88, Rarity.RARE, mage.cards.r.ReturnOfTheNightstalkers.class)); + cards.add(new SetCardInfo("Righteous Charge", 20, Rarity.COMMON, mage.cards.r.RighteousCharge.class)); + cards.add(new SetCardInfo("Righteous Fury", 21, Rarity.RARE, mage.cards.r.RighteousFury.class)); + cards.add(new SetCardInfo("River Bear", 144, Rarity.UNCOMMON, mage.cards.r.RiverBear.class)); + cards.add(new SetCardInfo("Salvage", 145, Rarity.COMMON, mage.cards.s.Salvage.class)); cards.add(new SetCardInfo("Screeching Drake", 44, Rarity.COMMON, mage.cards.s.ScreechingDrake.class)); cards.add(new SetCardInfo("Sea Drake", 45, Rarity.UNCOMMON, mage.cards.s.SeaDrake.class)); cards.add(new SetCardInfo("Sleight of Hand", 46, Rarity.COMMON, mage.cards.s.SleightOfHand.class)); cards.add(new SetCardInfo("Spitting Earth", 116, Rarity.COMMON, mage.cards.s.SpittingEarth.class)); - cards.add(new SetCardInfo("Steam Catapult", 142, Rarity.RARE, mage.cards.s.SteamCatapult.class)); + cards.add(new SetCardInfo("Steam Catapult", 22, Rarity.RARE, mage.cards.s.SteamCatapult.class)); cards.add(new SetCardInfo("Steam Frigate", 47, Rarity.COMMON, mage.cards.s.SteamFrigate.class)); cards.add(new SetCardInfo("Stone Rain", 117, Rarity.COMMON, mage.cards.s.StoneRain.class)); - cards.add(new SetCardInfo("Swamp", 163, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 164, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 165, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swarm of Rats", 29, Rarity.COMMON, mage.cards.s.SwarmOfRats.class)); - cards.add(new SetCardInfo("Sylvan Basilisk", 86, Rarity.RARE, mage.cards.s.SylvanBasilisk.class)); - cards.add(new SetCardInfo("Sylvan Yeti", 87, Rarity.RARE, mage.cards.s.SylvanYeti.class)); + cards.add(new SetCardInfo("Swamp", 157, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 158, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 159, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swarm of Rats", 89, Rarity.COMMON, mage.cards.s.SwarmOfRats.class)); + cards.add(new SetCardInfo("Sylvan Basilisk", 146, Rarity.RARE, mage.cards.s.SylvanBasilisk.class)); + cards.add(new SetCardInfo("Sylvan Yeti", 147, Rarity.RARE, mage.cards.s.SylvanYeti.class)); cards.add(new SetCardInfo("Talas Air Ship", 48, Rarity.COMMON, mage.cards.t.TalasAirShip.class)); cards.add(new SetCardInfo("Talas Explorer", 49, Rarity.COMMON, mage.cards.t.TalasExplorer.class)); cards.add(new SetCardInfo("Talas Merchant", 50, Rarity.COMMON, mage.cards.t.TalasMerchant.class)); cards.add(new SetCardInfo("Talas Researcher", 51, Rarity.RARE, mage.cards.t.TalasResearcher.class)); cards.add(new SetCardInfo("Talas Scout", 52, Rarity.COMMON, mage.cards.t.TalasScout.class)); cards.add(new SetCardInfo("Talas Warrior", 53, Rarity.RARE, mage.cards.t.TalasWarrior.class)); - cards.add(new SetCardInfo("Temple Acolyte", 143, Rarity.COMMON, mage.cards.t.TempleAcolyte.class)); - cards.add(new SetCardInfo("Temple Elder", 144, Rarity.UNCOMMON, mage.cards.t.TempleElder.class)); + cards.add(new SetCardInfo("Temple Acolyte", 23, Rarity.COMMON, mage.cards.t.TempleAcolyte.class)); + cards.add(new SetCardInfo("Temple Elder", 24, Rarity.UNCOMMON, mage.cards.t.TempleElder.class)); cards.add(new SetCardInfo("Temporal Manipulation", 54, Rarity.RARE, mage.cards.t.TemporalManipulation.class)); cards.add(new SetCardInfo("Theft of Dreams", 55, Rarity.UNCOMMON, mage.cards.t.TheftOfDreams.class)); cards.add(new SetCardInfo("Tidal Surge", 56, Rarity.COMMON, mage.cards.t.TidalSurge.class)); cards.add(new SetCardInfo("Time Ebb", 57, Rarity.COMMON, mage.cards.t.TimeEbb.class)); cards.add(new SetCardInfo("Touch of Brilliance", 58, Rarity.COMMON, mage.cards.t.TouchOfBrilliance.class)); - cards.add(new SetCardInfo("Town Sentry", 145, Rarity.COMMON, mage.cards.t.TownSentry.class)); - cards.add(new SetCardInfo("Tree Monkey", 88, Rarity.COMMON, mage.cards.t.TreeMonkey.class)); + cards.add(new SetCardInfo("Town Sentry", 25, Rarity.COMMON, mage.cards.t.TownSentry.class)); + cards.add(new SetCardInfo("Tree Monkey", 148, Rarity.COMMON, mage.cards.t.TreeMonkey.class)); cards.add(new SetCardInfo("Tremor", 118, Rarity.COMMON, mage.cards.t.Tremor.class)); - cards.add(new SetCardInfo("Trokin High Guard", 146, Rarity.COMMON, mage.cards.t.TrokinHighGuard.class)); + cards.add(new SetCardInfo("Trokin High Guard", 26, Rarity.COMMON, mage.cards.t.TrokinHighGuard.class)); cards.add(new SetCardInfo("Undo", 59, Rarity.UNCOMMON, mage.cards.u.Undo.class)); - cards.add(new SetCardInfo("Untamed Wilds", 89, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); - cards.add(new SetCardInfo("Vampiric Spirit", 30, Rarity.RARE, mage.cards.v.VampiricSpirit.class)); - cards.add(new SetCardInfo("Vengeance", 147, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); + cards.add(new SetCardInfo("Untamed Wilds", 149, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); + cards.add(new SetCardInfo("Vampiric Spirit", 90, Rarity.RARE, mage.cards.v.VampiricSpirit.class)); + cards.add(new SetCardInfo("Vengeance", 27, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); cards.add(new SetCardInfo("Volcanic Hammer", 119, Rarity.COMMON, mage.cards.v.VolcanicHammer.class)); - cards.add(new SetCardInfo("Volunteer Militia", 148, Rarity.COMMON, mage.cards.v.VolunteerMilitia.class)); - cards.add(new SetCardInfo("Warrior's Stand", 149, Rarity.UNCOMMON, mage.cards.w.WarriorsStand.class)); + cards.add(new SetCardInfo("Volunteer Militia", 28, Rarity.COMMON, mage.cards.v.VolunteerMilitia.class)); + cards.add(new SetCardInfo("Warrior's Stand", 29, Rarity.UNCOMMON, mage.cards.w.WarriorsStand.class)); + cards.add(new SetCardInfo("Wild Griffin", 30, Rarity.COMMON, mage.cards.w.WildGriffin.class)); + cards.add(new SetCardInfo("Wild Ox", 150, Rarity.UNCOMMON, mage.cards.w.WildOx.class)); cards.add(new SetCardInfo("Wildfire", 120, Rarity.RARE, mage.cards.w.Wildfire.class)); - cards.add(new SetCardInfo("Wild Griffin", 150, Rarity.COMMON, mage.cards.w.WildGriffin.class)); - cards.add(new SetCardInfo("Wild Ox", 90, Rarity.UNCOMMON, mage.cards.w.WildOx.class)); cards.add(new SetCardInfo("Wind Sail", 60, Rarity.COMMON, mage.cards.w.WindSail.class)); } } diff --git a/Mage.Sets/src/mage/sets/ScarsOfMirrodin.java b/Mage.Sets/src/mage/sets/ScarsOfMirrodin.java index 93cf471f043..0742778d39d 100644 --- a/Mage.Sets/src/mage/sets/ScarsOfMirrodin.java +++ b/Mage.Sets/src/mage/sets/ScarsOfMirrodin.java @@ -244,7 +244,7 @@ public final class ScarsOfMirrodin extends ExpansionSet { cards.add(new SetCardInfo("Tel-Jilad Defiance", 129, Rarity.COMMON, mage.cards.t.TelJiladDefiance.class)); cards.add(new SetCardInfo("Tel-Jilad Fallen", 130, Rarity.COMMON, mage.cards.t.TelJiladFallen.class)); cards.add(new SetCardInfo("Tempered Steel", 24, Rarity.RARE, mage.cards.t.TemperedSteel.class)); - cards.add(new SetCardInfo("Throne of Geth", 211, Rarity.UNCOMMON, mage.cards.t.ThroneofGeth.class)); + cards.add(new SetCardInfo("Throne of Geth", 211, Rarity.UNCOMMON, mage.cards.t.ThroneOfGeth.class)); cards.add(new SetCardInfo("Thrummingbird", 47, Rarity.UNCOMMON, mage.cards.t.Thrummingbird.class)); cards.add(new SetCardInfo("Tower of Calamities", 212, Rarity.RARE, mage.cards.t.TowerOfCalamities.class)); cards.add(new SetCardInfo("Trigon of Corruption", 213, Rarity.UNCOMMON, mage.cards.t.TrigonOfCorruption.class)); diff --git a/Mage.Sets/src/mage/sets/StarWars.java b/Mage.Sets/src/mage/sets/StarWars.java index 639afc2c3ba..64a7d9de17f 100644 --- a/Mage.Sets/src/mage/sets/StarWars.java +++ b/Mage.Sets/src/mage/sets/StarWars.java @@ -35,6 +35,7 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Acquire Target", 65, Rarity.COMMON, mage.cards.a.AcquireTarget.class)); cards.add(new SetCardInfo("Admiral Ackbar", 35, Rarity.RARE, mage.cards.a.AdmiralAckbar.class)); cards.add(new SetCardInfo("Adroit Hateflayer", 162, Rarity.COMMON, mage.cards.a.AdroitHateflayer.class)); + cards.add(new SetCardInfo("Afterburn", 600, Rarity.COMMON, mage.cards.a.Afterburn.class)); cards.add(new SetCardInfo("Anakin Skywalker", 163, Rarity.MYTHIC, mage.cards.a.AnakinSkywalker.class)); cards.add(new SetCardInfo("Ancient Holocron", 230, Rarity.UNCOMMON, mage.cards.a.AncientHolocron.class)); cards.add(new SetCardInfo("Aqualish Bounty Hunter", 66, Rarity.COMMON, mage.cards.a.AqualishBountyHunter.class)); @@ -42,6 +43,7 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Arrest", 2, Rarity.COMMON, mage.cards.a.Arrest.class)); cards.add(new SetCardInfo("Asajj Ventress", 164, Rarity.RARE, mage.cards.a.AsajjVentress.class)); cards.add(new SetCardInfo("AT-ST", 128, Rarity.RARE, mage.cards.a.ATST.class)); + cards.add(new SetCardInfo("Astromech Droid", 400, Rarity.COMMON, mage.cards.a.AstromechDroid.class)); cards.add(new SetCardInfo("Aurra Sing, Bane of Jedi", 165, Rarity.MYTHIC, mage.cards.a.AurraSingBaneOfJedi.class)); cards.add(new SetCardInfo("Bantha Herd", 3, Rarity.RARE, mage.cards.b.BanthaHerd.class)); cards.add(new SetCardInfo("Bathe in Bacta", 129, Rarity.COMMON, mage.cards.b.BatheInBacta.class)); @@ -49,7 +51,10 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Bib Fortuna", 68, Rarity.RARE, mage.cards.b.BibFortuna.class)); cards.add(new SetCardInfo("Black Market Dealer", 69, Rarity.UNCOMMON, mage.cards.b.BlackMarketDealer.class)); cards.add(new SetCardInfo("Blind Worship", 166, Rarity.RARE, mage.cards.b.BlindWorship.class)); + cards.add(new SetCardInfo("Bludgeoning Pain", 300, Rarity.COMMON, mage.cards.b.BludgeoningPain.class)); + cards.add(new SetCardInfo("Buried Ruin", 401, Rarity.COMMON, mage.cards.b.BuriedRuin.class)); cards.add(new SetCardInfo("Boba Fett", 167, Rarity.MYTHIC, mage.cards.b.BobaFett.class)); + cards.add(new SetCardInfo("Bor Gullet", 301, Rarity.UNCOMMON, mage.cards.b.BorGullet.class)); cards.add(new SetCardInfo("Bossk", 131, Rarity.RARE, mage.cards.b.Bossk.class)); cards.add(new SetCardInfo("Bounty Collector", 132, Rarity.UNCOMMON, mage.cards.b.BountyCollector.class)); cards.add(new SetCardInfo("Bounty Sniper", 98, Rarity.UNCOMMON, mage.cards.b.BountySniper.class)); @@ -57,14 +62,22 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Bull Rancor", 168, Rarity.RARE, mage.cards.b.BullRancor.class)); cards.add(new SetCardInfo("C-3PO and R2D2", 169, Rarity.RARE, mage.cards.c.C3POAndR2D2.class)); cards.add(new SetCardInfo("Cantina Band", 6, Rarity.COMMON, mage.cards.c.CantinaBand.class)); + cards.add(new SetCardInfo("Canto Bight Enforcer", 500, Rarity.UNCOMMON, mage.cards.c.CantoBightEnforcer.class)); + cards.add(new SetCardInfo("Cantonica Casino", 501, Rarity.RARE, mage.cards.c.CantonicaCasino.class)); + cards.add(new SetCardInfo("Captain Phasma", 502, Rarity.RARE, mage.cards.c.CaptainPhasma.class)); cards.add(new SetCardInfo("Capture", 99, Rarity.COMMON, mage.cards.c.Capture.class)); cards.add(new SetCardInfo("Carbonite Chamber", 170, Rarity.UNCOMMON, mage.cards.c.CarboniteChamber.class)); cards.add(new SetCardInfo("Chewbacca", 171, Rarity.RARE, mage.cards.c.Chewbacca.class)); + cards.add(new SetCardInfo("Chewbacca, the Beast", 601, Rarity.RARE, mage.cards.c.ChewbaccaTheBeast.class)); cards.add(new SetCardInfo("Chief Chirpa", 172, Rarity.RARE, mage.cards.c.ChiefChirpa.class)); + cards.add(new SetCardInfo("Chirrut Imwe", 302, Rarity.RARE, mage.cards.c.ChirrutImwe.class)); cards.add(new SetCardInfo("Cloaking Device", 38, Rarity.COMMON, mage.cards.c.CloakingDevice.class)); + cards.add(new SetCardInfo("Code Slice", 503, Rarity.COMMON, mage.cards.c.CodeSlice.class)); cards.add(new SetCardInfo("Commander Cody", 173, Rarity.RARE, mage.cards.c.CommanderCody.class)); cards.add(new SetCardInfo("Condemn", 7, Rarity.UNCOMMON, mage.cards.c.Condemn.class)); + cards.add(new SetCardInfo("Conscription", 602, Rarity.UNCOMMON, mage.cards.c.Conscription.class)); cards.add(new SetCardInfo("Corellian Corvette", 133, Rarity.UNCOMMON, mage.cards.c.CorellianCorvette.class)); + cards.add(new SetCardInfo("Corellian Gunship", 603, Rarity.COMMON, mage.cards.c.CorellianGunship.class)); cards.add(new SetCardInfo("Crossfire", 100, Rarity.COMMON, mage.cards.c.Crossfire.class)); cards.add(new SetCardInfo("Cruelty of the Sith", 174, Rarity.UNCOMMON, mage.cards.c.CrueltyOfTheSith.class)); cards.add(new SetCardInfo("Cunning Abduction", 175, Rarity.RARE, mage.cards.c.CunningAbduction.class)); @@ -74,24 +87,34 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Dark Trooper", 231, Rarity.UNCOMMON, mage.cards.d.DarkTrooper.class)); cards.add(new SetCardInfo("Darth Maul", 178, Rarity.RARE, mage.cards.d.DarthMaul.class)); cards.add(new SetCardInfo("Darth Sidious, Sith Lord", 179, Rarity.MYTHIC, mage.cards.d.DarthSidiousSithLord.class)); - cards.add(new SetCardInfo("Darth Tyranus", 180, Rarity.MYTHIC, mage.cards.d.DarthTyranus.class)); + cards.add(new SetCardInfo("Darth Tyranus, Count of Serenno", 180, Rarity.MYTHIC, mage.cards.d.DarthTyranusCountOfSerenno.class)); cards.add(new SetCardInfo("Darth Vader", 140, Rarity.MYTHIC, mage.cards.d.DarthVader.class)); cards.add(new SetCardInfo("Death Trooper", 71, Rarity.UNCOMMON, mage.cards.d.DeathTrooper.class)); + cards.add(new SetCardInfo("Delay Tactic", 504, Rarity.COMMON, mage.cards.d.DelayTactic.class)); cards.add(new SetCardInfo("Deploy The Troops", 8, Rarity.UNCOMMON, mage.cards.d.DeployTheTroops.class)); + cards.add(new SetCardInfo("Despair", 604, Rarity.UNCOMMON, mage.cards.d.Despair.class)); + cards.add(new SetCardInfo("Director Krennic", 303, Rarity.RARE, mage.cards.d.DirectorKrennic.class)); cards.add(new SetCardInfo("Doom Blade", 72, Rarity.UNCOMMON, mage.cards.d.DoomBlade.class)); cards.add(new SetCardInfo("Droid Commando", 73, Rarity.COMMON, mage.cards.d.DroidCommando.class)); cards.add(new SetCardInfo("Droid Factory", 239, Rarity.COMMON, mage.cards.d.DroidFactory.class)); cards.add(new SetCardInfo("Droid Foundry", 240, Rarity.UNCOMMON, mage.cards.d.DroidFoundry.class)); + cards.add(new SetCardInfo("Droid Uprising", 605, Rarity.UNCOMMON, mage.cards.d.DroidUprising.class)); cards.add(new SetCardInfo("Droideka", 9, Rarity.UNCOMMON, mage.cards.d.Droideka.class)); cards.add(new SetCardInfo("Drone Holocron", 232, Rarity.COMMON, mage.cards.d.DroneHolocron.class)); + cards.add(new SetCardInfo("Dryden Vos", 606, Rarity.RARE, mage.cards.d.DrydenVos.class)); cards.add(new SetCardInfo("Echo Base Commando", 181, Rarity.RARE, mage.cards.e.EchoBaseCommando.class)); cards.add(new SetCardInfo("EMP Blast", 10, Rarity.UNCOMMON, mage.cards.e.EMPBlast.class)); + cards.add(new SetCardInfo("Enfys Nest", 607, Rarity.MYTHIC, mage.cards.e.EnfysNest.class)); cards.add(new SetCardInfo("Escape Pod", 11, Rarity.COMMON, mage.cards.e.EscapePod.class)); cards.add(new SetCardInfo("Ewok Ambush", 134, Rarity.COMMON, mage.cards.e.EwokAmbush.class)); cards.add(new SetCardInfo("Ewok Firedancers", 135, Rarity.COMMON, mage.cards.e.EwokFiredancers.class)); cards.add(new SetCardInfo("Ewok Village", 241, Rarity.UNCOMMON, mage.cards.e.EwokVillage.class)); cards.add(new SetCardInfo("Exogorth", 136, Rarity.RARE, mage.cards.e.Exogorth.class)); + cards.add(new SetCardInfo("Fathier", 505, Rarity.COMMON, mage.cards.f.Fathier.class)); cards.add(new SetCardInfo("Ferocity of the Underworld", 182, Rarity.UNCOMMON, mage.cards.f.FerocityOfTheUnderworld.class)); + cards.add(new SetCardInfo("Finn", 402, Rarity.UNCOMMON, mage.cards.f.Finn.class)); + cards.add(new SetCardInfo("First Order Dreadnought", 506, Rarity.MYTHIC, mage.cards.f.FirstOrderDreadnought.class)); + cards.add(new SetCardInfo("Flame Trooper", 403, Rarity.COMMON, mage.cards.f.FlameTrooper.class)); cards.add(new SetCardInfo("Flames of Remembrance", 102, Rarity.RARE, mage.cards.f.FlamesOfRemembrance.class)); cards.add(new SetCardInfo("Force Choke", 183, Rarity.COMMON, mage.cards.f.ForceChoke.class)); cards.add(new SetCardInfo("Force Denial", 39, Rarity.COMMON, mage.cards.f.ForceDenial.class)); @@ -99,25 +122,35 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Force Healing", 12, Rarity.COMMON, mage.cards.f.ForceHealing.class)); cards.add(new SetCardInfo("Force Lightning", 103, Rarity.RARE, mage.cards.f.ForceLightning.class)); cards.add(new SetCardInfo("Force Mastery", 184, Rarity.RARE, mage.cards.f.ForceMastery.class)); + cards.add(new SetCardInfo("Force Projection", 507, Rarity.RARE, mage.cards.f.ForceProjection.class)); + cards.add(new SetCardInfo("Force Protection", 304, Rarity.COMMON, mage.cards.f.ForceProtection.class)); cards.add(new SetCardInfo("Force Pull", 137, Rarity.COMMON, mage.cards.f.ForcePull.class)); cards.add(new SetCardInfo("Force Push", 40, Rarity.UNCOMMON, mage.cards.f.ForcePush.class)); cards.add(new SetCardInfo("Force Reflex", 13, Rarity.COMMON, mage.cards.f.ForceReflex.class)); cards.add(new SetCardInfo("Force Scream", 104, Rarity.UNCOMMON, mage.cards.f.ForceScream.class)); cards.add(new SetCardInfo("Force Spark", 105, Rarity.COMMON, mage.cards.f.ForceSpark.class)); + cards.add(new SetCardInfo("Force Stasis", 404, Rarity.COMMON, mage.cards.f.ForceStasis.class)); + cards.add(new SetCardInfo("Force Telepathy", 508, Rarity.COMMON, mage.cards.f.ForceTelepathy.class)); cards.add(new SetCardInfo("Forest", "268a", Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Forest", "268b", Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Forest", "268c", Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Forest", "268d", Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Fulfill Contract", 224, Rarity.COMMON, mage.cards.f.FulfillContract.class)); + cards.add(new SetCardInfo("Gamble", 608, Rarity.RARE, mage.cards.g.Gamble.class)); cards.add(new SetCardInfo("Gamorrean Prison Guard", 106, Rarity.UNCOMMON, mage.cards.g.GamorreanPrisonGuard.class)); cards.add(new SetCardInfo("General Grievous", 185, Rarity.MYTHIC, mage.cards.g.GeneralGrievous.class)); + cards.add(new SetCardInfo("General Hux", 405, Rarity.UNCOMMON, mage.cards.g.GeneralHux.class)); + cards.add(new SetCardInfo("Gerrera's Revolutionary", 305, Rarity.COMMON, mage.cards.g.GerrerasRevolutionary.class)); cards.add(new SetCardInfo("Gifted Initiate", 14, Rarity.COMMON, mage.cards.g.GiftedInitiate.class)); + cards.add(new SetCardInfo("Glorious Charge", 509, Rarity.COMMON, mage.cards.g.GloriousCharge.class)); cards.add(new SetCardInfo("Grand Moff Tarkin", 75, Rarity.RARE, mage.cards.g.GrandMoffTarkin.class)); cards.add(new SetCardInfo("Greater Krayt Dragon", 186, Rarity.MYTHIC, mage.cards.g.GreaterKraytDragon.class)); cards.add(new SetCardInfo("Greedo", 187, Rarity.RARE, mage.cards.g.Greedo.class)); cards.add(new SetCardInfo("Gundark", 107, Rarity.UNCOMMON, mage.cards.g.Gundark.class)); cards.add(new SetCardInfo("Gungan Captain", 41, Rarity.COMMON, mage.cards.g.GunganCaptain.class)); + cards.add(new SetCardInfo("Hammerhead Corvette", 306, Rarity.UNCOMMON, mage.cards.h.HammerheadCorvette.class)); cards.add(new SetCardInfo("Han Solo", 108, Rarity.RARE, mage.cards.h.HanSolo.class)); + cards.add(new SetCardInfo("Han Solo, Scrumrat", 609, Rarity.RARE, mage.cards.h.HanSoloScrumrat.class)); cards.add(new SetCardInfo("Hazard Trooper", 76, Rarity.UNCOMMON, mage.cards.h.HazardTrooper.class)); cards.add(new SetCardInfo("Head Hunting", 77, Rarity.COMMON, mage.cards.h.HeadHunting.class)); cards.add(new SetCardInfo("Heavy Trooper", 78, Rarity.COMMON, mage.cards.h.HeavyTrooper.class)); @@ -129,8 +162,10 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("IG-88B", 79, Rarity.RARE, mage.cards.i.IG88B.class)); cards.add(new SetCardInfo("Images of the Past", 190, Rarity.COMMON, mage.cards.i.ImagesOfThePast.class)); cards.add(new SetCardInfo("Imperial Gunner", 109, Rarity.COMMON, mage.cards.i.ImperialGunner.class)); + cards.add(new SetCardInfo("Imperial Hovertank", 307, Rarity.UNCOMMON, mage.cards.i.ImperialHovertank.class)); cards.add(new SetCardInfo("Impulsive Wager", 110, Rarity.COMMON, mage.cards.i.ImpulsiveWager.class)); cards.add(new SetCardInfo("Insatiable Rakghoul", 80, Rarity.COMMON, mage.cards.i.InsatiableRakghoul.class)); + cards.add(new SetCardInfo("Inspire", 510, Rarity.COMMON, mage.cards.i.Inspire.class)); cards.add(new SetCardInfo("Interrogation", 81, Rarity.COMMON, mage.cards.i.Interrogation.class)); cards.add(new SetCardInfo("Ion Cannon", 15, Rarity.COMMON, mage.cards.i.IonCannon.class)); cards.add(new SetCardInfo("Iron Fist of the Empire", 191, Rarity.RARE, mage.cards.i.IronFistOfTheEmpire.class)); @@ -158,8 +193,11 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Jedi Training", 45, Rarity.UNCOMMON, mage.cards.j.JediTraining.class)); cards.add(new SetCardInfo("Jump Trooper", 46, Rarity.UNCOMMON, mage.cards.j.JumpTrooper.class)); cards.add(new SetCardInfo("Jungle Village", 245, Rarity.UNCOMMON, mage.cards.j.JungleVillage.class)); + cards.add(new SetCardInfo("Jyn Erso and Cassian Andor", 308, Rarity.RARE, mage.cards.j.JynErsoAndCassianAndor.class)); + cards.add(new SetCardInfo("Kalevan Star Yacht", 610, Rarity.UNCOMMON, mage.cards.k.KalevanStarYacht.class)); cards.add(new SetCardInfo("Kamino Cloning Facility", 246, Rarity.RARE, mage.cards.k.KaminoCloningFacility.class)); cards.add(new SetCardInfo("Ki-Adi-Mundi", 142, Rarity.RARE, mage.cards.k.KiAdiMundi.class)); + cards.add(new SetCardInfo("Kylo Ren", 406, Rarity.MYTHIC, mage.cards.k.KyloRen.class)); cards.add(new SetCardInfo("LAAT Gunship", 20, Rarity.UNCOMMON, mage.cards.l.LAATGunship.class)); cards.add(new SetCardInfo("Lando Calrissian", 21, Rarity.RARE, mage.cards.l.LandoCalrissian.class)); cards.add(new SetCardInfo("Legacy of the Beloved", 143, Rarity.RARE, mage.cards.l.LegacyOfTheBeloved.class)); @@ -167,7 +205,9 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Lightsaber", 234, Rarity.COMMON, mage.cards.l.Lightsaber.class)); cards.add(new SetCardInfo("Loyal Tauntaun", 22, Rarity.COMMON, mage.cards.l.LoyalTauntaun.class)); cards.add(new SetCardInfo("Luke Skywalker", 195, Rarity.MYTHIC, mage.cards.l.LukeSkywalker.class)); + cards.add(new SetCardInfo("Luke Skywalker, the Last Jedi", 511, Rarity.MYTHIC, mage.cards.l.LukeSkywalkerTheLastJedi.class)); cards.add(new SetCardInfo("Mace Windu", 47, Rarity.RARE, mage.cards.m.MaceWindu.class)); + cards.add(new SetCardInfo("Maelstrom Blockade", 611, Rarity.COMMON, mage.cards.m.MaelstromBlockade.class)); cards.add(new SetCardInfo("Maintenance Droid", 196, Rarity.COMMON, mage.cards.m.MaintenanceDroid.class)); cards.add(new SetCardInfo("Maintenance Hangar", 23, Rarity.RARE, mage.cards.m.MaintenanceHangar.class)); cards.add(new SetCardInfo("Mantellian Savrip", 144, Rarity.UNCOMMON, mage.cards.m.MantellianSavrip.class)); @@ -183,6 +223,8 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Mountain", "264b", Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Mountain", "264c", Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Mountain", "264d", Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); + cards.add(new SetCardInfo("Mouse Droid", 512, Rarity.COMMON, mage.cards.m.MouseDroid.class)); + cards.add(new SetCardInfo("Mud Trooper", 612, Rarity.UNCOMMON, mage.cards.m.MudTrooper.class)); cards.add(new SetCardInfo("N-1 Starfighter", 225, Rarity.COMMON, mage.cards.n.N1Starfighter.class)); cards.add(new SetCardInfo("Nebulon-B Frigate", 25, Rarity.COMMON, mage.cards.n.NebulonBFrigate.class)); cards.add(new SetCardInfo("Neophyte Hateflayer", 82, Rarity.COMMON, mage.cards.n.NeophyteHateflayer.class)); @@ -193,10 +235,12 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Novice Bounty Hunter", 114, Rarity.COMMON, mage.cards.n.NoviceBountyHunter.class)); cards.add(new SetCardInfo("Nute Gunray", 199, Rarity.RARE, mage.cards.n.NuteGunray.class)); cards.add(new SetCardInfo("Obi-Wan Kenobi", 200, Rarity.MYTHIC, mage.cards.o.ObiWanKenobi.class)); + cards.add(new SetCardInfo("Occupation", 309, Rarity.UNCOMMON, mage.cards.o.Occupation.class)); cards.add(new SetCardInfo("Open Season", 83, Rarity.UNCOMMON, mage.cards.o.OpenSeason.class)); cards.add(new SetCardInfo("Orbital Bombardment", 26, Rarity.RARE, mage.cards.o.OrbitalBombardment.class)); cards.add(new SetCardInfo("Order 66", 84, Rarity.RARE, mage.cards.o.Order66.class)); cards.add(new SetCardInfo("Ortolan Keyboardist", 50, Rarity.COMMON, mage.cards.o.OrtolanKeyboardist.class)); + cards.add(new SetCardInfo("Outer Rim Gang", 407, Rarity.COMMON, mage.cards.o.OuterRimGang.class)); cards.add(new SetCardInfo("Outer Rim Slaver", 201, Rarity.COMMON, mage.cards.o.OuterRimSlaver.class)); cards.add(new SetCardInfo("Outlaw Holocron", 235, Rarity.COMMON, mage.cards.o.OutlawHolocron.class)); cards.add(new SetCardInfo("Personal Energy Shield", 51, Rarity.COMMON, mage.cards.p.PersonalEnergyShield.class)); @@ -205,6 +249,9 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Plains", "252c", Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Plains", "252d", Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Plo Koon", 27, Rarity.RARE, mage.cards.p.PloKoon.class)); + cards.add(new SetCardInfo("Poe Dameron", 408, Rarity.UNCOMMON, mage.cards.p.PoeDameron.class)); + cards.add(new SetCardInfo("Porg Nest", 513, Rarity.UNCOMMON, mage.cards.p.PorgNest.class)); + cards.add(new SetCardInfo("Praetorian Trooper", 514, Rarity.RARE, mage.cards.p.PraetorianTrooper.class)); cards.add(new SetCardInfo("Precipice of Mortis", 202, Rarity.RARE, mage.cards.p.PrecipiceOfMortis.class)); cards.add(new SetCardInfo("Predator's Strike", 151, Rarity.COMMON, mage.cards.p.PredatorsStrike.class)); cards.add(new SetCardInfo("Preordain", 34, Rarity.UNCOMMON, mage.cards.p.Preordain.class)); @@ -214,19 +261,27 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Qui-Gon Jinn", 205, Rarity.RARE, mage.cards.q.QuiGonJinn.class)); cards.add(new SetCardInfo("Raging Reek", 115, Rarity.COMMON, mage.cards.r.RagingReek.class)); cards.add(new SetCardInfo("Rallying Fire", 116, Rarity.COMMON, mage.cards.r.RallyingFire.class)); + cards.add(new SetCardInfo("Range Trooper", 613, Rarity.UNCOMMON, mage.cards.r.RangeTrooper.class)); + cards.add(new SetCardInfo("Rathtar", 409, Rarity.COMMON, mage.cards.r.Rathtar.class)); cards.add(new SetCardInfo("Ravenous Wampa", 226, Rarity.UNCOMMON, mage.cards.r.RavenousWampa.class)); cards.add(new SetCardInfo("Regression", 152, Rarity.UNCOMMON, mage.cards.r.Regression.class)); cards.add(new SetCardInfo("Republic Frigate", 53, Rarity.COMMON, mage.cards.r.RepublicFrigate.class)); cards.add(new SetCardInfo("Repurpose", 85, Rarity.COMMON, mage.cards.r.Repurpose.class)); + cards.add(new SetCardInfo("Resistance", 310, Rarity.UNCOMMON, mage.cards.r.Resistance.class)); + cards.add(new SetCardInfo("Resistance Bomber", 515, Rarity.UNCOMMON, mage.cards.r.ResistanceBomber.class)); cards.add(new SetCardInfo("Revenge", 117, Rarity.COMMON, mage.cards.r.Revenge.class)); + cards.add(new SetCardInfo("Rey", 410, Rarity.RARE, mage.cards.r.Rey.class)); cards.add(new SetCardInfo("Riding Ronto", 28, Rarity.UNCOMMON, mage.cards.r.RidingRonto.class)); + cards.add(new SetCardInfo("Riot Trooper", 411, Rarity.COMMON, mage.cards.r.RiotTrooper.class)); cards.add(new SetCardInfo("Rocket Trooper", 118, Rarity.RARE, mage.cards.r.RocketTrooper.class)); cards.add(new SetCardInfo("Rogue's Passage", 248, Rarity.UNCOMMON, mage.cards.r.RoguesPassage.class)); cards.add(new SetCardInfo("Rule of two", 86, Rarity.UNCOMMON, mage.cards.r.RuleOfTwo.class)); cards.add(new SetCardInfo("Rumination", 54, Rarity.COMMON, mage.cards.r.Rumination.class)); cards.add(new SetCardInfo("Rumor Monger", 206, Rarity.UNCOMMON, mage.cards.r.RumorMonger.class)); cards.add(new SetCardInfo("Sabacc Game", 55, Rarity.UNCOMMON, mage.cards.s.SabaccGame.class)); + cards.add(new SetCardInfo("Sai Tok", 516, Rarity.UNCOMMON, mage.cards.s.SaiTok.class)); cards.add(new SetCardInfo("Salvage Squad", 207, Rarity.COMMON, mage.cards.s.SalvageSquad.class)); + cards.add(new SetCardInfo("Salvage Trader", 412, Rarity.COMMON, mage.cards.s.SalvageTrader.class)); cards.add(new SetCardInfo("Sand Trooper", 29, Rarity.COMMON, mage.cards.s.SandTrooper.class)); cards.add(new SetCardInfo("Sarlacc Pit", 208, Rarity.RARE, mage.cards.s.SarlaccPit.class)); cards.add(new SetCardInfo("Scout the Perimeter", 153, Rarity.COMMON, mage.cards.s.ScoutThePerimeter.class)); @@ -241,6 +296,7 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Shadow Trooper", 56, Rarity.COMMON, mage.cards.s.ShadowTrooper.class)); cards.add(new SetCardInfo("Shock Trooper", 119, Rarity.UNCOMMON, mage.cards.s.ShockTrooper.class)); cards.add(new SetCardInfo("Show of Dominance", 156, Rarity.UNCOMMON, mage.cards.s.ShowOfDominance.class)); + cards.add(new SetCardInfo("Sins of the Father", 413, Rarity.COMMON, mage.cards.s.SinsOfTheFather.class)); cards.add(new SetCardInfo("Sith Assassin", 87, Rarity.UNCOMMON, mage.cards.s.SithAssassin.class)); cards.add(new SetCardInfo("Sith Citadel", 249, Rarity.UNCOMMON, mage.cards.s.SithCitadel.class)); cards.add(new SetCardInfo("Sith Evoker", 88, Rarity.COMMON, mage.cards.s.SithEvoker.class)); @@ -262,6 +318,7 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Star Destroyer", 217, Rarity.RARE, mage.cards.s.StarDestroyer.class)); cards.add(new SetCardInfo("Strike Team Commando", 227, Rarity.COMMON, mage.cards.s.StrikeTeamCommando.class)); cards.add(new SetCardInfo("Super Battle Droid", 59, Rarity.COMMON, mage.cards.s.SuperBattleDroid.class)); + cards.add(new SetCardInfo("Supreme Leader Snoke", 517, Rarity.MYTHIC, mage.cards.s.SupremeLeaderSnoke.class)); cards.add(new SetCardInfo("Surprise Maneuver", 60, Rarity.COMMON, mage.cards.s.SurpriseManeuver.class)); cards.add(new SetCardInfo("Swamp", "260a", Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Swamp", "260b", Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); @@ -279,17 +336,26 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("The Death Star", 1, Rarity.MYTHIC, mage.cards.t.TheDeathStar.class)); cards.add(new SetCardInfo("TIE Bomber", 93, Rarity.UNCOMMON, mage.cards.t.TIEBomber.class)); cards.add(new SetCardInfo("TIE Interceptor", 94, Rarity.COMMON, mage.cards.t.TIEInterceptor.class)); + cards.add(new SetCardInfo("TIE Silencer", 518, Rarity.RARE, mage.cards.t.TIESilencer.class)); + cards.add(new SetCardInfo("TIE Striker", 312, Rarity.COMMON, mage.cards.t.TIEStriker.class)); + cards.add(new SetCardInfo("Thermal Detonator", 311, Rarity.COMMON, mage.cards.t.ThermalDetonator.class)); + cards.add(new SetCardInfo("Tobias Beckett", 614, Rarity.RARE, mage.cards.t.TobiasBeckett.class)); cards.add(new SetCardInfo("Trade Federation Battleship", 219, Rarity.RARE, mage.cards.t.TradeFederationBattleship.class)); cards.add(new SetCardInfo("Tri-Fighter", 228, Rarity.COMMON, mage.cards.t.TriFighter.class)); cards.add(new SetCardInfo("Trooper Armor", 237, Rarity.UNCOMMON, mage.cards.t.TrooperArmor.class)); cards.add(new SetCardInfo("Trooper Commando", 157, Rarity.UNCOMMON, mage.cards.t.TrooperCommando.class)); cards.add(new SetCardInfo("Twi'lek Seductress", 158, Rarity.COMMON, mage.cards.t.TwilekSeductress.class)); + cards.add(new SetCardInfo("U-Wing", 313, Rarity.UNCOMMON, mage.cards.u.UWing.class)); cards.add(new SetCardInfo("Ugnaught Scrap Worker", 61, Rarity.COMMON, mage.cards.u.UgnaughtScrapWorker.class)); + cards.add(new SetCardInfo("Underground Forum", 615, Rarity.UNCOMMON, mage.cards.u.UndergroundForum.class)); cards.add(new SetCardInfo("Underworld Slums", 251, Rarity.COMMON, mage.cards.u.UnderworldSlums.class)); cards.add(new SetCardInfo("Unity of the Droids", 220, Rarity.UNCOMMON, mage.cards.u.UnityOfTheDroids.class)); cards.add(new SetCardInfo("Unruly Sureshot", 95, Rarity.UNCOMMON, mage.cards.u.UnrulySureshot.class)); + cards.add(new SetCardInfo("Upsilon-class Shuttle", 414, Rarity.COMMON, mage.cards.u.UpsilonClassShuttle.class)); cards.add(new SetCardInfo("V-Wing", 126, Rarity.COMMON, mage.cards.v.VWing.class)); + cards.add(new SetCardInfo("Vader's Command", 314, Rarity.RARE, mage.cards.v.VadersCommand.class)); cards.add(new SetCardInfo("Vapor Snag", 62, Rarity.COMMON, mage.cards.v.VaporSnag.class)); + cards.add(new SetCardInfo("Vulptex", 519, Rarity.COMMON, mage.cards.v.Vulptex.class)); cards.add(new SetCardInfo("Weequay Beastmaster", 127, Rarity.UNCOMMON, mage.cards.w.WeequayBeastmaster.class)); cards.add(new SetCardInfo("Wild Holocron", 238, Rarity.COMMON, mage.cards.w.WildHolocron.class)); cards.add(new SetCardInfo("Wisdom of the Jedi", 221, Rarity.UNCOMMON, mage.cards.w.WisdomOfTheJedi.class)); @@ -301,5 +367,7 @@ public final class StarWars extends ExpansionSet { cards.add(new SetCardInfo("Y-Wing", 63, Rarity.UNCOMMON, mage.cards.y.YWing.class)); cards.add(new SetCardInfo("Yoda, Jedi Master", 223, Rarity.MYTHIC, mage.cards.y.YodaJediMaster.class)); cards.add(new SetCardInfo("Zam Wesell", 64, Rarity.RARE, mage.cards.z.ZamWesell.class)); + cards.add(new SetCardInfo("Island", "520a", Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); + cards.add(new SetCardInfo("Plains", "520b", Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.ZEN_FULL_ART_BASIC, true))); } } diff --git a/Mage.Sets/src/mage/sets/Tempest.java b/Mage.Sets/src/mage/sets/Tempest.java index bcb715359dd..a5fce2ce5a9 100644 --- a/Mage.Sets/src/mage/sets/Tempest.java +++ b/Mage.Sets/src/mage/sets/Tempest.java @@ -43,6 +43,7 @@ public final class Tempest extends ExpansionSet { cards.add(new SetCardInfo("Blood Frenzy", 164, Rarity.COMMON, mage.cards.b.BloodFrenzy.class)); cards.add(new SetCardInfo("Blood Pet", 109, Rarity.COMMON, mage.cards.b.BloodPet.class)); cards.add(new SetCardInfo("Boil", 165, Rarity.UNCOMMON, mage.cards.b.Boil.class)); + cards.add(new SetCardInfo("Booby Trap", 277, Rarity.RARE, mage.cards.b.BoobyTrap.class)); cards.add(new SetCardInfo("Bottle Gnomes", 278, Rarity.UNCOMMON, mage.cards.b.BottleGnomes.class)); cards.add(new SetCardInfo("Bounty Hunter", 110, Rarity.RARE, mage.cards.b.BountyHunter.class)); cards.add(new SetCardInfo("Broken Fall", 216, Rarity.COMMON, mage.cards.b.BrokenFall.class)); diff --git a/Mage.Sets/src/mage/sets/TimeSpiral.java b/Mage.Sets/src/mage/sets/TimeSpiral.java index dd82083812d..a730e269506 100644 --- a/Mage.Sets/src/mage/sets/TimeSpiral.java +++ b/Mage.Sets/src/mage/sets/TimeSpiral.java @@ -26,6 +26,8 @@ public final class TimeSpiral extends ExpansionSet { this.numBoosterRare = 1; this.ratioBoosterMythic = 0; cards.add(new SetCardInfo("Academy Ruins", 269, Rarity.RARE, mage.cards.a.AcademyRuins.class)); + cards.add(new SetCardInfo("Aether Web", 189, Rarity.COMMON, mage.cards.a.AetherWeb.class)); + cards.add(new SetCardInfo("Aetherflame Wall", 142, Rarity.COMMON, mage.cards.a.AetherflameWall.class)); cards.add(new SetCardInfo("Amrou Scout", 1, Rarity.COMMON, mage.cards.a.AmrouScout.class)); cards.add(new SetCardInfo("Amrou Seekers", 2, Rarity.COMMON, mage.cards.a.AmrouSeekers.class)); cards.add(new SetCardInfo("Ancestral Vision", 48, Rarity.RARE, mage.cards.a.AncestralVision.class)); @@ -68,6 +70,7 @@ public final class TimeSpiral extends ExpansionSet { cards.add(new SetCardInfo("Corpulent Corpse", 98, Rarity.COMMON, mage.cards.c.CorpulentCorpse.class)); cards.add(new SetCardInfo("Crookclaw Transmuter", 55, Rarity.COMMON, mage.cards.c.CrookclawTransmuter.class)); cards.add(new SetCardInfo("Curse of the Cabal", 99, Rarity.RARE, mage.cards.c.CurseOfTheCabal.class)); + cards.add(new SetCardInfo("Cyclopean Giant", 100, Rarity.COMMON, mage.cards.c.CyclopeanGiant.class)); cards.add(new SetCardInfo("Dark Withering", 101, Rarity.COMMON, mage.cards.d.DarkWithering.class)); cards.add(new SetCardInfo("D'Avenant Healer", 11, Rarity.COMMON, mage.cards.d.DAvenantHealer.class)); cards.add(new SetCardInfo("Deathspore Thallid", 102, Rarity.COMMON, mage.cards.d.DeathsporeThallid.class)); @@ -211,7 +214,9 @@ public final class TimeSpiral extends ExpansionSet { cards.add(new SetCardInfo("Plains", 283, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 284, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 285, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plated Pegasus", 34, Rarity.UNCOMMON, mage.cards.p.PlatedPegasus.class)); cards.add(new SetCardInfo("Plunder", 174, Rarity.COMMON, mage.cards.p.Plunder.class)); + cards.add(new SetCardInfo("Premature Burial", 125, Rarity.UNCOMMON, mage.cards.p.PrematureBurial.class)); cards.add(new SetCardInfo("Primal Forcemage", 212, Rarity.UNCOMMON, mage.cards.p.PrimalForcemage.class)); cards.add(new SetCardInfo("Prismatic Lens", 262, Rarity.COMMON, mage.cards.p.PrismaticLens.class)); cards.add(new SetCardInfo("Psionic Sliver", 72, Rarity.RARE, mage.cards.p.PsionicSliver.class)); @@ -283,6 +288,7 @@ public final class TimeSpiral extends ExpansionSet { cards.add(new SetCardInfo("Thallid Shell-Dweller", 226, Rarity.COMMON, mage.cards.t.ThallidShellDweller.class)); cards.add(new SetCardInfo("Thelonite Hermit", 228, Rarity.RARE, mage.cards.t.TheloniteHermit.class)); cards.add(new SetCardInfo("Thelon of Havenwood", 227, Rarity.RARE, mage.cards.t.ThelonOfHavenwood.class)); + cards.add(new SetCardInfo("Thick-Skinned Goblin", 182, Rarity.UNCOMMON, mage.cards.t.ThickSkinnedGoblin.class)); cards.add(new SetCardInfo("Think Twice", 86, Rarity.COMMON, mage.cards.t.ThinkTwice.class)); cards.add(new SetCardInfo("Thrill of the Hunt", 229, Rarity.COMMON, mage.cards.t.ThrillOfTheHunt.class)); cards.add(new SetCardInfo("Thunder Totem", 265, Rarity.UNCOMMON, mage.cards.t.ThunderTotem.class)); @@ -293,6 +299,7 @@ public final class TimeSpiral extends ExpansionSet { cards.add(new SetCardInfo("Trickbind", 88, Rarity.RARE, mage.cards.t.Trickbind.class)); cards.add(new SetCardInfo("Triskelavus", 266, Rarity.RARE, mage.cards.t.Triskelavus.class)); cards.add(new SetCardInfo("Tromp the Domains", 230, Rarity.UNCOMMON, mage.cards.t.TrompTheDomains.class)); + cards.add(new SetCardInfo("Truth or Tale", 89, Rarity.UNCOMMON, mage.cards.t.TruthOrTale.class)); cards.add(new SetCardInfo("Two-Headed Sliver", 183, Rarity.COMMON, mage.cards.t.TwoHeadedSliver.class)); cards.add(new SetCardInfo("Undying Rage", 184, Rarity.UNCOMMON, mage.cards.u.UndyingRage.class)); cards.add(new SetCardInfo("Unyaro Bees", 231, Rarity.RARE, mage.cards.u.UnyaroBees.class)); diff --git a/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java b/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java index c73f2796052..da2fe23c4bf 100644 --- a/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java +++ b/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java @@ -67,6 +67,7 @@ public final class TimeSpiralTimeshifted extends ExpansionSet { cards.add(new SetCardInfo("Gaea's Liege", 78, Rarity.SPECIAL, mage.cards.g.GaeasLiege.class)); cards.add(new SetCardInfo("Gemstone Mine", 119, Rarity.RARE, mage.cards.g.GemstoneMine.class)); cards.add(new SetCardInfo("Ghost Ship", 21, Rarity.SPECIAL, mage.cards.g.GhostShip.class)); + cards.add(new SetCardInfo("Giant Oyster", 22, Rarity.SPECIAL, mage.cards.g.GiantOyster.class)); cards.add(new SetCardInfo("Goblin Snowman", 64, Rarity.UNCOMMON, mage.cards.g.GoblinSnowman.class)); cards.add(new SetCardInfo("Grinning Totem", 110, Rarity.SPECIAL, mage.cards.g.GrinningTotem.class)); cards.add(new SetCardInfo("Hail Storm", 79, Rarity.SPECIAL, mage.cards.h.HailStorm.class)); diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 00114c8eb98..524cae92c96 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -26,6 +26,7 @@ public final class Unglued extends ExpansionSet { cards.add(new SetCardInfo("Elvish Impersonators", 56, Rarity.COMMON, mage.cards.e.ElvishImpersonators.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Fowl Play", 24, Rarity.COMMON, mage.cards.f.FowlPlay.class)); + cards.add(new SetCardInfo("Gerrymandering", 59, Rarity.UNCOMMON, mage.cards.g.Gerrymandering.class)); cards.add(new SetCardInfo("Goblin Tutor", 45, Rarity.UNCOMMON, mage.cards.g.GoblinTutor.class)); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); cards.add(new SetCardInfo("Hungry Hungry Heifer", 63, Rarity.UNCOMMON, mage.cards.h.HungryHungryHeifer.class)); @@ -42,6 +43,7 @@ public final class Unglued extends ExpansionSet { cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class)); cards.add(new SetCardInfo("Rock Lobster", 79, Rarity.COMMON, mage.cards.r.RockLobster.class)); cards.add(new SetCardInfo("Scissors Lizard", 80, Rarity.COMMON, mage.cards.s.ScissorsLizard.class)); + cards.add(new SetCardInfo("Spark Fiend", 51, Rarity.RARE, mage.cards.s.SparkFiend.class)); cards.add(new SetCardInfo("Strategy, Schmategy", 52, Rarity.RARE, mage.cards.s.StrategySchmategy.class)); cards.add(new SetCardInfo("Swamp", 86, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("The Cheese Stands Alone", 2, Rarity.RARE, mage.cards.t.TheCheeseStandsAlone.class)); diff --git a/Mage.Sets/src/mage/sets/UnlimitedEdition.java b/Mage.Sets/src/mage/sets/UnlimitedEdition.java index c2dc591ecf0..a08da1a590d 100644 --- a/Mage.Sets/src/mage/sets/UnlimitedEdition.java +++ b/Mage.Sets/src/mage/sets/UnlimitedEdition.java @@ -316,6 +316,7 @@ public final class UnlimitedEdition extends ExpansionSet { cards.add(new SetCardInfo("Will-o'-the-Wisp", 136, Rarity.RARE, mage.cards.w.WillOTheWisp.class)); cards.add(new SetCardInfo("Winter Orb", 276, Rarity.RARE, mage.cards.w.WinterOrb.class)); cards.add(new SetCardInfo("Wooden Sphere", 277, Rarity.UNCOMMON, mage.cards.w.WoodenSphere.class)); + cards.add(new SetCardInfo("Word of Command", 137, Rarity.RARE, mage.cards.w.WordOfCommand.class)); cards.add(new SetCardInfo("Wrath of God", 46, Rarity.RARE, mage.cards.w.WrathOfGod.class)); cards.add(new SetCardInfo("Zombie Master", 138, Rarity.RARE, mage.cards.z.ZombieMaster.class)); } diff --git a/Mage.Sets/src/mage/sets/UrzasLegacy.java b/Mage.Sets/src/mage/sets/UrzasLegacy.java index f365c690457..eaa00b8c3cd 100644 --- a/Mage.Sets/src/mage/sets/UrzasLegacy.java +++ b/Mage.Sets/src/mage/sets/UrzasLegacy.java @@ -46,6 +46,7 @@ public final class UrzasLegacy extends ExpansionSet { cards.add(new SetCardInfo("Cloud of Faeries", 29, Rarity.COMMON, mage.cards.c.CloudOfFaeries.class)); cards.add(new SetCardInfo("Crawlspace", 123, Rarity.RARE, mage.cards.c.Crawlspace.class)); cards.add(new SetCardInfo("Crop Rotation", 98, Rarity.COMMON, mage.cards.c.CropRotation.class)); + cards.add(new SetCardInfo("Damping Engine", 124, Rarity.RARE, mage.cards.d.DampingEngine.class)); cards.add(new SetCardInfo("Darkwatch Elves", 99, Rarity.UNCOMMON, mage.cards.d.DarkwatchElves.class)); cards.add(new SetCardInfo("Defender of Chaos", 75, Rarity.COMMON, mage.cards.d.DefenderOfChaos.class)); cards.add(new SetCardInfo("Defender of Law", 5, Rarity.COMMON, mage.cards.d.DefenderOfLaw.class)); diff --git a/Mage.Sets/src/mage/sets/Visions.java b/Mage.Sets/src/mage/sets/Visions.java index d2bfc1318e1..ea27845253c 100644 --- a/Mage.Sets/src/mage/sets/Visions.java +++ b/Mage.Sets/src/mage/sets/Visions.java @@ -1,4 +1,3 @@ - package mage.sets; import mage.cards.ExpansionSet; @@ -34,6 +33,7 @@ public final class Visions extends ExpansionSet { cards.add(new SetCardInfo("Army Ants", 126, Rarity.UNCOMMON, mage.cards.a.ArmyAnts.class)); cards.add(new SetCardInfo("Betrayal", 26, Rarity.COMMON, mage.cards.b.Betrayal.class)); cards.add(new SetCardInfo("Blanket of Night", 52, Rarity.UNCOMMON, mage.cards.b.BlanketOfNight.class)); + cards.add(new SetCardInfo("Bogardan Phoenix", 76, Rarity.RARE, mage.cards.b.BogardanPhoenix.class)); cards.add(new SetCardInfo("Brass-Talon Chimera", 142, Rarity.UNCOMMON, mage.cards.b.BrassTalonChimera.class)); cards.add(new SetCardInfo("Breathstealer's Crypt", 127, Rarity.RARE, mage.cards.b.BreathstealersCrypt.class)); cards.add(new SetCardInfo("Breezekeeper", 27, Rarity.COMMON, mage.cards.b.Breezekeeper.class)); @@ -117,6 +117,7 @@ public final class Visions extends ExpansionSet { cards.add(new SetCardInfo("Parapet", 14, Rarity.COMMON, mage.cards.p.Parapet.class)); cards.add(new SetCardInfo("Phyrexian Marauder", 151, Rarity.RARE, mage.cards.p.PhyrexianMarauder.class)); cards.add(new SetCardInfo("Phyrexian Walker", 152, Rarity.COMMON, mage.cards.p.PhyrexianWalker.class)); + cards.add(new SetCardInfo("Pillar Tombs of Aku", 67, Rarity.RARE, mage.cards.p.PillarTombsOfAku.class)); cards.add(new SetCardInfo("Prosperity", 40, Rarity.UNCOMMON, mage.cards.p.Prosperity.class)); cards.add(new SetCardInfo("Python", 68, Rarity.COMMON, mage.cards.p.Python.class)); cards.add(new SetCardInfo("Quicksand", 166, Rarity.UNCOMMON, mage.cards.q.Quicksand.class)); diff --git a/Mage.Sets/src/mage/sets/Weatherlight.java b/Mage.Sets/src/mage/sets/Weatherlight.java index f8194ad77ba..01abb9f2b1b 100644 --- a/Mage.Sets/src/mage/sets/Weatherlight.java +++ b/Mage.Sets/src/mage/sets/Weatherlight.java @@ -44,6 +44,7 @@ public final class Weatherlight extends ExpansionSet { cards.add(new SetCardInfo("Argivian Restoration", 34, Rarity.UNCOMMON, mage.cards.a.ArgivianRestoration.class)); cards.add(new SetCardInfo("Aura of Silence", 7, Rarity.UNCOMMON, mage.cards.a.AuraOfSilence.class)); cards.add(new SetCardInfo("Avizoa", 35, Rarity.RARE, mage.cards.a.Avizoa.class)); + cards.add(new SetCardInfo("Barishi", 119, Rarity.UNCOMMON, mage.cards.b.Barishi.class)); cards.add(new SetCardInfo("Barrow Ghoul", 61, Rarity.COMMON, mage.cards.b.BarrowGhoul.class)); cards.add(new SetCardInfo("Benalish Infantry", 8, Rarity.COMMON, mage.cards.b.BenalishInfantry.class)); cards.add(new SetCardInfo("Benalish Knight", 9, Rarity.COMMON, mage.cards.b.BenalishKnight.class)); diff --git a/Mage.Stats/pom.xml b/Mage.Stats/pom.xml index 2d0403d9c20..394db54aa1a 100644 --- a/Mage.Stats/pom.xml +++ b/Mage.Stats/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 org.mage diff --git a/Mage.Tests/pom.xml b/Mage.Tests/pom.xml index 5ee48c61bbf..1f5e3496407 100644 --- a/Mage.Tests/pom.xml +++ b/Mage.Tests/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage-tests diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java index 285708fa9d7..268b58f7ef2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java @@ -3,6 +3,7 @@ package org.mage.test.AI.basic; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBaseAI; @@ -30,6 +31,7 @@ public class CastCreaturesTest extends CardTestPlayerBaseAI { * This test fails sometimes, probably because two plains are tapped for the * first creature */ + @Ignore @Test // TODO: Find out why sometimes this produces an error - probably because of wrong mana usage of the AI - Not solved yet public void testSimpleCast2() { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java index 2d3d3f2779c..9fa648f4387 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java @@ -315,8 +315,8 @@ public class BloodMoonTest extends CardTestPlayerBase { * If Blood Moon is on the battlefield, Flagstones of Trokair will enter the * battlefield as a legendary non-basic Mountain. If Flagstones of Trokair * is put into the graveyard due to “Legends rule” or because it was - * destroyed, its ability doesn’t trigger, because it doesn’t exist: it - * won’t fetch you a Plains. + * destroyed, its ability doesn't trigger, because it doesn't exist: it + * won't fetch you a Plains. */ @Test public void testBloodMoonFlagstonesOfTrokair() { @@ -350,13 +350,13 @@ public class BloodMoonTest extends CardTestPlayerBase { } /** - * Because Blood Moon’s static ability operates only when it’s on the + * Because Blood Moon's static ability operates only when it's on the * battlefield and begins affecting any nonbasic lands immediately. In fact, - * Blood Moon’s effect is so quick that once a non-basic land hits the - * battlefield it’s going to be affected. Therefore: + * Blood Moon's effect is so quick that once a non-basic land hits the + * battlefield it's going to be affected. Therefore: * - * If a nonbasic land’s has EtB triggered abilities, these will not trigger - * because the ability isn’t there (it’s gone). Effects that modify the way + * If a nonbasic land's has EtB triggered abilities, these will not trigger + * because the ability isn't there (it's gone). Effects that modify the way * the land enters the battlefield are replacement effects. They are applied * before the permanent enters the battlefield and taking into account * continuous effects that already exist and would apply to the permanent. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SkylineCascadeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SkylineCascadeTest.java index 3f8e8bda75b..93974d8ee32 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SkylineCascadeTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SkylineCascadeTest.java @@ -49,8 +49,8 @@ public class SkylineCascadeTest extends CardTestPlayerBase { /** * Reported bug on Skyline Cascade not working properly. * - * "Skyline Cascade’s triggered ability doesn't tap the creature. It can target any creature, tapped or untapped. - * If that creature is already untapped at the beginning of its controller’s next untap step, the effect won’t do anything." + * "Skyline Cascade's triggered ability doesn't tap the creature. It can target any creature, tapped or untapped. + * If that creature is already untapped at the beginning of its controller's next untap step, the effect won't do anything." * http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=402038 * * An untapped creature will remain untapped. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/flicker/CloudshiftTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/flicker/CloudshiftTest.java index 87473214f4f..c43846eda9b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/flicker/CloudshiftTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/flicker/CloudshiftTest.java @@ -339,7 +339,7 @@ public class CloudshiftTest extends CardTestPlayerBase { * of the end step even if Flickerwisp is no longer on the battlefield. * 8/1/2008 If the permanent that returns to the battlefield has any * abilities that trigger at the beginning of the end step, those abilities - * won’t trigger that turn. + * won't trigger that turn. */ @Test public void testDoubleFlickerwisp() { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/AfflictTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/AfflictTest.java index 1cd269f6f3d..c0fea22a22a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/AfflictTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/AfflictTest.java @@ -52,7 +52,7 @@ public class AfflictTest extends CardTestPlayerBase { // {T}: Add {C}. // {2}, {T}: Exile target creature you control. - // {4}, {T}, Sacrifice Endless Sands: Return each creature card exiled with Endless Sands to the battlefield under its owner’s control. + // {4}, {T}, Sacrifice Endless Sands: Return each creature card exiled with Endless Sands to the battlefield under its owner's control. addCard(Zone.BATTLEFIELD, playerA, "Endless Sands"); // Deathtouch diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java index 85e285effe8..3950fa971b1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.abilities.keywords; import mage.abilities.mana.ManaOptions; @@ -163,8 +162,8 @@ public class BestowTest extends CardTestPlayerBase { * Bestowed creature can be used to sacrifice a creature for the Away part. * http://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/magic-rulings-archives/513828-bestow-far-away */ + @Ignore // TODO: make fused targeting support @Test - @Ignore // Handling of targets of Fused spells is not handled yet in TestPlayer class public void bestowWithFusedSpell() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); /** @@ -183,22 +182,22 @@ public class BestowTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Swamp", 3); addCard(Zone.BATTLEFIELD, playerB, "Island", 2); - /** - * Far {1}{U} Instant Return target creature to its owner's hand. Away - * {2}{B} Instant Target player sacrifices a creature. Fuse (You may - * cast one or both halves of this card from your hand.) - */ + // Instant + // Far {1}{U} Return target creature to its owner's hand. + // Away {2}{B} Target player sacrifices a creature. + // Fuse (You may cast one or both halves of this card from your hand.) addCard(Zone.HAND, playerB, "Far // Away"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nyxborn Rollicker using bestow", "Cyclops of One-Eyed Pass"); - castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "fused Far // Away", "Cyclops of One-Eyed Pass^targetPlayer=PlayerA"); - playerA.addTarget("Nyxborn Rollicker"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "fused Far // Away", "Cyclops of One-Eyed Pass"); + addTarget(playerB, playerA); + addTarget(playerA, "Nyxborn Rollicker"); setStopAt(1, PhaseStep.END_TURN); execute(); - assertHandCount(playerA, 0); + assertHandCount(playerA, "Cyclops of One-Eyed Pass", 1); assertHandCount(playerB, 0); assertGraveyardCount(playerB, "Far // Away", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChampionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChampionTest.java index 0989c155de6..d597ebdac92 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChampionTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ChampionTest.java @@ -18,7 +18,7 @@ public class ChampionTest extends CardTestPlayerBase { * 702.71a Champion represents two triggered abilities. “Champion an [object]” means “When this * permanent enters the battlefield, sacrifice it unless you exile another [object] you control” and * “When this permanent leaves the battlefield, return the exiled card to the battlefield under its - * owner’s control.” + * owner's control.” * * 702.71b The two abilities represented by champion are linked. See rule 607, “Linked Abilities.” * diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConspireTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConspireTest.java index 9db84082bba..7239f96223c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConspireTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConspireTest.java @@ -20,7 +20,7 @@ public class ConspireTest extends CardTestPlayerBase { * “As an additional cost to cast this spell, you may tap two untapped * creatures you control that each share a color with it” and “When you cast * this spell, if its conspire cost was paid, copy it. If the spell has any - * targets, you may choose new targets for the copy.” Paying a spell’s + * targets, you may choose new targets for the copy.” Paying a spell's * conspire cost follows the rules for paying additional costs in rules * 601.2b and 601.2e–g. * diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConstellationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConstellationTest.java index a7c55a1cae0..e6e6d6f050d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConstellationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ConstellationTest.java @@ -15,8 +15,8 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class ConstellationTest extends CardTestPlayerBase { /** - * Daxos's Torment {3}{B} Constellation — Whenever Daxos’s Torment or - * another enchantment enters the battlefield under your control, Daxos’s + * Daxos's Torment {3}{B} Constellation — Whenever Daxos's Torment or + * another enchantment enters the battlefield under your control, Daxos's * Torment becomes a 5/5 Demon creature with flying and haste in addition to * its other types until end of turn. */ @@ -135,10 +135,11 @@ public class ConstellationTest extends CardTestPlayerBase { @Test public void test_DaxosGotBoostWithLoseFlyAndGotItAgain() { // 112.10c If two or more effects add and remove the same ability, in general the most recent one prevails. - addCard(Zone.HAND, playerA, daxosCard, 1); - addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); - addCard(Zone.HAND, playerA, "Gravity Sphere", 1); // All creatures lose flying. - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.HAND, playerA, daxosCard, 1); // {3}{B} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // All creatures lose flying. + addCard(Zone.HAND, playerA, "Gravity Sphere", 1); // World Enchantment {2}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6); // got fly on enter, lose on gravity, got fly on gravity enter castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, daxosCard); @@ -192,12 +193,12 @@ public class ConstellationTest extends CardTestPlayerBase { // 613.7 -- dependacy effects (Mephidross Vampire must ALWAYS wait Daxos effect, not timestamp) addCard(Zone.HAND, playerA, daxosCard, 1); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + // Each creature you control is a Vampire in addition to its other creature types + addCard(Zone.HAND, playerA, "Mephidross Vampire", 1); // {4}{B}{B} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8); // - addCard(Zone.HAND, playerA, "Mephidross Vampire", 1); // Each creature you control is a Vampire in addition to its other creature types - addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6); - // - addCard(Zone.HAND, playerA, "Archetype of Courage", 1); // Enchantment to trigger Daxos - addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + addCard(Zone.HAND, playerA, "Archetype of Courage", 1); // Enchantment {1}{W}{W} to trigger Daxos + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); // dax cast castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, daxosCard); @@ -208,6 +209,15 @@ public class ConstellationTest extends CardTestPlayerBase { castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Archetype of Courage"); // make dax to creature castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mephidross Vampire"); // give vampire to creatures } else { + // Make sure not white mana is used here to cast the vampire + checkManaPool("before B mana", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "B", 0); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}"); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}"); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}"); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}"); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}"); + activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}"); + checkManaPool("after B mana", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "B", 6); castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mephidross Vampire"); // give vampire to creatures castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Archetype of Courage"); // make dax to creature } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java index 53e3e42c6f6..74583de4629 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java @@ -14,16 +14,16 @@ public class CyclingTest extends CardTestPlayerBase { /** * 702.28. Cycling 702.28a Cycling is an activated ability that functions - * only while the card with cycling is in a player’s hand. “Cycling [cost]” + * only while the card with cycling is in a player's hand. “Cycling [cost]” * means “[Cost], Discard this card: Draw a card.” 702.28b Although the - * cycling ability is playable only if the card is in a player’s hand, it + * cycling ability is playable only if the card is in a player's hand, it * continues to exist while the object is in play and in all other zones. * Therefore objects with cycling will be affected by effects that depend on * objects having one or more activated abilities. 702.28c Some cards with - * cycling have abilities that trigger when they’re cycled. “When you cycle + * cycling have abilities that trigger when they're cycled. “When you cycle * [this card]” means “When you discard [this card] to pay a cycling cost.” * These abilities trigger from whatever zone the card winds up in after - * it’s cycled. 702.28d Typecycling is a variant of the cycling ability. + * it's cycled. 702.28d Typecycling is a variant of the cycling ability. * “[Type]cycling [cost]” means “[Cost], Discard this card: Search your * library for a [type] card, reveal it, and put it into your hand. Then * shuffle your library.” This type is usually a subtype (as in @@ -32,7 +32,7 @@ public class CyclingTest extends CardTestPlayerBase { * abilities are cycling abilities, and typecycling costs are cycling costs. * Any cards that trigger when a player cycles a card will trigger when a * card is discarded to pay a typecycling cost. Any effect that stops - * players from cycling cards will stop players from activating cards’ + * players from cycling cards will stop players from activating cards' * typecycling abilities. Any effect that increases or reduces a cycling * cost will increase or reduce a typecycling cost. */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java index 74607e2c447..90cf0d8bd90 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DashTest.java @@ -19,10 +19,10 @@ public class DashTest extends CardTestPlayerBase { * which may create a delayed triggered ability, and a static ability that * functions while the object with dash is on the battlefield. “Dash [cost]” * means “You may cast this card by paying [cost] rather that its mana - * cost,” “If this spell’s dash cost was paid, return the permanent this - * spell becomes to its owner’s hand at the beginning of the next end step,” - * and “As long as this permanent’s dash cost was paid, it has haste.” - * Paying a card’s dash cost follows the rules for paying alternative costs + * cost,” “If this spell's dash cost was paid, return the permanent this + * spell becomes to its owner's hand at the beginning of the next end step,” + * and “As long as this permanent's dash cost was paid, it has haste.” + * Paying a card's dash cost follows the rules for paying alternative costs * in rules 601.2b and 601.2e–g. * */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ExploitTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ExploitTest.java index c0570e45ae9..152bc50c776 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ExploitTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ExploitTest.java @@ -21,8 +21,8 @@ public class ExploitTest extends CardTestPlayerBase { * 702.109b A creature with exploit “exploits a creature” when the controller of the exploit ability sacrifices a creature as that ability resolves. * * You choose whether to sacrifice a creature and which creature to sacrifice as the exploit ability resolves. - * You can sacrifice the creature with exploit if it’s still on the battlefield. This will cause its other ability to trigger. - * You can’t sacrifice more than one creature to any one exploit ability. + * You can sacrifice the creature with exploit if it's still on the battlefield. This will cause its other ability to trigger. + * You can't sacrifice more than one creature to any one exploit ability. * */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FadingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FadingTest.java index 304a9adad1d..276b655c6c4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FadingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FadingTest.java @@ -18,7 +18,7 @@ public class FadingTest extends CardTestPlayerBase { * 702.31. Fading * 702.31a Fading is a keyword that represents two abilities. “Fading N” means “This permanent * enters the battlefield with N fade counters on it” and “At the beginning of your upkeep, remove - * a fade counter from this permanent. If you can’t, sacrifice the permanent.” + * a fade counter from this permanent. If you can't, sacrifice the permanent.” */ /** diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/HideawayTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/HideawayTest.java index 51b6ac6a58f..6a4db4e04f6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/HideawayTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/HideawayTest.java @@ -22,7 +22,7 @@ public class HideawayTest extends CardTestPlayerBase { * at the top four cards of your library. Exile one of them face down and * put the rest on the bottom of your library in any order. The exiled card * gains ‘Any player who has controlled the permanent that exiled this card - * may look at this card in the exile zone.’” + * may look at this card in the exile zone.'” * */ /** diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/InfectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/InfectTest.java index f573b48cc3a..afe24632fc2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/InfectTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/InfectTest.java @@ -17,10 +17,10 @@ public class InfectTest extends CardTestPlayerBase { /** * * 702.89. Infect 702.89a Infect is a static ability. 702.89b Damage dealt - * to a player by a source with infect doesn’t cause that player to lose + * to a player by a source with infect doesn't cause that player to lose * life. Rather, it causes the player to get that many poison counters. See * rule 119.3. 702.89c Damage dealt to a creature by a source with infect - * isn’t marked on that creature. Rather, it causes that many -1/-1 counters + * isn't marked on that creature. Rather, it causes that many -1/-1 counters * to be put on that creature. See rule 119.3. 702.89d If a permanent leaves * the battlefield before an effect causes it to deal damage, its last known * information is used to determine whether it had infect. 702.89e The diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java index 99c54e77637..77d0fbe911e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java @@ -17,14 +17,14 @@ public class KickerTest extends CardTestPlayerBase { /** * 702.32. Kicker 702.32a Kicker is a static ability that functions while * the spell with kicker is on the stack. “Kicker [cost]” means “You may pay - * an additional [cost] as you cast this spell.” Paying a spell’s kicker + * an additional [cost] as you cast this spell.” Paying a spell's kicker * cost(s) follows the rules for paying additional costs in rules 601.2b and * 601.2e–g. 702.32b The phrase “Kicker [cost 1] and/or [cost 2]” means the * same thing as “Kicker [cost 1], kicker [cost 2].” 702.32c Multikicker is * a variant of the kicker ability. “Multikicker [cost]” means “You may pay * an additional [cost] any number of times as you cast this spell.” A - * multikicker cost is a kicker cost. 702.32d If a spell’s controller - * declares the intention to pay any of that spell’s kicker costs, that + * multikicker cost is a kicker cost. 702.32d If a spell's controller + * declares the intention to pay any of that spell's kicker costs, that * spell has been “kicked.” If a spell has two kicker costs or has * multikicker, it may be kicked multiple times. See rule 601.2b. 702.32e * Objects with kicker or multikicker have additional abilities that specify @@ -36,9 +36,9 @@ public class KickerTest extends CardTestPlayerBase { * “if it was kicked with its [A] kicker” and “if it was kicked with its [B] * kicker,” where A and B are the first and second kicker costs listed on * the card, respectively. Each of those abilities is linked to the - * appropriate kicker ability. 702.32g If part of a spell’s ability has its + * appropriate kicker ability. 702.32g If part of a spell's ability has its * effect only if that spell was kicked, and that part of the ability - * includes any targets, the spell’s controller chooses those targets only + * includes any targets, the spell's controller chooses those targets only * if that spell was kicked. Otherwise, the spell is cast as if it did not * have those targets. See rule 601.2c. * diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MadnessTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MadnessTest.java index e4d958812e6..b556c46b835 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MadnessTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MadnessTest.java @@ -16,12 +16,12 @@ public class MadnessTest extends CardTestPlayerBase { /** * 702.34. Madness 702.34a Madness is a keyword that represents two * abilities. The first is a static ability that functions while the card - * with madness is in a player’s hand. The second is a triggered ability + * with madness is in a player's hand. The second is a triggered ability * that functions when the first ability is applied. “Madness [cost]” means * “If a player would discard this card, that player discards it, but may * exile it instead of putting it into their graveyard” and “When this * card is exiled this way, its owner may cast it by paying [cost] rather - * than paying its mana cost. If that player doesn’t, he or she puts this + * than paying its mana cost. If that player doesn't, he or she puts this * card into their graveyard.” 702.34b Casting a spell using its * madness ability follows the rules for paying alternative costs in rules * 601.2b and 601.2e–g. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MetalcraftTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MetalcraftTest.java index 43d8fb89d3a..d37caa01a5f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MetalcraftTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MetalcraftTest.java @@ -23,7 +23,7 @@ public class MetalcraftTest extends CardTestPlayerBase { public void testMetalcraftFromBlinkmoth() { addCard(Zone.BATTLEFIELD, playerA, "Darksteel Citadel",1); - // Metalcraft - {this} is a 5/5 Golem artifact creature as long as you control three or more artifacts + // Metalcraft — {this} is a 5/5 Golem artifact creature as long as you control three or more artifacts addCard(Zone.BATTLEFIELD, playerA, "Rusted Relic", 1); // {T}: Add {C}to your mana pool. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RecoverTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RecoverTest.java index 47bc383735b..4fec8bfe4d5 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RecoverTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/RecoverTest.java @@ -14,7 +14,7 @@ public class RecoverTest extends CardTestPlayerBase { /** * 702.58a Recover is a triggered ability that functions only while the card - * with recover is in a player’s graveyard. “Recover [cost]” means “When a + * with recover is in a player's graveyard. “Recover [cost]” means “When a * creature is put into your graveyard from the battlefield, you may pay * [cost]. If you do, return this card from your graveyard to your hand. * Otherwise, exile this card.” diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReplicateTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReplicateTest.java index 2047814d48e..a347456ec9c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReplicateTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ReplicateTest.java @@ -20,7 +20,7 @@ public class ReplicateTest extends CardTestPlayerBase { * functions while the spell with replicate is on the stack. “Replicate [cost]” means “As an * additional cost to cast this spell, you may pay [cost] any number of times” and “When you cast * this spell, if a replicate cost was paid for it, copy it for each time its replicate cost was paid. If - * the spell has any targets, you may choose new targets for any of the copies.” Paying a spell’s + * the spell has any targets, you may choose new targets for any of the copies.” Paying a spell's * replicate cost follows the rules for paying additional costs in rules 601.2b and 601.2e–g. * 702.55b If a spell has multiple instances of replicate, each is paid separately and triggers based on * the payments made for it, not any other instance of replicate. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ScavengeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ScavengeTest.java index e07080e0244..b71c2fd51c2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ScavengeTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ScavengeTest.java @@ -21,7 +21,7 @@ public class ScavengeTest extends CardTestPlayerBase { // // 702.95a Scavenge is an activated ability that functions only while the card // with scavenge is in a graveyard. "Scavenge [cost]" means "[Cost], Exile this -// card from your graveyard: Put a number of +1/+1 counters equal to this card’s +// card from your graveyard: Put a number of +1/+1 counters equal to this card's // power on target creature. Activate this ability only any time you could cast // a sorcery." // diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransmuteTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransmuteTest.java index f0c44e83b9f..0a103a6885d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransmuteTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransmuteTest.java @@ -11,14 +11,14 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * 702.52. Transmute * * 702.52a Transmute is an activated ability that functions only while the card - * with transmute is in a player’s hand. “Transmute [cost]” means “[Cost], + * with transmute is in a player's hand. “Transmute [cost]” means “[Cost], * Discard this card: Search your library for a card with the same converted * mana cost as the discarded card, reveal that card, and put it into your hand. * Then shuffle your library. Play this ability only any time you could play a * sorcery.” * * 702.52b Although the transmute ability is playable only if the card is in a - * player’s hand, it continues to exist while the object is in play and in all + * player's hand, it continues to exist while the object is in play and in all * other zones. Therefore objects with transmute will be affected by effects * that depend on objects having one or more activated abilities. * diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/TinderWallTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/TinderWallTest.java new file mode 100644 index 00000000000..42d9b2adf92 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/TinderWallTest.java @@ -0,0 +1,40 @@ +package org.mage.test.cards.abilities.oneshot.damage; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class TinderWallTest extends CardTestPlayerBase { + + /** + * This test fails because the target is no longer seen as valid during + * resolution, because the source is no longer on the battlefield + * (sacrificed as cost) and therefore it's no longer blocking the target. + */ + @Test + public void testDamageFromInstantToPlayer() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + // Defender + // Sacrifice Tinder Wall: Add {R}{R}. + // {R}, Sacrifice Tinder Wall: Tinder Wall deals 2 damage to target creature it's blocking. + addCard(Zone.BATTLEFIELD, playerA, "Tinder Wall"); // Creature 0/3 + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + + attack(2, playerB, "Silvercoat Lion"); + block(2, playerA, "Tinder Wall", "Silvercoat Lion"); + activateAbility(2, PhaseStep.DECLARE_BLOCKERS, playerA, "{R}, Sacrifice", "Silvercoat Lion"); + + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Tinder Wall", 1); + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/library/PutToLibraryTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/library/PutToLibraryTest.java new file mode 100644 index 00000000000..fbaf5f07ad0 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/library/PutToLibraryTest.java @@ -0,0 +1,76 @@ +package org.mage.test.cards.abilities.oneshot.library; + +import java.util.ArrayList; +import mage.cards.Card; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class PutToLibraryTest extends CardTestPlayerBase { + + @Test + public void testPutSecondFromTop() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + // Put target creature into its owner's library second from the top. Its controller gains 3 life. + addCard(Zone.HAND, playerA, "Oust"); // Sorcery {W} + + addCard(Zone.BATTLEFIELD, playerB, "Dread Wanderer"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oust", "Dread Wanderer"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Oust", 1); + assertLibraryCount(playerB, "Dread Wanderer", 1); + + assertLife(playerA, 20); + assertLife(playerB, 23); + + ArrayList cardArray = new ArrayList<>(playerB.getLibrary().getCards(currentGame)); + Assert.assertTrue("Library has no cards but should have", cardArray.size() > 1); + Card secondCard = cardArray.get(1); + Assert.assertTrue("Second card from top should be Dread Wanderer, but it isn't", + secondCard != null && secondCard.getName().equals("Dread Wanderer")); + + } + + // Unexpectedly Absent doesn't work properly, no matter how much you pay for X the card is always returned on top of the library. + @Test + public void testUnexpectedlyAbsent() { + // Flying + // At the beginning of combat on your turn, you may pay {G}{U}. When you do, put a +1/+1 counter on another target creature you control, and that creature gains flying until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Skyrider Patrol", 1); + + // Put target nonland permanent into its owner's library just beneath the top X cards of that library. + addCard(Zone.HAND, playerB, "Unexpectedly Absent"); // Instant {X}{W}{W} + addCard(Zone.BATTLEFIELD, playerB, "Plains", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Unexpectedly Absent", "Skyrider Patrol"); + setChoice(playerB, "X=3"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Unexpectedly Absent", 1); + assertPermanentCount(playerA, "Skyrider Patrol", 0); + assertLibraryCount(playerA, "Skyrider Patrol", 1); + + ArrayList cardArray = new ArrayList<>(playerA.getLibrary().getCards(currentGame)); + Assert.assertTrue("Library has no cards but should have", cardArray.size() > 3); + Card fourthCard = cardArray.get(3);// get the 4th element + Assert.assertTrue("Fourth card from top should be Skyrider Patrol, but it isn't", + fourthCard != null && fourthCard.getName().equals("Skyrider Patrol")); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/AuratouchedMageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/AuratouchedMageTest.java index 932e71a8b8b..1d45c86ac01 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/AuratouchedMageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/AuratouchedMageTest.java @@ -25,7 +25,7 @@ public class AuratouchedMageTest extends CardTestPlayerBase { //If someone knows the way to elegantly handle the test mechanism in regards to no valid targets, please modify. The test works fine in practice. @Ignore public void testAuratouchedMageEffectHasMadeIntoTypeArtifact() { - //Any Aura card you find must be able to enchant Auratouched Mage as it currently exists, or as it most recently existed on the battlefield if it’s no + //Any Aura card you find must be able to enchant Auratouched Mage as it currently exists, or as it most recently existed on the battlefield if it's no //longer on the battlefield. If an effect has made the Mage an artifact, for example, you could search for an Aura with “enchant artifact.” //Expected result: An effect has made Auratouched Mage into an artifact upon entering the battlefield. An aura that only works on artifacts should work. addCard(Zone.BATTLEFIELD, playerA, "Plains", 7); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NaturesWillTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NaturesWillTest.java new file mode 100644 index 00000000000..2c8d49e50ae --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NaturesWillTest.java @@ -0,0 +1,67 @@ +package org.mage.test.cards.abilities.other; + +import mage.constants.MultiplayerAttackOption; +import mage.constants.PhaseStep; +import mage.constants.RangeOfInfluence; +import mage.constants.Zone; +import mage.game.FreeForAll; +import mage.game.Game; +import mage.game.GameException; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +import java.io.FileNotFoundException; + +public class NaturesWillTest extends CardTestPlayerBase { + @Override + protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 20); + playerA = createPlayer(game, playerA, "PlayerA"); + playerB = createPlayer(game, playerB, "PlayerB"); + playerC = createPlayer(game, playerC, "PlayerC"); + return game; + } + + + @Test + public void testAttackMultiplePlayers() { + addCard(Zone.HAND, playerA, "Nature's Will"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); + addCard(Zone.BATTLEFIELD, playerA, "Suntail Hawk"); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 4); + addCard(Zone.BATTLEFIELD, playerC, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nature's Will"); + attack(1, playerA, "Grizzly Bears", playerB); + attack(1, playerA, "Suntail Hawk", playerC); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertTappedCount("Forest", false, 4); + assertTappedCount("Mountain", true, 4); + assertTappedCount("Island", true, 4); + } + + @Test + public void testAttackOnePlayer() { + addCard(Zone.HAND, playerA, "Nature's Will"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 4); + addCard(Zone.BATTLEFIELD, playerC, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nature's Will"); + attack(1, playerA, "Grizzly Bears", playerB); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertTappedCount("Forest", false, 4); + assertTappedCount("Mountain", true, 4); + assertTappedCount("Island", false, 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/StormTheVaultTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/StormTheVaultTest.java new file mode 100644 index 00000000000..75f279af428 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/StormTheVaultTest.java @@ -0,0 +1,59 @@ +package org.mage.test.cards.abilities.other; + +import mage.constants.MultiplayerAttackOption; +import mage.constants.PhaseStep; +import mage.constants.RangeOfInfluence; +import mage.constants.Zone; +import mage.game.FreeForAll; +import mage.game.Game; +import mage.game.GameException; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +import java.io.FileNotFoundException; + +public class StormTheVaultTest extends CardTestPlayerBase { + @Override + protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 20); + playerA = createPlayer(game, playerA, "PlayerA"); + playerB = createPlayer(game, playerB, "PlayerB"); + playerC = createPlayer(game, playerC, "PlayerC"); + return game; + } + + + @Test + public void testAttackMultiplePlayers() { + addCard(Zone.BATTLEFIELD, playerA, "Storm the Vault"); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); + addCard(Zone.BATTLEFIELD, playerA, "Nessian Courser"); + addCard(Zone.BATTLEFIELD, playerA, "Suntail Hawk"); + addCard(Zone.BATTLEFIELD, playerA, "Lantern Kami"); + + attack(1, playerA, "Grizzly Bears", playerB); + attack(1, playerA, "Nessian Courser", playerB); + attack(1, playerA, "Suntail Hawk", playerC); + attack(1, playerA, "Lantern Kami", playerC); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Treasure", 2); + } + + @Test + public void testAttackOnePlayer() { + addCard(Zone.BATTLEFIELD, playerA, "Storm the Vault"); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); + addCard(Zone.BATTLEFIELD, playerA, "Suntail Hawk"); + + attack(1, playerA, "Grizzly Bears", playerB); + attack(1, playerA, "Suntail Hawk", playerB); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Treasure", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java index f9e7c56dab3..68936f22903 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/LegendarySorceryTest.java @@ -15,7 +15,7 @@ public class LegendarySorceryTest extends CardTestPlayerBase { @Test public void testCastSuccessful() { // (You may cast a legendary sorcery only if you control a legendary creature or planeswalker.) - // Exile all nonland permanents that aren’t legendary. + // Exile all nonland permanents that aren't legendary. addCard(Zone.HAND, playerA, "Urza's Ruinous Blast"); // Sorcery Legendary {4}{W} addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); // non Legendary @@ -46,7 +46,7 @@ public class LegendarySorceryTest extends CardTestPlayerBase { @Test public void testCastNotSuccessful() { // (You may cast a legendary sorcery only if you control a legendary creature or planeswalker.) - // Exile all nonland permanents that aren’t legendary. + // Exile all nonland permanents that aren't legendary. addCard(Zone.HAND, playerA, "Urza's Ruinous Blast"); // Sorcery Legendary {4}{W} addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); // non Legendary @@ -88,7 +88,7 @@ public class LegendarySorceryTest extends CardTestPlayerBase { // Flying, first strike, vigilance, trample, haste, protection from black and from red addCard(Zone.BATTLEFIELD, playerB, "Akroma, Angel of Wrath", 1); // Legendary // (You may cast a legendary sorcery only if you control a legendary creature or planeswalker.) - // Exile all nonland permanents that aren’t legendary. + // Exile all nonland permanents that aren't legendary. addCard(Zone.GRAVEYARD, playerB, "Urza's Ruinous Blast"); // Sorcery Legendary {4}{W} castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dire Fleet Daredevil"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/BecomesCreatureAttachedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/BecomesCreatureAttachedTest.java index 6aa25a080c8..1752370723b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/BecomesCreatureAttachedTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/BecomesCreatureAttachedTest.java @@ -41,7 +41,7 @@ public class BecomesCreatureAttachedTest extends CardTestPlayerBase { @Test public void test_AttachToLandWithColorReplace() { - // Enchanted land is a 2/2 blue Elemental creature with flying. It’s still a land. + // Enchanted land is a 2/2 blue Elemental creature with flying. It's still a land. addCard(Zone.HAND, playerA, "Wind Zendikon", 1); addCard(Zone.BATTLEFIELD, playerA, "Island", 1); @@ -64,7 +64,7 @@ public class BecomesCreatureAttachedTest extends CardTestPlayerBase { @Test public void test_AttachToLandWithColorAdd() { - // Enchanted land is a 2/2 blue Elemental creature with flying. It’s still a land. + // Enchanted land is a 2/2 blue Elemental creature with flying. It's still a land. addCard(Zone.HAND, playerA, "Deep Freeze", 1); addCard(Zone.BATTLEFIELD, playerA, "Island", 3); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java index 2d3819dc0da..abee351081c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/EnsoulArtifactTest.java @@ -2,7 +2,9 @@ package org.mage.test.cards.continuous; import mage.abilities.keyword.IndestructibleAbility; +import mage.constants.CardType; import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.constants.Zone; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -16,8 +18,9 @@ public class EnsoulArtifactTest extends CardTestPlayerBase { /** * Tests boost disappeared after creature died */ + @Test - public void testBoostWithUndying() { + public void test_Boost() { addCard(Zone.BATTLEFIELD, playerA, "Darksteel Citadel", 1); addCard(Zone.BATTLEFIELD, playerA, "Island", 2); @@ -30,7 +33,33 @@ public class EnsoulArtifactTest extends CardTestPlayerBase { execute(); assertAbility(playerA, "Darksteel Citadel", IndestructibleAbility.getInstance(), true); + assertType("Darksteel Citadel", CardType.CREATURE, true); assertPowerToughness(playerA, "Darksteel Citadel", 5, 5); } + @Test + public void test_BoostDisappearedOnBlink() { + addCard(Zone.BATTLEFIELD, playerA, "Darksteel Citadel", 1); + + // blink + addCard(Zone.HAND, playerA, "Momentary Blink", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + + // Enchanted artifact is a creature with base power and toughness 5/5 in addition to its other types. + addCard(Zone.HAND, playerA, "Ensoul Artifact"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ensoul Artifact", "Darksteel Citadel"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Momentary Blink", "Darksteel Citadel"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Momentary Blink", 0); + assertPermanentCount(playerA, "Darksteel Citadel", 1); + assertPowerToughness(playerA, "Darksteel Citadel", 0, 0); + assertType("Darksteel Citadel", CardType.CREATURE, false); + assertAbility(playerA, "Darksteel Citadel", IndestructibleAbility.getInstance(), true); + assertPermanentCount(playerA, "Ensoul Artifact", 0); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ImprisonedInTheMoonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ImprisonedInTheMoonTest.java index abd863a4b7e..8583715ed7c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ImprisonedInTheMoonTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ImprisonedInTheMoonTest.java @@ -21,7 +21,7 @@ public class ImprisonedInTheMoonTest extends CardTestPlayerBase { * * Card ruling: http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=414360 * If the enchanted permanent is a land and has land types, it retains those types even though it loses any intrinsic mana abilities associated with them. - * For example, a Plains enchanted by Imprisoned in the Moon is still a Plains, but it can’t tap for {W}, only for {C}. + * For example, a Plains enchanted by Imprisoned in the Moon is still a Plains, but it can't tap for {W}, only for {C}. */ @Test public void testEnchantUrzaLand() { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MetallicMiminTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MetallicMiminTest.java index 50f9d823ba7..04cdf394457 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MetallicMiminTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MetallicMiminTest.java @@ -19,7 +19,7 @@ public class MetallicMiminTest extends CardTestPlayerBase { * be getting a counter as long as you name the same type as the first one. * * 611.3c Continuous effects that modify characteristics of permanents do so - * simultaneously with the permanent entering the battlefield. They don’t + * simultaneously with the permanent entering the battlefield. They don't * wait until the permanent is on the battlefield and then change it. * Because such effects apply as the permanent enters the battlefield, they * are applied before determining whether the permanent will cause an @@ -28,7 +28,7 @@ public class MetallicMiminTest extends CardTestPlayerBase { * Example: A permanent with the static ability “All white creatures get * +1/+1” is on the battlefield. A creature spell that would normally create * a 1/1 white creature instead creates a 2/2 white creature. The creature - * doesn’t enter the battlefield as 1/1 and then change to 2/2. + * doesn't enter the battlefield as 1/1 and then change to 2/2. * */ @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java index 4f3e24dc01f..1cb16170ab4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java @@ -191,4 +191,34 @@ public class CleverImpersonatorTest extends CardTestPlayerBase { assertType(dReflection, CardType.ENCHANTMENT, true); } + @Test + public void testKindredDiscovery() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.HAND, playerA, "Kindred Discovery"); + + + addCard(Zone.BATTLEFIELD, playerB, "Island", 5); + // Skip your draw step. + addCard(Zone.BATTLEFIELD, playerB, "Dragon Appeasement"); + addCard(Zone.HAND, playerB, "Clever Impersonator"); + addCard(Zone.HAND, playerB, "Ornithopter", 2); + addCard(Zone.HAND, playerB, "Memnite"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kindred Discovery"); + setChoice(playerA, "Construct"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clever Impersonator"); + setChoice(playerB, "Kindred Discovery"); + setChoice(playerB, "Thopter"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Ornithopter"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Ornithopter"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Memnite"); + + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertHandCount(playerB, 2); + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java index 2bb567fbbd5..202b360e987 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CloneTest.java @@ -4,6 +4,7 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectsList; import mage.cards.Card; import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.StaticFilters; @@ -89,7 +90,7 @@ public class CloneTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves"); addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Executio", "Llanowar Elves"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Llanowar Elves"); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Clone"); setStopAt(1, PhaseStep.END_TURN); @@ -199,4 +200,32 @@ public class CloneTest extends CardTestPlayerBase { Assert.assertTrue("There should be a white and a blue Silvercoat Lion be on the battlefield", blueLion && whiteLion); } + @Test + public void testAdaptiveAutomaton() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + addCard(Zone.HAND, playerA, "Adaptive Automaton"); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 4); + addCard(Zone.HAND, playerB, "Clone"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Adaptive Automaton"); + setChoice(playerA, "Elf"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clone"); + setChoice(playerB, "Adaptive Automaton"); + setChoice(playerB, "Goblin"); + + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerA, "Adaptive Automaton", 1); + Permanent original = getPermanent("Adaptive Automaton", playerA); + Assert.assertTrue("The original Adaptive Automaton should be an Elf", original.hasSubtype(SubType.ELF, currentGame)); + + assertPermanentCount(playerB, "Adaptive Automaton", 1); + Permanent clone = getPermanent("Adaptive Automaton", playerB); + Assert.assertFalse("The cloned Adaptive Automaton should not be as Elf", clone.hasSubtype(SubType.ELF, currentGame)); + Assert.assertTrue("The cloned Adaptive Automaton should be a Goblin", clone.hasSubtype(SubType.GOBLIN, currentGame)); + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java index 6f2953e071f..2ec1c261ed3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java @@ -138,16 +138,16 @@ public class CopySpellTest extends CardTestPlayerBase { * * 702.46a Splice is a static ability that functions while a card is in your * hand. “Splice onto [subtype] [cost]” means “You may reveal this card from - * your hand as you cast a [subtype] spell. If you do, copy this card’s text + * your hand as you cast a [subtype] spell. If you do, copy this card's text * box onto that spell and pay [cost] as an additional cost to cast that - * spell.” Paying a card’s splice cost follows the rules for paying + * spell.” Paying a card's splice cost follows the rules for paying * additional costs in rules 601.2b and 601.2e–g. 601.2b If the spell is * modal the player announces the mode choice (see rule 700.2). If the * player wishes to splice any cards onto the spell (see rule 702.46), he or * she reveals those cards in their hand. 706.10. To copy a spell, * activated ability, or triggered ability means to put a copy of it onto - * the stack; a copy of a spell isn’t cast and a copy of an activated - * ability isn’t activated. A copy of a spell or ability copies both the + * the stack; a copy of a spell isn't cast and a copy of an activated + * ability isn't activated. A copy of a spell or ability copies both the * characteristics of the spell or ability and all decisions made for it, * including modes, targets, the value of X, and additional or alternative * costs. (See rule 601, “Casting Spells.”) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/HelmOfTheHostTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/HelmOfTheHostTest.java index 91d54cc9624..6de47b9fdbf 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/HelmOfTheHostTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/HelmOfTheHostTest.java @@ -27,7 +27,7 @@ public class HelmOfTheHostTest extends CardTestPlayerBase { // 0: Until end of turn, Gideon of the Trials becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn. // 0: You get an emblem with "As long as you control a Gideon planeswalker, you can't lose the game and your opponent can't win the game." addCard(Zone.BATTLEFIELD, playerA, "Gideon of the Trials", 1); - // At the beginning of combat on your turn, create a token that’s a copy of equipped creature, except the token isn’t legendary if equipped creature is legendary. That token gains haste. + // At the beginning of combat on your turn, create a token that's a copy of equipped creature, except the token isn't legendary if equipped creature is legendary. That token gains haste. // Equip {5} addCard(Zone.BATTLEFIELD, playerA, "Helm of the Host", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/KikiJikiMirrorBreakerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/KikiJikiMirrorBreakerTest.java index d82ee22b679..6a9fac02066 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/KikiJikiMirrorBreakerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/KikiJikiMirrorBreakerTest.java @@ -23,7 +23,7 @@ public class KikiJikiMirrorBreakerTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Kiki-Jiki, Mirror Breaker", 1); addCard(Zone.BATTLEFIELD, playerA, "Voice of Resurgence", 1); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Create a token that's a copy of target nonlegendary creature you control. That token has haste. Sacrifice it at the beginning of the next end step."); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step."); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -39,7 +39,7 @@ public class KikiJikiMirrorBreakerTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Kiki-Jiki, Mirror Breaker", 1); addCard(Zone.BATTLEFIELD, playerA, "Voice of Resurgence", 1); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Create a token that's a copy of target nonlegendary creature you control. That token has haste. Sacrifice it at the beginning of the next end step."); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step."); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -60,7 +60,7 @@ public class KikiJikiMirrorBreakerTest extends CardTestPlayerBase { // Flamebreak deals 3 damage to each creature without flying and each player. Creatures dealt damage this way can't be regenerated this turn. addCard(Zone.HAND, playerB, "Flamebreak"); - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Create a token that's a copy of target nonlegendary creature you control. That token has haste. Sacrifice it at the beginning of the next end step."); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step."); castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Flamebreak"); setStopAt(2, PhaseStep.END_TURN); @@ -95,7 +95,7 @@ public class KikiJikiMirrorBreakerTest extends CardTestPlayerBase { castSpell(2, PhaseStep.UPKEEP, playerA, "Blustersquall", "Humble Defector"); // Tap nontoken Defector so only the Token can be used later - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Create a token that's a copy of target nonlegendary creature you control. That token has haste. Sacrifice it at the beginning of the next end step."); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step."); activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "{T}: Draw two cards. Target opponent gains control"); @@ -137,7 +137,7 @@ public class KikiJikiMirrorBreakerTest extends CardTestPlayerBase { castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Body Double"); setChoice(playerB, "Silvercoat Lion"); - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Create a token that's a copy of target nonlegendary creature you control. That token has haste. Sacrifice it at the beginning of the next end step."); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step."); attack(2, playerB, "Silvercoat Lion"); setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java index 3953a7bec09..4cb9d4a3cdc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java @@ -450,8 +450,8 @@ public class PhantasmalImageTest extends CardTestPlayerBase { * Example: Two creatures are on the battlefield along with an artifact that * has the ability “Whenever a creature dies, you gain 1 life.” Someone * plays a spell that destroys all artifacts, creatures, and enchantments. - * The artifact’s ability triggers twice, even though the artifact goes to - * its owner’s graveyard at the same time as the creatures. + * The artifact's ability triggers twice, even though the artifact goes to + * its owner's graveyard at the same time as the creatures. * */ @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromLibraryWithoutPayingManaCostTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromLibraryWithoutPayingManaCostTest.java new file mode 100644 index 00000000000..9792254c176 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromLibraryWithoutPayingManaCostTest.java @@ -0,0 +1,115 @@ +package org.mage.test.cards.cost.alternate; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Quercitron + */ +public class CastFromLibraryWithoutPayingManaCostTest extends CardTestPlayerBase { + + /** + * Test for issue https://github.com/magefree/mage/issues/5189 + * + * I've cast Utter End via Sunforger, then later on I've shuffled Utter End from my GY back into my library + * via Elixir of Immortality. I cast Utter End again via Sunforger, but this time I don't get prompted to select + * a target - it keeps the old target, a permanent that's already in exile, and thus the recast Utter End fizzles. + */ + @Test + public void testCastCardFromLibraryTwice() { + addCard(Zone.BATTLEFIELD, playerA, "Storm Crow"); + // {R}{W}, Unattach Sunforger: Search your library for a red or white instant card with + // converted mana cost 4 or less and cast that card without paying its mana cost. Then shuffle your library. + // Equip {3} + addCard(Zone.BATTLEFIELD, playerA, "Sunforger"); + // {2}, {T}: You gain 5 life. Shuffle Elixir of Immortality and your graveyard into their owner's library. + addCard(Zone.BATTLEFIELD, playerA, "Elixir of Immortality"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 10); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 10); + // Exile target nonland permanent. + addCard(Zone.LIBRARY, playerA, "Utter End"); + + addCard(Zone.BATTLEFIELD, playerB, "Gray Ogre"); + addCard(Zone.BATTLEFIELD, playerB, "Hill Giant"); + + // Equip Sunforger to Storm Crow. + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Storm Crow"); + // Unattach Sunforger to cast Utter End from library targeting Gray Ogre. + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}{W}, Unattach"); + addTarget(playerA, "Utter End"); + addTarget(playerA, "Gray Ogre"); + + // Sacrifice Elixir of Immortality to shuffle Utter End from graveyard to library. + activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{2}, {T}: You gain 5 life"); + + // Equip Sunforger to Storm Crow again. + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip", "Storm Crow"); + // Unattach Sunforger to cast Utter End from library targeting Hill Giant. + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{R}{W}, Unattach"); + addTarget(playerA, "Utter End"); + addTarget(playerA, "Hill Giant"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + // Check that Elixir of Immortality was sacrificed. + assertPermanentCount(playerA, "Elixir of Immortality", 0); + + // Check that Gray Ogre was exiled. + assertPermanentCount(playerB, "Gray Ogre", 0); + // Check that Hill Giant was exiled. + assertPermanentCount(playerB, "Hill Giant", 0); + + // Check that Utter End is in the graveyard. + assertGraveyardCount(playerA, "Utter End", 1); + } + + @Test + public void testCastCardFromHandAndThenFromLibrary() { + addCard(Zone.BATTLEFIELD, playerA, "Storm Crow"); + // {R}{W}, Unattach Sunforger: Search your library for a red or white instant card with + // converted mana cost 4 or less and cast that card without paying its mana cost. Then shuffle your library. + // Equip {3} + addCard(Zone.BATTLEFIELD, playerA, "Sunforger"); + addCard(Zone.BATTLEFIELD, playerA, "Elixir of Immortality"); + // {2}, {T}: You gain 5 life. Shuffle Elixir of Immortality and your graveyard into their owner's library. + addCard(Zone.BATTLEFIELD, playerA, "Plains", 10); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 10); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10); + // Exile target nonland permanent. + addCard(Zone.HAND, playerA, "Utter End"); + + addCard(Zone.BATTLEFIELD, playerB, "Gray Ogre"); + addCard(Zone.BATTLEFIELD, playerB, "Hill Giant"); + + // Cast Utter End from hand targeting Gray Ogre. + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Utter End", "Gray Ogre"); + + // Sacrifice Elixir of Immortality to shuffle Utter End from graveyard to library. + activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{2}, {T}: You gain 5 life"); + + // Equip Sunforger to Storm Crow. + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip", "Storm Crow"); + // Unattach Sunforger to cast Utter End from library targeting Hill Giant. + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{R}{W}, Unattach"); + addTarget(playerA, "Utter End"); + addTarget(playerA, "Hill Giant"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + // Check that Elixir of Immortality was sacrificed. + assertPermanentCount(playerA, "Elixir of Immortality", 0); + + // Check that Gray Ogre was exiled. + assertPermanentCount(playerB, "Gray Ogre", 0); + // Check that Hill Giant was exiled. + assertPermanentCount(playerB, "Hill Giant", 0); + + // Check that Utter End is in the graveyard. + assertGraveyardCount(playerA, "Utter End", 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java index a682ccc2b3f..40ffdc079f8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java @@ -217,4 +217,33 @@ public class CostModificationTest extends CardTestPlayerBase { assertTappedCount("Plains", false, 2); // 2 for 1st Lion 1 for 2nd lion and only 1 mana needed to cast face down Zoetic } + + /** + * Confirm that Animar's cost reduction allows you to play spells that you wouldn't have enough mana for without it. + */ + @Test + public void AnimarSoulOfElementsTest() { + + // Protection from white and from black + // Whenever you cast a creature spell, put a +1/+1 counter on Animar, Soul of Elements. + // Creature spells you cast cost {1} less to cast for each +1/+1 counter on Animar. + addCard(Zone.BATTLEFIELD, playerA, "Animar, Soul of Elements"); + + addCard(Zone.HAND, playerA, "Silvercoat Lion", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + + addCard(Zone.HAND, playerA, "Zoetic Cavern"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 2); + assertCounterCount(playerA, "Animar, Soul of Elements", CounterType.P1P1, 2); + + assertTappedCount("Plains", true, 3); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java index 48a358dc8db..f1e04d3ffec 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java @@ -18,12 +18,12 @@ public class SpreadingSeasTest extends CardTestPlayerBase { * activated it on response, seas resolves but the manland loses creature * type what should not happened. * - * 305.7. If an effect changes a land’s subtype to one or more of the basic + * 305.7. If an effect changes a land's subtype to one or more of the basic * land types, the land no longer has its old land type. It loses all * abilities generated from its rules text and its old land types, and it * gains the appropriate mana ability for each new basic land type. Note - * that this doesn’t remove any abilities that were granted to the land by - * other effects. Changing a land’s subtype doesn’t add or remove any card + * that this doesn't remove any abilities that were granted to the land by + * other effects. Changing a land's subtype doesn't add or remove any card * types (such as creature) or supertypes (such as basic, legendary, and * snow) the land may have. If a land gains one or more land types in * addition to its own, it keeps its land types and rules text, and it gains diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/flip/SasayaOrochiAscendantTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/flip/SasayaOrochiAscendantTest.java new file mode 100644 index 00000000000..00f9d4a148b --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/flip/SasayaOrochiAscendantTest.java @@ -0,0 +1,51 @@ +package org.mage.test.cards.flip; + +import mage.abilities.mana.ManaOptions; +import mage.constants.ManaType; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.mage.test.utils.ManaOptionsTestUtils.assertDuplicatedManaOptions; +import static org.mage.test.utils.ManaOptionsTestUtils.assertManaOptions; + +/** + * + * @author LevelX2 + */ +public class SasayaOrochiAscendantTest extends CardTestPlayerBase { + + @Test + public void testSasayasEssence() { + addCard(Zone.HAND, playerA, "Plains", 7); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + + // Reveal your hand: If you have seven or more land cards in your hand, flip Sasaya, Orochi Ascendant. + // Sasaya's Essence: Legendary Enchantment + // Whenever a land you control is tapped for mana, for each other land you control with the same name, add one mana of any type that land produced. + addCard(Zone.BATTLEFIELD, playerA, "Sasaya, Orochi Ascendant", 1); + // Mana pools don't empty as steps and phases end. + addCard(Zone.HAND, playerA, "Upwelling", 1); // Enchantment {3}{G} + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reveal your hand: If you have seven or more land cards in your hand, flip"); + activateManaAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {G}"); + activateManaAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {G}"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Upwelling"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Sasaya's Essence", 1); + assertPermanentCount(playerA, "Upwelling", 1); + + assertManaPool(playerA, ManaType.GREEN, 2); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); + assertManaOptions("{G}", manaOptions); + + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java index 446b670ccbd..ac8367bab6c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ConditionalManaTest.java @@ -1,9 +1,9 @@ - package org.mage.test.cards.mana; import mage.abilities.keyword.FlyingAbility; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -48,6 +48,7 @@ public class ConditionalManaTest extends CardTestPlayerBase { } @Test + @Ignore public void testWorkingWithReflectingPool() { addCard(Zone.BATTLEFIELD, playerA, "Cavern of Souls", 1); // can give {C] or {any} mana ({any} with restrictions) addCard(Zone.BATTLEFIELD, playerA, "Reflecting Pool", 1); // must give {C} or {any} mana from the Cavern, but without restrictions diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ForbiddenOrchardTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ForbiddenOrchardTest.java new file mode 100644 index 00000000000..7e2bd1568b4 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ForbiddenOrchardTest.java @@ -0,0 +1,35 @@ +package org.mage.test.cards.mana; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class ForbiddenOrchardTest extends CardTestPlayerBase { + + @Test + public void testSpiritCreation() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + + // {T}: Add one mana of any color. + // Whenever you tap Forbidden Orchard for mana, create a 1/1 colorless Spirit creature token under target opponent's control. + addCard(Zone.BATTLEFIELD, playerA, "Forbidden Orchard", 1); + addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 1); + + assertPermanentCount(playerB, "Spirit", 1); + assertPermanentCount(playerA, "Spirit", 0); + + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java index a5c43cb548d..95cbd92c19c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvesterDruidTest.java @@ -1,10 +1,10 @@ - package org.mage.test.cards.mana; import mage.abilities.mana.ManaOptions; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; import static org.mage.test.utils.ManaOptionsTestUtils.*; @@ -16,6 +16,7 @@ import static org.mage.test.utils.ManaOptionsTestUtils.*; public class HarvesterDruidTest extends CardTestPlayerBase { @Test + @Ignore public void testOneInstance() { addCard(Zone.BATTLEFIELD, playerA, "Island", 1); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); @@ -34,6 +35,7 @@ public class HarvesterDruidTest extends CardTestPlayerBase { } @Test + @Ignore public void testTwoInstances() { addCard(Zone.BATTLEFIELD, playerA, "Island", 1); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java index a16e293090e..e979dad8041 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/NagaVitalistTest.java @@ -1,12 +1,14 @@ package org.mage.test.cards.mana; +import mage.abilities.mana.ManaOptions; import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; -import static org.mage.test.utils.ManaOptionsTestUtils.manaOptionsContain; +import static org.mage.test.utils.ManaOptionsTestUtils.assertDuplicatedManaOptions; +import static org.mage.test.utils.ManaOptionsTestUtils.assertManaOptions; /** * @@ -47,7 +49,14 @@ public class NagaVitalistTest extends CardTestPlayerBase { setStopAt(1, PhaseStep.PRECOMBAT_MAIN); execute(); - Assert.assertTrue("playerA must cast {Any}{Any}", manaOptionsContain(playerA.getManaAvailable(currentGame), "{Any}{Any}")); + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + Assert.assertEquals("mana variations don't fit", 5, manaOptions.size()); + assertManaOptions("{B}{B}", manaOptions); + assertManaOptions("{W}{W}", manaOptions); + assertManaOptions("{U}{U}", manaOptions); + assertManaOptions("{R}{R}", manaOptions); + assertManaOptions("{G}{G}", manaOptions); } public void nagaVitalist_GiftOfParadisesLandCanGiveAnyColorToNaga_Setup(int giftCastTurn, int nagaManaTapTurn, String nagaManaTapColor) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java index f384df1e5d5..5ba92659ea8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/ReflectingPoolTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.mana; import mage.abilities.mana.ManaOptions; @@ -6,6 +5,7 @@ import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -133,6 +133,7 @@ public class ReflectingPoolTest extends CardTestPlayerBase { * producing mana */ @Test + @Ignore public void testWithDifferentLands() { addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); @@ -161,7 +162,6 @@ public class ReflectingPoolTest extends CardTestPlayerBase { assertManaOptions("{W}{W}", options); } - @Test public void testReflectingPoolGiveNonMana() { addCard(Zone.HAND, playerA, bear1, 1); @@ -215,6 +215,7 @@ public class ReflectingPoolTest extends CardTestPlayerBase { } @Test + @Ignore public void testReflectingPoolAnyManaNeedWithoutCondition() { // any mana source without conditions (use any mana at any time) addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); @@ -232,6 +233,7 @@ public class ReflectingPoolTest extends CardTestPlayerBase { } @Test + @Ignore public void testReflectingPoolAnyManaNeedWithCondition() { // any mana source have condition to use (Reflecting Pool must ignore that condition) addCard(Zone.BATTLEFIELD, playerA, "Cavern of Souls", 1); // {C} or {any} @@ -256,7 +258,7 @@ public class ReflectingPoolTest extends CardTestPlayerBase { activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add one mana of any"); activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}"); - setChoice(playerA,"Black"); + setChoice(playerA, "Black"); setStopAt(1, PhaseStep.PRECOMBAT_MAIN); execute(); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/RiverOfTearsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/RiverOfTearsTest.java new file mode 100644 index 00000000000..6faaf0f6ad3 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/RiverOfTearsTest.java @@ -0,0 +1,61 @@ +package org.mage.test.cards.mana; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class RiverOfTearsTest extends CardTestPlayerBase { + + /** + * River of Tears doesn't produce black mana any time. Gatherer says: + * + * 17/11/2017 The turn you play River of Tears, it will produce Black when + * tapped for mana. + * + * 17/11/2017 River of Tears produces Black only after you've played a land, + * not after you've put a land onto the battlefield (such as with Evolving + * Wilds). + */ + @Test + public void testBlackAfterPlayed() { + // {T}: Add {U}. If you played a land this turn, add {B} instead. + addCard(Zone.HAND, playerA, "River of Tears", 1); // Land + + addCard(Zone.HAND, playerA, "Nightshade Stinger", 1); // Creature {B} + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "River of Tears"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Nightshade Stinger"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "River of Tears", 1); + assertTapped("River of Tears", true); + assertPermanentCount(playerA, "Nightshade Stinger", 1); + } + + @Test + public void testBlueInSecondTurn() { + // {T}: Add {U}. If you played a land this turn, add {B} instead. + addCard(Zone.HAND, playerA, "River of Tears", 1); // Land + + addCard(Zone.HAND, playerA, "Aven Envoy", 1); // Creature {B} + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "River of Tears"); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Aven Envoy"); + + setStopAt(3, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "River of Tears", 1); + assertTapped("River of Tears", true); + assertPermanentCount(playerA, "Aven Envoy", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/SylvokExplorerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/SylvokExplorerTest.java index 68a88a788bd..7351eba115b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/SylvokExplorerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/SylvokExplorerTest.java @@ -1,10 +1,10 @@ - package org.mage.test.cards.mana; import mage.abilities.mana.ManaOptions; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -32,6 +32,7 @@ public class SylvokExplorerTest extends CardTestPlayerBase { * mage.abilities.mana.AnyColorLandsProduceManaEffect.getNetMana(AnyColorLandsProduceManaAbility.java:181) */ @Test + @Ignore public void testOneInstance() { addCard(Zone.BATTLEFIELD, playerB, "Island", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java index dca08309a03..8a225060589 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/VorinclexVoiceOfHungerTest.java @@ -1,10 +1,10 @@ - package org.mage.test.cards.mana; import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -41,7 +41,6 @@ public class VorinclexVoiceOfHungerTest extends CardTestPlayerBase { * Vorinclex, Voice of Hunger is not mana doubling River of Tears. */ @Test - // @Ignore // TODO: need to fix Vorinclex, Voice of Hunger -- it's double fireup mana tap event public void testVorinclexVoiceofHungerRiverOfTearsManaMultiplier() { // Mana pools don't empty as steps and phases end. addCard(Zone.BATTLEFIELD, playerA, "Upwelling", 1); @@ -92,6 +91,7 @@ public class VorinclexVoiceOfHungerTest extends CardTestPlayerBase { } @Test + @Ignore public void testCastWithGemstoneCavern() { // Trample // Whenever you tap a land for mana, add one mana of any type that land produced. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java index 58d846e4290..78374c491bc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/prevention/SwansOfBrynArgollTest.java @@ -23,7 +23,7 @@ public class SwansOfBrynArgollTest extends CardTestPlayerBase{ addCard(Zone.BATTLEFIELD, playerA, "Swans of Bryn Argoll"); // Combust deals 5 damage to target white or blue creature. The damage can't be prevented. - // Combust can't be countered by spells or abilities. + // Combust can't be countered. addCard(Zone.HAND, playerB, "Combust", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2); @@ -48,7 +48,7 @@ public class SwansOfBrynArgollTest extends CardTestPlayerBase{ addCard(Zone.BATTLEFIELD, playerA, "Swans of Bryn Argoll"); // Banefire deals X damage to any target. - // If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented. + // If X is 5 or more, Banefire can't be countered and the damage can't be prevented. addCard(Zone.HAND, playerB, "Banefire", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 8); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java index 2d99e0ab1c6..1d428a30a08 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java @@ -196,7 +196,7 @@ public class DoublingSeasonTest extends CardTestPlayerBase { /** * Gatherer Ruling: * 10/1/2005: Planeswalkers will enter the battlefield with double the normal amount of loyalty counters. However, - * if you activate an ability whose cost has you put loyalty counters on a planeswalker, the number you put on isn’t doubled. + * if you activate an ability whose cost has you put loyalty counters on a planeswalker, the number you put on isn't doubled. * This is because those counters are put on as a cost, not as an effect. */ @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java index d29ae947e0d..3da3b7cefa0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java @@ -100,8 +100,8 @@ public class LeylineOfTheVoidTest extends CardTestPlayerBase { } /* - "Leyline of the Void’s second ability doesn’t affect token permanents that would be put into an opponent’s graveyard from the battlefield. - They’ll be put into that graveyard as normal (causing any applicable triggered abilities to trigger), then they’ll cease to exist." + "Leyline of the Void's second ability doesn't affect token permanents that would be put into an opponent's graveyard from the battlefield. + They'll be put into that graveyard as normal (causing any applicable triggered abilities to trigger), then they'll cease to exist." http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=107682 */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java index adc26769e73..028e5596100 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java @@ -321,7 +321,7 @@ public class ZoneChangeReplacementTest extends CardTestPlayerBase { } /** - * Jace, Vryn’s Prodigy – Jace, Telepath Unbound + * Jace, Vryn's Prodigy – Jace, Telepath Unbound * * You can't whip him back with Whip of Erebos , flip him and then keep him. * I think he is considered a new object after being exiled by his own diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/entersBattlefield/EntersTheBattlefieldTappedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/entersBattlefield/EntersTheBattlefieldTappedTest.java new file mode 100644 index 00000000000..ddd643e27f7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/entersBattlefield/EntersTheBattlefieldTappedTest.java @@ -0,0 +1,66 @@ +package org.mage.test.cards.replacement.entersBattlefield; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EntersTheBattlefieldTappedTest extends CardTestPlayerBase { + + /** + * Creatures that enter the battlefield tapped, like Dread Wanderer, if you + * bring them back from graveyard to the battlefield they enter untapped!! + */ + @Test + public void testTappedFromHand() { + + // Dread Wanderer enters the battlefield tapped. + // {2}{B}: Return Dread Wanderer from your graveyard to the battlefield. + // Activate this ability only any time you could cast a sorcery and only if you have one or fewer cards in hand. + addCard(Zone.HAND, playerA, "Dread Wanderer"); // Creature {B} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dread Wanderer"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Dread Wanderer", 1); + assertTapped("Dread Wanderer", true); + } + + @Test + public void testTappedFromGraveyard() { + + // Dread Wanderer enters the battlefield tapped. + // {2}{B}: Return Dread Wanderer from your graveyard to the battlefield. + // Activate this ability only any time you could cast a sorcery and only if you have one or fewer cards in hand. + addCard(Zone.GRAVEYARD, playerA, "Dread Wanderer"); // Creature {B} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{B}: Return "); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Dread Wanderer", 1); + assertTapped("Dread Wanderer", true); + } + + @Test + public void testScryLandEntersTapped() { + // Temple of Enlightenment enters the battlefield tapped. + // When Temple of Enlightenment enters the battlefield, scry 1. (Look at the top card of your library. You may put that card on the bottom of your library.) + addCard(Zone.HAND, playerA, "Temple of Enlightenment"); // Land + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Temple of Enlightenment"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Temple of Enlightenment", 1); + assertTapped("Temple of Enlightenment", true); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java index ac52c6f0ba0..7fb74ea1ada 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java @@ -127,7 +127,7 @@ public class CantCastTest extends CardTestPlayerBase { // Your opponents can't block with creatures with even converted mana costs. addCard(Zone.BATTLEFIELD, playerB, "Void Winnower"); - // Metalcraft - {T}: Add one mana of any color. Activate this ability only if you control three or more artifacts. + // Metalcraft — {T}: Add one mana of any color. Activate this ability only if you control three or more artifacts. addCard(Zone.HAND, playerA, "Mox Opal", 1); // {0} castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mox Opal"); @@ -191,7 +191,7 @@ public class CantCastTest extends CardTestPlayerBase { addCard(Zone.HAND, playerB, "Llanowar Elves", 1); // Creature {G} addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); - // Abrupt Decay can't be countered by spells or abilities. + // Abrupt Decay can't be countered. // Destroy target nonland permanent with converted mana cost 3 or less. addCard(Zone.HAND, playerB, "Abrupt Decay", 1); // {B}{G} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java index 334c6c5e595..0d8fa4034a3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/WorldEnchantmentsRuleTest.java @@ -15,8 +15,8 @@ public class WorldEnchantmentsRuleTest extends CardTestPlayerBase { /** * 704.5m If two or more permanents have the supertype world, all except the one that has had - * the world supertype for the shortest amount of time are put into their owners’ graveyards. - * In the event of a tie for the shortest amount of time, all are put into their owners’ graveyards. + * the world supertype for the shortest amount of time are put into their owners' graveyards. + * In the event of a tie for the shortest amount of time, all are put into their owners' graveyards. * This is called the “world rule. * */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/CullingScalesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/CullingScalesTest.java index 1080c5feea6..002fc3d92dd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/CullingScalesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/CullingScalesTest.java @@ -41,8 +41,8 @@ public class CullingScalesTest extends CardTestPlayerBase { @Test public void testCullingScalesFizzleByMakingLowerCostedPermanent() { - // Gatherer ruling: If the targeted permanent doesn’t have the lowest converted mana cost - // when the ability resolves, the ability is countered and the permanent isn’t destroyed. + // Gatherer ruling: If the targeted permanent doesn't have the lowest converted mana cost + // when the ability resolves, the ability is countered and the permanent isn't destroyed. addCard(Zone.HAND, playerB, "Raise the Alarm"); // Make 2 tokens addCard(Zone.BATTLEFIELD, playerB, "Elvish Visionary"); // CMC = 2 diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/TreeOfPerditionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/TreeOfPerditionTest.java index dc342355c18..3075bf0f8d1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/TreeOfPerditionTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/TreeOfPerditionTest.java @@ -26,7 +26,7 @@ public class TreeOfPerditionTest extends CardTestPlayerBase { /* Tree of Perdition - {3}{B} - Creature Plant - 0/13 - {T}: Exchange target opponent’s life total with Tree of Perdition’s toughness. + {T}: Exchange target opponent's life total with Tree of Perdition's toughness. Defender Tap: Exchange target opponent's life total with Tree of Perdition's toughness. */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java index c8263589cbb..713ea046c00 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java @@ -21,7 +21,7 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase { * This includes true vanilla creatures (such as Grizzly Bears), face-down creatures, * many tokens, and creatures that have lost their abilities (due to Ovinize, for example). * Any ability of any kind, whether or not the ability functions in the on the battlefield zone, - * including things like “Cycling 2” means the creature doesn’t get the bonus. + * including things like “Cycling 2” means the creature doesn't get the bonus. */ @Test public void trueVanillaCardsTest() { @@ -116,7 +116,7 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase { } /** - * Animated basic lands have mana abilities, so they won’t get the bonus. + * Animated basic lands have mana abilities, so they won't get the bonus. */ @Test @@ -139,8 +139,8 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase { * Some Auras and Equipment grant abilities to creatures, meaning the affected creature would no longer * get the +2/+2 bonus. For example, Flight grants flying to the enchanted creature. Other Auras and Equipment * do not, meaning the affected creature would continue to get the +2/+2 bonus. For example, Dehydration states - * something now true about the enchanted creature, but doesn’t give it any abilities. Auras and Equipment that - * grant abilities will use the words “gains” or “has,” and they’ll list a keyword ability or an ability in + * something now true about the enchanted creature, but doesn't give it any abilities. Auras and Equipment that + * grant abilities will use the words “gains” or “has,” and they'll list a keyword ability or an ability in * quotation marks. */ @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java index 3fcfd21c844..82f684bf6b0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java @@ -40,14 +40,14 @@ public class HivestoneTest extends CardTestPlayerBase { /** * Turns only your creatures on the battlefield, not in other zones, into - * Slivers. It won’t allow you to have Root Sliver on the battlefield and + * Slivers. It won't allow you to have Root Sliver on the battlefield and * make your Grizzly Bears uncounterable, for example. */ @Test public void rootSliverTest() { addCard(Zone.HAND, playerA, "Grizzly Bears", 1); addCard(Zone.BATTLEFIELD, playerA, "Hivestone", 1); - // Root Sliver can't be countered. Sliver spells can't be countered by spells or abilities. + // Root Sliver can't be countered. Sliver spells can't be countered. addCard(Zone.BATTLEFIELD, playerA, "Root Sliver", 1); addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbilityOwnershipTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbilityOwnershipTest.java new file mode 100644 index 00000000000..e1970fa1919 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbilityOwnershipTest.java @@ -0,0 +1,56 @@ +package org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class AbilityOwnershipTest extends CardTestPlayerBase { + + @Test + public void testOwned() { + addCard(Zone.GRAVEYARD, playerB, "Soul Snuffers"); + addCard(Zone.GRAVEYARD, playerB, "Minister of Pain"); + + addCard(Zone.HAND, playerA, "Rise of the Dark Realms"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 9); + addCard(Zone.BATTLEFIELD, playerA, "Obelisk Spider"); + + setLife(playerA, 20); + setLife(playerB, 20); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rise of the Dark Realms"); + setChoice(playerA, "Yes"); + addTarget(playerA, "Soul Snuffers"); // sacrifice to Exploit + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + // Obelisk Spider Triggers twice once for the counter on Obelisk Spider. Once for the counter on Minister of Pain. + assertLife(playerA, 22); + assertLife(playerB, 18); + } + + @Test + public void testToGraveyard() { + addCard(Zone.GRAVEYARD, playerB, "Soul Snuffers"); + addCard(Zone.GRAVEYARD, playerB, "Minister of Pain"); + addCard(Zone.BATTLEFIELD, playerB, "Obelisk Spider"); + + addCard(Zone.HAND, playerA, "Rise of the Dark Realms"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 9); + + setLife(playerA, 20); + setLife(playerB, 20); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rise of the Dark Realms"); + setChoice(playerA, "Yes"); + addTarget(playerA, "Soul Snuffers"); // sacrifice to Exploit + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/TuvasaTheSunlitTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/TuvasaTheSunlitTest.java new file mode 100644 index 00000000000..63b529c335f --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/TuvasaTheSunlitTest.java @@ -0,0 +1,40 @@ + +package org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author tamaroth + */ +public class TuvasaTheSunlitTest extends CardTestPlayerBase { + + /** + * Playing more than one enchantment spell in a single turn does not draw more than 1 additional card. + */ + @Test + public void testWithStriveSpell() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + // Whenever you play your first enchantment spell of the turn, draw a card. + addCard(Zone.BATTLEFIELD, playerA, "Tuvasa the Sunlit", 1); + + // Two enchantments to play + addCard(Zone.HAND, playerA, "Burgeoning", 1); + addCard(Zone.HAND, playerA, "Ajani's Welcome", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Burgeoning"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ajani's Welcome"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/step/EndStepTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/step/EndStepTriggerTest.java index db27567d730..8e94fe689f1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/step/EndStepTriggerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/step/EndStepTriggerTest.java @@ -66,7 +66,7 @@ public class EndStepTriggerTest extends CardTestPlayerBase { // Bound // Sacrifice a creature. Return up to X cards from your graveyard to your hand, where X is the number of colors that creature was. Exile this card. // Determined - // Other spells you control can't be countered by spells or abilities this turn. + // Other spells you control can't be countered this turn. // Draw a card. addCard(Zone.HAND, playerB, "Bound // Determined"); // Instant {3}{B}{G} // {G}{U} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/BoseijuTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/BoseijuTest.java index 850ad02180b..b5cc35648b6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/BoseijuTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/BoseijuTest.java @@ -15,7 +15,7 @@ public class BoseijuTest extends CardTestPlayerBase { * Legendary Land * Boseiju, Who Shelters All enters the battlefield tapped. * {T}, Pay 2 life: Add {C}. If that mana is spent on an - * instant or sorcery spell, that spell can't be countered by spells or abilities. + * instant or sorcery spell, that spell can't be countered. * */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/OvermasterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/OvermasterTest.java index 8cb0a04e440..f682616b507 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/OvermasterTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/OvermasterTest.java @@ -13,7 +13,7 @@ public class OvermasterTest extends CardTestPlayerBase { /* * Overmaster * Sorcery, R (1) - * The next instant or sorcery spell you cast this turn can't be countered by spells or abilities. + * The next instant or sorcery spell you cast this turn can't be countered. * Draw a card. * */ diff --git a/Mage.Tests/src/test/java/org/mage/test/combat/CanBlockMultipleCreaturesTest.java b/Mage.Tests/src/test/java/org/mage/test/combat/CanBlockMultipleCreaturesTest.java index 86a6d381335..bc7b9b0bbdb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/combat/CanBlockMultipleCreaturesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/combat/CanBlockMultipleCreaturesTest.java @@ -92,7 +92,7 @@ public class CanBlockMultipleCreaturesTest extends CardTestPlayerBase { public void testCanOnlyBlockSingle() { // Hundred-Handed One {2}{W}{W} - // Monstrosity 3. {3}{W}{W}{W} (If this creature isn’t monstrous, put three +1/+1 counters on it and it becomes monstrous.) + // Monstrosity 3. {3}{W}{W}{W} (If this creature isn't monstrous, put three +1/+1 counters on it and it becomes monstrous.) //As long as Hundred-Handed One is monstrous, it has reach and can block an additional ninety-nine creatures each combat. addCard(Zone.BATTLEFIELD, playerA, "Hundred-Handed One", 1); @@ -121,7 +121,7 @@ public class CanBlockMultipleCreaturesTest extends CardTestPlayerBase { public void testCanBlockMultiple() { // Hundred-Handed One {2}{W}{W} - // Monstrosity 3. {3}{W}{W}{W} (If this creature isn’t monstrous, put three +1/+1 counters on it and it becomes monstrous.) + // Monstrosity 3. {3}{W}{W}{W} (If this creature isn't monstrous, put three +1/+1 counters on it and it becomes monstrous.) // As long as Hundred-Handed One is monstrous, it has reach and can block an additional ninety-nine creatures each combat. addCard(Zone.BATTLEFIELD, playerA, "Hundred-Handed One", 1); // For monstrosity diff --git a/Mage.Tests/src/test/java/org/mage/test/combat/FirstStrikeTest.java b/Mage.Tests/src/test/java/org/mage/test/combat/FirstStrikeTest.java new file mode 100644 index 00000000000..d14691f3d55 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/combat/FirstStrikeTest.java @@ -0,0 +1,40 @@ +package org.mage.test.combat; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class FirstStrikeTest extends CardTestPlayerBase { + + + @Test + public void firstStrikeAttacker(){ + addCard(Zone.BATTLEFIELD, playerA, "Silver Knight", 1); + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); + + attack(1, playerA, "Silver Knight"); + block(1, playerB, "Grizzly Bears", "Silver Knight"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerB, "Grizzly Bears", 1); + assertGraveyardCount(playerA, "Silver Knight", 0); + } + + @Test + public void firstStrikeBlocker(){ + addCard(Zone.BATTLEFIELD, playerB, "Silver Knight", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + + attack(1, playerA, "Grizzly Bears"); + block(1, playerB, "Silver Knight", "Grizzly Bears"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Grizzly Bears", 1); + assertGraveyardCount(playerB, "Silver Knight", 0); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java b/Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java new file mode 100644 index 00000000000..179402a7de2 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java @@ -0,0 +1,34 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.commander.FFA3; + +import mage.constants.PhaseStep; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommander3PlayersFFA; + +/** + * + * @author LevelX2 + */ +public class PlayerLeftTest extends CardTestCommander3PlayersFFA { + + /** + * Check that if a player left the game, it's commander is also removed + */ + @Test + public void TestCommanderRemoved() { + + concede(1, PhaseStep.PRECOMBAT_MAIN, playerA); + setStopAt(1, PhaseStep.DECLARE_ATTACKERS); + execute(); + + assertCommandZoneCount(playerB, "Ob Nixilis of the Black Oath", 1); + assertCommandZoneCount(playerC, "Ob Nixilis of the Black Oath", 1); + assertCommandZoneCount(playerA, "Ob Nixilis of the Black Oath", 0); + + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/game/ends/PhageTheUntouchableTest.java b/Mage.Tests/src/test/java/org/mage/test/game/ends/PhageTheUntouchableTest.java index b068f3030dc..8679e5c112d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/game/ends/PhageTheUntouchableTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/game/ends/PhageTheUntouchableTest.java @@ -44,7 +44,7 @@ public class PhageTheUntouchableTest extends CardTestPlayerBase { Assert.assertTrue("Game has ended.", currentGame.hasEnded()); Assert.assertTrue("Player A has won.", playerA.hasWon()); - Assert.assertTrue("Game ist At end phase", currentGame.getPhase().getType().equals(TurnPhase.END)); + Assert.assertTrue("Game ist At end phase", currentGame.getPhase().getType() == TurnPhase.END); } diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java index 3bb09b04402..f2fbfe06a75 100644 --- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java @@ -1,4 +1,3 @@ - package org.mage.test.multiplayer; import java.io.FileNotFoundException; @@ -324,4 +323,98 @@ public class PlayerLeftGameRangeAllTest extends CardTestMultiPlayerBase { assertPermanentCount(playerD, "Silvercoat Lion", 1); } + + /** + * In an EDH game, a player controlling Thalia left the game and the ability + * still lasted for the rest of the game. Gamelog if it helps. + */ + @Test + public void TestThaliaHereticCatharContinuousEffectEndsIfPlayerDies() { + // Player order: A -> D -> C -> B + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // First strike + // Creatures and nonbasic lands your opponents control enter the battlefield tapped. + addCard(Zone.HAND, playerA, "Thalia, Heretic Cathar"); // Creature {2}{W} + + addCard(Zone.HAND, playerD, "Lightning Bolt"); + addCard(Zone.BATTLEFIELD, playerD, "Mountain", 1); + + addCard(Zone.HAND, playerC, "Pillarfield Ox", 1); + addCard(Zone.BATTLEFIELD, playerC, "Plains", 4); + + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thalia, Heretic Cathar"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Lightning Bolt", playerA); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerC, "Pillarfield Ox"); + + castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); + + setStopAt(4, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerD, "Lightning Bolt", 1); + + assertLife(playerA, -1); + Assert.assertFalse("Player D is no longer in the game", playerA.isInGame()); + + assertPermanentCount(playerC, "Pillarfield Ox", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + + assertTapped("Pillarfield Ox", false); + assertTapped("Silvercoat Lion", false); + + } + + /** + * In an EDH game, a player controlling Thalia left the game and the ability + * still lasted for the rest of the game. Gamelog if it helps. + */ + @Test + public void TestThaliaHereticCatharContinuousEffectEndsIfPlayerConcedes() { + // Player order: A -> D -> C -> B + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // First strike + // Creatures and nonbasic lands your opponents control enter the battlefield tapped. + addCard(Zone.HAND, playerA, "Thalia, Heretic Cathar"); // Creature {2}{W} + + addCard(Zone.HAND, playerD, "Juggernaut"); + addCard(Zone.BATTLEFIELD, playerD, "Plains", 4); + + addCard(Zone.HAND, playerC, "Pillarfield Ox", 1); + addCard(Zone.BATTLEFIELD, playerC, "Plains", 4); + + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thalia, Heretic Cathar"); + + concede(2, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Juggernaut"); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerC, "Pillarfield Ox"); + + castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); + + setStopAt(4, PhaseStep.BEGIN_COMBAT); + execute(); + + Assert.assertFalse("Player D is no longer in the game", playerA.isInGame()); + assertLife(playerA, 2); + + assertPermanentCount(playerD, "Juggernaut", 1); + assertPermanentCount(playerC, "Pillarfield Ox", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + + assertTapped("Pillarfield Ox", false); + assertTapped("Silvercoat Lion", false); + assertTapped("Juggernaut", false); + + } + } 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 b24a6c6355c..eed329f9580 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 @@ -1,4 +1,3 @@ - package org.mage.test.player; import java.io.Serializable; @@ -557,6 +556,13 @@ public class TestPlayer implements Player { actions.remove(action); checkProccessed = true; } + + // check mana pool: colors, amount + if (params[0].equals(CHECK_COMMAND_MANA_POOL) && params.length == 3) { + assertManaPool(action, game, computerPlayer, params[1], Integer.parseInt(params[2])); + actions.remove(action); + checkProccessed = true; + } } if (!checkProccessed) { @@ -679,6 +685,49 @@ public class TestPlayer implements Player { } } + private void assertManaPoolInner(PlayerAction action, Player player, ManaType manaType, Integer amount) { + Integer current = player.getManaPool().get(manaType); + Assert.assertEquals(action.getActionName() + " - mana pool must contain [" + amount.toString() + " " + manaType.toString() + "], but found [" + current.toString() + "]", amount, current); + } + + private void assertManaPool(PlayerAction action, Game game, Player player, String colors, Integer amount) { + Assert.assertNotEquals(action.getActionName() + " - must setup color", "", colors); + + // Can't use ObjectColor -- it's doesn't contain colorless -- need to use custom parse + for (int i = 0; i < colors.length(); i++) { + switch (colors.charAt(i)) { + case 'W': + assertManaPoolInner(action, player, ManaType.WHITE, amount); + break; + + case 'U': + assertManaPoolInner(action, player, ManaType.BLUE, amount); + break; + + case 'B': + assertManaPoolInner(action, player, ManaType.BLACK, amount); + break; + + case 'R': + assertManaPoolInner(action, player, ManaType.RED, amount); + break; + + case 'G': + assertManaPoolInner(action, player, ManaType.GREEN, amount); + break; + + case 'C': + assertManaPoolInner(action, player, ManaType.COLORLESS, amount); + break; + + default: + Assert.fail(action.getActionName() + " - unknown color char [" + colors.charAt(i) + "]"); + break; + } + } + } + + /* * Iterates through each player on the current turn and asserts if they can attack or block legally this turn */ @@ -774,6 +823,11 @@ public class TestPlayer implements Player { } } + @Override + public List getTurnControllers() { + return computerPlayer.getTurnControllers(); + } + @Override public void selectBlockers(Game game, UUID defendingPlayerId) { @@ -1436,6 +1490,11 @@ public class TestPlayer implements Player { computerPlayer.setGameUnderYourControl(value); } + @Override + public void setGameUnderYourControl(boolean value, boolean fullRestore) { + computerPlayer.setGameUnderYourControl(value, fullRestore); + } + @Override public void endOfTurn(Game game) { computerPlayer.endOfTurn(game); @@ -1991,11 +2050,21 @@ public class TestPlayer implements Player { return computerPlayer.searchLibrary(target, game); } + @Override + public boolean searchLibrary(TargetCardInLibrary target, Game game, boolean triggerEvents) { + return computerPlayer.searchLibrary(target, game, triggerEvents); + } + @Override public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId) { return computerPlayer.searchLibrary(target, game, targetPlayerId); } + @Override + public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents) { + return computerPlayer.searchLibrary(target, game, targetPlayerId, triggerEvents); + } + @Override public boolean flipCoin(Game game) { return computerPlayer.flipCoin(game); @@ -2135,6 +2204,11 @@ public class TestPlayer implements Player { return computerPlayer.canPlayCardsFromGraveyard(); } + @Override + public void setPayManaMode(boolean payManaMode) { + computerPlayer.setPayManaMode(payManaMode); + } + @Override public void setPlayCardsFromGraveyard(boolean playCardsFromGraveyard) { computerPlayer.setPlayCardsFromGraveyard(playCardsFromGraveyard); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java index f6790b940b5..c094cf874c8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java @@ -1,4 +1,3 @@ - package org.mage.test.serverside.base; import java.io.FileNotFoundException; @@ -25,9 +24,9 @@ public abstract class CardTestCommander3PlayersFFA extends CardTestPlayerAPIImpl @Override protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { Game game = new CommanderFreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ONE, 0, 40); - playerA = createPlayer(game, playerA, "PlayerA"); - playerB = createPlayer(game, playerB, "PlayerB"); - playerC = createPlayer(game, playerC, "PlayerC"); + playerA = createPlayer(game, playerA, "PlayerA", deckNameA); + playerB = createPlayer(game, playerB, "PlayerB", deckNameB); + playerC = createPlayer(game, playerC, "PlayerC", deckNameC); return game; } 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 27d02fbefd8..bf2a95d8702 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 @@ -54,6 +54,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT"; public static final String CHECK_COMMAND_COLOR = "COLOR"; public static final String CHECK_COMMAND_SUBTYPE = "SUBTYPE"; + public static final String CHECK_COMMAND_MANA_POOL = "MANA_POOL"; protected GameOptions gameOptions; @@ -259,6 +260,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement check(checkName, turnNum, step, player, CHECK_COMMAND_SUBTYPE, permanentName, subType.toString(), mustHave.toString()); } + public void checkManaPool(String checkName, int turnNum, PhaseStep step, TestPlayer player, String colors, Integer amount) { + check(checkName, turnNum, step, player, CHECK_COMMAND_MANA_POOL, colors, amount.toString()); + } + /** * Removes all cards from player's library from the game. Usually this * should be used once before initialization to form the library in certain @@ -980,7 +985,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement int actualCount = 0; for (ExileZone exile : currentGame.getExile().getExileZones()) { for (Card card : exile.getCards(currentGame)) { - if (card.getOwnerId().equals(owner.getId())) { + if (card.isOwnedBy(owner.getId())) { actualCount++; } } @@ -1000,7 +1005,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement int actualCount = 0; for (ExileZone exile : currentGame.getExile().getExileZones()) { for (Card card : exile.getCards(currentGame)) { - if (card.getOwnerId().equals(owner.getId()) && card.getName().equals(cardName)) { + if (card.isOwnedBy(owner.getId()) && card.getName().equals(cardName)) { actualCount++; } } diff --git a/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java b/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java index 9511ab69d23..d282dbc1a9f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/sets/BoosterGenerationTest.java @@ -4,12 +4,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; + +import mage.abilities.Ability; +import mage.abilities.keyword.PartnerWithAbility; import mage.cards.Card; import mage.cards.repository.CardInfo; import mage.cards.repository.CardScanner; -import mage.sets.FateReforged; -import mage.sets.MastersEditionII; -import mage.sets.MastersEditionIV; +import mage.constants.CardType; +import mage.constants.Rarity; + +import mage.sets.*; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -19,7 +24,6 @@ import org.junit.Test; import org.mage.test.serverside.base.MageTestBase; /** - * * @author nigelzor, JayDi85 */ public class BoosterGenerationTest extends MageTestBase { @@ -31,8 +35,35 @@ public class BoosterGenerationTest extends MageTestBase { private static final List basics = Arrays.asList("Plains", "Island", "Swamp", "Mountain", "Forest"); + private void checkOnePartnerBoost() { + List booster = Battlebond.getInstance().createBooster(); + boolean foundPartner = false; + String Partner = ""; + + for (Card card : booster) { + for (Ability ability : card.getAbilities()) { + if (ability instanceof PartnerWithAbility) { + if (foundPartner) { + Assert.assertEquals(Partner, card.getName()); + } else { + foundPartner = true; + Partner = ((PartnerWithAbility) ability).getPartnerName(); + } + } + } + } + } + + @Test + public void testBattlebondPartnerBoosters() { + for (int i = 0; i < 10; i++) { + checkOnePartnerBoost(); + } + } + @Test public void testFateReforged() { + List tapland = Arrays.asList( "Bloodfell Caves", "Blossoming Sands", "Dismal Backwater", "Jungle Hollow", "Rugged Highlands", "Scoured Barrens", "Swiftwater Cliffs", "Thornwood Falls", "Tranquil Cove", "Wind-Scarred Crag"); @@ -72,12 +103,12 @@ public class BoosterGenerationTest extends MageTestBase { Assert.assertEquals("Urza special lands must have 4 variation for each of 3 card", 3 * 4, setOrzaList.size()); List foundedUrzaList = new ArrayList<>(); - for (CardInfo cardInfo: setOrzaList) { + for (CardInfo cardInfo : setOrzaList) { Assert.assertTrue("card " + cardInfo.getName() + " must be in urza's list", needUrzaList.contains(cardInfo.getName())); foundedUrzaList.add(cardInfo.getName()); } - for (String needName: needUrzaList) { + for (String needName : needUrzaList) { Assert.assertTrue("can't find need card " + needName + " in special land list", foundedUrzaList.contains(needName)); } } @@ -92,13 +123,35 @@ public class BoosterGenerationTest extends MageTestBase { "Urza's Tower" ); - for(int i = 1; i <= 5; i++) { + for (int i = 1; i <= 5; i++) { List booster = MastersEditionIV.getInstance().createBooster(); assertTrue(str(booster), contains(booster, urzaLand, "ME4")); assertFalse(str(booster), contains(booster, basics, null)); } } + @Test + public void testCoreSet2019_DualLandsAreGenerated() { + List allCards = new ArrayList<>(); + for (int i = 0; i < 50; i++) { + List booster = CoreSet2019.getInstance().createBooster(); + // check that booster contains a land card + assertTrue(booster.stream().anyMatch(card -> card.getCardType().contains(CardType.LAND))); + allCards.addAll(booster); + } + // check that some dual lands were generated + assertTrue(allCards.stream().anyMatch(card -> card.getCardType().contains(CardType.LAND) && card.getRarity().equals(Rarity.COMMON))); + } + + @Test + public void testDominaria_EveryBoosterContainsLegendaryCreature() { + for (int i = 0; i < 10; i++) { + List booster = Dominaria.getInstance().createBooster(); + // check that booster contains legendary creature + assertTrue(booster.stream().anyMatch(card -> card.isCreature() && card.isLegendary())); + } + } + private static String str(List cards) { StringBuilder sb = new StringBuilder("["); Iterator iterator = cards.iterator(); 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 29d51f0ab89..bc84033378e 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 @@ -1,4 +1,3 @@ - package org.mage.test.stub; import java.io.Serializable; @@ -583,11 +582,21 @@ public class PlayerStub implements Player { return false; } + @Override + public boolean searchLibrary(TargetCardInLibrary target, Game game, boolean triggerEvents) { + return false; + } + @Override public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId) { return false; } + @Override + public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents) { + return false; + } + @Override public boolean canPlayLand() { return false; @@ -1298,6 +1307,21 @@ public class PlayerStub implements Player { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } + @Override + public List getTurnControllers() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void setGameUnderYourControl(boolean value, boolean fullRestore) { + + } + + @Override + public void setPayManaMode(boolean payManaMode) { + + } + @Override public boolean equals(Object o) { if (this == o) { @@ -1316,4 +1340,11 @@ public class PlayerStub implements Player { return this.getId().equals(obj.getId()); } + @Override + public int hashCode() { + int hash = 5; + hash = 41 * hash + Objects.hashCode(this.id); + return hash; + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java index f1c70e08386..e7d2c5e9461 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java @@ -1,4 +1,3 @@ - package org.mage.test.utils; import mage.abilities.mana.ManaOptions; @@ -233,6 +232,25 @@ public class ManaOptionsTest extends CardTestPlayerBase { } + @Test + public void testNykthos5() { + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 2); + addCard(Zone.BATTLEFIELD, playerA, "Sedge Scorpion", 4); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerA, "Nykthos, Shrine to Nyx", 1); + + setStopAt(1, PhaseStep.UPKEEP); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 3, manaOptions.size()); + assertManaOptions("{W}{W}{G}", manaOptions); + assertManaOptions("{C}{G}{G}{G}", manaOptions); + assertManaOptions("{G}{G}{G}{G}{G}", manaOptions); + } + @Test public void testDuplicatedDontHave1() { addCard(Zone.BATTLEFIELD, playerA, "City of Brass", 2); // Any @@ -417,4 +435,122 @@ public class ManaOptionsTest extends CardTestPlayerBase { Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); assertManaOptions("{C}", manaOptions); } + + @Test + public void testCharmedPedant() { + // {T}, Put the top card of your library into your graveyard: For each colored mana symbol in that card's mana cost, add one mana of that color. + // Activate this ability only any time you could cast an instant. + addCard(Zone.BATTLEFIELD, playerA, "Charmed Pendant", 1); + // {T}: Add {C}. + // {T}: Add {C}{C}. Spend this mana only to cast colorless Eldrazi spells or activate abilities of colorless Eldrazi. + addCard(Zone.BATTLEFIELD, playerA, "Eldrazi Temple", 1); + + setStopAt(1, PhaseStep.UPKEEP); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); + assertManaOptions("{C}{C}", manaOptions); + } + + @Test + public void testManaSourcesWithCosts() { + // {T}: Add {C} to your mana pool. + // {5}, {T}: Add {W}{U}{B}{R}{G} to your mana pool. + addCard(Zone.BATTLEFIELD, playerA, "Crystal Quarry", 1); + + // {T}: Add {C} to your mana pool. + // {W/B}, {T}: Add {W}{W}, {W}{B}, or {B}{B} to your mana pool. + addCard(Zone.BATTLEFIELD, playerA, "Fetid Heath", 3); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + + setStopAt(1, PhaseStep.UPKEEP); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 16, manaOptions.size()); + assertManaOptions("{C}{C}{C}{C}{W}{W}{W}", manaOptions); + assertManaOptions("{C}{C}{C}{W}{W}{W}{W}", manaOptions); + assertManaOptions("{C}{C}{C}{W}{W}{W}{B}", manaOptions); + assertManaOptions("{C}{C}{C}{W}{W}{B}{B}", manaOptions); + assertManaOptions("{C}{C}{W}{W}{W}{W}{W}", manaOptions); + assertManaOptions("{C}{C}{W}{W}{W}{W}{B}", manaOptions); + assertManaOptions("{C}{C}{W}{W}{W}{B}{B}", manaOptions); + assertManaOptions("{C}{C}{W}{W}{B}{B}{B}", manaOptions); + assertManaOptions("{C}{C}{W}{B}{B}{B}{B}", manaOptions); + assertManaOptions("{C}{W}{W}{W}{W}{W}{W}", manaOptions); + assertManaOptions("{C}{W}{W}{W}{W}{W}{B}", manaOptions); + assertManaOptions("{C}{W}{W}{W}{W}{B}{B}", manaOptions); + assertManaOptions("{C}{W}{W}{W}{B}{B}{B}", manaOptions); + assertManaOptions("{C}{W}{W}{B}{B}{B}{B}", manaOptions); + assertManaOptions("{C}{W}{B}{B}{B}{B}{B}", manaOptions); + assertManaOptions("{C}{B}{B}{B}{B}{B}{B}", manaOptions); + } + + @Test + public void testSungrassPrairie() { + // {1}, {T}: Add {G}{W}. + addCard(Zone.BATTLEFIELD, playerA, "Sungrass Prairie", 1); + // {T}: Add one mana of any color to your mana pool. + addCard(Zone.BATTLEFIELD, playerA, "Alloy Myr", 2); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 2, manaOptions.size()); + + assertManaOptions("{W}{G}{Any}", manaOptions); + assertManaOptions("{Any}{Any}", manaOptions); + } + + @Test + public void testSungrassPrairie2() { + // {1}, {T}: Add {G}{W}. + addCard(Zone.BATTLEFIELD, playerA, "Sungrass Prairie", 5); + // ({T}: Add {U} or {W} to your mana pool.) + addCard(Zone.BATTLEFIELD, playerA, "Tundra", 9); + // ({T}: Add {G} or {U} to your mana pool.) + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 3); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 88, manaOptions.size()); + + assertManaOptions("{W}{W}{W}{W}{W}{W}{W}{W}{W}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions); + assertManaOptions("{W}{W}{W}{W}{W}{W}{W}{W}{U}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions); + } + + @Test + public void testSungrassPrairie3() { + // {1}, {T}: Add {G}{W}. + addCard(Zone.BATTLEFIELD, playerA, "Sungrass Prairie", 1); + // ({T}: Add {U} or {W} to your mana pool.) + addCard(Zone.BATTLEFIELD, playerA, "Tundra", 1); + // ({T}: Add {G} or {U} to your mana pool.) + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 1); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 4, manaOptions.size()); + assertManaOptions("{U}{U}", manaOptions); + assertManaOptions("{W}{G}{G}", manaOptions); + assertManaOptions("{W}{U}{G}", manaOptions); + assertManaOptions("{W}{W}{G}", manaOptions); + } + } diff --git a/Mage.Updater/pom.xml b/Mage.Updater/pom.xml index 953864d6478..c9ab517c295 100644 --- a/Mage.Updater/pom.xml +++ b/Mage.Updater/pom.xml @@ -5,7 +5,7 @@ mage-root org.mage - 1.4.30 + 1.4.31 4.0.0 diff --git a/Mage.Verify/pom.xml b/Mage.Verify/pom.xml index 2b5f9eeabd5..90c41da8661 100644 --- a/Mage.Verify/pom.xml +++ b/Mage.Verify/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage-verify @@ -49,7 +49,7 @@ org.mage mage-client - 1.4.30 + 1.4.31 diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 344b52e7ea9..27d780138ff 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -72,6 +72,13 @@ public class VerifyCardDataTest { // subtype skipListCreate("SUBTYPE"); + skipListAddName("SUBTYPE", "Dragon Egg"); // remove when MTGJSON is updated with M19 + skipListAddName("SUBTYPE", "Rukh Egg"); // remove when MTGJSON is updated with M19 + skipListAddName("SUBTYPE", "Roc Egg"); // remove when MTGJSON is updated with M19 + skipListAddName("SUBTYPE", "Summoner's Egg"); // remove when MTGJSON is updated with M19 + skipListAddName("SUBTYPE", "Ludevic's Test Subject"); // remove when MTGJSON is updated with M19 + skipListAddName("SUBTYPE", "Prowling Pangolin"); // remove when MTGJSON is updated with M19 + skipListAddName("SUBTYPE", "Electryte"); // remove when MTGJSON is updated with M19 // number skipListCreate("NUMBER"); diff --git a/Mage/pom.xml b/Mage/pom.xml index 55d268b455c..d7881372f8b 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 mage diff --git a/Mage/src/main/java/mage/MageObjectReference.java b/Mage/src/main/java/mage/MageObjectReference.java index c9e67326439..ff72668e405 100644 --- a/Mage/src/main/java/mage/MageObjectReference.java +++ b/Mage/src/main/java/mage/MageObjectReference.java @@ -1,4 +1,3 @@ - package mage; import java.io.Serializable; @@ -24,6 +23,11 @@ public class MageObjectReference implements Comparable, Ser private final int zoneChangeCounter; public MageObjectReference(MageObject mageObject, Game game) { + if (mageObject == null) { + this.sourceId = null; + this.zoneChangeCounter = -1; + return; + } this.sourceId = mageObject.getId(); this.zoneChangeCounter = mageObject.getZoneChangeCounter(game); } diff --git a/Mage/src/main/java/mage/Mana.java b/Mage/src/main/java/mage/Mana.java index a3900cf9475..f6a594292fb 100644 --- a/Mage/src/main/java/mage/Mana.java +++ b/Mage/src/main/java/mage/Mana.java @@ -1,4 +1,3 @@ - package mage; import java.io.Serializable; @@ -30,6 +29,14 @@ public class Mana implements Comparable, Serializable, Copyable { * Default constructor. Creates a {@link Mana} object with 0 values. */ public Mana() { + red = 0; + green = 0; + blue = 0; + white = 0; + black = 0; + generic = 0; + colorless = 0; + flag = false; } /** @@ -54,6 +61,7 @@ public class Mana implements Comparable, Serializable, Copyable { this.generic = notNegative(generic, "Generic"); this.colorless = notNegative(colorless, "Colorless"); this.any = notNegative(any, "Any"); + this.flag = false; } /** @@ -492,25 +500,25 @@ public class Mana implements Comparable, Serializable, Copyable { if (generic > 0) { sbMana.append('{').append(Integer.toString(generic)).append('}'); } - if (colorless >= 20) { + if (colorless >= 20) { sbMana.append(Integer.toString(colorless)).append("{C}"); } - if (white >= 20) { + if (white >= 20) { sbMana.append(Integer.toString(white)).append("{W}"); } - if (blue >= 20) { + if (blue >= 20) { sbMana.append(Integer.toString(blue)).append("{U}"); } - if (black >= 20) { + if (black >= 20) { sbMana.append(Integer.toString(black)).append("{B}"); } - if (red >= 20) { + if (red >= 20) { sbMana.append(Integer.toString(red)).append("{R}"); } - if (green >= 20) { + if (green >= 20) { sbMana.append(Integer.toString(green)).append("{G}"); } - if (any >= 20) { + if (any >= 20) { sbMana.append(Integer.toString(any)).append("{Any}"); } for (int i = 0; i < colorless && colorless < 20; i++) { @@ -908,7 +916,7 @@ public class Mana implements Comparable, Serializable, Copyable { return true; } else if (mana.colorless > 0 && this.colorless > 0 && includeColorless) { return true; - } else if (mana.any > 0 && this.count() > 0){ + } else if (mana.any > 0 && this.count() > 0) { return true; } @@ -1043,7 +1051,8 @@ public class Mana implements Comparable, Serializable, Copyable { /** * Returns if this {@link Mana} object has more than or equal values of mana - * as the passed in {@link Mana} object. + * as the passed in {@link Mana} object. Ignores {Any} mana to prevent + * endless iterations. * * @param mana the mana to compare with * @return if this object has more than or equal mana to the passed in @@ -1082,13 +1091,44 @@ public class Mana implements Comparable, Serializable, Copyable { moreMana = mana1; lessMana = mana2; } - if (lessMana.getWhite() > moreMana.getWhite() - || lessMana.getRed() > moreMana.getRed() - || lessMana.getGreen() > moreMana.getGreen() - || lessMana.getBlue() > moreMana.getBlue() - || lessMana.getBlack() > moreMana.getBlack() - || lessMana.getColorless() > moreMana.getColorless() - || lessMana.getAny() > moreMana.getAny()) { + int anyDiff = mana2.getAny() - mana1.getAny(); + if (lessMana.getWhite() > moreMana.getWhite()) { + anyDiff -= lessMana.getWhite() - moreMana.getWhite(); + if (anyDiff < 0) { + return null; + } + } + if (lessMana.getRed() > moreMana.getRed()) { + anyDiff -= lessMana.getRed() - moreMana.getRed(); + if (anyDiff < 0) { + return null; + } + } + if (lessMana.getGreen() > moreMana.getGreen()) { + anyDiff -= lessMana.getGreen() - moreMana.getGreen(); + if (anyDiff < 0) { + return null; + } + } + if (lessMana.getBlue() > moreMana.getBlue()) { + anyDiff -= lessMana.getBlue() - moreMana.getBlue(); + if (anyDiff < 0) { + return null; + } + } + if (lessMana.getBlack() > moreMana.getBlack()) { + anyDiff -= lessMana.getBlack() - moreMana.getBlack(); + if (anyDiff < 0) { + return null; + } + } + if (lessMana.getColorless() > moreMana.getColorless()) { + anyDiff -= lessMana.getColorless() - moreMana.getColorless(); + if (anyDiff < 0) { + return null; + } + } + if (lessMana.getAny() > moreMana.getAny()) { return null; } return moreMana; diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index a08f421cf62..800b1242a3c 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -460,7 +460,7 @@ public abstract class AbilityImpl implements Ability { // controller specific alternate spell costs if (!noMana && !alternativeCostisUsed) { if (this.getAbilityType() == AbilityType.SPELL - // 117.9a Only one alternative cost can be applied to any one spell as it’s being cast. + // 117.9a Only one alternative cost can be applied to any one spell as it's being cast. // So an alternate spell ability can't be paid with Omniscience && ((SpellAbility) this).getSpellAbilityType() != SpellAbilityType.BASE_ALTERNATE) { for (AlternativeSourceCosts alternativeSourceCosts : controller.getAlternativeSourceCosts()) { @@ -910,7 +910,7 @@ public abstract class AbilityImpl implements Ability { } MageObject object = game.getObject(this.getSourceId()); // emblem/planes are always actual - if (object != null && (object instanceof Emblem || object instanceof Plane)) { + if (object instanceof Emblem || object instanceof Plane) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index aaf3ece4068..6b48461d8f7 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -178,7 +178,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa break; case OWNER: Permanent permanent = game.getPermanent(getSourceId()); - if (!permanent.getOwnerId().equals(playerId)) { + if (!permanent.isOwnedBy(playerId)) { return ActivationStatus.getFalse(); } break; @@ -191,7 +191,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa Permanent enchantment = game.getPermanent(getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null) { Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); - if (enchanted != null && enchanted.getControllerId().equals(playerId)) { + if (enchanted != null && enchanted.isControlledBy(playerId)) { break; } } @@ -223,7 +223,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa } else if (mageObject instanceof Plane) { return ((Plane) mageObject).getControllerId().equals(playerId); } else if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) { - return ((Card) mageObject).getOwnerId().equals(playerId); + return ((Card) mageObject).isOwnedBy(playerId); } } return false; diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index f521276d7e2..712dba5b529 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -198,8 +198,8 @@ public class Modes extends LinkedHashMap { // 700.2d // Some spells and abilities specify that a player other than their controller chooses a mode for it. - // In that case, the other player does so when the spell or ability’s controller normally would do so. - // If there is more than one other player who could make such a choice, the spell or ability’s controller decides which of those players will make the choice. + // In that case, the other player does so when the spell or ability's controller normally would do so. + // If there is more than one other player who could make such a choice, the spell or ability's controller decides which of those players will make the choice. UUID playerId = null; if (modeChooser == TargetController.OPPONENT) { TargetOpponent targetOpponent = new TargetOpponent(); diff --git a/Mage/src/main/java/mage/abilities/PlayLandAbility.java b/Mage/src/main/java/mage/abilities/PlayLandAbility.java index 928882f8229..939f28e328e 100644 --- a/Mage/src/main/java/mage/abilities/PlayLandAbility.java +++ b/Mage/src/main/java/mage/abilities/PlayLandAbility.java @@ -31,7 +31,7 @@ public class PlayLandAbility extends ActivatedAbilityImpl { return ActivationStatus.getFalse(); } //20091005 - 114.2a - return new ActivationStatus(game.getActivePlayerId().equals(playerId) && game.getPlayer(playerId).canPlayLand() && game.canPlaySorcery(playerId), permittingObject); + return new ActivationStatus(game.isActivePlayer(playerId) && game.getPlayer(playerId).canPlayLand() && game.canPlaySorcery(playerId), permittingObject); } @Override diff --git a/Mage/src/main/java/mage/abilities/SpecialActions.java b/Mage/src/main/java/mage/abilities/SpecialActions.java index 716acff4d18..ed2da19d372 100644 --- a/Mage/src/main/java/mage/abilities/SpecialActions.java +++ b/Mage/src/main/java/mage/abilities/SpecialActions.java @@ -27,7 +27,7 @@ public class SpecialActions extends AbilitiesImpl { public LinkedHashMap getControlledBy(UUID controllerId, boolean manaAction) { LinkedHashMap controlledBy = new LinkedHashMap<>(); for (SpecialAction action: this) { - if (action.getControllerId().equals(controllerId) && action.isManaAction() == manaAction) { + if (action.isControlledBy(controllerId) && action.isManaAction() == manaAction) { controlledBy.put(action.id, action); } } diff --git a/Mage/src/main/java/mage/abilities/SpellAbility.java b/Mage/src/main/java/mage/abilities/SpellAbility.java index d6e29580d61..201d2deb349 100644 --- a/Mage/src/main/java/mage/abilities/SpellAbility.java +++ b/Mage/src/main/java/mage/abilities/SpellAbility.java @@ -1,6 +1,7 @@ package mage.abilities; +import java.util.Optional; import java.util.UUID; import mage.MageObject; import mage.MageObjectReference; @@ -19,6 +20,7 @@ import mage.constants.TimingRule; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.stack.Spell; import mage.players.Player; /** @@ -76,7 +78,7 @@ public class SpellAbility extends ActivatedAbilityImpl { MageObjectReference permittingSource = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, playerId, game); if (permittingSource == null) { Card card = game.getCard(sourceId); - if (!(card != null && card.getOwnerId().equals(playerId))) { + if (!(card != null && card.isOwnedBy(playerId))) { return ActivationStatus.getFalse(); } } @@ -210,6 +212,26 @@ public class SpellAbility extends ActivatedAbilityImpl { return this; } + public Card getCharacteristics(Game game) { + Spell spell = game.getSpell(this.getId()); + if (spell != null) { + return spell; + } + return game.getCard(this.getSourceId()); + } + + public static SpellAbility getSpellAbilityFromEvent(GameEvent event, Game game) { + 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(); + } + return card.getSpellAbility(); + } + public void setId(UUID idToUse) { this.id = idToUse; } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 901ac407fb2..e341ee74be2 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -141,7 +141,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge * fail to do anything. The ability could be unable to find the object * because the object never entered the specified zone, because it left * the zone before the ability resolved, or because it is in a zone that - * is hidden from a player, such as a library or an opponent’s hand. + * is hidden from a player, such as a library or an opponent's hand. * (This rule applies even if the object leaves the zone and returns * again before the ability resolves.) The most common zone-change * triggers are enters-the-battlefield triggers and diff --git a/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java index 7ef05216fdc..85716ef8017 100644 --- a/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java @@ -31,7 +31,7 @@ public class AllyEntersBattlefieldTriggeredAbility extends TriggeredAbilityImpl @Override public boolean checkTrigger(GameEvent event, Game game) { EntersTheBattlefieldEvent ebe = (EntersTheBattlefieldEvent) event; - return ebe.getTarget().getControllerId().equals(this.controllerId) + return ebe.getTarget().isControlledBy(this.controllerId) && (event.getTargetId().equals(this.getSourceId()) || (ebe.getTarget().hasSubtype(SubType.ALLY, game) && !event.getTargetId().equals(this.getSourceId()))); } diff --git a/Mage/src/main/java/mage/abilities/common/AttackedByCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttackedByCreatureTriggeredAbility.java index d0272977943..89c0741a67b 100644 --- a/Mage/src/main/java/mage/abilities/common/AttackedByCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttackedByCreatureTriggeredAbility.java @@ -60,7 +60,7 @@ public class AttackedByCreatureTriggeredAbility extends TriggeredAbilityImpl { UUID defendingPlayer = game.getCombat().getDefendingPlayerId(event.getSourceId(), game); Permanent attackingCreature = game.getPermanent(event.getSourceId()); if (filter.match(attackingCreature, game) - && getControllerId().equals(defendingPlayer) + && isControlledBy(defendingPlayer) && attackingCreature != null) { switch (setTargetPointer) { case PERMANENT: diff --git a/Mage/src/main/java/mage/abilities/common/AttacksAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksAllTriggeredAbility.java index 14e601238f3..c290a39cc2e 100644 --- a/Mage/src/main/java/mage/abilities/common/AttacksAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttacksAllTriggeredAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.common; import java.util.UUID; @@ -67,7 +66,7 @@ public class AttacksAllTriggeredAbility extends TriggeredAbilityImpl { check = true; } else { Permanent planeswalker = game.getPermanent(event.getTargetId()); - if (planeswalker != null && planeswalker.isPlaneswalker() && planeswalker.getControllerId().equals(getControllerId())) { + if (planeswalker != null && planeswalker.isPlaneswalker() && planeswalker.isControlledBy(getControllerId())) { check = true; } } @@ -102,7 +101,10 @@ public class AttacksAllTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a " + filter.getMessage() + " attacks" + (attacksYouOrYourPlaneswalker ? " you or a planeswalker you control" : "") + ", " + super.getRule(); + return "Whenever " + (filter.getMessage().startsWith("an") ? "" : "a ") + + filter.getMessage() + " attacks" + + (attacksYouOrYourPlaneswalker ? " you or a planeswalker you control" : "") + + ", " + super.getRule(); } } diff --git a/Mage/src/main/java/mage/abilities/common/AttacksAloneTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksAloneTriggeredAbility.java index b8e819da4b8..f88cf4762ea 100644 --- a/Mage/src/main/java/mage/abilities/common/AttacksAloneTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AttacksAloneTriggeredAbility.java @@ -37,7 +37,7 @@ public class AttacksAloneTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if(game.getActivePlayerId().equals(this.controllerId) ) { + if(game.isActivePlayer(this.controllerId) ) { UUID creatureId = this.getSourceId(); if(creatureId != null) { if(game.getCombat().attacksAlone() && Objects.equals(creatureId, game.getCombat().getAttackers().get(0))) { diff --git a/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java index 41ddae73ad1..70eeed7514e 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java @@ -41,7 +41,7 @@ public class BecomesMonstrousTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isCreature() - && (permanent.getControllerId().equals(getControllerId()))) { + && (permanent.isControlledBy(getControllerId()))) { this.getEffects().setTargetPointer(new FixedTarget(permanent, game)); return true; } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesTargetTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesTargetTriggeredAbility.java index 750dc8cd374..54263a11bc1 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesTargetTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesTargetTriggeredAbility.java @@ -5,6 +5,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.Zone; import mage.filter.FilterStackObject; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.StackObject; @@ -18,7 +19,7 @@ public class BecomesTargetTriggeredAbility extends TriggeredAbilityImpl { private final FilterStackObject filter; public BecomesTargetTriggeredAbility(Effect effect) { - this(effect, new FilterStackObject("a spell or ability")); + this(effect, StaticFilters.FILTER_SPELL_OR_ABILITY); } public BecomesTargetTriggeredAbility(Effect effect, FilterStackObject filter) { diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java index 71ae888c954..81483eea7f8 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfCombatTriggeredAbility.java @@ -77,11 +77,11 @@ public class BeginningOfCombatTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { switch (targetController) { case YOU: - return "At the beginning of combat on your turn, " + generateZoneString() + getEffects().getText(modes.getMode()); + return "At the beginning of combat on your turn, " + generateZoneString() + super.getRule(); case OPPONENT: - return "At the beginning of each opponent's combat step, " + generateZoneString() + getEffects().getText(modes.getMode()); + return "At the beginning of each opponent's combat step, " + generateZoneString() + super.getRule(); case ANY: - return "At the beginning of each combat, " + generateZoneString() + getEffects().getText(modes.getMode()); + return "At the beginning of each combat, " + generateZoneString() + super.getRule(); } return ""; } diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java index 04c2da9409f..bb91497e55a 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfDrawTriggeredAbility.java @@ -77,7 +77,7 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl { Permanent attachment = game.getPermanent(sourceId); if (attachment != null && attachment.getAttachedTo() != null) { Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); - if (attachedTo != null && attachedTo.getControllerId().equals(event.getPlayerId())) { + if (attachedTo != null && attachedTo.isControlledBy(event.getPlayerId())) { if (getTargets().isEmpty()) { this.getEffects().setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java index 9b725a36538..abbebcf05e3 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfEndStepTriggeredAbility.java @@ -79,7 +79,7 @@ public class BeginningOfEndStepTriggeredAbility extends TriggeredAbilityImpl { Permanent attachment = game.getPermanent(sourceId); if (attachment != null && attachment.getAttachedTo() != null) { Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); - if (attachedTo != null && attachedTo.getControllerId().equals(event.getPlayerId())) { + if (attachedTo != null && attachedTo.isControlledBy(event.getPlayerId())) { if (getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java index ee91ec32cb4..49d7c0a70e3 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java @@ -91,7 +91,7 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl { Permanent attachment = game.getPermanent(sourceId); if (attachment != null && attachment.getAttachedTo() != null) { Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); - if (attachedTo != null && attachedTo.getControllerId().equals(event.getPlayerId())) { + if (attachedTo != null && attachedTo.isControlledBy(event.getPlayerId())) { if (setTargetPointer && getTargets().isEmpty()) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); diff --git a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java new file mode 100644 index 00000000000..76bee0ed4e0 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java @@ -0,0 +1,92 @@ + +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author North, Loki + */ +public class BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility extends TriggeredAbilityImpl { + + protected FilterPermanent filter; + protected String rule; + + public BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(Effect effect, boolean optional) { + this(effect, StaticFilters.FILTER_PERMANENT_CREATURE, optional, null); + } + + public BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional) { + this(effect, filter, optional, null); + } + + public BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, String rule) { + super(Zone.BATTLEFIELD, effect, optional); + this.filter = filter; + this.rule = rule; + } + + public BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(final BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility ability) { + super(ability); + this.filter = ability.filter; + this.rule = ability.rule; + + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_BLOCKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + for (CombatGroup group : game.getCombat().getGroups()) { + if (group.getAttackers().contains(sourceId)){ + if (filter == null){ + return group.getBlocked(); + } + for (UUID uuid : group.getBlockers()){ + Permanent permanent = game.getPermanentOrLKIBattlefield(uuid); + if (permanent != null && filter.match(permanent, game)){ + return true; + } + } + } else if (group.getBlockers().contains(sourceId)){ + if (filter == null){ + return true; + } + for (UUID uuid : group.getAttackers()){ + Permanent permanent = game.getPermanentOrLKIBattlefield(uuid); + if (permanent != null && filter.match(permanent, game)){ + return true; + } + } + } + } + return false; + } + + @Override + public String getRule() { + if (rule != null) { + return rule; + } + return "Whenever {this} blocks or becomes blocked by one or more " + (filter != null ? filter.getMessage() : "creatures") + ", " + super.getRule(); + } + + @Override + public BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility copy() { + return new BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java b/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java index 873abb84fdf..7aaab64c222 100644 --- a/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java @@ -22,7 +22,7 @@ public class CantBeCounteredAbility extends StaticAbility { @Override public String getRule() { - return "{this} can't be countered."; + return "This spell can't be countered."; } @Override diff --git a/Mage/src/main/java/mage/abilities/common/CastOnlyIfConditionIsTrueEffect.java b/Mage/src/main/java/mage/abilities/common/CastOnlyIfConditionIsTrueEffect.java index 3dbe99ee57a..3c32c37aace 100644 --- a/Mage/src/main/java/mage/abilities/common/CastOnlyIfConditionIsTrueEffect.java +++ b/Mage/src/main/java/mage/abilities/common/CastOnlyIfConditionIsTrueEffect.java @@ -50,7 +50,7 @@ public class CastOnlyIfConditionIsTrueEffect extends ContinuousRuleModifyingEffe } private String setText() { - StringBuilder sb = new StringBuilder("cast {this} only "); + StringBuilder sb = new StringBuilder("cast this spell only "); if (condition != null) { sb.append(' ').append(condition.toString()); } diff --git a/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.java index e16db409c8e..9aa3611a459 100644 --- a/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.java @@ -4,6 +4,7 @@ package mage.abilities.common; import java.util.HashSet; import java.util.Set; import java.util.UUID; + import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.Zone; @@ -11,8 +12,8 @@ import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -20,22 +21,25 @@ import mage.game.permanent.Permanent; */ public class ControlledCreaturesDealCombatDamagePlayerTriggeredAbility extends TriggeredAbilityImpl { - private boolean madeDamage = false; private Set damagedPlayerIds = new HashSet<>(); + private boolean setTargetPointer; public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Effect effect) { this(Zone.BATTLEFIELD, effect); } public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone zone, Effect effect) { + this(zone, effect, false); + } + + public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone zone, Effect effect, boolean setTargetPointer) { super(zone, effect, false); + this.setTargetPointer = setTargetPointer; } public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(final ControlledCreaturesDealCombatDamagePlayerTriggeredAbility ability) { super(ability); - this.madeDamage = ability.madeDamage; this.damagedPlayerIds = new HashSet<>(); - this.damagedPlayerIds.addAll(ability.damagedPlayerIds); } @Override @@ -55,28 +59,19 @@ public class ControlledCreaturesDealCombatDamagePlayerTriggeredAbility extends T if (event.getType() == EventType.DAMAGED_PLAYER) { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && p != null && p.getControllerId().equals(this.getControllerId())) { - madeDamage = true; + if (damageEvent.isCombatDamage() && p != null && p.isControlledBy(this.getControllerId()) && !damagedPlayerIds.contains(event.getPlayerId())) { damagedPlayerIds.add(event.getPlayerId()); - } - } - if (event.getType() == EventType.COMBAT_DAMAGE_STEP_PRIORITY) { - if (madeDamage) { - Set damagedPlayersCopy = new HashSet<>(); - damagedPlayersCopy.addAll(damagedPlayerIds); - for (Effect effect : this.getEffects()) { - effect.setValue("damagedPlayers", damagedPlayersCopy); + if (setTargetPointer) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + } } - damagedPlayerIds.clear(); - madeDamage = false; return true; } } - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.GRAVEYARD) { - damagedPlayerIds.clear(); - } + if (event.getType() == EventType.COMBAT_DAMAGE_STEP_PRIORITY || + (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(getSourceId()))) { + damagedPlayerIds.clear(); } return false; } diff --git a/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java index 19ee35058a9..ba3e9555d74 100644 --- a/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java @@ -94,7 +94,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); if (filter.match(permanent, sourceId, controllerId, game) - && (permanent.getControllerId().equals(this.controllerId) ^ opponentController)) { + && (permanent.isControlledBy(this.controllerId) ^ opponentController)) { if (!this.getTargets().isEmpty()) { Target target = this.getTargets().get(0); if (target instanceof TargetPlayer) { diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java index 5cf8d73b167..10a3024d065 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsDamageToACreatureAttachedTriggeredAbility.java @@ -48,8 +48,7 @@ public class DealsDamageToACreatureAttachedTriggeredAbility extends TriggeredAbi if (!combatOnly || ((DamagedCreatureEvent) event).isCombatDamage()) { Permanent attachment = game.getPermanent(this.getSourceId()); if (attachment != null - && attachment.getAttachedTo() != null - && event.getSourceId().equals(attachment.getAttachedTo())) { + && attachment.isAttachedTo(event.getSourceId())) { if (setTargetPointer) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java index d3ff537c9bb..9fdf532e9f7 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAttachedTriggeredAbility.java @@ -67,7 +67,7 @@ public class DealsDamageToAPlayerAttachedTriggeredAbility extends TriggeredAbili } } if (targetController == TargetController.YOU) { - if (!this.getControllerId().equals(event.getPlayerId())) { + if (!this.isControlledBy(event.getPlayerId())) { return false; } } diff --git a/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggerAbility.java b/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java similarity index 67% rename from Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggerAbility.java rename to Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java index d91c609f8fe..97f7c15618e 100644 --- a/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggerAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; @@ -13,23 +12,23 @@ import mage.game.stack.StackObject; * * @author Styxo */ -public class DiscardedByOpponentTriggerAbility extends TriggeredAbilityImpl { +public class DiscardedByOpponentTriggeredAbility extends TriggeredAbilityImpl { - public DiscardedByOpponentTriggerAbility(Effect effect) { + public DiscardedByOpponentTriggeredAbility(Effect effect) { this(effect, false); } - public DiscardedByOpponentTriggerAbility(Effect effect, boolean optional) { + public DiscardedByOpponentTriggeredAbility(Effect effect, boolean optional) { super(Zone.GRAVEYARD, effect, optional); } - public DiscardedByOpponentTriggerAbility(final DiscardedByOpponentTriggerAbility ability) { + public DiscardedByOpponentTriggeredAbility(final DiscardedByOpponentTriggeredAbility ability) { super(ability); } @Override - public DiscardedByOpponentTriggerAbility copy() { - return new DiscardedByOpponentTriggerAbility(this); + public DiscardedByOpponentTriggeredAbility copy() { + return new DiscardedByOpponentTriggeredAbility(this); } @Override @@ -50,6 +49,6 @@ public class DiscardedByOpponentTriggerAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "When a spell or ability an opponent controls causes you to discard {this}, " + super.getRule(); + return "When a spell or ability an opponent controls causes you to discard this card, " + super.getRule(); } } diff --git a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldControlledTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldControlledTriggeredAbility.java index 1b5434c9501..0d273a2c80e 100644 --- a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldControlledTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldControlledTriggeredAbility.java @@ -53,7 +53,7 @@ public class EntersBattlefieldControlledTriggeredAbility extends EntersBattlefie public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { Permanent permanent = game.getPermanent(event.getTargetId()); - return permanent != null && permanent.getControllerId().equals(this.getControllerId()); + return permanent != null && permanent.isControlledBy(this.getControllerId()); } return false; } diff --git a/Mage/src/main/java/mage/abilities/common/ExertCreatureControllerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/ExertCreatureControllerTriggeredAbility.java index ff91f35fb00..8598ec694ea 100644 --- a/Mage/src/main/java/mage/abilities/common/ExertCreatureControllerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/ExertCreatureControllerTriggeredAbility.java @@ -27,7 +27,7 @@ public class ExertCreatureControllerTriggeredAbility extends TriggeredAbilityImp @Override public boolean checkTrigger(GameEvent event, Game game) { - boolean weAreExerting = getControllerId().equals(event.getPlayerId()); + boolean weAreExerting = isControlledBy(event.getPlayerId()); Permanent exerted = game.getPermanent(event.getTargetId()); boolean exertedIsCreature = (exerted != null) && exerted.isCreature(); return weAreExerting && exertedIsCreature; diff --git a/Mage/src/main/java/mage/abilities/common/LandfallAbility.java b/Mage/src/main/java/mage/abilities/common/LandfallAbility.java index e31252feb01..3718685a67a 100644 --- a/Mage/src/main/java/mage/abilities/common/LandfallAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LandfallAbility.java @@ -48,7 +48,7 @@ public class LandfallAbility extends TriggeredAbilityImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isLand() - && permanent.getControllerId().equals(this.controllerId)) { + && permanent.isControlledBy(this.controllerId)) { triggeringLand = permanent; if (setTargetPointer == SetTargetPointer.PERMANENT) { for (Effect effect : getAllEffects()) { diff --git a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java index a67372514e4..df73e1f2efa 100644 --- a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java @@ -51,7 +51,7 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { if (filter.match(zEvent.getTarget(), this.getSourceId(), this.getControllerId(), game)) { - if (onlyToControllerGraveyard && !this.getControllerId().equals(game.getOwnerId(zEvent.getTargetId()))) { + if (onlyToControllerGraveyard && !this.isControlledBy(game.getOwnerId(zEvent.getTargetId()))) { return false; } if (setTargetPointer) { diff --git a/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java index 2e00f8551fb..9fac7a0a948 100644 --- a/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java @@ -43,7 +43,7 @@ public class SacrificeIfCastAtInstantTimeTriggeredAbility extends TriggeredAbili // CHECK Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getSourceId().equals(getSourceId())) { - return !(game.isMainPhase() && game.getActivePlayerId().equals(event.getPlayerId()) && game.getStack().size() == 1); + return !(game.isMainPhase() && game.isActivePlayer(event.getPlayerId()) && game.getStack().size() == 1); } return false; } diff --git a/Mage/src/main/java/mage/abilities/common/SanctuaryTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SanctuaryInterveningIfTriggeredAbility.java similarity index 86% rename from Mage/src/main/java/mage/abilities/common/SanctuaryTriggeredAbility.java rename to Mage/src/main/java/mage/abilities/common/SanctuaryInterveningIfTriggeredAbility.java index efb2bffd4d9..9e07b935227 100644 --- a/Mage/src/main/java/mage/abilities/common/SanctuaryTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SanctuaryInterveningIfTriggeredAbility.java @@ -8,7 +8,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.constants.TargetController; import mage.filter.FilterPermanent; @@ -19,7 +19,7 @@ import mage.filter.predicate.mageobject.ColorPredicate; * * @author TheElk801 */ -public class SanctuaryTriggeredAbility extends ConditionalTriggeredAbility { +public class SanctuaryInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { private static Condition makeOrCondition(ObjectColor color1, ObjectColor color2) { FilterPermanent filter = new FilterPermanent(); @@ -48,7 +48,7 @@ public class SanctuaryTriggeredAbility extends ConditionalTriggeredAbility { return ability; } - public SanctuaryTriggeredAbility(OneShotEffect effect1, OneShotEffect effect2, ObjectColor color1, ObjectColor color2, String text) { + public SanctuaryInterveningIfTriggeredAbility(OneShotEffect effect1, OneShotEffect effect2, ObjectColor color1, ObjectColor color2, String text) { super(makeTrigger(effect1, effect2, color1, color2), makeOrCondition(color1, color2), text); } } diff --git a/Mage/src/main/java/mage/abilities/common/SpellCastAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SpellCastAllTriggeredAbility.java index e8f89f36198..b59492ab8c0 100644 --- a/Mage/src/main/java/mage/abilities/common/SpellCastAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SpellCastAllTriggeredAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; @@ -6,6 +5,7 @@ import mage.abilities.effects.Effect; import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; @@ -17,13 +17,12 @@ import mage.target.targetpointer.FixedTarget; */ public class SpellCastAllTriggeredAbility extends TriggeredAbilityImpl { - private static final FilterSpell spellCard = new FilterSpell("a spell"); protected FilterSpell filter; protected String rule; protected SetTargetPointer setTargetPointer; public SpellCastAllTriggeredAbility(Effect effect, boolean optional) { - this(Zone.BATTLEFIELD, effect, spellCard, optional, SetTargetPointer.NONE); + this(Zone.BATTLEFIELD, effect, StaticFilters.FILTER_SPELL_A, optional, SetTargetPointer.NONE); } public SpellCastAllTriggeredAbility(Effect effect, FilterSpell filter, boolean optional) { diff --git a/Mage/src/main/java/mage/abilities/common/SpellCounteredControllerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SpellCounteredControllerTriggeredAbility.java index ffa9768a1df..a0d3c0f0e84 100644 --- a/Mage/src/main/java/mage/abilities/common/SpellCounteredControllerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SpellCounteredControllerTriggeredAbility.java @@ -48,7 +48,7 @@ public class SpellCounteredControllerTriggeredAbility extends TriggeredAbilityIm if (stackObjectThatCountered == null) { stackObjectThatCountered = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK); } - if (stackObjectThatCountered != null && stackObjectThatCountered.getControllerId().equals(getControllerId())) { + if (stackObjectThatCountered != null && stackObjectThatCountered.isControlledBy(getControllerId())) { StackObject counteredStackObject = (StackObject) game.getLastKnownInformation(event.getTargetId(), Zone.STACK); return counteredStackObject != null && (counteredStackObject instanceof Spell); } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfMainPhaseDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfMainPhaseDelayedTriggeredAbility.java index 310986bb28b..23b8331c9ce 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfMainPhaseDelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfMainPhaseDelayedTriggeredAbility.java @@ -78,7 +78,7 @@ public class AtTheBeginOfMainPhaseDelayedTriggeredAbility extends DelayedTrigger Permanent attachment = game.getPermanent(sourceId); if (attachment != null && attachment.getAttachedTo() != null) { Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); - if (attachedTo != null && attachedTo.getControllerId().equals(event.getPlayerId())) { + if (attachedTo != null && attachedTo.isControlledBy(event.getPlayerId())) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfNextEndStepDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfNextEndStepDelayedTriggeredAbility.java index 81b502a4052..0fff4ee32ad 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfNextEndStepDelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfNextEndStepDelayedTriggeredAbility.java @@ -69,7 +69,7 @@ public class AtTheBeginOfNextEndStepDelayedTriggeredAbility extends DelayedTrigg Permanent attachment = game.getPermanent(sourceId); if (attachment != null && attachment.getAttachedTo() != null) { Permanent attachedTo = game.getPermanent(attachment.getAttachedTo()); - if (attachedTo != null && attachedTo.getControllerId().equals(event.getPlayerId())) { + if (attachedTo != null && attachedTo.isControlledBy(event.getPlayerId())) { correctEndPhase = true; } } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility.java new file mode 100644 index 00000000000..7fe37d42791 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/delayed/AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common.delayed; + +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.constants.Duration; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author jeffwadsworth + */ +public class AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility extends DelayedTriggeredAbility { + + public AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility(Effect effect) { + this(effect, Duration.Custom, true); + } + + public AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility(Effect effect, Duration duration, boolean triggerOnlyOnce) { + super(effect, duration, triggerOnlyOnce); + } + + public AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility(AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility copy() { + return new AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DRAW_STEP_PRE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.controllerId); + } +} + diff --git a/Mage/src/main/java/mage/abilities/common/delayed/PactDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/PactDelayedTriggeredAbility.java index 5b5ff0795f5..1bb565531ab 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/PactDelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/PactDelayedTriggeredAbility.java @@ -36,7 +36,7 @@ public class PactDelayedTriggeredAbility extends DelayedTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return game.getActivePlayerId().equals(this.getControllerId()); + return game.isActivePlayer(this.getControllerId()); } diff --git a/Mage/src/main/java/mage/abilities/condition/common/CommanderInPlayCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CommanderInPlayCondition.java index ffe21e2839b..ac0d85ce0e3 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/CommanderInPlayCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/CommanderInPlayCondition.java @@ -24,7 +24,7 @@ public enum CommanderInPlayCondition implements Condition { if (controller != null) { for (UUID commanderId : controller.getCommandersIds()) { Permanent commander = game.getPermanent(commanderId); - if (commander != null && commander.getControllerId().equals(source.getControllerId())) { + if (commander != null && commander.isControlledBy(source.getControllerId())) { 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 d609bb85d6c..b327e6e2141 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/ControllerAttackedThisTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/ControllerAttackedThisTurnCondition.java @@ -16,6 +16,6 @@ public enum ControllerAttackedThisTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName()); - return source.getControllerId().equals(game.getActivePlayerId()) && watcher != null && !watcher.getAttackedThisTurnCreatures().isEmpty(); + return source.isControlledBy(game.getActivePlayerId()) && watcher != null && !watcher.getAttackedThisTurnCreatures().isEmpty(); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java b/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java index ea19fed5592..070fb08b36b 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java @@ -26,7 +26,7 @@ public class IsStepCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return phaseStep == game.getStep().getType() && (!onlyDuringYourSteps || game.getActivePlayerId().equals(source.getControllerId())); + return phaseStep == game.getStep().getType() && (!onlyDuringYourSteps || game.isActivePlayer(source.getControllerId())); } @Override diff --git a/Mage/src/main/java/mage/abilities/condition/common/MeldCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MeldCondition.java index 30905d724ea..4b95507e5a6 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MeldCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MeldCondition.java @@ -27,8 +27,8 @@ public class MeldCondition implements Condition { MageObject sourceMageObject = source.getSourceObjectIfItStillExists(game); if (sourceMageObject != null && sourceMageObject instanceof Permanent) { Permanent sourcePermanent = (Permanent) sourceMageObject; - if (sourcePermanent.getControllerId().equals(source.getControllerId()) - && sourcePermanent.getOwnerId().equals(source.getControllerId())) { + if (sourcePermanent.isControlledBy(source.getControllerId()) + && sourcePermanent.isOwnedBy(source.getControllerId())) { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); filter.add(new NamePredicate(this.meldWithName)); filter.add(new OwnerIdPredicate(source.getControllerId())); diff --git a/Mage/src/main/java/mage/abilities/condition/common/MonarchIsSourceControllerCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MonarchIsSourceControllerCondition.java index 2576e5c9ba9..deffa175d8e 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MonarchIsSourceControllerCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MonarchIsSourceControllerCondition.java @@ -15,7 +15,7 @@ public enum MonarchIsSourceControllerCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return source.getControllerId().equals(game.getMonarchId()); + return source.isControlledBy(game.getMonarchId()); } @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 index dc53a3a610e..ae960029b08 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MyMainPhaseCondition.java @@ -20,7 +20,7 @@ public enum MyMainPhaseCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return game.getActivePlayerId().equals(source.getControllerId()) && + return game.isActivePlayer(source.getControllerId()) && turnPhases.contains(game.getTurn().getPhase().getType()); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/MyTurnBeforeAttackersDeclaredCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MyTurnBeforeAttackersDeclaredCondition.java index c78e4d8438d..abe44f72e2e 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MyTurnBeforeAttackersDeclaredCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MyTurnBeforeAttackersDeclaredCondition.java @@ -16,7 +16,7 @@ public enum MyTurnBeforeAttackersDeclaredCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - if (game.getActivePlayerId().equals(source.getControllerId())) { + if (game.isActivePlayer(source.getControllerId())) { TurnPhase turnPhase = game.getTurn().getPhase().getType(); if (turnPhase == TurnPhase.BEGINNING || turnPhase == TurnPhase.PRECOMBAT_MAIN) { return true; diff --git a/Mage/src/main/java/mage/abilities/condition/common/MyTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MyTurnCondition.java index a8a6126ee74..70309455a54 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MyTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MyTurnCondition.java @@ -10,7 +10,7 @@ public enum MyTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - return game.getActivePlayerId().equals(source.getControllerId()); + return game.isActivePlayer(source.getControllerId()); } @Override diff --git a/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java b/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java index 97a88393844..fef3c1e04c0 100644 --- a/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java +++ b/Mage/src/main/java/mage/abilities/costs/AlternativeCostSourceAbility.java @@ -230,7 +230,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter if (condition == null || alternateCosts.size() == 1) { sb.append(" rather than pay this spell's mana cost"); } else if (alternateCosts.isEmpty()) { - sb.append("cast {this} without paying its mana cost"); + sb.append("cast this spell without paying its mana cost"); } sb.append('.'); if (numberCosts == 1 && remarkText != null) { diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileFromHandCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileFromHandCost.java index 9b88cad032e..ef07db5c289 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ExileFromHandCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ExileFromHandCost.java @@ -1,4 +1,3 @@ - package mage.abilities.costs.common; import java.util.ArrayList; diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileSourceCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileSourceCost.java index 4414e063bcc..5e460a9b445 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ExileSourceCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ExileSourceCost.java @@ -44,7 +44,7 @@ public class ExileSourceCost extends CostImpl { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { MageObject sourceObject = ability.getSourceObject(game); Player controller = game.getPlayer(controllerId); - if (controller != null && sourceObject != null && (sourceObject instanceof Card)) { + if (controller != null && sourceObject instanceof Card) { UUID exileZoneId = null; String exileZoneName = ""; if (toUniqueExileZone) { diff --git a/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java b/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java index cfbd0fbbe3b..55ea9f43f85 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/PayLoyaltyCost.java @@ -41,7 +41,7 @@ public class PayLoyaltyCost extends CostImpl { * Gatherer Ruling: 10/1/2005: Planeswalkers will enter the battlefield with * double the normal amount of loyalty counters. However, if you activate an * ability whose cost has you put loyalty counters on a planeswalker, the - * number you put on isn’t doubled. This is because those counters are put + * number you put on isn't doubled. This is because those counters are put * on as a cost, not as an effect. * */ diff --git a/Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java b/Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java new file mode 100644 index 00000000000..daf8d54be58 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/common/RevealSecretOpponentCost.java @@ -0,0 +1,68 @@ +package mage.abilities.costs.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.common.ChooseSecretOpponentEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * + * @author LevelX2 + * @author credman0 + */ +public class RevealSecretOpponentCost extends CostImpl { + + public RevealSecretOpponentCost() { + this.text = "Reveal the player you chose"; + } + + public RevealSecretOpponentCost(final RevealSecretOpponentCost cost) { + super(cost); + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OWNER); + if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { + return false; + } + UUID opponentId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OPPONENT); + return opponentId != null; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + UUID playerThatChoseId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OWNER); + if (playerThatChoseId == null || !playerThatChoseId.equals(controllerId)) { + return false; + } + UUID opponentId = (UUID) game.getState().getValue(sourceId + ChooseSecretOpponentEffect.SECRET_OPPONENT); + if (opponentId != null) { + game.getState().setValue(sourceId + ChooseSecretOpponentEffect.SECRET_OWNER, null); // because only once, the vale is set to null + Player controller = game.getPlayer(controllerId); + Player opponent = game.getPlayer(opponentId); + MageObject sourceObject = game.getObject(sourceId); + if (controller != null && opponent != null && sourceObject != null) { + if (sourceObject instanceof Permanent) { + ((Permanent) sourceObject).addInfo(ChooseSecretOpponentEffect.SECRET_OPPONENT, null, game); + } + game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " reveals the secretly chosen opponent " + opponent.getLogName()); + } + paid = true; + } + return paid; + } + + @Override + public RevealSecretOpponentCost copy() { + return new RevealSecretOpponentCost(this); + } + + +} diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java index 1c51f624089..082f09c47db 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java @@ -207,7 +207,9 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { return true; } Player player = game.getPlayer(controllerId); - assignPayment(game, ability, player.getManaPool(), costToPay); + if (!player.getManaPool().isForcedToPay()) { + assignPayment(game, ability, player.getManaPool(), costToPay); + } game.getState().getSpecialActions().removeManaActions(); while (!isPaid()) { ManaCost unpaid = this.getUnpaid(); diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java index e7fc43af0bf..dbf25f6df43 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java @@ -117,7 +117,9 @@ public class ManaCostsImpl extends ArrayList implements M } Player player = game.getPlayer(controllerId); - assignPayment(game, ability, player.getManaPool(), this); + if (!player.getManaPool().isForcedToPay()) { + assignPayment(game, ability, player.getManaPool(), this); + } game.getState().getSpecialActions().removeManaActions(); while (!isPaid()) { ManaCost unpaid = this.getUnpaid(); @@ -235,10 +237,15 @@ public class ManaCostsImpl extends ArrayList implements M @Override public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) { - if (!pool.isAutoPayment() && pool.getUnlockedManaType() == null) { + boolean wasUnlockedManaType = (pool.getUnlockedManaType() != null); + if (!pool.isAutoPayment() && !wasUnlockedManaType) { // if auto payment is inactive and no mana type was clicked manually - do nothing return; } + ManaCosts referenceCosts = null; + if (pool.isForcedToPay()) { + referenceCosts = this.copy(); + } // attempt to pay colorless costs (not generic) mana costs first for (ManaCost cost : this) { if (!cost.isPaid() && cost instanceof ColorlessManaCost) { @@ -318,6 +325,31 @@ public class ManaCostsImpl extends ArrayList implements M } // stop using mana of the clicked mana type pool.lockManaType(); + if (!wasUnlockedManaType) { + handleForcedToPayOnlyForCurrentPayment(game, pool, referenceCosts); + } + } + + private void handleForcedToPayOnlyForCurrentPayment(Game game, ManaPool pool, ManaCosts referenceCosts) { + // for Word of Command + if (pool.isForcedToPay()) { + if (referenceCosts != null && this.getText().equals(referenceCosts.getText())) { + UUID playerId = pool.getPlayerId(); + Player player = game.getPlayer(playerId); + if (player != null) { + game.undo(playerId); + this.clearPaid(); + this.setX(referenceCosts.getX()); + player.getManaPool().restoreMana(pool.getPoolBookmark()); + game.bookmarkState(); + } + } + } + } + + public void forceManaRollback(Game game, ManaPool pool) { + // for Word of Command + handleForcedToPayOnlyForCurrentPayment(game, pool, this); } @Override diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java new file mode 100644 index 00000000000..44a96ae3867 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java @@ -0,0 +1,104 @@ +package mage.abilities.decorator; + +import mage.abilities.Modes; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.condition.Condition; +import mage.abilities.effects.Effect; +import mage.abilities.effects.Effects; +import mage.constants.EffectType; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * Adds condition to {@link mage.abilities.effects.ContinuousEffect}. Acts as + * decorator. + * + * @author nantuko + */ +public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityImpl { + + protected TriggeredAbility ability; + protected Condition condition; + protected String abilityText; + + /** + * Triggered ability with a condition. Set the optionality for the trigger + * ability itself. + * + * @param ability + * @param condition + * @param text explicit rule text for the ability, if null or empty, the + * rule text generated by the triggered ability itself is used. + */ + public ConditionalInterveningIfTriggeredAbility(TriggeredAbility ability, Condition condition, String text) { + super(ability.getZone(), null); + this.ability = ability; + this.modes = ability.getModes(); + this.condition = condition; + this.abilityText = text; + } + + public ConditionalInterveningIfTriggeredAbility(final ConditionalInterveningIfTriggeredAbility triggered) { + super(triggered); + this.ability = triggered.ability.copy(); + this.condition = triggered.condition; + this.abilityText = triggered.abilityText; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + return condition.apply(game, this); + } + + @Override + public ConditionalInterveningIfTriggeredAbility copy() { + return new ConditionalInterveningIfTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return ability.checkEventType(event, game); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ability.setSourceId(this.getSourceId()); + ability.setControllerId(this.getControllerId()); + return ability.checkTrigger(event, game); + } + + @Override + public String getRule() { + if (abilityText == null || abilityText.isEmpty()) { + return ability.getRule(); + } + return abilityText; + } + + @Override + public Effects getEffects() { + return ability.getEffects(); + } + + @Override + public void addEffect(Effect effect) { + ability.addEffect(effect); + } + + @Override + public Modes getModes() { + return ability.getModes(); + } + + @Override + public Effects getEffects(Game game, EffectType effectType) { + return ability.getEffects(game, effectType); + } + + @Override + public boolean isOptional() { + return ability.isOptional(); + } + +} diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalManaEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalManaEffect.java index bc4c67000cf..7d2f3a75fe8 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalManaEffect.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalManaEffect.java @@ -1,6 +1,6 @@ - package mage.abilities.decorator; +import java.util.List; import mage.Mana; import mage.abilities.Ability; import mage.abilities.condition.Condition; @@ -47,7 +47,11 @@ public class ConditionalManaEffect extends ManaEffect { if (controller == null) { return false; } - controller.getManaPool().addMana(getMana(game, source), game, source); + Mana mana = getMana(game, source); + if (produceMana(true, game, source).getAny() > 0) { + checkToFirePossibleEvents(mana, game, source); + } + controller.getManaPool().addMana(mana, game, source); return true; } @@ -56,6 +60,21 @@ public class ConditionalManaEffect extends ManaEffect { return new ConditionalManaEffect(this); } + @Override + public Mana getMana(Game game, Ability source) { + return produceMana(false, game, source); + } + + @Override + public List getNetMana(Game game, Ability source) { + if (condition.apply(game, source)) { + return effect.getNetMana(game, source); + } else if (otherwiseEffect != null) { + return otherwiseEffect.getNetMana(game, source); + } + return null; + } + @Override public Mana produceMana(boolean netMana, Game game, Ability source) { Mana mana = new Mana(); @@ -75,7 +94,6 @@ public class ConditionalManaEffect extends ManaEffect { mana.setAny(0); mana.add(choice.getMana(amount)); } - checkToFirePossibleEvents(mana, game, source); } return mana; } diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalTriggeredAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalTriggeredAbility.java index a450227a675..b77c66df9db 100644 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalTriggeredAbility.java @@ -4,6 +4,7 @@ import mage.abilities.Modes; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.Condition; +import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.constants.EffectType; import mage.game.Game; @@ -13,7 +14,7 @@ import mage.game.events.GameEvent; * Adds condition to {@link mage.abilities.effects.ContinuousEffect}. Acts as * decorator. * - * @author nantuko + * @author noahg */ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl { @@ -45,11 +46,6 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl { this.abilityText = triggered.abilityText; } - @Override - public boolean checkInterveningIfClause(Game game) { - return condition.apply(game, this); - } - @Override public ConditionalTriggeredAbility copy() { return new ConditionalTriggeredAbility(this); @@ -64,7 +60,7 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { ability.setSourceId(this.getSourceId()); ability.setControllerId(this.getControllerId()); - return ability.checkTrigger(event, game); + return ability.checkTrigger(event, game) && condition.apply(game, this); } @Override @@ -80,6 +76,11 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl { return ability.getEffects(); } + @Override + public void addEffect(Effect effect) { + ability.addEffect(effect); + } + @Override public Modes getModes() { return ability.getModes(); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestConvertedManaCostValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestConvertedManaCostValue.java index 0acf8d10df0..9d603e0bcf0 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestConvertedManaCostValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestConvertedManaCostValue.java @@ -3,6 +3,8 @@ package mage.abilities.dynamicvalue.common; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -13,19 +15,26 @@ import mage.players.Player; */ public class HighestConvertedManaCostValue implements DynamicValue { + private final FilterPermanent filter; + + public HighestConvertedManaCostValue() { + this(StaticFilters.FILTER_PERMANENTS); + } + + public HighestConvertedManaCostValue(FilterPermanent filter) { + this.filter = filter; + } + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - int highCMC = 0; Player controller = game.getPlayer(sourceAbility.getControllerId()); - if (controller != null) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controller.getId())) { - if (permanent.getSpellAbility() != null) { - int cmc = permanent.getSpellAbility().getManaCosts().convertedManaCost(); - if (cmc > highCMC) { - highCMC = cmc; - } - } - } + if (controller == null) { + return 0; + } + int highCMC = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { + int cmc = permanent.getConvertedManaCost(); + highCMC = Math.max(highCMC, cmc); } return highCMC; } 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 d2e841f7206..767c185e7a6 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaSpentToCastCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ManaSpentToCastCount.java @@ -29,7 +29,7 @@ public class ManaSpentToCastCount implements DynamicValue { } if (spell != null) { // NOT the cmc of the spell on the stack - return spell.getSpellAbility().getManaCostsToPay().convertedManaCost() + spell.getSpellAbility().getManaCostsToPay().getX(); + return spell.getSpellAbility().getManaCostsToPay().convertedManaCost(); } return 0; } 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 69a7ce93153..66c49c96185 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouOwnThatOpponentsControlCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouOwnThatOpponentsControlCount.java @@ -17,7 +17,7 @@ public class PermanentsYouOwnThatOpponentsControlCount implements DynamicValue { int count = 0; for (Permanent permanent : game.getBattlefield().getActivePermanents(sourceAbility.getControllerId(), game)) { - if (!permanent.getOwnerId().equals(permanent.getControllerId()) && permanent.getOwnerId().equals(sourceAbility.getControllerId())) { + if (!permanent.isOwnedBy(permanent.getControllerId()) && permanent.isOwnedBy(sourceAbility.getControllerId())) { if (opponentIds.contains(permanent.getControllerId())) { count++; } diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java index d80c1d61975..f908f16fd99 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java @@ -180,7 +180,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu Player player = game.getPlayer(startingControllerId); if (player != null) { if (player.isInGame()) { - return game.getActivePlayerId().equals(startingControllerId) && game.getTurnNum() != startingTurn; + return game.isActivePlayer(startingControllerId) && game.getTurnNum() != startingTurn; } return player.hasReachedNextTurnAfterLeaving(); } diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java index 7c170cc5f6a..0fd1aee39b3 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java @@ -465,7 +465,7 @@ public class ContinuousEffects implements Serializable { for (SpliceCardEffect effect : spliceCardEffects) { Set abilities = spliceCardEffects.getAbility(effect.getId()); for (Ability ability : abilities) { - if (ability.getControllerId().equals(playerId) && (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null))) { + if (ability.isControlledBy(playerId) && (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null))) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { spliceEffects.add(effect); break; @@ -543,7 +543,7 @@ public class ContinuousEffects implements Serializable { * @param game * @return */ - private List getApplicableAsThoughEffects(AsThoughEffectType type, Game game) { + public List getApplicableAsThoughEffects(AsThoughEffectType type, Game game) { List asThoughEffectsList = new ArrayList<>(); if (asThoughEffectsMap.containsKey(type)) { for (AsThoughEffect effect : asThoughEffectsMap.get(type)) { @@ -570,7 +570,7 @@ public class ContinuousEffects implements Serializable { * the mana cost or alternative cost (as determined in rule 601.2b), plus * all additional costs and cost increases, and minus all cost reductions. * If the mana component of the total cost is reduced to nothing by cost - * reduction effects, it is considered to be {0}. It can’t be reduced to + * reduction effects, it is considered to be {0}. It can't be reduced to * less than {0}. Once the total cost is determined, any effects that * directly affect the total cost are applied. Then the resulting total cost * becomes “locked in.” If effects would change the total cost after this diff --git a/Mage/src/main/java/mage/abilities/effects/EquipEffect.java b/Mage/src/main/java/mage/abilities/effects/EquipEffect.java new file mode 100644 index 00000000000..1a4b6ed17ad --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/EquipEffect.java @@ -0,0 +1,39 @@ +package mage.abilities.effects; + +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +public class EquipEffect extends AttachEffect { + + public EquipEffect(Outcome outcome) { + super(outcome, "Equip"); + } + + public EquipEffect(EquipEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + //301.5c An Equipment that’s also a creature can’t equip a creature. An Equipment that loses the subtype + // “Equipment” can’t equip a creature. An Equipment can’t equip itself. An Equipment that equips an illegal or + // nonexistent permanent becomes unattached from that permanent but remains on the battlefield. (This is a + // state-based action. See rule 704.) An Equipment can’t equip more than one creature. If a spell or ability + // would cause an Equipment to equip more than one creature, the Equipment’s controller chooses which creature + // it equips. + if (sourcePermanent != null && sourcePermanent.hasSubtype(SubType.EQUIPMENT, game) && !sourcePermanent.isCreature()) { + return super.apply(game, source); + } + return false; + } + + @Override + public EquipEffect copy(){ + return new EquipEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java b/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java index 6804ff9b867..11545d7d271 100644 --- a/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/GainAbilitySpellsEffect.java @@ -41,7 +41,7 @@ public class GainAbilitySpellsEffect extends ContinuousEffectImpl { Permanent permanent = game.getPermanent(source.getSourceId()); if (player != null && permanent != null) { for (Card card : game.getExile().getAllCards(game)) { - if (card.getOwnerId().equals(source.getControllerId()) && filter.match(card, game)) { + if (card.isOwnedBy(source.getControllerId()) && filter.match(card, game)) { game.getState().addOtherAbility(card, ability); } } @@ -61,7 +61,7 @@ public class GainAbilitySpellsEffect extends ContinuousEffectImpl { } } for (StackObject stackObject : game.getStack()) { - if (stackObject.getControllerId().equals(source.getControllerId())) { + if (stackObject.isControlledBy(source.getControllerId())) { Card card = game.getCard(stackObject.getSourceId()); if (card != null && filter.match(card, game)) { if (!card.getAbilities().contains(ability)) { diff --git a/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java b/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java index 5d3fa062c82..a0ea8297392 100644 --- a/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java @@ -76,6 +76,10 @@ public abstract class RequirementEffect extends ContinuousEffectImpl { return null; } + public int getMinNumberOfBlockers() { + return 0; + } + /** * Player related check The player returned or controlled planeswalker must * be attacked with at least one attacker diff --git a/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java index 2ae6968b89d..ab6f7d5c28c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java @@ -33,7 +33,7 @@ import java.util.List; * 702.37. Amplify 702.37a Amplify is a static ability. “Amplify N” means “As * this object enters the battlefield, reveal any number of cards from your hand * that share a creature type with it. This permanent enters the battlefield - * with N +1/+1 counters on it for each card revealed this way. You can’t reveal + * with N +1/+1 counters on it for each card revealed this way. You can't reveal * this card or any other cards that are entering the battlefield at the same * time as this card.” 702.37b If a creature has multiple instances of amplify, * each one works separately. diff --git a/Mage/src/main/java/mage/abilities/effects/common/CanBlockAsThoughtItHadShadowEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CanBlockAsThoughtItHadShadowEffect.java new file mode 100644 index 00000000000..2725b186366 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/CanBlockAsThoughtItHadShadowEffect.java @@ -0,0 +1,38 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; + +import java.util.UUID; + +public class CanBlockAsThoughtItHadShadowEffect extends AsThoughEffectImpl { + + public CanBlockAsThoughtItHadShadowEffect(Duration duration) { + super(AsThoughEffectType.BLOCK_SHADOW, duration, Outcome.Benefit); + staticText = "{this} can block creatures with shadow as though {this} had shadow"; + } + + public CanBlockAsThoughtItHadShadowEffect(final CanBlockAsThoughtItHadShadowEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public CanBlockAsThoughtItHadShadowEffect copy() { + return new CanBlockAsThoughtItHadShadowEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + return sourceId.equals(source.getSourceId()); + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java index 820431e0f1e..78aafb7885c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredControlledEffect.java @@ -61,7 +61,7 @@ public class CantBeCounteredControlledEffect extends ContinuousRuleModifyingEffe @Override public boolean applies(GameEvent event, Ability source, Game game) { Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getControllerId().equals(source.getControllerId()) + if (spell != null && spell.isControlledBy(source.getControllerId()) && filterTarget.match(spell, source.getSourceId(), source.getControllerId(), game)) { if (filterSource == null) { return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredSourceEffect.java index 7a6e7f1fb3f..c1a6bb87c53 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CantBeCounteredSourceEffect.java @@ -21,7 +21,7 @@ public class CantBeCounteredSourceEffect extends ContinuousRuleModifyingEffectIm public CantBeCounteredSourceEffect() { super(Duration.WhileOnStack, Outcome.Benefit, false, true); - staticText = "{this} can't be countered"; + staticText = "this spell can't be countered"; } public CantBeCounteredSourceEffect(final CantBeCounteredSourceEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/NameACardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseACardNameEffect.java similarity index 80% rename from Mage/src/main/java/mage/abilities/effects/common/NameACardEffect.java rename to Mage/src/main/java/mage/abilities/effects/common/ChooseACardNameEffect.java index 66b2d4e276b..e8fc6ab1086 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/NameACardEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseACardNameEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.MageObject; @@ -17,13 +16,15 @@ import mage.util.CardUtil; * * @author LevelX2 */ -public class NameACardEffect extends OneShotEffect { +public class ChooseACardNameEffect extends OneShotEffect { public static String INFO_KEY = "NAMED_CARD"; public enum TypeOfName { ALL, + NOT_BASIC_LAND_NAME, + NONBASIC_LAND_NAME, NON_ARTIFACT_AND_NON_LAND_NAME, NON_LAND_NAME, NON_LAND_AND_NON_CREATURE_NAME, @@ -33,13 +34,13 @@ public class NameACardEffect extends OneShotEffect { private final TypeOfName typeOfName; - public NameACardEffect(TypeOfName typeOfName) { + public ChooseACardNameEffect(TypeOfName typeOfName) { super(Outcome.Detriment); this.typeOfName = typeOfName; staticText = setText(); } - public NameACardEffect(final NameACardEffect effect) { + public ChooseACardNameEffect(final ChooseACardNameEffect effect) { super(effect); this.typeOfName = effect.typeOfName; } @@ -58,6 +59,14 @@ public class NameACardEffect extends OneShotEffect { cardChoice.setChoices(CardRepository.instance.getNames()); cardChoice.setMessage("Choose a card name"); break; + case NOT_BASIC_LAND_NAME: + cardChoice.setChoices(CardRepository.instance.getNotBasicLandNames()); + cardChoice.setMessage("Choose a card name other than a basic land card name"); + break; + case NONBASIC_LAND_NAME: + cardChoice.setChoices(CardRepository.instance.getNonbasicLandNames()); + cardChoice.setMessage("Choose a nonbasic land card name"); + break; case NON_ARTIFACT_AND_NON_LAND_NAME: cardChoice.setChoices(CardRepository.instance.getNonArtifactAndNonLandNames()); cardChoice.setMessage("Choose a nonartifact, nonland card name"); @@ -96,8 +105,8 @@ public class NameACardEffect extends OneShotEffect { } @Override - public NameACardEffect copy() { - return new NameACardEffect(this); + public ChooseACardNameEffect copy() { + return new ChooseACardNameEffect(this); } private String setText() { @@ -106,6 +115,12 @@ public class NameACardEffect extends OneShotEffect { case ALL: sb.append("card"); break; + case NOT_BASIC_LAND_NAME: + sb.append("card name other than a basic land card"); + break; + case NONBASIC_LAND_NAME: + sb.append("nonbasic land card name"); + break; case NON_ARTIFACT_AND_NON_LAND_NAME: sb.append("nonartifact, nonland card"); break; diff --git a/Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java new file mode 100644 index 00000000000..6c1a8ba5c61 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/ChooseSecretOpponentEffect.java @@ -0,0 +1,68 @@ +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; +/** + * + * @author LevelX2 + * @author credman0 + */ +public class ChooseSecretOpponentEffect extends OneShotEffect { + + public static final String SECRET_OPPONENT = "_secOpp"; + public static final String SECRET_OWNER = "_secOwn"; + + public ChooseSecretOpponentEffect() { + super(Outcome.Neutral); + staticText = "secretly choose an opponent"; + } + + public ChooseSecretOpponentEffect(final ChooseSecretOpponentEffect effect) { + super(effect); + } + + @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) { + TargetOpponent targetOpponent = new TargetOpponent(); + targetOpponent.setTargetName("opponent (secretly)"); + while (!controller.choose(outcome, targetOpponent, source.getSourceId(), game)) { + if (!controller.canRespond()) { + return false; + } + } + if (targetOpponent.getTargets().isEmpty()) { + return false; + } + if (!game.isSimulation()) { + game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has secretly chosen an opponent."); + } + game.getState().setValue(mageObject.getId() + SECRET_OPPONENT, targetOpponent.getTargets().get(0)); + game.getState().setValue(mageObject.getId() + SECRET_OWNER, controller.getId()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo(SECRET_OPPONENT, + CardUtil.addToolTipMarkTags(controller.getLogName() + " has secretly chosen an opponent."), game); + } + } + return false; + } + + @Override + public ChooseSecretOpponentEffect copy() { + return new ChooseSecretOpponentEffect(this); + } + + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java index 1fb1364e36f..d74258916fa 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java @@ -1,10 +1,14 @@ package mage.abilities.effects.common; +import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; @@ -61,25 +65,64 @@ public class CopyPermanentEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getPermanentEntering(source.getSourceId()); - if (sourceObject == null) { - sourceObject = game.getObject(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourcePermanent = game.getPermanentEntering(source.getSourceId()); + if (sourcePermanent == null) { + sourcePermanent = game.getObject(source.getSourceId()); } - if (player != null && sourceObject != null) { + if (controller != null && sourcePermanent != null) { Permanent copyFromPermanent = null; if (useTargetOfAbility) { copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); } else { Target target = new TargetPermanent(filter); target.setNotTarget(true); - if (target.canChoose(source.getSourceId(), player.getId(), game)) { - player.choose(Outcome.Copy, target, source.getSourceId(), game); + if (target.canChoose(source.getSourceId(), controller.getId(), game)) { + controller.choose(Outcome.Copy, target, source.getSourceId(), game); copyFromPermanent = game.getPermanent(target.getFirstTarget()); } } if (copyFromPermanent != null) { - bluePrintPermanent = game.copyPermanent(copyFromPermanent, sourceObject.getId(), source, applier); + bluePrintPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, applier); + + //if object is a copy of an aura, it needs to attach + if (bluePrintPermanent.hasSubtype(SubType.AURA, game)){ + //copied from mage.cards.c.CopyEnchantment.java + Target target = bluePrintPermanent.getSpellAbility().getTargets().get(0); + Outcome auraOutcome = Outcome.BoostCreature; + for (Ability ability : bluePrintPermanent.getAbilities()) { + if (ability instanceof SpellAbility) { + for (Effect effect : ability.getEffects()) { + if (effect instanceof AttachEffect) { + auraOutcome = effect.getOutcome(); + } + } + } + } + + /*if this is a copy of a copy, the copy's target has been + *copied and needs to be cleared + */ + { + UUID targetId = target.getFirstTarget(); + if(targetId != null) + target.remove(targetId); + } + + target.setNotTarget(true); + if (controller.choose(auraOutcome, target, source.getSourceId(), game)) { + UUID targetId = target.getFirstTarget(); + Permanent targetPermanent = game.getPermanent(targetId); + Player targetPlayer = game.getPlayer(targetId); + if (targetPermanent != null) { + targetPermanent.addAttachment(sourcePermanent.getId(), game); + } else if (targetPlayer != null) { + targetPlayer.addAttachment(sourcePermanent.getId(), game); + } else { + return false; + } + } + } } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java index 56463f3927f..63b3018d234 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java @@ -5,10 +5,10 @@ import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.token.TokenImpl; import mage.game.permanent.token.Token; public class CopyTokenEffect extends ContinuousEffectImpl { + protected Token token; public CopyTokenEffect(Token token) { @@ -28,19 +28,19 @@ public class CopyTokenEffect extends ContinuousEffectImpl { permanent.setName(token.getName()); permanent.getColor(game).setColor(token.getColor(game)); permanent.getCardType().clear(); - for (CardType type: token.getCardType()) { + for (CardType type : token.getCardType()) { permanent.addCardType(type); } permanent.getSubtype(game).clear(); - for (SubType type: token.getSubtype(game)) { + for (SubType type : token.getSubtype(game)) { permanent.getSubtype(game).add(type); } permanent.getSuperType().clear(); - for (SuperType type: token.getSuperType()) { + for (SuperType type : token.getSuperType()) { permanent.addSuperType(type); } permanent.getAbilities().clear(); - for (Ability ability: token.getAbilities()) { + for (Ability ability : token.getAbilities()) { permanent.addAbility(ability, game); } permanent.getPower().setValue(token.getPower().getValue()); 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 8bb428ddb1c..092c8ec92cb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import java.util.ArrayList; @@ -8,6 +7,8 @@ import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.Mode; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; @@ -17,6 +18,7 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.EmptyToken; @@ -33,7 +35,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { private final UUID playerId; private final CardType additionalCardType; - private boolean gainsHaste; + private boolean hasHaste; private final int number; private List addedTokenPermanents; private SubType additionalSubType; @@ -62,12 +64,12 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { this(playerId, null, false); } - public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean gainsHaste) { - this(playerId, additionalCardType, gainsHaste, 1); + public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean hasHaste) { + this(playerId, additionalCardType, hasHaste, 1); } - public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean gainsHaste, int number) { - this(playerId, additionalCardType, gainsHaste, number, false, false); + public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean hasHaste, int number) { + this(playerId, additionalCardType, hasHaste, number, false, false); } /** @@ -75,24 +77,24 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { * @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 gainsHaste the token gains haste + * @param hasHaste the token gains haste * @param number number of tokens to put into play * @param tapped * @param attacking */ - public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean gainsHaste, int number, boolean tapped, boolean attacking) { - this(playerId, additionalCardType, gainsHaste, number, tapped, attacking, null); + public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean hasHaste, int number, boolean tapped, boolean attacking) { + this(playerId, additionalCardType, hasHaste, number, tapped, attacking, null); } - public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean gainsHaste, int number, boolean tapped, boolean attacking, UUID attackedPlayer) { - this(playerId, additionalCardType, gainsHaste, number, tapped, attacking, attackedPlayer, Integer.MIN_VALUE, Integer.MIN_VALUE, false); + public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean hasHaste, int number, boolean tapped, boolean attacking, UUID attackedPlayer) { + this(playerId, additionalCardType, hasHaste, number, tapped, attacking, attackedPlayer, Integer.MIN_VALUE, Integer.MIN_VALUE, false); } - public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean gainsHaste, int number, boolean tapped, boolean attacking, UUID attackedPlayer, int power, int toughness, boolean gainsFlying) { + public CreateTokenCopyTargetEffect(UUID playerId, CardType additionalCardType, boolean hasHaste, int number, boolean tapped, boolean attacking, UUID attackedPlayer, int power, int toughness, boolean gainsFlying) { super(Outcome.PutCreatureInPlay); this.playerId = playerId; this.additionalCardType = additionalCardType; - this.gainsHaste = gainsHaste; + this.hasHaste = hasHaste; this.addedTokenPermanents = new ArrayList<>(); this.number = number; this.tapped = tapped; @@ -107,7 +109,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { super(effect); this.playerId = effect.playerId; this.additionalCardType = effect.additionalCardType; - this.gainsHaste = effect.gainsHaste; + this.hasHaste = effect.hasHaste; this.addedTokenPermanents = new ArrayList<>(effect.addedTokenPermanents); this.number = effect.number; this.additionalSubType = effect.additionalSubType; @@ -124,14 +126,6 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { this.isntLegendary = effect.isntLegendary; } - public void setBecomesArtifact(boolean becomesArtifact) { - this.becomesArtifact = becomesArtifact; - } - - public void setIsntLegendary(boolean isntLegendary) { - this.isntLegendary = isntLegendary; - } - @Override public boolean apply(Game game, Ability source) { UUID targetId; @@ -187,7 +181,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { if (additionalCardType != null && !token.getCardType().contains(additionalCardType)) { token.addCardType(additionalCardType); } - if (gainsHaste) { + if (hasHaste) { token.addAbility(HasteAbility.getInstance()); } if (gainsFlying) { @@ -282,4 +276,33 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { public void setUseLKI(boolean useLKI) { this.useLKI = useLKI; } + + public void setBecomesArtifact(boolean becomesArtifact) { + this.becomesArtifact = becomesArtifact; + } + + public void setIsntLegendary(boolean isntLegendary) { + this.isntLegendary = isntLegendary; + } + + public void setHasHaste(boolean hasHaste) { + this.hasHaste = hasHaste; + } + + public void exileTokensCreatedAtNextEndStep(Game game, Ability source) { + for (Permanent tokenPermanent : addedTokenPermanents) { + ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD); + exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect), source); + } + } + + public void exileTokensCreatedAtEndOfCombat(Game game, Ability source) { + for (Permanent tokenPermanent : addedTokenPermanents) { + + ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD); + exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game)); + game.addDelayedTriggeredAbility(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), source); + } + } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java b/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java index 3ccefeef6bd..12654a1b432 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java @@ -26,7 +26,7 @@ public class CreatureExploresTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent creature = game.getPermanentOrLKIBattlefield(event.getTargetId()); if (creature != null) { - return creature.getControllerId().equals(getControllerId()); + return creature.isControlledBy(getControllerId()); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java index 9cb85eaa08d..410568577fa 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java @@ -77,7 +77,7 @@ class DetainAllRestrictionEffect extends RestrictionEffect { for (FixedTarget fixedTarget : this.detainedObjects) { Permanent permanent = game.getPermanent(fixedTarget.getFirst(game, source)); if (permanent != null) { - permanent.addInfo(new StringBuilder("detain").append(getId()).toString(), "[Detained]", game); + permanent.addInfo("detain" + getId(), "[Detained]", game); } } } @@ -85,11 +85,11 @@ class DetainAllRestrictionEffect extends RestrictionEffect { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) { - if (game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { for (FixedTarget fixedTarget : this.detainedObjects) { Permanent permanent = game.getPermanent(fixedTarget.getFirst(game, source)); if (permanent != null) { - permanent.addInfo(new StringBuilder("detain").append(getId()).toString(), "", game); + permanent.addInfo("detain" + getId(), "", game); } } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/DetainTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DetainTargetEffect.java index a47a2345999..57b2a4c89ff 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DetainTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DetainTargetEffect.java @@ -24,8 +24,8 @@ import mage.util.CardUtil; // 701.26. Detain // // 701.26a Certain spells and abilities can detain a permanent. Until the next -// turn of the controller of that spell or ability, that permanent can’t attack -// or block and its activated abilities can’t be activated. +// turn of the controller of that spell or ability, that permanent can't attack +// or block and its activated abilities can't be activated. // public class DetainTargetEffect extends OneShotEffect { @@ -118,7 +118,7 @@ class DetainRestrictionEffect extends RestrictionEffect { @Override public boolean isInactive(Ability source, Game game) { if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) { - if (game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { + if (game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) { for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java b/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java index e0882ae4466..a68dc8e27f4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java @@ -141,6 +141,7 @@ public class DoIfCostPaid extends OneShotEffect { String costText = cost.getText(); if (costText != null && !costText.toLowerCase(Locale.ENGLISH).startsWith("put") + && !costText.toLowerCase(Locale.ENGLISH).startsWith("return") && !costText.toLowerCase(Locale.ENGLISH).startsWith("exile") && !costText.toLowerCase(Locale.ENGLISH).startsWith("discard") && !costText.toLowerCase(Locale.ENGLISH).startsWith("sacrifice") diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java index 7ce2f8b92a4..c5351ce1fc4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepSourceEffect.java @@ -60,7 +60,7 @@ public class DontUntapInControllersNextUntapStepSourceEffect extends ContinuousR } // remember the turn of the untap step the effect has to be applied if (event.getType() == GameEvent.EventType.UNTAP_STEP - && game.getActivePlayerId().equals(source.getControllerId())) { + && game.isActivePlayer(source.getControllerId())) { if (validForTurnNum == game.getTurnNum()) { // the turn has a second untap step but the effect is already related to the first untap step discard(); return false; @@ -70,7 +70,7 @@ public class DontUntapInControllersNextUntapStepSourceEffect extends ContinuousR // skip untap action if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getType() == GameEvent.EventType.UNTAP - && game.getActivePlayerId().equals(source.getControllerId()) + && game.isActivePlayer(source.getControllerId()) && event.getTargetId().equals(source.getSourceId())) { discard(); return true; 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 2fa58dbf5cd..49d5651cbf7 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersNextUntapStepTargetEffect.java @@ -101,8 +101,8 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR for (UUID targetId : getTargetPointer().getTargets(game, source)) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { - if (game.getActivePlayerId().equals(permanent.getControllerId()) - && ((onlyIfControlledByPlayer == null) || (game.getActivePlayerId().equals(onlyIfControlledByPlayer)))) { // if effect works only for specific player, all permanents have to be set to handled in that players untap step + if (game.isActivePlayer(permanent.getControllerId()) + && ((onlyIfControlledByPlayer == null) || (game.isActivePlayer(onlyIfControlledByPlayer)))) { // if effect works only for specific player, all permanents have to be set to handled in that players untap step if (!handledTargetsDuringTurn.containsKey(targetId)) { // it's the untep step of the current controller and the effect was not handled for this target yet, so do it now handledTargetsDuringTurn.put(targetId, false); @@ -127,8 +127,8 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR && !handledTargetsDuringTurn.get(event.getTargetId()) && getTargetPointer().getTargets(game, source).contains(event.getTargetId())) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && game.getActivePlayerId().equals(permanent.getControllerId())) { - if ((onlyIfControlledByPlayer == null) || game.getActivePlayerId().equals(onlyIfControlledByPlayer)) { // If onlyIfControlledByPlayer is set, then don't apply unless we're currently controlled by the specified player. + if (permanent != null && game.isActivePlayer(permanent.getControllerId())) { + if ((onlyIfControlledByPlayer == null) || game.isActivePlayer(onlyIfControlledByPlayer)) { // If onlyIfControlledByPlayer is set, then don't apply unless we're currently controlled by the specified player. handledTargetsDuringTurn.put(event.getTargetId(), !twoSteps); return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java index 152ec2f29ce..f7d139f97c5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepAllEffect.java @@ -61,7 +61,7 @@ public class DontUntapInControllersUntapStepAllEffect extends ContinuousRuleModi if (permanent != null) { switch(targetController) { case YOU: - if (!permanent.getControllerId().equals(source.getControllerId())) { + if (!permanent.isControlledBy(source.getControllerId())) { return false; } break; @@ -76,7 +76,7 @@ public class DontUntapInControllersUntapStepAllEffect extends ContinuousRuleModi default: throw new RuntimeException("Type of TargetController not supported!"); } - if (game.getActivePlayerId().equals(permanent.getControllerId()) && // controller's untap step + if (game.isActivePlayer(permanent.getControllerId()) && // controller's untap step filter.match(permanent, source.getSourceId(), source.getControllerId(), game)) { return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java index 541bdd908e9..9371f56249b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java @@ -60,7 +60,7 @@ public class DontUntapInControllersUntapStepEnchantedEffect extends ContinuousRu Permanent enchantment = game.getPermanent(source.getSourceId()); if (enchantment != null && enchantment.getAttachedTo() != null && event.getTargetId().equals(enchantment.getAttachedTo())) { Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); - if (permanent != null && permanent.getControllerId().equals(game.getActivePlayerId())) { + if (permanent != null && permanent.isControlledBy(game.getActivePlayerId())) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java index 636677a5544..8c2d9842beb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepSourceEffect.java @@ -50,7 +50,7 @@ public class DontUntapInControllersUntapStepSourceEffect extends ContinuousRuleM if (game.getTurn().getStepType() == PhaseStep.UNTAP && event.getTargetId().equals(source.getSourceId())) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.getControllerId().equals(game.getActivePlayerId())) { + if (permanent != null && permanent.isControlledBy(game.getActivePlayerId())) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java index a5fae993f38..f825e6da9fb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepTargetEffect.java @@ -59,7 +59,7 @@ public class DontUntapInControllersUntapStepTargetEffect extends ContinuousRuleM for (UUID targetId : targetPointer.getTargets(game, source)) { if (event.getTargetId().equals(targetId)) { Permanent permanent = game.getPermanent(targetId); - if (permanent != null && game.getActivePlayerId().equals(permanent.getControllerId())) { + if (permanent != null && game.isActivePlayer(permanent.getControllerId())) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java index ba35b495d04..82f48cce45e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInPlayersNextUntapStepAllEffect.java @@ -81,7 +81,7 @@ public class DontUntapInPlayersNextUntapStepAllEffect extends ContinuousRuleModi } // remember the turn of the untap step the effect has to be applied if (event.getType() == EventType.UNTAP_STEP) { - if (game.getActivePlayerId().equals(getTargetPointer().getFirst(game, source))) { + if (game.isActivePlayer(getTargetPointer().getFirst(game, source))) { if (validForTurnNum == game.getTurnNum()) { // the turn has a second untap step but the effect is already related to the first untap step discard(); return false; @@ -94,13 +94,13 @@ public class DontUntapInPlayersNextUntapStepAllEffect extends ContinuousRuleModi Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { Player controller = game.getPlayer(source.getControllerId()); - if (!permanent.getControllerId().equals(getTargetPointer().getFirst(game, source))) { + if (!permanent.isControlledBy(getTargetPointer().getFirst(game, source))) { return false; } if (controller != null && !game.isOpponent(controller, permanent.getControllerId())) { return false; } - if (game.getActivePlayerId().equals(permanent.getControllerId()) + if (game.isActivePlayer(permanent.getControllerId()) && // controller's untap step filter.match(permanent, source.getSourceId(), source.getControllerId(), game)) { return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardTargetEffect.java index 39c3b8711a6..26fa8a8a177 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardTargetEffect.java @@ -28,10 +28,10 @@ public class DrawDiscardTargetEffect extends OneShotEffect { this.cardsToDiscard = cardsToDiscard; staticText = new StringBuilder("Target player draws ") .append(cardsToDraw == 1?"a": CardUtil.numberToText(cardsToDraw)) - .append(" card").append(cardsToDraw == 1?" ": "s") + .append(" card").append(cardsToDraw == 1?"": "s") .append(", then discards ") .append(cardsToDiscard == 1?"a": CardUtil.numberToText(cardsToDiscard)) - .append(" card").append(cardsToDiscard == 1?" ": "s").toString(); + .append(" card").append(cardsToDiscard == 1?"": "s").toString(); } public DrawDiscardTargetEffect(final DrawDiscardTargetEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/EpicEffect.java b/Mage/src/main/java/mage/abilities/effects/common/EpicEffect.java index 0433c9723ba..eb54beb178d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/EpicEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/EpicEffect.java @@ -26,10 +26,10 @@ import mage.players.Player; * * 702.49. Epic 702.49a Epic represents two spell abilities, one of which * creates a delayed triggered ability. “Epic” means “For the rest of the game, - * you can’t cast spells,” and “At the beginning of each of your upkeeps for the + * you can't cast spells,” and “At the beginning of each of your upkeeps for the * rest of the game, copy this spell except for its epic ability. If the spell * has any targets, you may choose new targets for the copy.” See rule 706.10. - * 702.49b A player can’t cast spells once a spell with epic he or she controls + * 702.49b A player can't cast spells once a spell with epic he or she controls * resolves, but effects (such as the epic ability itself) can still put copies * of spells onto the stack. * */ diff --git a/Mage/src/main/java/mage/abilities/effects/common/FortifyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FortifyEffect.java new file mode 100644 index 00000000000..192540d4693 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/FortifyEffect.java @@ -0,0 +1,38 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +public class FortifyEffect extends AttachEffect{ + + public FortifyEffect(Outcome outcome) { + super(outcome, "Fortify"); + } + + public FortifyEffect(FortifyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + //Some artifacts have the subtype “Fortification.” A Fortification can be attached to a land. It can’t legally + // be attached to an object that isn’t a land. Fortification’s analog to the equip keyword ability is the + // fortify keyword ability. Rules 301.5a–e apply to Fortifications in relation to lands just as they apply to + // Equipment in relation to creatures, with one clarification relating to rule 301.5c: a Fortification that’s + // also a creature (not a land) can’t fortify a land. (See rule 702.66, “Fortify.”) + if (sourcePermanent != null && sourcePermanent.hasSubtype(SubType.FORTIFICATION, game) && !sourcePermanent.isCreature() + && !sourcePermanent.isLand()) { + return super.apply(game, source); + } + return false; + } + + @Override + public FortifyEffect copy(){ + return new FortifyEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java index d1b21c2e862..d8a79bfc80f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/GainLifeTargetEffect.java @@ -60,7 +60,7 @@ public class GainLifeTargetEffect extends OneShotEffect { String message = life.getMessage(); if (!mode.getTargets().isEmpty()) { - sb.append("Target ").append(mode.getTargets().get(0).getTargetName()); + sb.append("target ").append(mode.getTargets().get(0).getTargetName()); } else { sb.append("that player"); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java b/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java index 9480384322f..377fbcb8ee0 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/HideawayPlayEffect.java @@ -51,7 +51,7 @@ public class HideawayPlayEffect extends OneShotEffect { */ if (card.isLand()) { UUID playerId = controller.getId(); - if (!game.getActivePlayerId().equals(playerId) || !game.getPlayer(playerId).canPlayLand()) { + if (!game.isActivePlayer(playerId) || !game.getPlayer(playerId).canPlayLand()) { return false; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java index d27e8f43208..285dd2b9fa8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryAndPickControllerEffect.java @@ -61,6 +61,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff private boolean putOnTopSelected; private boolean anyOrder; + //TODO: These constructors are a mess public LookLibraryAndPickControllerEffect(DynamicValue numberOfCards, boolean mayShuffleAfter, DynamicValue numberToPick, FilterCard pickFilter, boolean putOnTop) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java index 87395253fa0..1fd35fb54bc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java @@ -82,7 +82,7 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect { } } if (mayShuffleAfter) { - if (player.chooseUse(Outcome.Benefit, (player == targetPlayer ? "Shuffle your library?" : "Do you want the chosen player to shuffle his or her library?"), source, game)) { + if (player.chooseUse(Outcome.Benefit, (player == targetPlayer ? "Shuffle your library?" : "Do you want the chosen player to shuffle their library?"), source, game)) { targetPlayer.shuffleLibrary(source, game); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/LoseLifePermanentControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LoseLifePermanentControllerEffect.java new file mode 100644 index 00000000000..5d6ecf576b7 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/LoseLifePermanentControllerEffect.java @@ -0,0 +1,63 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + + + +/** + * This effect applies to the permanent's controller which originated the ability, but not to the controller of that + * source ability. + * @author jesusjbr + */ +public class LoseLifePermanentControllerEffect extends OneShotEffect { + + protected DynamicValue amount; + + public LoseLifePermanentControllerEffect(int amount) { + this(new StaticValue(amount)); + } + + public LoseLifePermanentControllerEffect(DynamicValue amount) { + super(Outcome.LoseLife); + this.amount = amount; + setText(); + } + + public LoseLifePermanentControllerEffect(final LoseLifePermanentControllerEffect effect) { + super(effect); + this.amount = effect.amount.copy(); + } + + @Override + public LoseLifePermanentControllerEffect copy() { + return new LoseLifePermanentControllerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + Player player = null; + if (permanent != null) { + player = game.getPlayer(permanent.getControllerId()); + } + if (player != null) { + player.loseLife(amount.calculate(game, source, this), game, false); + return true; + } + return false; + } + + private void setText() { + StringBuilder sb = new StringBuilder(); + sb.append("controller ").append("loses").append(amount.toString()).append("life"); + staticText += sb.toString(); + } + +} \ No newline at end of file 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 64151380763..a74f8d79626 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PopulateEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PopulateEffect.java @@ -24,10 +24,10 @@ import mage.target.targetpointer.FixedTarget; // 701.27. Populate // // 701.27a To populate means to choose a creature token you control and put a -// token onto the battlefield that’s a copy of that creature token. +// token onto the battlefield that's a copy of that creature token. // // 701.27b If you control no creature tokens when instructed to populate, you -// won’t put a token onto the battlefield. +// won't put a token onto the battlefield. // public class PopulateEffect extends OneShotEffect { @@ -44,7 +44,7 @@ public class PopulateEffect extends OneShotEffect { public PopulateEffect(String prefixText) { super(Outcome.Copy); - this.staticText = (!prefixText.isEmpty() ? prefixText + " p" : "P") + "opulate (Put a token onto the battlefield that's a copy of a creature token you control.)"; + this.staticText = (!prefixText.isEmpty() ? prefixText + " p" : "P") + "opulate (Create a token that's a copy of a creature token you control.)"; } public PopulateEffect(final PopulateEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java index 96df3d277a5..b72b54d01cf 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java @@ -1,5 +1,3 @@ - - package mage.abilities.effects.common; import java.util.HashMap; @@ -15,13 +13,12 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreatureOrPlayerAmount; +import mage.target.TargetAmount; /** * * @author LevelX2 */ - public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl { private final Map targetAmountMap = new HashMap<>(); @@ -44,9 +41,9 @@ public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl super.init(source, game); Target target = source.getTargets().get(0); MageObject sourceObject = game.getObject(source.getSourceId()); - if (target instanceof TargetCreatureOrPlayerAmount && sourceObject != null) { - TargetCreatureOrPlayerAmount multiTarget = (TargetCreatureOrPlayerAmount) target; - for (UUID targetId: multiTarget.getTargets()) { + if (target instanceof TargetAmount && sourceObject != null) { + TargetAmount multiTarget = (TargetAmount) target; + for (UUID targetId : multiTarget.getTargets()) { Player player = null; Permanent permanent = game.getPermanent(targetId); if (permanent == null) { @@ -107,7 +104,7 @@ public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl if (duration == Duration.EndOfTurn) { sb.append("this turn "); } - sb.append("to any number of target creatures and/or players, divided as you choose"); + sb.append("to any number of targets, divided as you choose"); return sb.toString(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutOnLibraryTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutOnLibraryTargetEffect.java index c6a2ab15429..f0cd06bc606 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PutOnLibraryTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PutOnLibraryTargetEffect.java @@ -78,7 +78,7 @@ public class PutOnLibraryTargetEffect extends OneShotEffect { Cards cardsPlayer = new CardsImpl(); for (Iterator iterator = cards.iterator(); iterator.hasNext();) { Card next = iterator.next(); - if (next.getOwnerId().equals(owner.getId())) { + if (next.isOwnedBy(owner.getId())) { cardsPlayer.add(next); iterator.remove(); } @@ -97,7 +97,7 @@ public class PutOnLibraryTargetEffect extends OneShotEffect { Cards cardsPlayer = new CardsImpl(); for (Iterator iterator = permanents.iterator(); iterator.hasNext();) { Permanent next = iterator.next(); - if (next.getOwnerId().equals(owner.getId())) { + if (next.isOwnedBy(owner.getId())) { cardsPlayer.add(next); iterator.remove(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandTargetEffect.java index c3f6ed2d72a..51252895a9d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandTargetEffect.java @@ -57,7 +57,7 @@ public class ReturnToHandTargetEffect extends OneShotEffect { for (Target target : source.getTargets()) { for (UUID targetId : target.getTargets()) { MageObject mageObject = game.getObject(targetId); - if (mageObject instanceof Spell && ((Spell) mageObject).isCopy()) { + if (mageObject instanceof Spell && mageObject.isCopy()) { copyIds.add(targetId); } else if (mageObject instanceof Card) { cards.add((Card) mageObject); @@ -68,7 +68,7 @@ public class ReturnToHandTargetEffect extends OneShotEffect { for (UUID targetId : targetPointer.getTargets(game, source)) { MageObject mageObject = game.getObject(targetId); if (mageObject != null) { - if (mageObject instanceof Spell && ((Spell) mageObject).isCopy()) { + if (mageObject instanceof Spell && mageObject.isCopy()) { copyIds.add(targetId); } else { cards.add((Card) mageObject); diff --git a/Mage/src/main/java/mage/abilities/effects/common/RevealHandSourceControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RevealHandSourceControllerEffect.java new file mode 100644 index 00000000000..c3e5e59e888 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/RevealHandSourceControllerEffect.java @@ -0,0 +1,42 @@ + +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author noahg + */ +public class RevealHandSourceControllerEffect extends OneShotEffect { + + public RevealHandSourceControllerEffect() { + super(Outcome.Discard); + this.staticText = "reveal your hand"; + } + + public RevealHandSourceControllerEffect(final RevealHandSourceControllerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (player != null && sourceObject != null) { + player.revealCards(sourceObject.getIdName(), player.getHand(), game); + return true; + } + return false; + } + + @Override + public RevealHandSourceControllerEffect copy() { + return new RevealHandSourceControllerEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java index 267371c7dc5..243c524d5c8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import java.util.ArrayList; @@ -39,7 +38,8 @@ public class SacrificeOpponentsEffect extends OneShotEffect { public SacrificeOpponentsEffect(DynamicValue amount, FilterPermanent filter) { super(Outcome.Sacrifice); this.amount = amount; - this.filter = filter; + this.filter = filter.copy(); + this.filter.add(new ControllerPredicate(TargetController.YOU)); setText(); } @@ -57,7 +57,6 @@ public class SacrificeOpponentsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { List perms = new ArrayList<>(); - filter.add(new ControllerPredicate(TargetController.YOU)); for (UUID playerId : game.getOpponents(source.getControllerId())) { Player player = game.getPlayer(playerId); if (player != null) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java index 26e828dc580..b4e9339de44 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java @@ -44,7 +44,7 @@ public class SacrificeSourceEffect extends OneShotEffect { if (sourceObject instanceof Permanent) { Permanent permanent = (Permanent) sourceObject; // you can only sacrifice a permanent you control - if (source.getControllerId().equals(permanent.getControllerId())) { + if (source.isControlledBy(permanent.getControllerId())) { return permanent.sacrifice(source.getSourceId(), game); } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/SkipNextDrawStepControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SkipNextDrawStepControllerEffect.java new file mode 100644 index 00000000000..f498b90eebb --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/SkipNextDrawStepControllerEffect.java @@ -0,0 +1,74 @@ +/* + * + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + * + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.game.Game; +import mage.game.turn.TurnMod; +import mage.players.Player; + +/** + * + * @author noahg + */ +public class SkipNextDrawStepControllerEffect extends OneShotEffect { + + public SkipNextDrawStepControllerEffect() { + this("you skip your next draw step"); + } + + public SkipNextDrawStepControllerEffect(String text) { + super(Outcome.Detriment); + this.staticText = text; + } + + public SkipNextDrawStepControllerEffect(SkipNextDrawStepControllerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + game.getState().getTurnMods().add(new TurnMod(player.getId(), PhaseStep.DRAW)); + return true; + } + return false; + } + + @Override + public SkipNextDrawStepControllerEffect copy() { + return new SkipNextDrawStepControllerEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/SkipUntapOptionalSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SkipUntapOptionalSourceEffect.java index 667c0bb2950..dbe05cd6b7f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SkipUntapOptionalSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SkipUntapOptionalSourceEffect.java @@ -27,7 +27,7 @@ public class SkipUntapOptionalSourceEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { return permanent.getId().equals(source.getSourceId()) - && permanent.getControllerId().equals(game.getActivePlayerId()) && // your untap step + && permanent.isControlledBy(game.getActivePlayerId()) && // your untap step permanent.isTapped(); } 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 e15baaf796b..93647512202 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import java.util.List; @@ -7,7 +6,6 @@ import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.filter.FilterPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -18,7 +16,7 @@ import mage.players.Player; */ public class TapAllTargetPlayerControlsEffect extends OneShotEffect { - private FilterPermanent filter; + private final FilterPermanent filter; public TapAllTargetPlayerControlsEffect(FilterPermanent filter) { super(Outcome.Tap); @@ -34,8 +32,7 @@ public class TapAllTargetPlayerControlsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); if (player != null) { - filter.add(new ControllerIdPredicate(player.getId())); - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); + List permanents = game.getBattlefield().getAllActivePermanents(filter, player.getId(), game); for (Permanent p : permanents) { p.tap(game); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/TapSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TapSourceEffect.java index e229d41f4ea..8239cc578c3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TapSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TapSourceEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; @@ -38,6 +37,9 @@ public class TapSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + permanent = game.getPermanentEntering(source.getSourceId()); + } if (permanent != null) { if (withoutTrigger) { permanent.setTapped(true); 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 f650830fb0c..ccc695b67bb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/UntapLandsEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import java.util.UUID; @@ -47,7 +46,12 @@ public class UntapLandsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - int tappedLands = game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game).size(); + int tappedLands; + if (upTo) { + tappedLands = game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game).size(); + } else { + tappedLands = game.getBattlefield().getAllActivePermanents(filter, game).size(); + } TargetLandPermanent target = new TargetLandPermanent(upTo ? 0 : Math.min(tappedLands, amount), amount, filter, true); if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java b/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java index 5841feef03b..62f74e35980 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/WishEffect.java @@ -86,7 +86,7 @@ public class WishEffect extends OneShotEffect { } if (alsoFromExile) { for (Card exileCard : exile) { - if (exileCard.getOwnerId().equals(source.getControllerId()) && filter.match(exileCard, game)) { + if (exileCard.isOwnedBy(source.getControllerId()) && filter.match(exileCard, game)) { filteredCards.add(exileCard); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackControllerAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackControllerAttachedEffect.java index 04aae7f845e..09e122ede9e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackControllerAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackControllerAttachedEffect.java @@ -38,7 +38,7 @@ public class CantAttackControllerAttachedEffect extends RestrictionEffect { return false; } Permanent planeswalker = game.getPermanent(defenderId); - return planeswalker == null || !planeswalker.getControllerId().equals(source.getControllerId()); + return planeswalker == null || !planeswalker.isControlledBy(source.getControllerId()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouOrPlaneswalkerAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouOrPlaneswalkerAllEffect.java index fa228c16e67..b603326ddff 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouOrPlaneswalkerAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackYouOrPlaneswalkerAllEffect.java @@ -44,7 +44,7 @@ public class CantAttackYouOrPlaneswalkerAllEffect extends RestrictionEffect { return false; } Permanent planeswalker = game.getPermanent(defenderId); - return planeswalker == null || !planeswalker.getControllerId().equals(source.getControllerId()); + return planeswalker == null || !planeswalker.isControlledBy(source.getControllerId()); } @Override 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 ebf276e5612..0eef90ee664 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 @@ -56,7 +56,7 @@ public class CantAttackYouUnlessPayManaAllEffect extends PayCostToAttackBlockEff } } // attack target is controlling player - if (source.getControllerId().equals(event.getTargetId())) { + if (source.isControlledBy(event.getTargetId())) { return true; } // or attack target is a planeswalker of the controlling player @@ -64,7 +64,7 @@ public class CantAttackYouUnlessPayManaAllEffect extends PayCostToAttackBlockEff Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.isPlaneswalker() - && permanent.getControllerId().equals(source.getControllerId())) { + && permanent.isControlledBy(source.getControllerId())) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedAttachedEffect.java index 39647dd438b..6fc49b43cda 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedAttachedEffect.java @@ -36,7 +36,7 @@ public class CantBeBlockedAttachedEffect extends RestrictionEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { Permanent attachment = game.getPermanent(source.getSourceId()); - return attachment != null && attachment.getAttachedTo() != null - && attachment.getAttachedTo().equals(permanent.getId()); + return attachment != null + && attachment.isAttachedTo(permanent.getId()); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedTargetEffect.java index 73562578359..15d43ec0eaf 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedTargetEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.combat; import mage.abilities.Ability; @@ -6,6 +5,8 @@ import mage.abilities.Mode; import mage.abilities.effects.RestrictionEffect; import mage.constants.Duration; import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; @@ -17,16 +18,27 @@ import mage.util.CardUtil; */ public class CantBeBlockedTargetEffect extends RestrictionEffect { + private final FilterCreaturePermanent filter; + public CantBeBlockedTargetEffect() { this(Duration.EndOfTurn); } public CantBeBlockedTargetEffect(Duration duration) { + this(StaticFilters.FILTER_PERMANENT_CREATURE, duration); + this.staticText = null; + } + + public CantBeBlockedTargetEffect(FilterCreaturePermanent filter, Duration duration) { super(duration, Outcome.Benefit); + this.filter = filter; + staticText = new StringBuilder("{this} can't be blocked ") + .append(filter.getMessage().startsWith("except by") ? "" : "by ").append(filter.getMessage()).toString(); } public CantBeBlockedTargetEffect(CantBeBlockedTargetEffect effect) { super(effect); + this.filter = effect.filter; } @Override @@ -36,7 +48,7 @@ public class CantBeBlockedTargetEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - return false; + return !filter.match(blocker, source.getSourceId(), source.getControllerId(), game); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/GoadAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/GoadAllEffect.java index d525e0b372c..c24a7630db6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/GoadAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/GoadAllEffect.java @@ -33,7 +33,7 @@ public class GoadAllEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) { - if (!creature.getControllerId().equals(source.getControllerId())) { + if (!creature.isControlledBy(source.getControllerId())) { Effect effect = new GoadTargetEffect(); effect.setTargetPointer(new FixedTarget(creature, game)); effect.apply(game, source); diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllSourceEffect.java index 82cc2d8ccb9..4f4fc76fe66 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllSourceEffect.java @@ -1,11 +1,11 @@ - - package mage.abilities.effects.common.combat; import java.util.UUID; import mage.constants.Duration; import mage.abilities.Ability; import mage.abilities.effects.RequirementEffect; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -15,23 +15,33 @@ import mage.game.permanent.Permanent; */ public class MustBeBlockedByAllSourceEffect extends RequirementEffect { + private final FilterCreaturePermanent filter; + public MustBeBlockedByAllSourceEffect() { this(Duration.WhileOnBattlefield); } public MustBeBlockedByAllSourceEffect(Duration duration) { + this(duration, StaticFilters.FILTER_PERMANENT_CREATURES); + } + + public MustBeBlockedByAllSourceEffect(Duration duration, FilterCreaturePermanent filter) { super(duration); - staticText = "All creatures able to block {this} do so"; + this.filter = filter; + staticText = "All " + filter.getMessage() + " able to block {this} do so"; } public MustBeBlockedByAllSourceEffect(final MustBeBlockedByAllSourceEffect effect) { super(effect); + this.filter = effect.filter; } @Override public boolean applies(Permanent permanent, Ability source, Game game) { Permanent sourceCreature = game.getPermanent(source.getSourceId()); - if (sourceCreature != null && sourceCreature.isAttacking()) { + if (sourceCreature != null + && sourceCreature.isAttacking() + && filter.match(permanent, game)) { return permanent.canBlock(source.getSourceId(), game); } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java index f07636b3b5c..7375856341d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java @@ -35,18 +35,26 @@ import mage.game.permanent.Permanent; * @author LevelX2 */ public class MustBeBlockedByAtLeastOneSourceEffect extends RequirementEffect { + + private int minNumberOfBlockers; public MustBeBlockedByAtLeastOneSourceEffect() { this(Duration.EndOfTurn); } public MustBeBlockedByAtLeastOneSourceEffect(Duration duration) { + this(duration, 1); + } + + public MustBeBlockedByAtLeastOneSourceEffect(Duration duration, int minNumberOfBlockers) { super(duration); + this.minNumberOfBlockers = minNumberOfBlockers; staticText = "{this} must be blocked " + (duration == Duration.EndOfTurn ? "this turn " : "") + "if able"; } public MustBeBlockedByAtLeastOneSourceEffect(final MustBeBlockedByAtLeastOneSourceEffect effect) { super(effect); + this.minNumberOfBlockers = effect.minNumberOfBlockers; } @Override @@ -69,6 +77,11 @@ public class MustBeBlockedByAtLeastOneSourceEffect extends RequirementEffect { return source.getSourceId(); } + @Override + public int getMinNumberOfBlockers() { + return minNumberOfBlockers; + } + @Override public MustBeBlockedByAtLeastOneSourceEffect copy() { return new MustBeBlockedByAtLeastOneSourceEffect(this); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java index 3d4470dd573..4f76c81b722 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/ActivateAbilitiesAnyTimeYouCouldCastInstantEffect.java @@ -44,7 +44,7 @@ public class ActivateAbilitiesAnyTimeYouCouldCastInstantEffect extends AsThoughE @Override public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game) { - return affectedAbility.getControllerId().equals(source.getControllerId()) + return affectedAbility.isControlledBy(source.getControllerId()) && activatedAbility.isInstance(affectedAbility); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java index c3e07473abe..b8f09330394 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeTargetEffect.java @@ -88,7 +88,7 @@ public class AddCardTypeTargetEffect extends ContinuousEffectImpl { sb.append(cardType.toString().toLowerCase(Locale.ENGLISH)).append(" "); } sb.append("in addition to its other types"); - if (getDuration().equals(Duration.EndOfTurn)) { + if (getDuration() == Duration.EndOfTurn) { sb.append(" until end of turn"); } return sb.toString(); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java new file mode 100644 index 00000000000..bb86dce4a5d --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddChosenSubtypeEffect.java @@ -0,0 +1,37 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; + +public class AddChosenSubtypeEffect extends ContinuousEffectImpl { + + public AddChosenSubtypeEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + staticText = "{this} is the chosen type in addition to its other types"; + } + + public AddChosenSubtypeEffect(final AddChosenSubtypeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(permanent.getId(), game); + if (subType != null && !permanent.hasSubtype(subType, game)) { + permanent.getSubtype(game).add(subType); + } + } + return true; + } + + @Override + public AddChosenSubtypeEffect copy() { + return new AddChosenSubtypeEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorAllEffect.java new file mode 100644 index 00000000000..f5cefeefbf5 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesColorAllEffect.java @@ -0,0 +1,154 @@ +/* + * + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + * + */ +package mage.abilities.effects.common.continuous; + +import mage.MageObject; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.choices.ChoiceColor; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author LevelX + */ +public class BecomesColorAllEffect extends ContinuousEffectImpl { + + private ObjectColor setColor; + protected boolean loseOther; + protected FilterPermanent filter; + + /** + * Set the color of a spell or permanent + * + * @param duration + */ + public BecomesColorAllEffect(Duration duration) { + this(null, duration); + } + + public BecomesColorAllEffect(ObjectColor setColor, Duration duration) { + this(setColor, duration, new FilterPermanent("All permanents"), true, null); + } + + public BecomesColorAllEffect(ObjectColor setColor, Duration duration, FilterPermanent filter, boolean loseOther, String text) { + super(duration, Layer.ColorChangingEffects_5, SubLayer.NA, Outcome.Neutral); + this.setColor = setColor; + this.filter = filter; + this.loseOther = loseOther; + staticText = text; + } + + public BecomesColorAllEffect(final BecomesColorAllEffect effect) { + super(effect); + this.setColor = effect.setColor; + this.filter = effect.filter; + this.loseOther = effect.loseOther; + } + + @Override + public void init(Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return; + } + if (setColor == null) { + ChoiceColor choice = new ChoiceColor(); + if (!controller.choose(Outcome.PutManaInPool, choice, game)) { + discard(); + return; + } + setColor = choice.getColor(); + if (!game.isSimulation()) { + game.informPlayers(controller.getLogName() + " has chosen the color: " + setColor.toString()); + } + } + + super.init(source, game); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + if (setColor != null) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + if (permanent != null) { + switch (layer) { + case ColorChangingEffects_5: + if (loseOther) { + permanent.getColor(game).setColor(new ObjectColor()); + } + permanent.getColor(game).addColor(setColor); + break; + } + } else if (duration == Duration.Custom) { + discard(); + } + } + return true; + } + return false; + } + + @Override + public BecomesColorAllEffect copy() { + return new BecomesColorAllEffect(this); + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + StringBuilder sb = new StringBuilder(); + sb.append(filter.getMessage()); + sb.append(" become "); + if (setColor == null) { + sb.append("the color of your choice"); + } else { + sb.append(setColor.getDescription()); + } + if (!duration.toString().equals("")) { + sb.append(' ').append(duration.toString()); + } + return sb.toString(); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java index 18d7b54bb43..d127b409438 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect.java @@ -16,7 +16,6 @@ import mage.game.permanent.token.Token; public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends ContinuousEffectImpl { public enum LoseType { - NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE_AND_PT } @@ -102,6 +101,7 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co } break; + case ColorChangingEffects_5: if (sublayer == SubLayer.NA) { if (loseType == LoseType.ALL) { @@ -116,6 +116,7 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co } } break; + case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { switch (loseType) { @@ -132,12 +133,13 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co } break; + case PTChangingEffects_7: if (sublayer == SubLayer.SetPT_7b) { permanentAttachedTo.getPower().setValue(token.getPower().getValue()); permanentAttachedTo.getToughness().setValue(token.getToughness().getValue()); - break; } + break; } } if (!attachedExists) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java index 63181779803..ba868a521fe 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java @@ -5,7 +5,6 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.keyword.FlyingAbility; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; @@ -19,6 +18,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements protected Token token; protected String theyAreStillType; protected boolean losePreviousTypes; + protected boolean loseAbilities; protected DynamicValue power = null; protected DynamicValue toughness = null; @@ -31,13 +31,16 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements } public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration, boolean losePreviousTypes, boolean characterDefining, DynamicValue power, DynamicValue toughness) { + this(token, theyAreStillType,duration,losePreviousTypes,characterDefining,power,toughness,false); + } + public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration, boolean losePreviousTypes, boolean characterDefining, DynamicValue power, DynamicValue toughness, boolean loseAbilities) { super(duration, Outcome.BecomeCreature); this.characterDefining = characterDefining; this.token = token; this.theyAreStillType = theyAreStillType; this.losePreviousTypes = losePreviousTypes; this.power = power; - this.toughness = toughness; + this.toughness = toughness;this.loseAbilities=loseAbilities; setText(); this.addDependencyType(DependencyType.BecomeCreature); @@ -47,7 +50,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements super(effect); this.token = effect.token.copy(); this.theyAreStillType = effect.theyAreStillType; - this.losePreviousTypes = effect.losePreviousTypes; + this.losePreviousTypes = effect.losePreviousTypes;this.loseAbilities=effect.loseAbilities; if (effect.power != null) { this.power = effect.power.copy(); } @@ -108,6 +111,8 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { + if(loseAbilities){ + permanent.removeAllAbilities(source.getSourceId(), game);} for (Ability ability : token.getAbilities()) { permanent.addAbility(ability, source.getSourceId(), game); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java index d49b6d7e7ff..bf9e508a8b5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllEffect.java @@ -147,7 +147,7 @@ public class BoostAllEffect extends ContinuousEffectImpl { protected void setText() { StringBuilder sb = new StringBuilder(); if (excludeSource) { - sb.append("Other "); + sb.append("other "); } sb.append(filter.getMessage()).append(" get "); String p = power.toString(); 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 5a50943bff1..e20ec587178 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 @@ -65,7 +65,7 @@ public class CantCastMoreThanOneSpellEffect extends ContinuousRuleModifyingEffec break; case CONTROLLER_ATTACHED_TO: Permanent attachment = game.getPermanent(source.getSourceId()); - if (attachment == null || !attachment.getAttachedTo().equals(event.getPlayerId())) { + if (attachment == null || !attachment.isAttachedTo(event.getPlayerId())) { return false; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java index 62d34920388..762e6539aef 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java @@ -51,7 +51,7 @@ public class CastAsThoughItHadFlashAllEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID affectedSpellId, Ability source, UUID affectedControllerId, Game game) { - if (anyPlayer || source.getControllerId().equals(affectedControllerId)) { + if (anyPlayer || source.isControlledBy(affectedControllerId)) { Card card = game.getCard(affectedSpellId); return card != null && filter.match(card, game); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java index 09c6d6c75a6..749c7813b6e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java @@ -21,9 +21,9 @@ import mage.players.Player; */ //20130711 /* - * 903.11. If a commander would be put into its owner’s graveyard from anywhere, that player may put it into the command zone instead. + * 903.11. If a commander would be put into its owner's graveyard from anywhere, that player may put it into the command zone instead. * 903.12. If a commander would be put into the exile zone from anywhere, its owner may put it into the command zone instead. - * 903.9. If a commander would be exiled from anywhere or put into its owner’s hand, graveyard, or + * 903.9. If a commander would be exiled from anywhere or put into its owner's hand, graveyard, or library from anywhere, its owner may put it into the command zone instead. This replacement effect may apply more than once to the same event. This is an exception to rule 614.5. */ @@ -35,7 +35,7 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl { public CommanderReplacementEffect(UUID commanderId, boolean alsoHand, boolean alsoLibrary) { super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "If a commander would be put into its owner’s graveyard from anywhere, that player may put it into the command zone instead. If a commander would be put into the exile zone from anywhere, its owner may put it into the command zone instead."; + staticText = "If a commander would be put into its owner's graveyard from anywhere, that player may put it into the command zone instead. If a commander would be put into the exile zone from anywhere, its owner may put it into the command zone instead."; this.commanderId = commanderId; this.duration = Duration.EndOfGame; this.alsoHand = alsoHand; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java index e79074f1bc3..37c32f864a9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java @@ -98,7 +98,7 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl { } if (permanent1 != null && permanent2 != null) { // exchange works only for two different controllers - if (permanent1.getControllerId().equals(permanent2.getControllerId())) { + if (permanent1.isControlledBy(permanent2.getControllerId())) { // discard effect if controller of both permanents is the same discard(); return; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java index bc5f1856972..aa2ea4b16c6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.continuous; import java.util.HashMap; @@ -16,6 +15,7 @@ import mage.constants.Outcome; import mage.constants.SubLayer; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -29,11 +29,11 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl { protected FilterPermanent filter; public GainAbilityControlledEffect(Ability ability, Duration duration) { - this(ability, duration, new FilterPermanent("permanents")); + this(ability, duration, StaticFilters.FILTER_PERMANENT); } public GainAbilityControlledEffect(CompoundAbility ability, Duration duration) { - this(ability, duration, new FilterPermanent("permanents")); + this(ability, duration, StaticFilters.FILTER_PERMANENT); } public GainAbilityControlledEffect(Ability ability, Duration duration, FilterPermanent filter) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java index 01becdd24b6..e58f88cda63 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControlledSpellsEffect.java @@ -48,7 +48,7 @@ public class GainAbilityControlledSpellsEffect extends ContinuousEffectImpl { if (player != null && permanent != null) { for (StackObject stackObject : game.getStack()) { // only spells cast, so no copies of spells - if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) { + if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; if (filter.match(spell, game)) { if (!spell.getAbilities().contains(ability)) { 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 d511d6e5d2f..881e3190246 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 @@ -88,7 +88,7 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl { return true; } if (durationPhaseStep != null && durationPhaseStep == game.getPhase().getStep().getType()) { - if (!sameStep && game.getActivePlayerId().equals(durationPlayerId) || game.getPlayer(durationPlayerId).hasReachedNextTurnAfterLeaving()) { + if (!sameStep && game.isActivePlayer(durationPlayerId) || game.getPlayer(durationPlayerId).hasReachedNextTurnAfterLeaving()) { return true; } } else { 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 455fb38e09d..993134026fa 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 @@ -83,7 +83,7 @@ public class GainControlTargetEffect extends ContinuousEffectImpl { Permanent permanent = game.getPermanent(permanentId); if (permanent != null) { targetStillExists = true; - if (!permanent.getControllerId().equals(controllingPlayerId)) { + if (!permanent.isControlledBy(controllingPlayerId)) { GameEvent loseControlEvent = GameEvent.getEvent(GameEvent.EventType.LOSE_CONTROL, permanentId, source.getId(), permanent.getControllerId()); if (game.replaceEvent(loseControlEvent)) { return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java index 5d56fdf130d..fd56dcee2b9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.continuous; import java.util.HashMap; @@ -15,6 +14,7 @@ import mage.constants.Outcome; import mage.constants.SubLayer; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -28,11 +28,11 @@ public class LoseAbilityAllEffect extends ContinuousEffectImpl { protected FilterPermanent filter; public LoseAbilityAllEffect(Ability ability, Duration duration) { - this(ability, duration, new FilterPermanent("permanents")); + this(ability, duration, StaticFilters.FILTER_PERMANENT); } public LoseAbilityAllEffect(CompoundAbility ability, Duration duration) { - this(ability, duration, new FilterPermanent("permanents")); + this(ability, duration, StaticFilters.FILTER_PERMANENT); } public LoseAbilityAllEffect(Ability ability, Duration duration, FilterPermanent filter) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java new file mode 100644 index 00000000000..ac44c271aab --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseArtifactTypeTargetEffect.java @@ -0,0 +1,77 @@ + +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * + * @author noahg + */ +public class LoseArtifactTypeTargetEffect extends ContinuousEffectImpl{ + + public LoseArtifactTypeTargetEffect(Duration duration) { + super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral); + dependencyTypes.add(DependencyType.ArtifactAddingRemoving); + setText("isn't an artifact"); + } + + public LoseArtifactTypeTargetEffect(final LoseArtifactTypeTargetEffect effect) { + super(effect); + } + + @Override + public LoseArtifactTypeTargetEffect copy() { + return new LoseArtifactTypeTargetEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); //To change body of generated methods, choose Tools | Templates. + if (duration.isOnlyValidIfNoZoneChange()) { + // If source permanent is no longer onto battlefield discard the effect + if (source.getSourcePermanentIfItStillExists(game) == null) { + discard(); + } + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + for (UUID targetId : targetPointer.getTargets(game, source)) { + if (targetId != null) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.getCardType().remove(CardType.ARTIFACT); + permanent.getSubtype(game).removeAll(SubType.getArtifactTypes(false)); + } + 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; + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java index 5dd1ffdc771..35e63cc3619 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java @@ -50,7 +50,7 @@ public class PlayTheTopCardEffect extends AsThoughEffectImpl { Card cardOnTop = game.getCard(objectId); if (cardOnTop != null && affectedControllerId.equals(source.getControllerId()) - && cardOnTop.getOwnerId().equals(source.getControllerId()) + && cardOnTop.isOwnedBy(source.getControllerId()) && (!cardOnTop.getManaCost().isEmpty() || cardOnTop.isLand()) && filter.match(cardOnTop, game)) { Player player = game.getPlayer(cardOnTop.getOwnerId()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/SetPowerToughnessEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/SetPowerToughnessEnchantedEffect.java index e33d30a36da..a5f1cf72e30 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/SetPowerToughnessEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/SetPowerToughnessEnchantedEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.continuous; import mage.abilities.Ability; @@ -16,13 +15,24 @@ import mage.game.permanent.Permanent; */ public class SetPowerToughnessEnchantedEffect extends ContinuousEffectImpl { + private final int power; + private final int toughness; + public SetPowerToughnessEnchantedEffect() { + this(0, 2); + } + + public SetPowerToughnessEnchantedEffect(int power, int toughness) { super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.SetPT_7b, Outcome.BoostCreature); - staticText = "Enchanted creature has base power and toughness 0/2"; + staticText = "Enchanted creature has base power and toughness " + power + "/" + toughness; + this.power = power; + this.toughness = toughness; } public SetPowerToughnessEnchantedEffect(final SetPowerToughnessEnchantedEffect effect) { super(effect); + this.power = effect.power; + this.toughness = effect.toughness; } @Override @@ -36,8 +46,8 @@ public class SetPowerToughnessEnchantedEffect extends ContinuousEffectImpl { if (enchantment != null && enchantment.getAttachedTo() != null) { Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); if (enchanted != null) { - enchanted.getPower().setValue(0); - enchanted.getToughness().setValue(2); + enchanted.getPower().setValue(power); + enchanted.getToughness().setValue(toughness); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java index 1fd92243eca..76999b4f193 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java @@ -44,7 +44,7 @@ public class UntapAllDuringEachOtherPlayersUntapStepEffect extends ContinuousEff applied = Boolean.FALSE; } if (!applied && layer == Layer.RulesEffects) { - if (!source.getControllerId().equals(game.getActivePlayerId()) && game.getStep().getType() == PhaseStep.UNTAP) { + if (!source.isControlledBy(game.getActivePlayerId()) && game.getStep().getType() == PhaseStep.UNTAP) { game.getState().setValue(source.getSourceId() + "applied", true); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { boolean untap = true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapSourceDuringEachOtherPlayersUntapStepEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapSourceDuringEachOtherPlayersUntapStepEffect.java index aa2dcbe44db..d1ede8e3a3b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapSourceDuringEachOtherPlayersUntapStepEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapSourceDuringEachOtherPlayersUntapStepEffect.java @@ -39,7 +39,7 @@ public class UntapSourceDuringEachOtherPlayersUntapStepEffect extends Continuous applied = Boolean.FALSE; } if (!applied && layer == Layer.RulesEffects) { - if (!source.getControllerId().equals(game.getActivePlayerId()) + if (!source.isControlledBy(game.getActivePlayerId()) && game.getStep() != null && game.getStep().getType() == PhaseStep.UNTAP) { game.getState().setValue(source.getSourceId() + "applied", true); diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/AbilitiesCostReductionControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/AbilitiesCostReductionControllerEffect.java index 75e4ade46e6..b0b53d2d82c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/AbilitiesCostReductionControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/AbilitiesCostReductionControllerEffect.java @@ -44,7 +44,7 @@ public class AbilitiesCostReductionControllerEffect extends CostModificationEffe @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify.getControllerId().equals(source.getControllerId()) + return abilityToModify.isControlledBy(source.getControllerId()) && activatedAbility.isInstance(abilityToModify); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementControllerEffect.java index 9c1631f0717..7023fc78847 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementControllerEffect.java @@ -69,7 +69,7 @@ public class SpellsCostIncreasementControllerEffect extends CostModificationEffe @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { return this.filter.match(spell, game); diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java index bc2f1e2382f..4947acadf22 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java @@ -120,10 +120,10 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - if (onlyControlled && !abilityToModify.getControllerId().equals(source.getControllerId())) { + if (onlyControlled && !abilityToModify.isControlledBy(source.getControllerId())) { return false; } - if (controllerId != null && !abilityToModify.getControllerId().equals(controllerId)) { + if (controllerId != null && !abilityToModify.isControlledBy(controllerId)) { return false; } if (abilityToModify instanceof SpellAbility) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java index 55068aec822..a58c1a2cb0f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java @@ -114,7 +114,7 @@ public class SpellsCostReductionControllerEffect extends CostModificationEffectI @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility) { - if (abilityToModify.getControllerId().equals(source.getControllerId())) { + if (abilityToModify.isControlledBy(source.getControllerId())) { Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spell != null) { return this.filter.match(spell, source.getSourceId(), source.getControllerId(), game); diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java new file mode 100644 index 00000000000..775ca85982c --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCountersAttachedEffect.java @@ -0,0 +1,91 @@ + +package mage.abilities.effects.common.counter; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.counters.Counter; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +import java.util.Locale; + +/** + * + * @author noahg + */ +public class RemoveCountersAttachedEffect extends OneShotEffect { + + private Counter counter; + private DynamicValue amount; + private String textEnchanted; + + public RemoveCountersAttachedEffect(Counter counter, String textEnchanted) { + this(counter, new StaticValue(0), textEnchanted); + } + + /** + * + * @param counter + * @param amount this amount will be added to the counter instances + * @param textEnchanted text used for the enchanted permanent in rule text + */ + public RemoveCountersAttachedEffect(Counter counter, DynamicValue amount, String textEnchanted) { + super(Outcome.UnboostCreature); + this.counter = counter.copy(); + this.amount = amount; + this.textEnchanted = textEnchanted; + setText(); + } + + public RemoveCountersAttachedEffect(final RemoveCountersAttachedEffect effect) { + super(effect); + if (effect.counter != null) { + this.counter = effect.counter.copy(); + } + this.amount = effect.amount; + this.textEnchanted = effect.textEnchanted; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null && permanent.getAttachedTo() != null) { + Permanent attachedTo = game.getPermanent(permanent.getAttachedTo()); + if (attachedTo != null && counter != null) { + Counter newCounter = counter.copy(); + newCounter.add(amount.calculate(game, source, this)); + attachedTo.removeCounters(newCounter, game); + } + return true; + } + return false; + } + + private void setText() { + StringBuilder sb = new StringBuilder(); + // put a +1/+1 counter on it + sb.append("remove "); + if (counter.getCount() > 1) { + sb.append(CardUtil.numberToText(counter.getCount())).append(' '); + sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters from "); + } else { + sb.append("a "); + sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter from "); + } + sb.append(textEnchanted); + if (!amount.getMessage().isEmpty()) { + sb.append(" for each ").append(amount.getMessage()); + } + staticText = sb.toString(); + } + + @Override + public RemoveCountersAttachedEffect copy() { + return new RemoveCountersAttachedEffect(this); + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java index edf8f95a1ed..b70c8bb1815 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/enterAttribute/EnterAttributeAddChosenSubtypeEffect.java @@ -11,6 +11,8 @@ import mage.game.permanent.Permanent; /** * + * IMPORTANT: This only adds the chosen subtype while the source permanent is entering the battlefield. + * You should also use @link{mage.abilities.effects.common.continuous.AddChosenSubtypeEffect} to make the subtype persist. * @author LevelX2 */ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect { @@ -34,12 +36,8 @@ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect { Permanent permanent = game.getPermanentEntering(source.getSourceId()); SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type"); if (permanent != null && subtype != null) { - MageObject mageObject = permanent.getBasicMageObject(game); - if (!mageObject.getSubtype(null).contains(subtype)) { - mageObject.getSubtype(null).add(subtype); - } - if (!permanent.getSubtype(null).contains(subtype)) { - permanent.getSubtype(null).add(subtype); + if (!permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/replacement/DiesReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/replacement/DiesReplacementEffect.java index bf08c67125d..12ece0c7b53 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/replacement/DiesReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/replacement/DiesReplacementEffect.java @@ -29,7 +29,7 @@ public class DiesReplacementEffect extends ReplacementEffectImpl { public DiesReplacementEffect(MageObjectReference objectRef, Duration duration) { super(duration, Outcome.Exile); this.objectRef = objectRef; - staticText = "If that creature would die " + (duration.equals(Duration.EndOfTurn) ? "this turn" : "") + ", exile it instead"; + staticText = "If that creature would die " + (duration == Duration.EndOfTurn ? "this turn" : "") + ", exile it instead"; } public DiesReplacementEffect(final DiesReplacementEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyDuringPhaseStepSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyDuringPhaseStepSourceEffect.java index 9fa8319e43d..710b91be92a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyDuringPhaseStepSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CastOnlyDuringPhaseStepSourceEffect.java @@ -59,7 +59,7 @@ public class CastOnlyDuringPhaseStepSourceEffect extends ContinuousRuleModifying } private String setText() { - StringBuilder sb = new StringBuilder("cast {this} only during "); + StringBuilder sb = new StringBuilder("cast this spell only during "); if (turnPhase != null) { sb.append(turnPhase.toString()); } 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 12ee9f50f59..7126808c810 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 @@ -17,7 +17,7 @@ public class CastOnlyIfYouHaveCastAnotherSpellEffect extends ContinuousRuleModif public CastOnlyIfYouHaveCastAnotherSpellEffect() { super(Duration.EndOfGame, Outcome.Detriment); - staticText = "Cast {this} only if you've cast another spell this turn"; + staticText = "Cast this spell only if you've cast another spell this turn"; } public CastOnlyIfYouHaveCastAnotherSpellEffect(final CastOnlyIfYouHaveCastAnotherSpellEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/TargetsHaveToTargetPermanentIfAbleEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/TargetsHaveToTargetPermanentIfAbleEffect.java index 833badab0f4..944262e9acc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/TargetsHaveToTargetPermanentIfAbleEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/TargetsHaveToTargetPermanentIfAbleEffect.java @@ -23,8 +23,8 @@ import mage.players.Player; import mage.target.Target; /** - * 6/8/2016 If a spell or ability’s targets are changed, or if a copy of a spell - * or ability is put onto the stack and has new targets chosen, it doesn’t have + * 6/8/2016 If a spell or ability's targets are changed, or if a copy of a spell + * or ability is put onto the stack and has new targets chosen, it doesn't have * to target a Flagbearer. * * 3/16/2017 A Flagbearer only requires targeting of itself when choosing targets diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java index 1128fd4550e..2a4f1f90cca 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchTargetGraveyardHandLibraryForCardNameAndExileEffect.java @@ -26,7 +26,7 @@ public abstract class SearchTargetGraveyardHandLibraryForCardNameAndExileEffect protected String searchForText; /* Slaughter Games - * 10/1/2012: You can leave any cards with that name in the zone they are in. You don’t have to exile them. + * 10/1/2012: You can leave any cards with that name in the zone they are in. You don't have to exile them. * * Sowing Salt * 2/1/2005: The copies must be found if they are in publicly viewable zones. Finding copies while searching private zones is optional. diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java new file mode 100644 index 00000000000..e2d20da03b4 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/keyword/EchoEffect.java @@ -0,0 +1,94 @@ +package mage.abilities.effects.keyword; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.OneShotEffect; +import mage.constants.AsThoughEffectType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.Locale; + +public class EchoEffect extends OneShotEffect { + + protected Cost cost; + protected DynamicValue amount; + + public EchoEffect(Cost costs) { + super(Outcome.Sacrifice); + this.cost = costs; + this.amount = null; + } + + public EchoEffect(DynamicValue amount) { + super(Outcome.Sacrifice); + this.amount = amount; + this.cost = null; + } + + public EchoEffect(final EchoEffect effect) { + super(effect); + this.cost = effect.cost; + this.amount = effect.amount; + } + + @Override + public boolean apply(Game game, Ability source) { + if (cost == null) { + cost = new ManaCostsImpl(Integer.toString(amount.calculate(game, source, this))); + } + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && source.getSourceObjectIfItStillExists(game) != null) { + if (game.getContinuousEffects().asThough(source.getSourceId(), AsThoughEffectType.PAY_0_ECHO, source, source.getControllerId(), game) != null) { + Cost altCost = new ManaCostsImpl("{0}"); + if (controller.chooseUse(Outcome.Benefit, "Pay {0} instead of the echo cost?", source, game)) { + altCost.clearPaid(); + if (altCost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ECHO_PAID, source.getSourceId(), source.getSourceId(), source.getControllerId())); + return true; + } + } + } + if (controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + '?', source, game)) { + cost.clearPaid(); + if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ECHO_PAID, source.getSourceId(), source.getSourceId(), source.getControllerId())); + return true; + } + } + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + permanent.sacrifice(source.getSourceId(), game); + } + return true; + } + return false; + } + + @Override + public EchoEffect copy() { + return new EchoEffect(this); + } + + @Override + public String getText(Mode mode) { + StringBuilder sb = new StringBuilder("sacrifice {this} unless you "); + String costText = cost.getText(); + if (costText.toLowerCase(Locale.ENGLISH).startsWith("discard")) { + sb.append(costText.substring(0, 1).toLowerCase(Locale.ENGLISH)); + sb.append(costText.substring(1)); + } else { + sb.append("pay ").append(costText); + } + + return sb.toString(); + + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/InvestigateEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/InvestigateEffect.java index 395b4fb37b2..5f0aaf40644 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/InvestigateEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/InvestigateEffect.java @@ -19,7 +19,7 @@ public class InvestigateEffect extends CreateTokenEffect { public InvestigateEffect() { super(new ClueArtifactToken()); - this.staticText = "Investigate. (Create a colorless Clue artifact token onto the battlefield with \"{2}, Sacrifice this artifact: Draw a card.\")"; + this.staticText = "Investigate. (Create a colorless Clue artifact token with \"{2}, Sacrifice this artifact: Draw a card.\")"; } public InvestigateEffect(final InvestigateEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/mana/AddManaOfAnyColorEffect.java b/Mage/src/main/java/mage/abilities/effects/mana/AddManaOfAnyColorEffect.java index 8170ed8ebe8..ae568822690 100644 --- a/Mage/src/main/java/mage/abilities/effects/mana/AddManaOfAnyColorEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/mana/AddManaOfAnyColorEffect.java @@ -1,6 +1,7 @@ - package mage.abilities.effects.mana; +import java.util.ArrayList; +import java.util.List; import mage.Mana; import mage.abilities.Ability; import mage.choices.ChoiceColor; @@ -13,25 +14,28 @@ import mage.util.CardUtil; */ public class AddManaOfAnyColorEffect extends BasicManaEffect { - protected int amount; + protected final int amount; + protected final ArrayList netMana = new ArrayList<>(); public AddManaOfAnyColorEffect() { this(1); } - public AddManaOfAnyColorEffect(final int amount) { + public AddManaOfAnyColorEffect(int amount) { super(new Mana(0, 0, 0, 0, 0, 0, amount, 0)); this.amount = amount; - this.staticText = new StringBuilder("add ") - .append(CardUtil.numberToText(amount)) - .append(" mana of any ") - .append(amount > 1 ? "one " : "") - .append("color").toString(); + 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)); + this.staticText = "add " + CardUtil.numberToText(amount) + " mana of any " + (amount > 1 ? "one " : "") + "color"; } public AddManaOfAnyColorEffect(final AddManaOfAnyColorEffect effect) { super(effect); this.amount = effect.amount; + this.netMana.addAll(effect.netMana); } @Override @@ -41,23 +45,32 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.getManaPool().addMana(getMana(game, source), game, source); + return true; + } + 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()); if (controller != null) { String mes = String.format("Select color of %d mana to add it", this.amount); ChoiceColor choice = new ChoiceColor(true, mes, game.getObject(source.getSourceId())); if (controller.choose(outcome, choice, game)) { - if (choice.getColor() == null) { - return false; + if (choice.getColor() != null) { + return choice.getMana(amount); } - Mana createdMana = choice.getMana(amount); - if (createdMana != null) { - checkToFirePossibleEvents(createdMana, game, source); - controller.getManaPool().addMana(createdMana, game, source); - } - return true; } } - return false; + return null; } public int getAmount() { diff --git a/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java b/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java index ef351303bff..8e443916432 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java @@ -69,7 +69,7 @@ class AuraSwapEffect extends OneShotEffect { Permanent auraSourcePermanent = game.getPermanent(source.getSourceId()); if (auraSourcePermanent != null && auraSourcePermanent.hasSubtype(SubType.AURA, game) - && auraSourcePermanent.getOwnerId().equals(source.getControllerId())) { + && auraSourcePermanent.isOwnedBy(source.getControllerId())) { Permanent enchantedPermanent = game.getPermanent(auraSourcePermanent.getAttachedTo()); filterCardToCheck.add(new AuraCardCanAttachToPermanentId(enchantedPermanent.getId())); TargetCardInHand target = new TargetCardInHand(filterCardToCheck); diff --git a/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java b/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java new file mode 100644 index 00000000000..a40d3de2f53 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java @@ -0,0 +1,107 @@ +package mage.abilities.keyword; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +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.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; + +/** + * + * @author Plopman + */ +public class CommanderStormAbility extends TriggeredAbilityImpl { + + public CommanderStormAbility() { + super(Zone.STACK, new CommanderStormEffect()); + this.ruleAtTheTop = true; + } + + private CommanderStormAbility(final CommanderStormAbility ability) { + super(ability); + } + + @Override + public CommanderStormAbility copy() { + return new CommanderStormAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getSourceId().equals(getSourceId())) { + StackObject spell = game.getStack().getStackObject(getSourceId()); + if (spell instanceof Spell) { + for (Effect effect : this.getEffects()) { + effect.setValue("StormSpell", spell); + effect.setValue("StormSpellRef", new MageObjectReference(spell.getId(), game)); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "When you cast this spell, copy it for each time you've " + + "cast your commander from the command zone this game. " + + "You may choose new targets for the copies."; + } +} + +class CommanderStormEffect extends OneShotEffect { + + public CommanderStormEffect() { + super(Outcome.Copy); + } + + public CommanderStormEffect(final CommanderStormEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + MageObjectReference spellRef = (MageObjectReference) this.getValue("StormSpellRef"); + if (spellRef == null) { + return false; + } + int stormCount = 0; + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + stormCount = player.getCommandersIds().stream().map( + (commanderId) -> (Integer) game.getState().getValue(commanderId + "_castCount") + ).map((castCount) -> castCount).reduce(stormCount, Integer::sum); + if (stormCount == 0) { + return true; + } + Spell spell = (Spell) this.getValue("StormSpell"); + if (spell == null) { + return false; + } + game.informPlayers(spell.getLogName() + " will be copied " + stormCount + " time" + (stormCount > 1 ? "s" : "")); + for (int i = 0; i < stormCount; i++) { + spell.createCopyOnStack(game, source, source.getControllerId(), true); + } + return true; + } + + @Override + public CommanderStormEffect copy() { + return new CommanderStormEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java b/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java index 406498f5a36..212d940a9fa 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ConspireAbility.java @@ -42,7 +42,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate; * you may tap two untapped creatures you control that each share a color with it" * and "When you cast this spell, if its conspire cost was paid, copy it. * If the spell has any targets, you may choose new targets for the copy." - * Paying a spell’s conspire cost follows the rules for paying additional costs in rules 601.2b and 601.2e–g. + * Paying a spell's conspire cost follows the rules for paying additional costs in rules 601.2b and 601.2e–g. * 702.77b If a spell has multiple instances of conspire, each is paid separately and triggers * based on its own payment, not any other instance of conspire. * * diff --git a/Mage/src/main/java/mage/abilities/keyword/CumulativeUpkeepAbility.java b/Mage/src/main/java/mage/abilities/keyword/CumulativeUpkeepAbility.java index f7622a09815..546de34cf26 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CumulativeUpkeepAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CumulativeUpkeepAbility.java @@ -16,6 +16,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.events.ManaEvent; import mage.game.permanent.Permanent; import mage.players.Player; @@ -84,7 +85,7 @@ class CumulativeUpkeepEffect extends OneShotEffect { if (player.chooseUse(Outcome.Benefit, "Pay " + totalCost.getText() + '?', source, game)) { totalCost.clearPaid(); if (totalCost.payOrRollback(source, game, source.getSourceId(), source.getControllerId())) { - game.fireEvent(new GameEvent(EventType.PAID_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), ageCounter, false)); + game.fireEvent(new ManaEvent(EventType.PAID_CUMULATIVE_UPKEEP, permanent.getId(), permanent.getId(), player.getId(), totalCost.getUsedManaToPay())); return true; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/DelveAbility.java b/Mage/src/main/java/mage/abilities/keyword/DelveAbility.java index 0639f19bbfd..68055acec90 100644 --- a/Mage/src/main/java/mage/abilities/keyword/DelveAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/DelveAbility.java @@ -27,20 +27,20 @@ import mage.util.CardUtil; /** * 702.65. Delve 702.65a Delve is a static ability that functions while the * spell with delve is on the stack. “Delve” means “For each generic mana in - * this spell’s total cost, you may exile a card from your graveyard rather than + * this spell's total cost, you may exile a card from your graveyard rather than * pay that mana.” The delve ability isn't an additional or alternative cost and * applies only after the total cost of the spell with delve is determined. * 702.65b Multiple instances of delve on the same spell are redundant. * * The rules for delve have changed slightly since it was last in an expansion. * Previously, delve reduced the cost to cast a spell. Under the current rules, - * you exile cards from your graveyard at the same time you pay the spell’s + * you exile cards from your graveyard at the same time you pay the spell's * cost. Exiling a card this way is simply another way to pay that cost. * Delve - * doesn't change a spell’s mana cost or converted mana cost. For example, Dead - * Drop’s converted mana cost is 10 even if you exiled three cards to cast it. * - * You can’t exile cards to pay for the colored mana requirements of a spell - * with delve. * You can’t exile more cards than the generic mana requirement of - * a spell with delve. For example, you can’t exile more than nine cards from + * doesn't change a spell's mana cost or converted mana cost. For example, Dead + * Drop's converted mana cost is 10 even if you exiled three cards to cast it. * + * You can't exile cards to pay for the colored mana requirements of a spell + * with delve. * You can't exile more cards than the generic mana requirement of + * a spell with delve. For example, you can't exile more than nine cards from * your graveyard to cast Dead Drop. * Because delve isn't an alternative cost, * it can be used in conjunction with alternative costs. * diff --git a/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java b/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java index 58a054e63e8..afdda45c0de 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java @@ -1,23 +1,18 @@ package mage.abilities.keyword; -import java.util.Locale; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; +import mage.abilities.effects.keyword.EchoEffect; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; + +import java.util.UUID; /** * @@ -82,7 +77,7 @@ public class EchoAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - // reset the echo paid state back, if creature enteres the battlefield + // reset the echo paid state back, if creature enters the battlefield if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId())) { @@ -128,70 +123,3 @@ public class EchoAbility extends TriggeredAbilityImpl { } } -class EchoEffect extends OneShotEffect { - - protected Cost cost; - protected DynamicValue amount; - - public EchoEffect(Cost costs) { - super(Outcome.Sacrifice); - this.cost = costs; - this.amount = null; - } - - public EchoEffect(DynamicValue amount) { - super(Outcome.Sacrifice); - this.amount = amount; - this.cost = null; - } - - public EchoEffect(final EchoEffect effect) { - super(effect); - this.cost = effect.cost; - this.amount = effect.amount; - } - - @Override - public boolean apply(Game game, Ability source) { - if (amount != null) { - cost = new ManaCostsImpl(Integer.toString(amount.calculate(game, source, this))); - } - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null - && source.getSourceObjectIfItStillExists(game) != null) { - if (controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + '?', source, game)) { - cost.clearPaid(); - if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ECHO_PAID, source.getSourceId(), source.getSourceId(), source.getControllerId())); - return true; - } - } - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - return true; - } - return false; - } - - @Override - public EchoEffect copy() { - return new EchoEffect(this); - } - - @Override - public String getText(Mode mode) { - StringBuilder sb = new StringBuilder("sacrifice {this} unless you "); - String costText = cost.getText(); - if (costText.toLowerCase(Locale.ENGLISH).startsWith("discard")) { - sb.append(costText.substring(0, 1).toLowerCase(Locale.ENGLISH)); - sb.append(costText.substring(1)); - } else { - sb.append("pay ").append(costText); - } - - return sb.toString(); - - } -} diff --git a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java index 16faaa9763d..6495c39ceca 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java @@ -1,9 +1,10 @@ - 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; @@ -19,28 +20,20 @@ import mage.target.common.TargetControlledCreaturePermanent; */ public class EquipAbility extends ActivatedAbilityImpl { + public EquipAbility(int cost) { + this(Outcome.AddAbility, new GenericManaCost(cost)); + } + public EquipAbility(Outcome outcome, Cost cost) { this(outcome, cost, new TargetControlledCreaturePermanent()); } public EquipAbility(Outcome outcome, Cost cost, Target target) { - super(Zone.BATTLEFIELD, new AttachEffect(outcome, "Equip"), cost); + super(Zone.BATTLEFIELD, new EquipEffect(outcome), cost); this.addTarget(target); this.timing = TimingRule.SORCERY; } - @Override - public ActivationStatus canActivate(UUID playerId, Game game) { - ActivationStatus activationStatus = super.canActivate(playerId, game); - if (activationStatus.canActivate()) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && permanent.hasSubtype(SubType.EQUIPMENT, game)) { - return activationStatus; - } - } - return activationStatus; - } - public EquipAbility(final EquipAbility ability) { super(ability); } diff --git a/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java index 2467d1246e5..ab0f8004b1e 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java @@ -16,7 +16,7 @@ import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.Card; import mage.constants.Outcome; @@ -42,7 +42,7 @@ public class EvokeAbility extends StaticAbility implements AlternativeSourceCost super(Zone.ALL, null); name = EVOKE_KEYWORD; this.addEvokeCost(manaString); - Ability ability = new ConditionalTriggeredAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect()), EvokedCondition.instance, "Sacrifice {this} when it enters the battlefield and was evoked."); + Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect()), EvokedCondition.instance, "Sacrifice {this} when it enters the battlefield and was evoked."); ability.setRuleVisible(false); addSubAbility(ability); diff --git a/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java b/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java index 66d3f4f063c..7e2183feb28 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EvolveAbility.java @@ -84,7 +84,7 @@ public class EvolveAbility extends TriggeredAbilityImpl { Permanent triggeringCreature = game.getPermanent(event.getTargetId()); if (triggeringCreature != null && triggeringCreature.isCreature() - && triggeringCreature.getControllerId().equals(this.controllerId)) { + && triggeringCreature.isControlledBy(this.controllerId)) { Permanent sourceCreature = game.getPermanent(sourceId); if (sourceCreature != null && isPowerOrThoughnessGreater(sourceCreature, triggeringCreature)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage/src/main/java/mage/abilities/keyword/ExaltedAbility.java b/Mage/src/main/java/mage/abilities/keyword/ExaltedAbility.java index 2f89fa3dcd7..1fe2febcd42 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ExaltedAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ExaltedAbility.java @@ -35,7 +35,7 @@ public class ExaltedAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.isActivePlayer(this.controllerId)) { if (game.getCombat().attacksAlone()) { this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getCombat().getAttackers().get(0))); return true; diff --git a/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java b/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java index 2a8ec6fc76f..9bc38f8a203 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FadingAbility.java @@ -15,7 +15,7 @@ import mage.game.permanent.Permanent; /* * 702.31. Fading * - * 702.31a Fading is a keyword that represents two abilities. “Fading N” means “This permanent enters the battlefield with N fade counters on it” and “At the beginning of your upkeep, remove a fade counter from this permanent. If you can’t, sacrifice the permanent.” + * 702.31a Fading is a keyword that represents two abilities. “Fading N” means “This permanent enters the battlefield with N fade counters on it” and “At the beginning of your upkeep, remove a fade counter from this permanent. If you can't, sacrifice the permanent.” * */ public class FadingAbility extends EntersBattlefieldAbility { @@ -28,7 +28,7 @@ public class FadingAbility extends EntersBattlefieldAbility { 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."; + + " 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) { @@ -51,7 +51,7 @@ class FadingEffect extends OneShotEffect { FadingEffect() { super(Outcome.Sacrifice); - staticText = "remove a fade counter from this permanent. If you can’t, sacrifice the permanent"; + staticText = "remove a fade counter from this permanent. If you can't, sacrifice the permanent"; } FadingEffect(final FadingEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java b/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java index db20407e78e..5e411a5c370 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java @@ -45,7 +45,7 @@ public class ForecastAbility extends LimitedTimesPerTurnActivatedAbility { public ActivationStatus canActivate(UUID playerId, Game game) { // May be activated only during the upkeep step of the card's owner // Because it can only be activated from a players hand it should be ok to check here with controllerId instead of card.getOwnerId(). - if (!game.getActivePlayerId().equals(controllerId) || PhaseStep.UPKEEP != game.getStep().getType()) { + if (!game.isActivePlayer(controllerId) || PhaseStep.UPKEEP != game.getStep().getType()) { return ActivationStatus.getFalse(); } return super.canActivate(playerId, game); diff --git a/Mage/src/main/java/mage/abilities/keyword/FortifyAbility.java b/Mage/src/main/java/mage/abilities/keyword/FortifyAbility.java index 95c2e7be559..748c53cf811 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FortifyAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FortifyAbility.java @@ -2,13 +2,23 @@ package mage.abilities.keyword; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.FortifyEffect; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.TimingRule; import mage.constants.Zone; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.Cost; import mage.abilities.effects.common.AttachEffect; import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** * @@ -17,10 +27,19 @@ import mage.target.TargetPermanent; //20091005 - 702.64 public class FortifyAbility extends ActivatedAbilityImpl { - public FortifyAbility(Zone zone, AttachEffect effect, Cost cost) { - super(zone, effect, cost); - this.addTarget(new TargetPermanent(new FilterControlledLandPermanent())); - timing = TimingRule.SORCERY; + + public FortifyAbility(int cost) { + this(Outcome.AddAbility, new GenericManaCost(cost)); + } + + public FortifyAbility(Outcome outcome, Cost cost) { + this(outcome, cost, new TargetPermanent(new FilterControlledLandPermanent())); + } + + public FortifyAbility(Outcome outcome, Cost cost, Target target) { + super(Zone.BATTLEFIELD, new FortifyEffect(outcome), cost); + this.addTarget(target); + this.timing = TimingRule.SORCERY; } public FortifyAbility(final FortifyAbility ability) { @@ -31,4 +50,10 @@ public class FortifyAbility extends ActivatedAbilityImpl { public FortifyAbility copy() { return new FortifyAbility(this); } + + + @Override + public String getRule() { + return "Fortify " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": Attach to target land you control. Fortify only as a sorcery.)"; + } } \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java b/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java index 28fab9980a2..2d0c6829bf4 100644 --- a/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java @@ -140,7 +140,7 @@ class HideawayLookAtFaceDownCardEffect extends AsThoughEffectImpl { // TODO: Does not handle if a player had the control of the land permanent some time before // we would need to add a watcher to handle this Permanent sourcePermanet = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (sourcePermanet != null && sourcePermanet.getControllerId().equals(affectedControllerId)) { + if (sourcePermanet != null && sourcePermanet.isControlledBy(affectedControllerId)) { ExileZone exile = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); Card card = game.getCard(objectId); if (exile != null && exile.contains(objectId) && card != null) { diff --git a/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java b/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java index 39522121f52..a3ea9163adc 100644 --- a/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/KickerAbility.java @@ -1,7 +1,7 @@ - package mage.abilities.keyword; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; @@ -14,6 +14,7 @@ import mage.constants.AbilityType; import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; +import mage.game.events.GameEvent; import mage.players.Player; /** @@ -51,7 +52,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo protected static final String KICKER_REMINDER_MANA = "You may pay an additional {cost} as you cast this spell."; protected static final String KICKER_REMINDER_COST = "You may {cost} in addition to any other costs as you cast this spell."; - protected Map activations = new HashMap<>(); // zoneChangeCounter, activations + protected Map activations = new ConcurrentHashMap<>(); // zoneChangeCounter, activations protected String keywordText; protected String reminderText; @@ -152,6 +153,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo amount += activations.get(key); } activations.put(key, amount); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.KICKED, source.getSourceId(), source.getSourceId(), source.getControllerId())); } private String getActivationKey(Ability source, String costText, Game game) { diff --git a/Mage/src/main/java/mage/abilities/keyword/MonstrosityAbility.java b/Mage/src/main/java/mage/abilities/keyword/MonstrosityAbility.java index f613b88586d..d194f74e974 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MonstrosityAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MonstrosityAbility.java @@ -21,23 +21,23 @@ import mage.util.CardUtil; * * 701.28. Monstrosity * - * 701.28a “Monstrosity N” means “If this permanent isn’t monstrous, put N +1/+1 counters on it + * 701.28a “Monstrosity N” means “If this permanent isn't monstrous, put N +1/+1 counters on it * and it becomes monstrous.” Monstrous is a condition of that permanent that can be * referred to by other abilities. * - * 701.28b If a permanent’s ability instructs a player to “monstrosity X,” other abilities of + * 701.28b If a permanent's ability instructs a player to “monstrosity X,” other abilities of * that permanent may also refer to X. The value of X in those abilities is equal to * the value of X as that permanent became monstrous. * - * * Once a creature becomes monstrous, it can’t become monstrous again. If the creature + * * Once a creature becomes monstrous, it can't become monstrous again. If the creature * is already monstrous when the monstrosity ability resolves, nothing happens. * - * * Monstrous isn’t an ability that a creature has. It’s just something true about that + * * Monstrous isn't an ability that a creature has. It's just something true about that * creature. If the creature stops being a creature or loses its abilities, it will * continue to be monstrous. * - * * An ability that triggers when a creature becomes monstrous won’t trigger if that creature - * isn’t on the battlefield when its monstrosity ability resolves. + * * An ability that triggers when a creature becomes monstrous won't trigger if that creature + * isn't on the battlefield when its monstrosity ability resolves. * * @author LevelX2 */ diff --git a/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java b/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java index 4eb32f5c561..5737f0b50b0 100644 --- a/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import java.util.UUID; @@ -16,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.UnblockedPredicate; import mage.game.Game; +import mage.game.command.CommandObject; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetControlledCreaturePermanent; @@ -43,6 +43,7 @@ import mage.target.common.TargetControlledPermanent; */ public class NinjutsuAbility extends ActivatedAbilityImpl { + private final boolean commander; private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("unblocked attacker you control"); static { @@ -54,13 +55,19 @@ public class NinjutsuAbility extends ActivatedAbilityImpl { * @param manaCost ninjutsu mana cost */ public NinjutsuAbility(ManaCost manaCost) { - super(Zone.HAND, new NinjutsuEffect(), manaCost); - this.addCost(new RevealNinjutsuCardCost()); + this(manaCost, false); + } + + public NinjutsuAbility(ManaCost manaCost, boolean commander) { + super(commander ? Zone.ALL : Zone.HAND, new NinjutsuEffect(), manaCost); + this.addCost(new RevealNinjutsuCardCost(commander)); this.addCost(new ReturnAttackerToHandTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); + this.commander = commander; } public NinjutsuAbility(NinjutsuAbility ability) { super(ability); + this.commander = ability.commander; } @Override @@ -70,9 +77,13 @@ public class NinjutsuAbility extends ActivatedAbilityImpl { @Override public String getRule() { - return new StringBuilder("Ninjutsu ").append(getManaCostsToPay().getText()).append(" (") - .append(getManaCostsToPay().getText()) - .append(" Return an unblocked attacker you control to hand: Put this card onto the battlefield from your hand tapped and attacking.)").toString(); + return (commander ? "Commander n" : "N") + "injutsu " + + getManaCostsToPay().getText() + " (" + + getManaCostsToPay().getText() + + " Return an unblocked attacker you control to hand: " + + "Put this card onto the battlefield from your hand" + + (commander ? " or the command zone " : " ") + + "tapped and attacking.)"; } } @@ -80,7 +91,8 @@ class NinjutsuEffect extends OneShotEffect { public NinjutsuEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Put this card onto the battlefield from your hand tapped and attacking"; + this.staticText = "Put this card onto the battlefield " + + "from your hand tapped and attacking"; } public NinjutsuEffect(final NinjutsuEffect effect) { @@ -165,12 +177,16 @@ class ReturnAttackerToHandTargetCost extends CostImpl { class RevealNinjutsuCardCost extends CostImpl { - public RevealNinjutsuCardCost() { + private final boolean commander; + + public RevealNinjutsuCardCost(boolean commander) { this.text = "reveal ninjutsu card"; + this.commander = commander; } public RevealNinjutsuCardCost(RevealNinjutsuCardCost cost) { super(cost); + this.commander = cost.commander; } @Override @@ -178,6 +194,15 @@ class RevealNinjutsuCardCost extends CostImpl { Player player = game.getPlayer(controllerId); Card card = player.getHand().get(ability.getSourceId(), game); + if (card == null && commander + && player.getCommandersIds().contains(ability.getSourceId())) { + for (CommandObject coj : game.getState().getCommand()) { + if (coj != null && coj.getId().equals(ability.getSourceId())) { + card = game.getCard(ability.getSourceId()); + } + break; + } + } if (card != null) { Cards cards = new CardsImpl(card); player.revealCards("Ninjutsu", cards, game); diff --git a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java index b32005c0537..9a1de9fd982 100644 --- a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java @@ -107,7 +107,7 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game) { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(sourceId); - if (!card.getOwnerId().equals(source.getControllerId())) { + if (!card.isOwnedBy(source.getControllerId())) { return false; } // because can activate is always called twice, result from first call will be used diff --git a/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java b/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java index c8e5a4d6be6..c6bac07f934 100644 --- a/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/RecoverAbility.java @@ -18,7 +18,7 @@ import mage.players.Player; /** * 702.58a Recover is a triggered ability that functions only while the card - * with recover is in a player’s graveyard. “Recover [cost]” means “When a + * with recover is in a player's graveyard. “Recover [cost]” means “When a * creature is put into your graveyard from the battlefield, you may pay [cost]. * If you do, return this card from your graveyard to your hand. Otherwise, * exile this card.” @@ -49,7 +49,7 @@ public class RecoverAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { - if (zEvent.getTarget().getOwnerId().equals(getControllerId()) + if (zEvent.getTarget().isOwnedBy(getControllerId()) && zEvent.getTarget().isCreature() && !zEvent.getTarget().getId().equals(getSourceId())) { return true; diff --git a/Mage/src/main/java/mage/abilities/keyword/RepairAbility.java b/Mage/src/main/java/mage/abilities/keyword/RepairAbility.java index 46e22d57fa8..5a270a4d9e6 100644 --- a/Mage/src/main/java/mage/abilities/keyword/RepairAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/RepairAbility.java @@ -11,7 +11,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.condition.common.SourceHasCounterCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -36,7 +36,7 @@ public class RepairAbility extends DiesTriggeredAbility { public RepairAbility(int count) { super(new AddCountersSourceEffect(CounterType.REPAIR.createInstance(), new StaticValue(count), false, true)); - addSubAbility(new RepairBeginningOfUpkeepTriggeredAbility()); + addSubAbility(new RepairBeginningOfUpkeepInterveningIfTriggeredAbility()); addSubAbility(new RepairCastFromGraveyardTriggeredAbility()); ruleText = "Repair " + count + " (When this creature dies, put " + count @@ -84,7 +84,7 @@ class RepairCastFromGraveyardEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId); + return source.isControlledBy(affectedControllerId); } } @@ -127,9 +127,9 @@ class RepairCastFromGraveyardTriggeredAbility extends TriggeredAbilityImpl { } } -class RepairBeginningOfUpkeepTriggeredAbility extends ConditionalTriggeredAbility { +class RepairBeginningOfUpkeepInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { - public RepairBeginningOfUpkeepTriggeredAbility() { + public RepairBeginningOfUpkeepInterveningIfTriggeredAbility() { super(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new RemoveCounterSourceEffect(CounterType.REPAIR.createInstance()), TargetController.YOU, false), new SourceHasCounterCondition(CounterType.REPAIR), "At the beginning of your upkeep, remove a repair counter from {this}"); @@ -137,12 +137,12 @@ class RepairBeginningOfUpkeepTriggeredAbility extends ConditionalTriggeredAbilit } - public RepairBeginningOfUpkeepTriggeredAbility(final RepairBeginningOfUpkeepTriggeredAbility effect) { + public RepairBeginningOfUpkeepInterveningIfTriggeredAbility(final RepairBeginningOfUpkeepInterveningIfTriggeredAbility effect) { super(effect); } @Override - public RepairBeginningOfUpkeepTriggeredAbility copy() { - return new RepairBeginningOfUpkeepTriggeredAbility(this); + public RepairBeginningOfUpkeepInterveningIfTriggeredAbility copy() { + return new RepairBeginningOfUpkeepInterveningIfTriggeredAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/keyword/ScavengeAbility.java b/Mage/src/main/java/mage/abilities/keyword/ScavengeAbility.java index dc5f28fdc18..a83256e7743 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ScavengeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ScavengeAbility.java @@ -28,7 +28,7 @@ import mage.target.common.TargetCreaturePermanent; // // 702.95a Scavenge is an activated ability that functions only while the card // with scavenge is in a graveyard. "Scavenge [cost]" means "[Cost], Exile this -// card from your graveyard: Put a number of +1/+1 counters equal to this card’s +// card from your graveyard: Put a number of +1/+1 counters equal to this card's // power on target creature. Activate this ability only any time you could cast // a sorcery." // diff --git a/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java b/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java index a84782d2b4d..da422af6d8f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SoulbondAbility.java @@ -48,9 +48,9 @@ import mage.util.GameLog; * 702.94d A creature can be paired with only one other creature. * * 702.94e A paired creature becomes unpaired if any of the following occur: - * another player gains control of it or the creature it’s paired with; it or - * the creature it’s paired with stops being a creature; or it or the creature - * it’s paired with leaves the battlefield. + * another player gains control of it or the creature it's paired with; it or + * the creature it's paired with stops being a creature; or it or the creature + * it's paired with leaves the battlefield. * * @author LevelX2 */ @@ -78,7 +78,7 @@ public class SoulbondAbility extends EntersBattlefieldTriggeredAbility { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(getControllerId())) { if (permanent.isCreature()) { if (permanent.getId().equals(getSourceId())) { - if (permanent.getControllerId().equals(getControllerId())) { + if (permanent.isControlledBy(getControllerId())) { self = true; if (other) { return true; @@ -195,7 +195,7 @@ class SoulbondEntersOtherAbility extends EntersBattlefieldAllTriggeredAbility { // if you control both this creature and another creature and both are unpaired if (game.getBattlefield().countAll(filter, getControllerId(), game) > 0) { Permanent sourcePermanent = game.getPermanent(getSourceId()); - if (sourcePermanent != null && sourcePermanent.getControllerId().equals(getControllerId()) && sourcePermanent.getPairedCard() == null) { + if (sourcePermanent != null && sourcePermanent.isControlledBy(getControllerId()) && sourcePermanent.getPairedCard() == null) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/StormAbility.java b/Mage/src/main/java/mage/abilities/keyword/StormAbility.java index fd4f4f5791d..45b99a4ab62 100644 --- a/Mage/src/main/java/mage/abilities/keyword/StormAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/StormAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import mage.MageObjectReference; @@ -14,6 +13,7 @@ import mage.game.events.GameEvent.EventType; import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.watchers.common.CastSpellLastTurnWatcher; +import org.apache.log4j.Logger; /** * @@ -75,17 +75,21 @@ class StormEffect extends OneShotEffect { MageObjectReference spellRef = (MageObjectReference) this.getValue("StormSpellRef"); if (spellRef != null) { CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getSimpleName()); - int stormCount = watcher.getSpellOrder(spellRef, game) - 1; - if (stormCount > 0) { - Spell spell = (Spell) this.getValue("StormSpell"); - if (spell != null) { - if (!game.isSimulation()) { - game.informPlayers("Storm: " + spell.getLogName() + " will be copied " + stormCount + " time" + (stormCount > 1 ? "s" : "")); - } - for (int i = 0; i < stormCount; i++) { - spell.createCopyOnStack(game, source, source.getControllerId(), true); + if (watcher != null) { + int stormCount = watcher.getSpellOrder(spellRef, game) - 1; + if (stormCount > 0) { + Spell spell = (Spell) this.getValue("StormSpell"); + if (spell != null) { + if (!game.isSimulation()) { + game.informPlayers("Storm: " + spell.getLogName() + " will be copied " + stormCount + " time" + (stormCount > 1 ? "s" : "")); + } + for (int i = 0; i < stormCount; i++) { + spell.createCopyOnStack(game, source, source.getControllerId(), true); + } } } + } else { + Logger.getLogger(StormEffect.class).fatal("CastSpellLastTurnWatcher not found. game = " + game == null ? "NULL" : game.getGameType().toString()); } return true; } diff --git a/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java b/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java index fd817165fdf..7c4d3afdc43 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java @@ -14,7 +14,7 @@ import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.VariableManaCost; -import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; @@ -82,7 +82,7 @@ import mage.target.targetpointer.FixedTarget; * play the spell if possible, even if that player doesn't want to. Normal * timing considerations for the spell are ignored (for example, if the * suspended card is a creature and this ability resolves during your upkeep, - * you’re able to play the card), but other play restrictions are not ignored. + * you're able to play the card), but other play restrictions are not ignored. * * If the second triggered ability of suspend resolves and the suspended card * can't be played due to a lack of legal targets or a play restriction, for @@ -154,7 +154,7 @@ public class SuspendAbility extends SpecialAction { if (card.getManaCost().isEmpty()) { setRuleAtTheTop(true); } - addSubAbility(new SuspendBeginningOfUpkeepTriggeredAbility()); + addSubAbility(new SuspendBeginningOfUpkeepInterveningIfTriggeredAbility()); addSubAbility(new SuspendPlayCardAbility()); } ruleText = sb.toString(); @@ -174,7 +174,7 @@ public class SuspendAbility extends SpecialAction { ability.setControllerId(card.getOwnerId()); game.getState().addOtherAbility(card, ability); - SuspendBeginningOfUpkeepTriggeredAbility ability1 = new SuspendBeginningOfUpkeepTriggeredAbility(); + SuspendBeginningOfUpkeepInterveningIfTriggeredAbility ability1 = new SuspendBeginningOfUpkeepInterveningIfTriggeredAbility(); ability1.setSourceId(card.getId()); ability1.setControllerId(card.getOwnerId()); game.getState().addOtherAbility(card, ability1); @@ -343,7 +343,7 @@ class SuspendPlayCardEffect extends OneShotEffect { } if (!abilitiesToRemove.isEmpty()) { for (Ability ability : card.getAbilities()) { - if (ability instanceof SuspendBeginningOfUpkeepTriggeredAbility || ability instanceof SuspendPlayCardAbility) { + if (ability instanceof SuspendBeginningOfUpkeepInterveningIfTriggeredAbility || ability instanceof SuspendPlayCardAbility) { abilitiesToRemove.add(ability); } } @@ -405,9 +405,9 @@ class GainHasteEffect extends ContinuousEffectImpl { } -class SuspendBeginningOfUpkeepTriggeredAbility extends ConditionalTriggeredAbility { +class SuspendBeginningOfUpkeepInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { - public SuspendBeginningOfUpkeepTriggeredAbility() { + public SuspendBeginningOfUpkeepInterveningIfTriggeredAbility() { super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), TargetController.YOU, false), SuspendedCondition.instance, "At the beginning of your upkeep, if this card ({this}) is suspended, remove a time counter from it."); @@ -415,12 +415,12 @@ class SuspendBeginningOfUpkeepTriggeredAbility extends ConditionalTriggeredAbili } - public SuspendBeginningOfUpkeepTriggeredAbility(final SuspendBeginningOfUpkeepTriggeredAbility effect) { + public SuspendBeginningOfUpkeepInterveningIfTriggeredAbility(final SuspendBeginningOfUpkeepInterveningIfTriggeredAbility effect) { super(effect); } @Override - public SuspendBeginningOfUpkeepTriggeredAbility copy() { - return new SuspendBeginningOfUpkeepTriggeredAbility(this); + public SuspendBeginningOfUpkeepInterveningIfTriggeredAbility copy() { + return new SuspendBeginningOfUpkeepInterveningIfTriggeredAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/keyword/TransmuteAbility.java b/Mage/src/main/java/mage/abilities/keyword/TransmuteAbility.java index fc6f979b3bf..f0143e4f0fc 100644 --- a/Mage/src/main/java/mage/abilities/keyword/TransmuteAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/TransmuteAbility.java @@ -23,14 +23,14 @@ import mage.target.common.TargetCardInLibrary; * 702.52. Transmute * * 702.52a Transmute is an activated ability that functions only while the card - * with transmute is in a player’s hand. “Transmute [cost]” means “[Cost], + * with transmute is in a player's hand. “Transmute [cost]” means “[Cost], * Discard this card: Search your library for a card with the same converted * mana cost as the discarded card, reveal that card, and put it into your hand. * Then shuffle your library. Play this ability only any time you could play a * sorcery.” * * 702.52b Although the transmute ability is playable only if the card is in a - * player’s hand, it continues to exist while the object is in play and in all + * player's hand, it continues to exist while the object is in play and in all * other zones. Therefore objects with transmute will be affected by effects * that depend on objects having one or more activated abilities. * diff --git a/Mage/src/main/java/mage/abilities/keyword/UnleashAbility.java b/Mage/src/main/java/mage/abilities/keyword/UnleashAbility.java index 38aaf03e4b7..271f8db3ffd 100644 --- a/Mage/src/main/java/mage/abilities/keyword/UnleashAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/UnleashAbility.java @@ -22,7 +22,7 @@ import mage.players.Player; // // 702.96a Unleash is a keyword that represents two static abilities. // "Unleash" means "You may have this permanent enter the battlefield with an additional +1/+1 counter on it" -// and "This permanent can’t block as long as it has a +1/+1 counter on it." +// and "This permanent can't block as long as it has a +1/+1 counter on it." public class UnleashAbility extends SimpleStaticAbility { public UnleashAbility() { diff --git a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java index 0d5f9b861f3..59806252712 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java @@ -73,7 +73,10 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl ArrayList dynamicNetMana = new ArrayList<>(); for (Effect effect : getEffects()) { if (effect instanceof ManaEffect) { - dynamicNetMana.addAll(((ManaEffect) effect).getNetMana(game, this)); + List effectNetMana = ((ManaEffect) effect).getNetMana(game, this); + if (effectNetMana != null) { + dynamicNetMana.addAll(effectNetMana); + } } } return dynamicNetMana; diff --git a/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java b/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java index 054f3159369..44ad62ff232 100644 --- a/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/CommanderColorIdentityManaAbility.java @@ -1,6 +1,6 @@ - package mage.abilities.mana; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import mage.Mana; @@ -42,6 +42,7 @@ public class CommanderColorIdentityManaAbility extends ActivatedManaAbilityImpl @Override public List getNetMana(Game game) { + List netManas = new ArrayList<>(); if (netMana.isEmpty() && game != null) { Player controller = game.getPlayer(getControllerId()); if (controller != null) { @@ -68,7 +69,8 @@ public class CommanderColorIdentityManaAbility extends ActivatedManaAbilityImpl } } } - return netMana; + netManas.addAll(netMana); + return netManas; } @Override diff --git a/Mage/src/main/java/mage/abilities/mana/ConditionalManaAbility.java b/Mage/src/main/java/mage/abilities/mana/ConditionalManaAbility.java index 8ae3ad06895..c2d0a97511f 100644 --- a/Mage/src/main/java/mage/abilities/mana/ConditionalManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/ConditionalManaAbility.java @@ -1,5 +1,3 @@ - - package mage.abilities.mana; import java.util.ArrayList; @@ -14,7 +12,6 @@ import mage.game.Game; * * @author LevelX2 */ - public class ConditionalManaAbility extends ActivatedManaAbilityImpl { ConditionalManaEffect conditionalManaEffect; @@ -36,8 +33,6 @@ public class ConditionalManaAbility extends ActivatedManaAbilityImpl { @Override public List getNetMana(Game game) { - List newNetMana = new ArrayList<>(); - newNetMana.add(conditionalManaEffect.getMana(game, this)); - return newNetMana; + return new ArrayList<>(conditionalManaEffect.getNetMana(game, this)); } } diff --git a/Mage/src/main/java/mage/abilities/mana/ManaOptions.java b/Mage/src/main/java/mage/abilities/mana/ManaOptions.java index ebebd74b2df..bfd32e47478 100644 --- a/Mage/src/main/java/mage/abilities/mana/ManaOptions.java +++ b/Mage/src/main/java/mage/abilities/mana/ManaOptions.java @@ -1,4 +1,3 @@ - package mage.abilities.mana; import java.util.ArrayList; @@ -12,6 +11,7 @@ import mage.abilities.costs.common.TapSourceCost; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ManaEvent; +import org.apache.log4j.Logger; /** * @@ -24,6 +24,8 @@ import mage.game.events.ManaEvent; */ public class ManaOptions extends ArrayList { + private static final Logger logger = Logger.getLogger(ManaOptions.class); + public ManaOptions() { } @@ -51,7 +53,7 @@ public class ManaOptions extends ArrayList { boolean hasTapCost = hasTapCost(abilities.get(0)); for (Mana netMana : netManas) { for (Mana mana : copy) { - if (!hasTapCost || checkTappedForManaReplacement(abilities.get(0), game, netMana)) { + if (!hasTapCost /* || checkTappedForManaReplacement(abilities.get(0), game, netMana) */) { // Seems to produce endless iterations so deactivated for now: https://github.com/magefree/mage/issues/5023 Mana newMana = new Mana(); newMana.add(mana); newMana.add(netMana); @@ -112,6 +114,7 @@ public class ManaOptions extends ArrayList { } public void addManaWithCost(List abilities, Game game) { + int replaces = 0; if (isEmpty()) { this.add(new Mana()); } @@ -151,7 +154,7 @@ public class ManaOptions extends ArrayList { } } } - } else if (abilities.size() > 1) { + } else { //perform a union of all existing options and the new options List copy = copy(); this.clear(); @@ -185,6 +188,7 @@ public class ManaOptions extends ArrayList { Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana); if (moreValuable != null) { existingMana.setToMana(moreValuable); + replaces++; continue CombineWithExisting; } } @@ -200,6 +204,10 @@ public class ManaOptions extends ArrayList { } } } + if (this.size() > 30 || replaces > 30) { + logger.trace("ManaOptionsCosts " + this.size() + " Ign:" + replaces + " => " + this.toString()); + logger.trace("Abilities: " + abilities.toString()); + } } public void addMana(Mana addMana) { @@ -219,7 +227,7 @@ public class ManaOptions extends ArrayList { if (options.size() == 1) { //if there is only one mana option available add it to all the existing options addMana(options.get(0)); - } else if (options.size() > 1) { + } else { //perform a union of all existing options and the new options List copy = copy(); this.clear(); @@ -252,20 +260,28 @@ public class ManaOptions extends ArrayList { this.clear(); for (Mana mana : copy) { Mana oldMan = mana.copy(); - if (mana.includesMana(cost)) { - // colorless costs can be paid with different colored mana, can lead to different color combinations + if (mana.includesMana(cost)) { // it can be paid + // generic mana costs can be paid with different colored mana, can lead to different color combinations if (cost.getGeneric() > 0 && cost.getGeneric() > (mana.getGeneric() + mana.getColorless())) { Mana coloredCost = cost.copy(); coloredCost.setGeneric(0); mana.subtract(coloredCost); + boolean oldManaWasReplaced = false; for (Mana payCombination : getPossiblePayCombinations(cost.getGeneric(), mana)) { Mana newMana = mana.copy(); newMana.subtract(payCombination); newMana.add(addMana); - if (oldMan.contains(newMana) && oldMan.count() > newMana.count()) { - newMana.setToMana(oldMan); + Mana moreValuable = Mana.getMoreValuableMana(oldMan, newMana); + if (!oldMan.equals(moreValuable)) { + this.add(newMana); + if (moreValuable != null) { + oldManaWasReplaced = true; // the new mana includes all possibilities of the old one + } } - this.add(newMana); + + } + if (!oldManaWasReplaced) { + this.add(oldMan); } } else { while (mana.includesMana(cost)) { @@ -300,28 +316,33 @@ public class ManaOptions extends ArrayList { existingManas.add(new Mana()); } for (Mana existingMana : existingManas) { - Mana manaToPay = manaAvailable.copy(); - manaToPay.subtract(existingMana); - if (manaToPay.getBlack() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlackMana(1).toString())) { - manaToPay.subtract(Mana.BlackMana(1)); + Mana manaToPayFrom = manaAvailable.copy(); + manaToPayFrom.subtract(existingMana); + if (manaToPayFrom.getBlack() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlackMana(1).toString())) { + manaToPayFrom.subtract(Mana.BlackMana(1)); addManaCombination(Mana.BlackMana(1), existingMana, payCombinations, payCombinationsStrings); } - if (manaToPay.getBlue() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlueMana(1).toString())) { - manaToPay.subtract(Mana.BlueMana(1)); + if (manaToPayFrom.getBlue() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlueMana(1).toString())) { + manaToPayFrom.subtract(Mana.BlueMana(1)); addManaCombination(Mana.BlueMana(1), existingMana, payCombinations, payCombinationsStrings); } - if (manaToPay.getGreen() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.GreenMana(1).toString())) { - manaToPay.subtract(Mana.GreenMana(1)); + if (manaToPayFrom.getGreen() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.GreenMana(1).toString())) { + manaToPayFrom.subtract(Mana.GreenMana(1)); addManaCombination(Mana.GreenMana(1), existingMana, payCombinations, payCombinationsStrings); } - if (manaToPay.getRed() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.RedMana(1).toString())) { - manaToPay.subtract(Mana.RedMana(1)); + if (manaToPayFrom.getRed() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.RedMana(1).toString())) { + manaToPayFrom.subtract(Mana.RedMana(1)); addManaCombination(Mana.RedMana(1), existingMana, payCombinations, payCombinationsStrings); } - if (manaToPay.getWhite() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.WhiteMana(1).toString())) { - manaToPay.subtract(Mana.WhiteMana(1)); + if (manaToPayFrom.getWhite() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.WhiteMana(1).toString())) { + manaToPayFrom.subtract(Mana.WhiteMana(1)); addManaCombination(Mana.WhiteMana(1), existingMana, payCombinations, payCombinationsStrings); } + // Pay with any only needed if colored payment was not possible + if (payCombinations.isEmpty() && manaToPayFrom.getAny() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.AnyMana(1).toString())) { + manaToPayFrom.subtract(Mana.AnyMana(1)); + addManaCombination(Mana.AnyMana(1), existingMana, payCombinations, payCombinationsStrings); + } } } } else { @@ -349,5 +370,16 @@ public class ManaOptions extends ArrayList { list.add(s); } } + // Remove fully included variations + for (int i = this.size() - 1; i >= 0; i--) { + for (int ii = 0; ii < i; ii++) { + Mana moreValuable = Mana.getMoreValuableMana(this.get(i), this.get(ii)); + if (moreValuable != null) { + this.get(ii).setToMana(moreValuable); + this.remove(i); + break; + } + } + } } } diff --git a/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java b/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java index 4998d58b5c5..0877a667c25 100644 --- a/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java @@ -1,6 +1,6 @@ - package mage.abilities.mana; +import java.util.ArrayList; import java.util.List; import mage.Mana; import mage.abilities.costs.Cost; @@ -55,7 +55,7 @@ public class SimpleManaAbility extends ActivatedManaAbilityImpl { if (predictable) { return super.getNetMana(game); } - return netMana; + return new ArrayList(netMana); } } diff --git a/Mage/src/main/java/mage/abilities/mana/TriggeredManaAbility.java b/Mage/src/main/java/mage/abilities/mana/TriggeredManaAbility.java index 92054553ac6..41173683bd1 100644 --- a/Mage/src/main/java/mage/abilities/mana/TriggeredManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/TriggeredManaAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.mana; import java.util.ArrayList; @@ -54,7 +53,7 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen } return newNetMana; } - return netMana; + return new ArrayList(netMana); } /** diff --git a/Mage/src/main/java/mage/abilities/mana/conditional/ConditionalSpellManaBuilder.java b/Mage/src/main/java/mage/abilities/mana/conditional/ConditionalSpellManaBuilder.java index c1d071e93f0..86f5939b30c 100644 --- a/Mage/src/main/java/mage/abilities/mana/conditional/ConditionalSpellManaBuilder.java +++ b/Mage/src/main/java/mage/abilities/mana/conditional/ConditionalSpellManaBuilder.java @@ -63,7 +63,7 @@ class SpellCastManaCondition extends ManaCondition implements Condition { public boolean apply(Game game, Ability source) { if (source instanceof SpellAbility) { MageObject object = game.getObject(source.getSourceId()); - if (object != null && (object instanceof StackObject)) { + if ((object instanceof StackObject)) { return filter.match((StackObject) object, source.getSourceId(), source.getControllerId(), game); } } diff --git a/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java b/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java new file mode 100644 index 00000000000..ebd11af1fb6 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java @@ -0,0 +1,136 @@ +package mage.abilities.meta; + +import mage.MageObject; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * A triggered ability that combines several others and triggers whenever one or more of them would. The abilities + * passed in should have null as their effect, and should have their own targets set if necessary. All other information + * will be passed in from changes to this Ability. Note: this does NOT work with abilities that have intervening if clauses. + * @author noahg + */ +public class OrTriggeredAbility extends TriggeredAbilityImpl { + + private final String ruleTrigger; + private TriggeredAbility[] triggeredAbilities; + private List triggeringAbilities; + + public OrTriggeredAbility(Zone zone, Effect effect, TriggeredAbility... abilities) { + this(zone, effect, false, null, abilities); + } + + public OrTriggeredAbility(Zone zone, Effect effect, boolean optional, String ruleTrigger, TriggeredAbility... abilities) { + super(zone, effect, optional); + this.triggeredAbilities = abilities; + this.ruleTrigger = ruleTrigger; + this.triggeringAbilities = new ArrayList<>(); + for (TriggeredAbility ability : triggeredAbilities) { + //Remove useless data + ability.getEffects().clear(); + } + } + + public OrTriggeredAbility(OrTriggeredAbility ability) { + super(ability); + this.triggeredAbilities = new TriggeredAbility[ability.triggeredAbilities.length]; + for (int i = 0; i < this.triggeredAbilities.length; i++){ + this.triggeredAbilities[i] = ability.triggeredAbilities[i].copy(); + } + this.triggeringAbilities = new ArrayList<>(ability.triggeringAbilities); + this.ruleTrigger = ability.ruleTrigger; + } + + + @Override + public boolean checkEventType(GameEvent event, Game game) { + for (TriggeredAbility ability : triggeredAbilities) { + if (ability.checkEventType(event, game)){ + System.out.println("Correct event type (" + event.getType() + ")"); + return true; + } + } + return false; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + boolean toRet = false; + for (int i = 0; i < triggeredAbilities.length; i++) { + TriggeredAbility ability = triggeredAbilities[i]; + if (ability.checkEventType(event, game) && ability.checkTrigger(event, game)) { + System.out.println("Triggered from " + ability.getRule()); + triggeringAbilities.add(i); + toRet = true; + } + System.out.println("Checked " + ability.getRule()); + } + return toRet; + } + + @Override + public OrTriggeredAbility copy() { + return new OrTriggeredAbility(this); + } + + @Override + public String getRule() { + if (ruleTrigger != null && !ruleTrigger.isEmpty()) { + return ruleTrigger + super.getRule(); + } + StringBuilder sb = new StringBuilder(); + if (triggeredAbilities[0].getRule().length() > 0) { + sb.append(triggeredAbilities[0].getRule().substring(0, 1).toUpperCase()) + .append(triggeredAbilities[0].getRule().substring(1).toLowerCase()); + } + + for (int i = 1; i < (triggeredAbilities.length - 1); i++) { + sb.append(triggeredAbilities[i].getRule().toLowerCase()); + } + + sb.append(" or ").append(triggeredAbilities[triggeredAbilities.length - 1].getRule().toLowerCase()); + return sb.toString() + super.getRule(); + } + + + @Override + public void setControllerId(UUID controllerId) { + super.setControllerId(controllerId); + for (TriggeredAbility ability : triggeredAbilities) { + ability.setControllerId(controllerId); + } + } + + @Override + public void setSourceId(UUID sourceId) { + super.setSourceId(sourceId); + for (TriggeredAbility ability : triggeredAbilities) { + ability.setSourceId(sourceId); + } + } + + @Override + public void addWatcher(Watcher watcher) { + super.addWatcher(watcher); + for (TriggeredAbility ability : triggeredAbilities) { + ability.addWatcher(watcher); + } + } + + @Override + public void setSourceObject(MageObject sourceObject, Game game) { + super.setSourceObject(sourceObject, game); + for (TriggeredAbility ability : triggeredAbilities) { + ability.setSourceObject(sourceObject, game); + } + } +} diff --git a/Mage/src/main/java/mage/cards/Card.java b/Mage/src/main/java/mage/cards/Card.java index 7408bc8b9c2..bac8f59d403 100644 --- a/Mage/src/main/java/mage/cards/Card.java +++ b/Mage/src/main/java/mage/cards/Card.java @@ -168,4 +168,8 @@ public interface Card extends MageObject { boolean addAttachment(UUID permanentId, Game game); boolean removeAttachment(UUID permanentId, Game game); + + default boolean isOwnedBy(UUID controllerId){ + return getOwnerId().equals(controllerId); + } } diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index 8b6e87a77d2..4130242ad79 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -1,9 +1,6 @@ package mage.cards; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.*; import mage.MageObject; import mage.MageObjectImpl; import mage.Mana; @@ -12,7 +9,7 @@ import mage.abilities.*; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCost; import mage.abilities.costs.common.RemoveVariableCountersTargetCost; -import mage.abilities.effects.common.NameACardEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.repository.PluginClassloaderRegistery; import mage.constants.*; @@ -45,6 +42,13 @@ import mage.util.SubTypeList; import mage.watchers.Watcher; import org.apache.log4j.Logger; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + public abstract class CardImpl extends MageObjectImpl implements Card { private static final long serialVersionUID = 1L; @@ -59,7 +63,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { protected UUID ownerId; protected String cardNumber; - public String expansionSetCode; + protected String expansionSetCode; protected String tokenSetCode; protected String tokenDescriptor; protected Rarity rarity; @@ -401,7 +405,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { case CHOSEN_NAME: //Declaration of Naught only ability.getTargets().clear(); FilterSpell filterSpell = new FilterSpell("spell with the chosen name"); - filterSpell.add(new NamePredicate((String) game.getState().getValue(ability.getSourceId().toString() + NameACardEffect.INFO_KEY))); + filterSpell.add(new NamePredicate((String) game.getState().getValue(ability.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))); TargetSpell target = new TargetSpell(1, filterSpell); ability.addTarget(target); break; @@ -779,7 +783,15 @@ public abstract class CardImpl extends MageObjectImpl implements Card { @Override public boolean addCounters(Counter counter, Ability source, Game game, List appliedEffects, boolean isEffect) { boolean returnCode = true; - UUID sourceId = (source == null ? getId() : source.getSourceId()); + UUID sourceId = getId(); + if (source != null) { + MageObject object = game.getObject(source.getId()); + if (object instanceof StackObject) { + sourceId = source.getId(); + } else { + sourceId = source.getSourceId(); + } + } GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount()); countersEvent.setAppliedEffects(appliedEffects); countersEvent.setFlag(isEffect); diff --git a/Mage/src/main/java/mage/cards/ExpansionSet.java b/Mage/src/main/java/mage/cards/ExpansionSet.java index 290ca6f63c9..15e4b052d3b 100644 --- a/Mage/src/main/java/mage/cards/ExpansionSet.java +++ b/Mage/src/main/java/mage/cards/ExpansionSet.java @@ -1,9 +1,11 @@ package mage.cards; +import mage.ObjectColor; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.abilities.Ability; import mage.constants.Rarity; import mage.constants.SetType; import mage.util.CardUtil; @@ -13,14 +15,19 @@ import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; +import mage.abilities.keyword.PartnerWithAbility; +import org.apache.log4j.Logger; + /** * @author BetaSteward_at_googlemail.com */ public abstract class ExpansionSet implements Serializable { + private static final Logger logger = Logger.getLogger(ExpansionSet.class); public final static CardGraphicInfo NON_FULL_USE_VARIOUS = new CardGraphicInfo(null, true); public final static CardGraphicInfo FULL_ART_BFZ_VARIOUS = new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true); + public class SetCardInfo implements Serializable { private final String name; @@ -88,14 +95,20 @@ public abstract class ExpansionSet implements Serializable { protected int numBoosterSpecial; protected int numBoosterLands; - protected int ratioBoosterSpecialLand = 0; // if > 0 basic lands are replaced with special land in the ratio every X land is replaced by special land + protected int ratioBoosterSpecialLand = 0; // if > 0 basic lands are replaced with special land with probability ratioBoosterSpecialLandNumerator / ratioBoosterSpecialLand + protected int ratioBoosterSpecialLandNumerator = 1; protected int numBoosterCommon; protected int numBoosterUncommon; protected int numBoosterRare; protected int numBoosterDoubleFaced; // -1 = include normally 0 = exclude 1-n = include explicit protected int ratioBoosterMythic; - protected boolean needsLegends = false; + protected boolean hasPartnerMechanic = false; + + protected boolean needsLegendCreature = false; + protected boolean validateBoosterColors = true; + protected double rejectMissingColorProbability = 0.8; + protected double rejectSameColorUncommonsProbability = 0.8; protected int maxCardNumberInBooster; // used to omit cards with collector numbers beyond the regular cards in a set for boosters @@ -172,6 +185,32 @@ public abstract class ExpansionSet implements Serializable { return theBooster; } + protected int AddMissingPartner(List booster, boolean partnerAllowed, int max, int i) { + + for (Ability ability : booster.get(booster.size() - 1).getAbilities()) { + //Check if fetched card has the PartnerWithAbility + if (ability instanceof PartnerWithAbility) { + //Check if the pack already contains a partner pair + if (partnerAllowed) { + //Added card always replaces an uncommon card + Card card = CardRepository.instance.findCard(((PartnerWithAbility) ability).getPartnerName()).getCard(); + if (i < max) { + booster.add(card); + } else { + booster.set(0, card); + } + //2 return value indicates found partner + return 2; + } else { + //If partner already exists, remove card and loop again + booster.remove(booster.size() - 1); + return 0; + } + } + } + return 1; + } + protected void addToBooster(List booster, List cards) { if (!cards.isEmpty()) { CardInfo cardInfo = cards.remove(RandomUtil.nextInt(cards.size())); @@ -185,17 +224,164 @@ public abstract class ExpansionSet implements Serializable { } public List createBooster() { - if (needsLegends) { - for (int i = 0; i < 100000; i++) {//don't want to somehow loop forever - List booster = tryBooster(); - for (Card card : booster) { - if (card.isLegendary() && card.isCreature()) {// Dominaria packs must contain at least one legendary creature. - return booster; + + for (int i = 0; i < 100; i++) {//don't want to somehow loop forever + + List booster; + if (hasPartnerMechanic) { + // battlebond's partners cards + booster = createPartnerBooster(); + } else { + // all other sets + booster = tryBooster(); + } + + if (boosterIsValid(booster)) { + return booster; + } + } + + // return random booster if can't do valid + logger.error(String.format("Can't generate valid booster for set [%s - %s]", this.getCode(), this.getName())); + return tryBooster(); + } + + protected boolean boosterIsValid(List booster) { + if (validateBoosterColors) { + if (!validateColors(booster)) { + return false; + } + } + + if (needsLegendCreature) { + if (booster.stream().noneMatch(card -> card.isLegendary() && card.isCreature())) { + return false; + } + } + + // TODO: add partner check + // TODO: add booster size check? + return true; + } + + protected boolean validateColors(List booster) { + List magicColors = + Arrays.asList(ObjectColor.WHITE, ObjectColor.BLUE, ObjectColor.BLACK, ObjectColor.RED, ObjectColor.GREEN); + + // all cards colors + Map colorWeight = new HashMap<>(); + // uncommon/rare/mythic cards colors + Map uncommonWeight = new HashMap<>(); + + for (ObjectColor color : magicColors) { + colorWeight.put(color, 0); + uncommonWeight.put(color, 0); + } + + // count colors in the booster + for (Card card : booster) { + ObjectColor cardColor = card.getColor(null); + if (cardColor != null) { + List colors = cardColor.getColors(); + // todo: do we need gold color? + colors.remove(ObjectColor.GOLD); + if (!colors.isEmpty()) { + // 60 - full card weight + // multicolored cards add part of the weight to each color + int cardColorWeight = 60 / colors.size(); + for (ObjectColor color : colors) { + colorWeight.put(color, colorWeight.get(color) + cardColorWeight); + if (card.getRarity() != Rarity.COMMON) { + uncommonWeight.put(color, uncommonWeight.get(color) + cardColorWeight); + } } } } } - return tryBooster(); + + // check that all colors are present + if (magicColors.stream().anyMatch(color -> colorWeight.get(color) < 60)) { + // reject only part of the boosters + if (RandomUtil.nextDouble() < rejectMissingColorProbability) { + return false; + } + } + + // check that we don't have 3 or more uncommons/rares of the same color + if (magicColors.stream().anyMatch(color -> uncommonWeight.get(color) >= 180)) { + // reject only part of the boosters + if (RandomUtil.nextDouble() < rejectSameColorUncommonsProbability) { + return false; + } + } + + return true; + } + + public List createPartnerBooster() { + + List booster = new ArrayList<>(); + + boolean partnerAllowed = true; + + List uncommons = getCardsByRarity(Rarity.UNCOMMON); + for (int i = 0; i < numBoosterUncommon; i++) { + while (true) { + addToBooster(booster, uncommons); + int check = AddMissingPartner(booster, partnerAllowed, numBoosterUncommon - 1, i); + if (check == 1) { + break; + } + if (check == 2) { + partnerAllowed = false; + //Be sure to account for the added card + if (i != numBoosterUncommon - 1) { + i += 1; + } + break; + } + } + } + + int numSpecialCommons = getNumberOfSpecialCommons(); + int numCommonsToGenerate = numBoosterCommon - numSpecialCommons; + + List commons = getCardsByRarity(Rarity.COMMON); + for (int i = 0; i < numCommonsToGenerate; i++) { + addToBooster(booster, commons); + } + + + List rares = getCardsByRarity(Rarity.RARE); + List mythics = getCardsByRarity(Rarity.MYTHIC); + for (int i = 0; i < numBoosterRare; i++) { + if (ratioBoosterMythic > 0 && RandomUtil.nextInt(ratioBoosterMythic) == 0) { + while (true) { + addToBooster(booster, mythics); + int check = AddMissingPartner(booster, partnerAllowed, -1, 1); + if (check == 1) { + break; + } + if (check == 2) { + partnerAllowed = false; + break; + } + } + } else { + while (true) { + addToBooster(booster, rares); + int check = AddMissingPartner(booster, partnerAllowed, -1, 1); + if (check == 1) { + break; + } + if (check == 2) { + partnerAllowed = false; + break; + } + } + } + } + return booster; } public List tryBooster() { @@ -208,7 +394,7 @@ public abstract class ExpansionSet implements Serializable { List specialLands = getSpecialLand(); List basicLands = getCardsByRarity(Rarity.LAND); for (int i = 0; i < numBoosterLands; i++) { - if (ratioBoosterSpecialLand > 0 && RandomUtil.nextInt(ratioBoosterSpecialLand) == 0 && specialLands != null) { + if (ratioBoosterSpecialLand > 0 && RandomUtil.nextInt(ratioBoosterSpecialLand) < ratioBoosterSpecialLandNumerator && specialLands != null) { addToBooster(booster, specialLands); } else { addToBooster(booster, basicLands); 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 33ed4d5946d..14d2b31f570 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java @@ -83,7 +83,7 @@ public class TxtDeckImporter extends DeckImporter { return; } String lineNum = line.substring(0, delim).trim(); - String lineName = line.substring(delim).replace("’", "\'").trim(); + String lineName = line.substring(delim).replace("'", "\'").trim(); lineName = lineName .replace("&", "//") .replace("Æ", "Ae") @@ -92,6 +92,7 @@ public class TxtDeckImporter extends DeckImporter { .replace("í", "i") .replace("â", "a") .replace("á", "a") + .replace("ú", "u") .replace("\"", "'"); if (lineName.contains("//") && !lineName.contains(" // ")) { lineName = lineName.replace("//", " // "); diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 41098b83bc7..adbd4d05c5b 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -1,4 +1,3 @@ - package mage.cards.repository; import com.j256.ormlite.dao.Dao; @@ -17,6 +16,7 @@ import java.util.*; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetType; +import mage.constants.SuperType; import mage.util.RandomUtil; import org.apache.log4j.Logger; @@ -32,7 +32,7 @@ public enum CardRepository { // 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 = 112; + private static final long CARD_CONTENT_VERSION = 118; private Dao cardDao; private Set classNames; @@ -153,6 +153,56 @@ public enum CardRepository { return names; } + public Set getNonbasicLandNames() { + Set names = new TreeSet<>(); + try { + QueryBuilder qb = cardDao.queryBuilder(); + qb.distinct().selectColumns("name"); + Where where = qb.where(); + where.and( + where.not().like("supertypes", '%' + SuperType.BASIC.name() + '%'), + where.like("types", '%' + CardType.LAND.name() + '%') + ); + List results = cardDao.query(qb.prepare()); + for (CardInfo card : results) { + int result = card.getName().indexOf(" // "); + if (result > 0) { + names.add(card.getName().substring(0, result)); + names.add(card.getName().substring(result + 4)); + } else { + names.add(card.getName()); + } + } + } catch (SQLException ex) { + Logger.getLogger(CardRepository.class).error("Error getting non-land names from DB : " + ex); + + } + return names; + } + + public Set getNotBasicLandNames() { + Set names = new TreeSet<>(); + try { + QueryBuilder qb = cardDao.queryBuilder(); + qb.distinct().selectColumns("name"); + qb.where().not().like("supertypes", new SelectArg('%' + SuperType.BASIC.name() + '%')); + List results = cardDao.query(qb.prepare()); + for (CardInfo card : results) { + int result = card.getName().indexOf(" // "); + if (result > 0) { + names.add(card.getName().substring(0, result)); + names.add(card.getName().substring(result + 4)); + } else { + names.add(card.getName()); + } + } + } catch (SQLException ex) { + Logger.getLogger(CardRepository.class).error("Error getting non-land names from DB : " + ex); + + } + return names; + } + public Set getCreatureNames() { Set names = new TreeSet<>(); try { @@ -205,7 +255,10 @@ public enum CardRepository { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("name"); Where where = qb.where(); - where.and(where.not().like("types", '%' + CardType.CREATURE.name() + '%'), where.not().like("types", '%' + CardType.LAND.name() + '%')); + where.and( + where.not().like("types", '%' + CardType.CREATURE.name() + '%'), + where.not().like("types", '%' + CardType.LAND.name() + '%') + ); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { int result = card.getName().indexOf(" // "); @@ -228,7 +281,10 @@ public enum CardRepository { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("name"); Where where = qb.where(); - where.and(where.not().like("types", '%' + CardType.ARTIFACT.name() + '%'), where.not().like("types", '%' + CardType.LAND.name() + '%')); + where.and( + where.not().like("types", '%' + CardType.ARTIFACT.name() + '%'), + where.not().like("types", '%' + CardType.LAND.name() + '%') + ); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { int result = card.getName().indexOf(" // "); diff --git a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java index a8fd506d91c..7bdb97e5ce4 100644 --- a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java +++ b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java @@ -29,7 +29,7 @@ public enum ExpansionRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "expansion"; private static final long EXPANSION_DB_VERSION = 5; - private static final long EXPANSION_CONTENT_VERSION = 15; + private static final long EXPANSION_CONTENT_VERSION = 16; private Dao expansionDao; diff --git a/Mage/src/main/java/mage/constants/AsThoughEffectType.java b/Mage/src/main/java/mage/constants/AsThoughEffectType.java index 7afa2c60002..f2357a77e1a 100644 --- a/Mage/src/main/java/mage/constants/AsThoughEffectType.java +++ b/Mage/src/main/java/mage/constants/AsThoughEffectType.java @@ -18,6 +18,7 @@ public enum AsThoughEffectType { BLOCK_SWAMPWALK, BLOCK_MOUNTAINWALK, BLOCK_FORESTWALK, + DAMAGE_NOT_BLOCKED, BE_BLOCKED, PLAY_FROM_NOT_OWN_HAND_ZONE, CAST_AS_INSTANT, @@ -25,7 +26,7 @@ public enum AsThoughEffectType { DAMAGE, SHROUD, HEXPROOF, - PAY, + PAY_0_ECHO, LOOK_AT_FACE_DOWN, SPEND_OTHER_MANA, SPEND_ONLY_MANA, diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 082b3478e27..fef2c75e130 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -1,12 +1,12 @@ package mage.constants; +import mage.util.SubTypeList; + import java.util.Arrays; import java.util.EnumSet; import java.util.Set; import java.util.stream.Collectors; -import mage.util.SubTypeList; - public enum SubType { //205.3k Instants and sorceries share their lists of subtypes; these subtypes are called spell types. @@ -64,6 +64,7 @@ public enum SubType { AZRA("Azra", SubTypeSet.CreatureType), // B BADGER("Badger", SubTypeSet.CreatureType), + BARABEL("Barabel", SubTypeSet.CreatureType, true), // Star Wars BARBARIAN("Barbarian", SubTypeSet.CreatureType), BASILISK("Basilisk", SubTypeSet.CreatureType), BAT("Bat", SubTypeSet.CreatureType), @@ -99,6 +100,7 @@ public enum SubType { COWARD("Coward", SubTypeSet.CreatureType), CRAB("Crab", SubTypeSet.CreatureType), CROCODILE("Crocodile", SubTypeSet.CreatureType), + CROLUTE("Crolute", SubTypeSet.CreatureType, true), // Star Wars CYBORG("Cyborg", SubTypeSet.CreatureType, true), // Star Wars CYCLOPS("Cyclops", SubTypeSet.CreatureType), // D @@ -204,6 +206,7 @@ public enum SubType { LICID("Licid", SubTypeSet.CreatureType), LIZARD("Lizard", SubTypeSet.CreatureType), LOBSTER("Lobster", SubTypeSet.CreatureType, true), // Unglued + LUKE("Luke", SubTypeSet.PlaneswalkerType, true), // Star Wars // M MANTELLIAN("Mantellian", SubTypeSet.CreatureType, true), // Star Wars MANTICORE("Manticore", SubTypeSet.CreatureType), @@ -247,6 +250,7 @@ public enum SubType { OX("Ox", SubTypeSet.CreatureType), OYSTER("Oyster", SubTypeSet.CreatureType), // P + PANGOLIN("Pangolin", SubTypeSet.CreatureType), PEGASUS("Pegasus", SubTypeSet.CreatureType), PENTAVITE("Pentavite", SubTypeSet.CreatureType), PEST("Pest", SubTypeSet.CreatureType), @@ -311,6 +315,7 @@ public enum SubType { SPONGE("Sponge", SubTypeSet.CreatureType), SQUID("Squid", SubTypeSet.CreatureType), SQUIRREL("Squirrel", SubTypeSet.CreatureType), + SNOKE("Snoke", SubTypeSet.PlaneswalkerType, true), // Star Wars STARFISH("Starfish", SubTypeSet.CreatureType), STARSHIP("Starship", SubTypeSet.CreatureType, true), // Star Wars SULLUSTAN("Sullustan", SubTypeSet.CreatureType, true), // Star Wars @@ -362,6 +367,7 @@ public enum SubType { ZUBERA("Zubera", SubTypeSet.CreatureType), // Planeswalker AJANI("Ajani", SubTypeSet.PlaneswalkerType), + AMINATOU("Aminatou", SubTypeSet.PlaneswalkerType), ANGRATH("Angrath", SubTypeSet.PlaneswalkerType), ARLINN("Arlinn", SubTypeSet.PlaneswalkerType), ASHIOK("Ashiok", SubTypeSet.PlaneswalkerType), @@ -374,6 +380,7 @@ public enum SubType { DOOKU("Dooku", SubTypeSet.PlaneswalkerType, true), // Star Wars DOVIN("Dovin", SubTypeSet.PlaneswalkerType), ELSPETH("Elspeth", SubTypeSet.PlaneswalkerType), + ESTRID("Estrid", SubTypeSet.PlaneswalkerType), FREYALISE("Freyalise", SubTypeSet.PlaneswalkerType), GARRUK("Garruk", SubTypeSet.PlaneswalkerType), GIDEON("Gideon", SubTypeSet.PlaneswalkerType), @@ -402,8 +409,10 @@ public enum SubType { TIBALT("Tibalt", SubTypeSet.PlaneswalkerType), UGIN("Ugin", SubTypeSet.PlaneswalkerType), VENSER("Venser", SubTypeSet.PlaneswalkerType), + VIVIEN("Vivien", SubTypeSet.PlaneswalkerType), VRASKA("Vraska", SubTypeSet.PlaneswalkerType), WILL("Will", SubTypeSet.PlaneswalkerType), + WINDGRACE("Windgrace", SubTypeSet.PlaneswalkerType), XENAGOS("Xenagos", SubTypeSet.PlaneswalkerType), YANGGU("Yanggu", SubTypeSet.PlaneswalkerType), YANLING("Yanling", SubTypeSet.PlaneswalkerType), @@ -454,12 +463,20 @@ public enum SubType { return null; } - ; - public SubTypeSet getSubTypeSet() { return subTypeSet; } + public static Set getArtifactTypes(boolean withCustomSets) { + Set subTypes = EnumSet.noneOf(SubType.class); + for (SubType subType : values()) { + if (subType.getSubTypeSet() == SubTypeSet.ArtifactType && (withCustomSets || !subType.customSet)) { + subTypes.add(subType); + } + } + return subTypes; + } + public static Set getPlaneswalkerTypes(boolean withCustomSets) { Set subTypes = EnumSet.noneOf(SubType.class); for (SubType subType : values()) { diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index b859ad613bf..2ded9a796bc 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -25,6 +25,7 @@ public enum CounterType { CRYSTAL("crystal"), CUBE("cube"), CURRENCY("currency"), + DEATH("death"), DELAY("delay"), DEPLETION("depletion"), DESPAIR("despair"), @@ -79,6 +80,7 @@ public enum CounterType { MUSTER("muster"), NET("net"), OMEN("omen"), + ORE("ore"), P0P1(new BoostCounter(0, 1).name), P1P0(new BoostCounter(1, 0).name), P1P1(new BoostCounter(1, 1).name), @@ -104,6 +106,7 @@ public enum CounterType { SHIELD("shield"), SHRED("shred"), SLIME("slime"), + SLUMBER("slumber"), SOOT("soot"), SPITE("spite"), SPORE("spore"), diff --git a/Mage/src/main/java/mage/designations/Monarch.java b/Mage/src/main/java/mage/designations/Monarch.java index d6e783fe02d..0281b3c4590 100644 --- a/Mage/src/main/java/mage/designations/Monarch.java +++ b/Mage/src/main/java/mage/designations/Monarch.java @@ -27,7 +27,7 @@ public class Monarch extends Designation { } } -// At the beginning of the monarch’s end step, that player draws a card +// At the beginning of the monarch's end step, that player draws a card class MonarchDrawTriggeredAbility extends BeginningOfEndStepTriggeredAbility { public MonarchDrawTriggeredAbility() { @@ -60,7 +60,7 @@ class MonarchDrawTriggeredAbility extends BeginningOfEndStepTriggeredAbility { @Override public String getRule() { - return "At the beginning of the monarch’s end step, that player draws a card."; + return "At the beginning of the monarch's end step, that player draws a card."; } } @@ -84,8 +84,7 @@ class MonarchDealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility public boolean checkTrigger(GameEvent event, Game game) { if (((DamagedPlayerEvent) event).isCombatDamage()) { MageObject damagingObject = game.getObject(event.getSourceId()); - if (damagingObject != null - && damagingObject instanceof Permanent + if (damagingObject instanceof Permanent && damagingObject.isCreature() && event.getTargetId().equals(game.getMonarchId())) { setControllerId(event.getPlayerId()); diff --git a/Mage/src/main/java/mage/filter/Filter.java b/Mage/src/main/java/mage/filter/Filter.java index 56a91556592..7da73e27762 100644 --- a/Mage/src/main/java/mage/filter/Filter.java +++ b/Mage/src/main/java/mage/filter/Filter.java @@ -18,7 +18,7 @@ public interface Filter extends Serializable { boolean match(E o, Game game); - Filter add(Predicate predicate); + Filter add(Predicate predicate); boolean checkObjectClass(Object object); diff --git a/Mage/src/main/java/mage/filter/FilterCard.java b/Mage/src/main/java/mage/filter/FilterCard.java index cd26cea65f4..d3da298bffa 100644 --- a/Mage/src/main/java/mage/filter/FilterCard.java +++ b/Mage/src/main/java/mage/filter/FilterCard.java @@ -1,4 +1,3 @@ - package mage.filter; import java.util.ArrayList; @@ -67,7 +66,10 @@ public class FilterCard extends FilterObject { return Predicates.and(extraPredicates).apply(new ObjectSourcePlayer(card, sourceId, playerId), game); } - public void add(ObjectPlayerPredicate predicate) { + public final void add(ObjectPlayerPredicate predicate) { + if (isLockedFilter()) { + throw new UnsupportedOperationException("You may not modify a locked filter"); + } extraPredicates.add(predicate); } diff --git a/Mage/src/main/java/mage/filter/FilterImpl.java b/Mage/src/main/java/mage/filter/FilterImpl.java index a077c1e6ad4..cf1c847b7b8 100644 --- a/Mage/src/main/java/mage/filter/FilterImpl.java +++ b/Mage/src/main/java/mage/filter/FilterImpl.java @@ -1,4 +1,3 @@ - package mage.filter; import java.util.ArrayList; @@ -15,15 +14,16 @@ import mage.game.Game; */ public abstract class FilterImpl implements Filter { - protected List> predicates = new ArrayList<>(); + protected List> predicates = new ArrayList<>(); protected String message; - protected boolean lockedFilter = false; // Helps to prevent to "accidently" modify the StaticFilters objects + protected boolean lockedFilter; // Helps to prevent "accidentally" modifying the StaticFilters objects @Override public abstract FilterImpl copy(); public FilterImpl(String name) { this.message = name; + this.lockedFilter = false; } public FilterImpl(final FilterImpl filter) { @@ -41,7 +41,7 @@ public abstract class FilterImpl implements Filter { } @Override - public final Filter add(Predicate predicate) { + public final Filter add(Predicate predicate) { if (isLockedFilter()) { throw new UnsupportedOperationException("You may not modify a locked filter"); } @@ -55,7 +55,7 @@ public abstract class FilterImpl implements Filter { } @Override - public void setMessage(String message) { + public final void setMessage(String message) { if (isLockedFilter()) { throw new UnsupportedOperationException("You may not modify a locked filter"); } diff --git a/Mage/src/main/java/mage/filter/FilterPermanent.java b/Mage/src/main/java/mage/filter/FilterPermanent.java index 06530a5140e..e5cf7537ab5 100644 --- a/Mage/src/main/java/mage/filter/FilterPermanent.java +++ b/Mage/src/main/java/mage/filter/FilterPermanent.java @@ -1,4 +1,3 @@ - package mage.filter; import java.util.ArrayList; @@ -27,11 +26,6 @@ public class FilterPermanent extends FilterObject implements FilterIn super("permanent"); } - public FilterPermanent(final FilterPermanent filter) { - super(filter); - this.extraPredicates = new ArrayList<>(filter.extraPredicates); - } - public FilterPermanent(String name) { super(name); } @@ -43,11 +37,16 @@ public class FilterPermanent extends FilterObject implements FilterIn public FilterPermanent(Set subtypesList, String name) { super(name); - for (SubType subtype: subtypesList) { + for (SubType subtype : subtypesList) { this.add(new SubtypePredicate(subtype)); } } + public FilterPermanent(final FilterPermanent filter) { + super(filter); + this.extraPredicates = new ArrayList<>(filter.extraPredicates); + } + @Override public boolean checkObjectClass(Object object) { return object instanceof Permanent; @@ -62,7 +61,10 @@ public class FilterPermanent extends FilterObject implements FilterIn return Predicates.and(extraPredicates).apply(new ObjectSourcePlayer(permanent, sourceId, playerId), game); } - public void add(ObjectPlayerPredicate predicate) { + public final void add(ObjectPlayerPredicate predicate) { + if (isLockedFilter()) { + throw new UnsupportedOperationException("You may not modify a locked filter"); + } extraPredicates.add(predicate); } diff --git a/Mage/src/main/java/mage/filter/FilterPlayer.java b/Mage/src/main/java/mage/filter/FilterPlayer.java index 323180e1b9d..907dfb34340 100644 --- a/Mage/src/main/java/mage/filter/FilterPlayer.java +++ b/Mage/src/main/java/mage/filter/FilterPlayer.java @@ -1,4 +1,3 @@ - package mage.filter; import java.util.ArrayList; @@ -34,6 +33,9 @@ public class FilterPlayer extends FilterImpl { } public void add(ObjectPlayerPredicate predicate) { + if (isLockedFilter()) { + throw new UnsupportedOperationException("You may not modify a locked filter"); + } extraPredicates.add(predicate); } diff --git a/Mage/src/main/java/mage/filter/FilterStackObject.java b/Mage/src/main/java/mage/filter/FilterStackObject.java index dc180df68d1..8a448dc9096 100644 --- a/Mage/src/main/java/mage/filter/FilterStackObject.java +++ b/Mage/src/main/java/mage/filter/FilterStackObject.java @@ -1,4 +1,3 @@ - package mage.filter; import java.util.ArrayList; @@ -21,7 +20,7 @@ public class FilterStackObject extends FilterObject { protected List>> extraPredicates = new ArrayList<>(); public FilterStackObject() { - super("spell or ability"); + this("spell or ability"); } public FilterStackObject(String name) { @@ -41,7 +40,10 @@ public class FilterStackObject extends FilterObject { return Predicates.and(extraPredicates).apply(new ObjectSourcePlayer(stackObject, sourceId, playerId), game); } - public void add(ObjectPlayerPredicate predicate) { + public final void add(ObjectPlayerPredicate predicate) { + if (isLockedFilter()) { + throw new UnsupportedOperationException("You may not modify a locked filter"); + } extraPredicates.add(predicate); } diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 4e9531e8c79..0fcf903c4c3 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -137,6 +137,12 @@ public final class StaticFilters { FILTER_PERMANENT.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENTS = new FilterPermanent("permanents"); + + static { + FILTER_PERMANENTS.setLockedFilter(true); + } + public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_AN = new FilterArtifactPermanent("an artifact"); static { @@ -382,6 +388,17 @@ public final class StaticFilters { static { FILTER_PERMANENTS_NON_LAND.setLockedFilter(true); } + public static final FilterStackObject FILTER_SPELL_OR_ABILITY_OPPONENTS = new FilterStackObject("spell or ability and opponent controls"); + + static { + FILTER_SPELL_OR_ABILITY_OPPONENTS.add(new ControllerPredicate(TargetController.OPPONENT)); + FILTER_SPELL_OR_ABILITY_OPPONENTS.setLockedFilter(true); + } + public static final FilterStackObject FILTER_SPELL_OR_ABILITY = new FilterStackObject(); + + static { + FILTER_SPELL_OR_ABILITY.setLockedFilter(true); + } public static final FilterCreatureSpell FILTER_SPELL_A_CREATURE = new FilterCreatureSpell("a creature spell"); @@ -418,26 +435,35 @@ public final class StaticFilters { FILTER_SPELL_A_MULTICOLORED.setLockedFilter(true); } - public static final FilterSpell FILTER_INSTANT_OR_SORCERY_SPELL = new FilterSpell("instant or sorcery spell"); + public static final FilterSpell FILTER_SPELL_AN_INSTANT_OR_SORCERY = new FilterSpell("an instant or sorcery spell"); static { - FILTER_INSTANT_OR_SORCERY_SPELL.add(Predicates.or( + FILTER_SPELL_AN_INSTANT_OR_SORCERY.add(Predicates.or( new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY) )); - FILTER_INSTANT_OR_SORCERY_SPELL.setLockedFilter(true); + FILTER_SPELL_AN_INSTANT_OR_SORCERY.setLockedFilter(true); } - - public static final FilterSpell FILTER_INSTANT_OR_SORCERY_SPELLS = new FilterSpell("instant or sorcery spells"); + public static final FilterSpell FILTER_SPELL_INSTANT_OR_SORCERY = new FilterSpell("instant or sorcery spell"); static { - FILTER_INSTANT_OR_SORCERY_SPELLS.add(Predicates.or( + FILTER_SPELL_INSTANT_OR_SORCERY.add(Predicates.or( new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY) )); - FILTER_INSTANT_OR_SORCERY_SPELLS.setLockedFilter(true); + FILTER_SPELL_INSTANT_OR_SORCERY.setLockedFilter(true); } - public static final FilterPermanent FILTER_CREATURE_TOKENS = new FilterCreaturePermanent("creature tokens"); + + public static final FilterSpell FILTER_SPELLS_INSTANT_OR_SORCERY = new FilterSpell("instant or sorcery spells"); + + static { + FILTER_SPELLS_INSTANT_OR_SORCERY.add(Predicates.or( + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY) + )); + FILTER_SPELLS_INSTANT_OR_SORCERY.setLockedFilter(true); + } + public static final FilterCreaturePermanent FILTER_CREATURE_TOKENS = new FilterCreaturePermanent("creature tokens"); static { FILTER_CREATURE_TOKENS.add(new TokenPredicate()); diff --git a/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java b/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java index d00b601abe5..9cbee3044f3 100644 --- a/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterControlledPlaneswalkerPermanent.java @@ -1,20 +1,26 @@ - package mage.filter.common; import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; /** * * @author LevelX2 */ - public class FilterControlledPlaneswalkerPermanent extends FilterControlledPermanent { public FilterControlledPlaneswalkerPermanent() { this("planeswalker you control"); } + public FilterControlledPlaneswalkerPermanent(SubType subType, String name) { + super(name); + this.add(new CardTypePredicate(CardType.PLANESWALKER)); + this.add(new SubtypePredicate(subType)); + } + public FilterControlledPlaneswalkerPermanent(String name) { super(name); this.add(new CardTypePredicate(CardType.PLANESWALKER)); diff --git a/Mage/src/main/java/mage/filter/common/FilterPermanentOrSuspendedCard.java b/Mage/src/main/java/mage/filter/common/FilterPermanentOrSuspendedCard.java index 7779b083ace..68689b03f33 100644 --- a/Mage/src/main/java/mage/filter/common/FilterPermanentOrSuspendedCard.java +++ b/Mage/src/main/java/mage/filter/common/FilterPermanentOrSuspendedCard.java @@ -30,6 +30,8 @@ package mage.filter.common; import java.util.UUID; + +import mage.MageObject; import mage.abilities.keyword.SuspendAbility; import mage.cards.Card; import mage.counters.CounterType; @@ -46,7 +48,7 @@ import mage.game.permanent.Permanent; * * @author emerald000 */ -public class FilterPermanentOrSuspendedCard extends FilterImpl implements FilterInPlay { +public class FilterPermanentOrSuspendedCard extends FilterImpl implements FilterInPlay { protected FilterCard cardFilter; protected FilterPermanent permanentFilter; @@ -71,11 +73,11 @@ public class FilterPermanentOrSuspendedCard extends FilterImpl implement @Override public boolean checkObjectClass(Object object) { - return true; + return object instanceof MageObject; } @Override - public boolean match(Object o, Game game) { + public boolean match(MageObject o, Game game) { if (o instanceof Permanent) { return permanentFilter.match((Permanent) o, game); } else if (o instanceof Card) { @@ -85,7 +87,7 @@ public class FilterPermanentOrSuspendedCard extends FilterImpl implement } @Override - public boolean match(Object o, UUID sourceId, UUID playerId, Game game) { + public boolean match(MageObject o, UUID sourceId, UUID playerId, Game game) { if (o instanceof Permanent) { return permanentFilter.match((Permanent) o, sourceId, playerId, game); } else if (o instanceof Card) { @@ -106,7 +108,7 @@ public class FilterPermanentOrSuspendedCard extends FilterImpl implement this.permanentFilter = permanentFilter; } - public void setSpellFilter(FilterCard cardFilter) { + public void setCardFilter(FilterCard cardFilter) { this.cardFilter = cardFilter; } diff --git a/Mage/src/main/java/mage/filter/common/FilterSpellOrPermanent.java b/Mage/src/main/java/mage/filter/common/FilterSpellOrPermanent.java index e9753a36a7f..5a8c08ec3ae 100644 --- a/Mage/src/main/java/mage/filter/common/FilterSpellOrPermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterSpellOrPermanent.java @@ -30,10 +30,14 @@ package mage.filter.common; import java.util.UUID; + +import mage.MageObject; import mage.filter.FilterImpl; import mage.filter.FilterInPlay; import mage.filter.FilterPermanent; import mage.filter.FilterSpell; +import mage.filter.predicate.ObjectPlayer; +import mage.filter.predicate.ObjectPlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; @@ -42,7 +46,7 @@ import mage.game.stack.Spell; * * @author LevelX */ -public class FilterSpellOrPermanent extends FilterImpl implements FilterInPlay { +public class FilterSpellOrPermanent extends FilterImpl implements FilterInPlay { protected FilterPermanent permanentFilter; protected FilterSpell spellFilter; @@ -65,11 +69,11 @@ public class FilterSpellOrPermanent extends FilterImpl implements Filter @Override public boolean checkObjectClass(Object object) { - return true; + return object instanceof MageObject; } @Override - public boolean match(Object o, Game game) { + public boolean match(MageObject o, Game game) { if (o instanceof Spell) { return spellFilter.match((Spell) o, game); } else if (o instanceof Permanent) { @@ -79,7 +83,7 @@ public class FilterSpellOrPermanent extends FilterImpl implements Filter } @Override - public boolean match(Object o, UUID sourceId, UUID playerId, Game game) { + public boolean match(MageObject o, UUID sourceId, UUID playerId, Game game) { if (o instanceof Spell) { return spellFilter.match((Spell) o, sourceId, playerId, game); } else if (o instanceof Permanent) { @@ -88,11 +92,19 @@ public class FilterSpellOrPermanent extends FilterImpl implements Filter return false; } + public final void add(ObjectPlayerPredicate predicate) { + if (isLockedFilter()) { + throw new UnsupportedOperationException("You may not modify a locked filter"); + } + spellFilter.add(predicate); + permanentFilter.add(predicate); + } + public FilterPermanent getPermanentFilter() { return this.permanentFilter; } - public FilterSpell getspellFilter() { + public FilterSpell getSpellFilter() { return this.spellFilter; } diff --git a/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java b/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java index 9b5d4c6b679..e5deb8194e2 100644 --- a/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java @@ -1,21 +1,27 @@ package mage.filter.predicate.ability; -import mage.MageObject; -import mage.abilities.Ability; import mage.filter.predicate.Predicate; import mage.game.Game; +import mage.game.stack.StackAbility; +import mage.game.stack.StackObject; /** * * @author LevelX2 */ -public class ArtifactSourcePredicate implements Predicate { +public class ArtifactSourcePredicate implements Predicate { + + public ArtifactSourcePredicate() { + } @Override - public boolean apply(Ability input, Game game) { - MageObject sourceObject = input.getSourceObject(game); - return sourceObject != null && sourceObject.isArtifact(); + public boolean apply(StackObject input, Game game) { + if (input instanceof StackAbility) { + StackAbility ability = (StackAbility) input; + return ability.getSourceObject(game).isArtifact(); + } + return false; } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/AbilityPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/AbilityPredicate.java index b592d15f69d..08a9cd27e97 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/AbilityPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/AbilityPredicate.java @@ -28,13 +28,8 @@ public class AbilityPredicate implements Predicate { } else { abilities = input.getAbilities(); } - - for (Ability ability : abilities) { - if (abilityClass.equals(ability.getClass())) { - return true; - } - } - return false; + return abilities.stream().anyMatch(ability -> ability.getClass().equals(abilityClass)); + } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java index dd122607790..21a8c11bf8b 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java @@ -1,29 +1,26 @@ package mage.filter.predicate.mageobject; -import java.util.UUID; import mage.MageObject; import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.constants.SubType; -import mage.filter.predicate.Predicate; +import mage.filter.predicate.ObjectPlayerPredicate; +import mage.filter.predicate.ObjectSourcePlayer; import mage.game.Game; /** * * @author LoneFox */ -public class ChosenSubtypePredicate implements Predicate { +public class ChosenSubtypePredicate implements ObjectPlayerPredicate> { - private final UUID cardID; - - public ChosenSubtypePredicate(UUID cardID) { - this.cardID = cardID; + public ChosenSubtypePredicate() { } @Override - public boolean apply(MageObject input, Game game) { - SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(cardID, game); - return input.hasSubtype(subType, game); + public boolean apply(ObjectSourcePlayer input, Game game) { + SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(input.getSourceId(), game); + return input.getObject().hasSubtype(subType, game); } @Override 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 810def1d91e..f1598666111 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/MulticoloredPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/MulticoloredPredicate.java @@ -16,7 +16,7 @@ public class MulticoloredPredicate implements Predicate { @Override public boolean apply(MageObject input, Game game) { // 708.3. Each split card that consists of two halves with different colored mana symbols in their mana costs - // is a multicolored card while it’s not a spell on the stack. While it’s a spell on the stack, it’s only the + // is a multicolored card while it's not a spell on the stack. While it's a spell on the stack, it's only the // color or colors of the half or halves being cast. # if (input instanceof SplitCardHalf && game.getState().getZone(input.getId()) != Zone.STACK) { return 1 < ((SplitCardHalf) input).getMainCard().getColor(game).getColorCount(); diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java index 23df06400d6..e5c060ea0d7 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java @@ -5,6 +5,7 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Mode; import mage.filter.predicate.Predicate; +import mage.game.Controllable; import mage.game.Game; import mage.game.stack.StackObject; import mage.target.Target; @@ -13,7 +14,7 @@ import mage.target.Target; * * @author jeffwadsworth */ -public class NumberOfTargetsPredicate implements Predicate { +public class NumberOfTargetsPredicate implements Predicate { private final int targets; @@ -22,7 +23,7 @@ public class NumberOfTargetsPredicate implements Predicate { } @Override - public boolean apply(MageObject input, Game game) { + public boolean apply(Controllable input, Game game) { StackObject stackObject = game.getState().getStack().getStackObject(input.getId()); if (stackObject != null) { int numberOfTargets = 0; diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/SharesColorPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/SharesColorPredicate.java new file mode 100644 index 00000000000..a261bf58fc9 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/SharesColorPredicate.java @@ -0,0 +1,39 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package mage.filter.predicate.mageobject; + +import mage.MageObject; +import mage.ObjectColor; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.Predicate; +import mage.game.Game; + +/** + * + * @author noahg + */ + +public class SharesColorPredicate implements Predicate { + + private final ObjectColor color; + + public SharesColorPredicate(ObjectColor color) { + this.color = color; + } + + @Override + public boolean apply(MageObject input, Game game) { + return color != null && input.getColor(game).shares(color); + + } + + @Override + public String toString() { + return "shares a color"; + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/VariableManaCostPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/VariableManaCostPredicate.java index 08a8f2ba747..7759d5d3b26 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/VariableManaCostPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/VariableManaCostPredicate.java @@ -16,12 +16,8 @@ public class VariableManaCostPredicate implements Predicate { @Override public boolean apply(MageObject input, Game game) { - for (ManaCost manaCost : input.getManaCost()) { - if (manaCost instanceof VariableManaCost) { - return true; - } - } - return false; + return input.getManaCost().stream().anyMatch(manaCost -> manaCost instanceof VariableManaCost); + } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/other/OwnerIdPredicate.java b/Mage/src/main/java/mage/filter/predicate/other/OwnerIdPredicate.java index 8cf872e132c..15c2a46491c 100644 --- a/Mage/src/main/java/mage/filter/predicate/other/OwnerIdPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/other/OwnerIdPredicate.java @@ -19,8 +19,8 @@ public class OwnerIdPredicate implements Predicate { } @Override - public boolean apply(Card input, Game game) { - return ownerId.equals(input.getOwnerId()); + public boolean apply(Card card, Game game) { + return card.isOwnedBy(ownerId); } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/other/OwnerPredicate.java b/Mage/src/main/java/mage/filter/predicate/other/OwnerPredicate.java index f70c92b5cb9..1050e0d04a1 100644 --- a/Mage/src/main/java/mage/filter/predicate/other/OwnerPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/other/OwnerPredicate.java @@ -30,18 +30,18 @@ public class OwnerPredicate implements ObjectPlayerPredicate> switch (targetOwner) { case YOU: - if (card.getOwnerId().equals(playerId)) { + if (card.isOwnedBy(playerId)) { return true; } break; case OPPONENT: - if (!card.getOwnerId().equals(playerId) + if (!card.isOwnedBy(playerId) && game.getPlayer(playerId).hasOpponent(card.getOwnerId(), game)) { return true; } break; case NOT_YOU: - if (!card.getOwnerId().equals(playerId)) { + if (!card.isOwnedBy(playerId)) { return true; } break; diff --git a/Mage/src/main/java/mage/filter/predicate/other/PlayerCanGainLifePredicate.java b/Mage/src/main/java/mage/filter/predicate/other/PlayerCanGainLifePredicate.java index 2c82ab33876..dcb75de1053 100644 --- a/Mage/src/main/java/mage/filter/predicate/other/PlayerCanGainLifePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/other/PlayerCanGainLifePredicate.java @@ -18,11 +18,14 @@ public class PlayerCanGainLifePredicate implements ObjectSourcePlayerPredicate input, Game game) { Player player = input.getObject(); - return player.isCanGainLife(); + if(player != null) { + return player.isCanGainLife(); + } + return false; } @Override public String toString() { - return "Player can gain live"; + return "Player can gain life"; } } diff --git a/Mage/src/main/java/mage/filter/predicate/other/SpellZonePredicate.java b/Mage/src/main/java/mage/filter/predicate/other/SpellZonePredicate.java new file mode 100644 index 00000000000..b9b85b26725 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/other/SpellZonePredicate.java @@ -0,0 +1,35 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.filter.predicate.other; + +import mage.constants.Zone; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; + +/** + * + * @author BetaSteward + */ +public class SpellZonePredicate implements Predicate { + + private final Zone zone; + + public SpellZonePredicate(Zone zone) { + this.zone = zone; + } + + @Override + public boolean apply(StackObject input, Game game) { + return input instanceof Spell && ((Spell) input).getFromZone().match(zone); + } + + @Override + public String toString() { + return "SpellZone(" + zone + ')'; + } +} diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToControlledPermanentPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToControlledPermanentPredicate.java index afcbfc3eaa4..c8257e2c2dd 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToControlledPermanentPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToControlledPermanentPredicate.java @@ -17,7 +17,7 @@ public class AttachedToControlledPermanentPredicate implements ObjectPlayerPredi Permanent attachement = input.getObject(); if (attachement != null) { Permanent permanent = game.getPermanent(attachement.getAttachedTo()); - if (permanent != null && permanent.getControllerId().equals(input.getPlayerId())) { + if (permanent != null && permanent.isControlledBy(input.getPlayerId())) { return true; } } 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 949f6a20a59..b1ba27d4005 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/BlockedByIdPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/BlockedByIdPredicate.java @@ -1,4 +1,3 @@ - package mage.filter.predicate.permanent; import java.util.UUID; @@ -6,6 +5,7 @@ import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; +import mage.watchers.common.BlockedAttackerWatcher; /** * @@ -25,6 +25,13 @@ public class BlockedByIdPredicate implements Predicate { if (combatGroup.getBlockers().contains(blockerId) && combatGroup.getAttackers().contains(input.getId())) { return true; } + } // 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()); + if (watcher != null) { + return watcher.creatureHasBlockedAttacker(input, blocker, game); + } } return false; } 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 a36e3bdffb0..8be4989a9fd 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/CommanderPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/CommanderPredicate.java @@ -19,13 +19,12 @@ public class CommanderPredicate implements Predicate { @Override public boolean apply(Permanent input, Game game) { Player owner = game.getPlayer(input.getOwnerId()); - return input.isCreature() - && owner != null + return owner != null && owner.getCommandersIds().contains(input.getId()); } @Override public String toString() { - return "Commander creature"; + return "Commander"; } } diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/ControllerIsActivePlayerPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/ControllerIsActivePlayerPredicate.java new file mode 100644 index 00000000000..1f0b7009741 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/permanent/ControllerIsActivePlayerPredicate.java @@ -0,0 +1,27 @@ + +package mage.filter.predicate.permanent; + +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * + * @author North + */ +public class ControllerIsActivePlayerPredicate implements Predicate { + @Override + public boolean apply(Permanent input, Game game) { + if(input.getControllerId() == null){ + return false; + } + return game.isActivePlayer(input.getControllerId()); + } + + @Override + public String toString() { + return "controlled by the active player"; + } +} diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/ControllerPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/ControllerPredicate.java index 1a90b57cb49..d77c180f958 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/ControllerPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/ControllerPredicate.java @@ -28,7 +28,7 @@ public class ControllerPredicate implements ObjectPlayerPredicate { @Override public boolean apply(Permanent input, Game game) { - for (Counter counter: input.getCounters(game).values()) { - if (counter.getCount()> 0) { - return true; - } - } - return false; + return input.getCounters(game).values().stream().anyMatch(counter -> counter.getCount() > 0); + } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java index 51ab150de8d..0ec99dfe6c4 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerControlsPredicate.java @@ -14,7 +14,7 @@ public class DefendingPlayerControlsPredicate implements ObjectSourcePlayerPredi @Override public boolean apply(ObjectSourcePlayer input, Game game) { - return input.getObject().getControllerId().equals(game.getCombat().getDefendingPlayerId(input.getSourceId(), game)); + return input.getObject().isControlledBy(game.getCombat().getDefendingPlayerId(input.getSourceId(), game)); } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java index a0326cb54ec..fe044d827e1 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/DefendingPlayerOwnsCardPredicate.java @@ -14,7 +14,7 @@ public class DefendingPlayerOwnsCardPredicate implements ObjectSourcePlayerPredi @Override public boolean apply(ObjectSourcePlayer input, Game game) { - return input.getObject().getOwnerId().equals(game.getCombat().getDefendingPlayerId(input.getSourceId(), game)); + return input.getObject().isOwnedBy(game.getCombat().getDefendingPlayerId(input.getSourceId(), game)); } @Override 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 f6b218c4eb5..c548735dc50 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/EnchantedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/EnchantedPredicate.java @@ -1,7 +1,10 @@ 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; @@ -14,13 +17,11 @@ public class EnchantedPredicate implements Predicate { @Override public boolean apply(Permanent input, Game game) { - for (UUID attachmentId : input.getAttachments()) { - Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.isEnchantment()) { - return true; - } - } - return false; + return input.getAttachments() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(MageObject::isEnchantment); } @Override 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 87ca0911f69..cb0b266d9e8 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java @@ -5,27 +5,26 @@ */ package mage.filter.predicate.permanent; -import java.util.UUID; import mage.constants.SubType; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.Objects; + /** - * * @author LevelX2 */ public class EquippedPredicate implements Predicate { @Override public boolean apply(Permanent input, Game game) { - for (UUID attachmentId : input.getAttachments()) { - Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.hasSubtype(SubType.EQUIPMENT, game)) { - return true; - } - } - return false; + return input.getAttachments() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(attachment -> attachment.hasSubtype(SubType.EQUIPMENT, game)); + } @Override diff --git a/Mage/src/main/java/mage/game/Controllable.java b/Mage/src/main/java/mage/game/Controllable.java index aad1d744d13..025b8f3720d 100644 --- a/Mage/src/main/java/mage/game/Controllable.java +++ b/Mage/src/main/java/mage/game/Controllable.java @@ -10,4 +10,8 @@ import java.util.UUID; public interface Controllable { UUID getControllerId(); UUID getId(); + + default boolean isControlledBy(UUID controllerID){ + return getControllerId().equals(controllerID); + } } diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index 5ae398beeab..8ab4089a447 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -3,6 +3,8 @@ package mage.game; import java.io.Serializable; import java.util.*; +import java.util.stream.Collectors; + import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; @@ -119,15 +121,17 @@ public interface Game extends MageItem, Serializable { * @param playerId * @return */ - default public Set getOpponents(UUID playerId) { - Set opponents = new HashSet<>(); + default Set getOpponents(UUID playerId) { Player player = getPlayer(playerId); - for (UUID opponentId : player.getInRange()) { - if (!opponentId.equals(playerId)) { - opponents.add(opponentId); - } - } - return opponents; + return player.getInRange().stream() + .filter(opponentId -> !opponentId.equals(playerId)) + .collect(Collectors.toSet()); + + } + + + default boolean isActivePlayer(UUID playerId){ + return getActivePlayerId().equals(playerId); } /** @@ -141,7 +145,7 @@ public interface Game extends MageItem, Serializable { * @param playerToCheckId * @return */ - default public boolean isOpponent(Player player, UUID playerToCheckId) { + default boolean isOpponent(Player player, UUID playerToCheckId) { return !player.getId().equals(playerToCheckId); } @@ -394,6 +398,8 @@ public interface Game extends MageItem, Serializable { void playPriority(UUID activePlayerId, boolean resuming); + void resetControlAfterSpellResolve(UUID topId); + boolean endTurn(Ability source); int doAction(MageAction action); diff --git a/Mage/src/main/java/mage/game/GameCommanderImpl.java b/Mage/src/main/java/mage/game/GameCommanderImpl.java index fc20ad69ed6..f6c2e6779de 100644 --- a/Mage/src/main/java/mage/game/GameCommanderImpl.java +++ b/Mage/src/main/java/mage/game/GameCommanderImpl.java @@ -147,7 +147,7 @@ public abstract class GameCommanderImpl extends GameImpl { } /* 20130711 - *903.14a A player that’s been dealt 21 or more combat damage by the same commander + *903.14a A player that's been dealt 21 or more combat damage by the same commander * over the course of the game loses the game. (This is a state-based action. See rule 704.) * */ diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 259d7e53358..20f6284b9b9 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1,4 +1,3 @@ - package mage.game; import java.io.IOException; @@ -1023,6 +1022,7 @@ public abstract class GameImpl implements Game, Serializable { 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()); @@ -1396,6 +1396,7 @@ public abstract class GameImpl implements Game, Serializable { try { top = state.getStack().peek(); top.resolve(this); + resetControlAfterSpellResolve(top.getId()); } finally { if (top != null) { state.getStack().remove(top, this); // seems partly redundant because move card from stack to grave is already done and the stack removed @@ -1410,6 +1411,37 @@ public abstract class GameImpl implements Game, Serializable { } } + @Override + public void resetControlAfterSpellResolve(UUID topId) { + // for Word of Command + Spell spell = getSpellOrLKIStack(topId); + if (spell != null) { + if (spell.getCommandedBy() != null) { + UUID commandedBy = spell.getCommandedBy(); + UUID spellControllerId = null; + if (commandedBy.equals(spell.getControllerId())) { + spellControllerId = spell.getSpellAbility().getFirstTarget(); // i.e. resolved spell is Word of Command + } else { + spellControllerId = spell.getControllerId(); // i.e. resolved spell is the target opponent's spell + } + if (commandedBy != null && spellControllerId != null) { + Player turnController = getPlayer(commandedBy); + if (turnController != null) { + Player targetPlayer = getPlayer(spellControllerId); + if (targetPlayer != null) { + targetPlayer.setGameUnderYourControl(true, false); + informPlayers(turnController.getLogName() + " lost control over " + targetPlayer.getLogName()); + if (targetPlayer.getTurnControlledBy().equals(turnController.getId())) { + turnController.getPlayersUnderYourControl().remove(targetPlayer.getId()); + } + } + } + } + spell.setCommandedBy(null); + } + } + } + /** * This checks if the stack gets filled iterated, without ever getting empty * If the defined number of iterations with not more than 4 different @@ -1866,7 +1898,7 @@ public abstract class GameImpl implements Game, Serializable { //702.93e.: ...another player gains control // ...or the creature it's paired with leaves the battlefield. Permanent paired = perm.getPairedCard().getPermanent(this); - if (paired == null || !perm.getControllerId().equals(paired.getControllerId()) || paired.getPairedCard() == null) { + if (paired == null || !perm.isControlledBy(paired.getControllerId()) || paired.getPairedCard() == null) { perm.setPairedCard(null); if (paired != null && paired.getPairedCard() != null) { paired.setPairedCard(null); @@ -1877,7 +1909,7 @@ public abstract class GameImpl implements Game, Serializable { if (perm.getBandedCards() != null && !perm.getBandedCards().isEmpty()) { for (UUID bandedId : new ArrayList<>(perm.getBandedCards())) { Permanent banded = getPermanent(bandedId); - if (banded == null || !perm.getControllerId().equals(banded.getControllerId()) || !banded.getBandedCards().contains(perm.getId())) { + if (banded == null || !perm.isControlledBy(banded.getControllerId()) || !banded.getBandedCards().contains(perm.getId())) { perm.removeBandedCard(bandedId); if (banded != null && banded.getBandedCards().contains(perm.getId())) { banded.removeBandedCard(perm.getId()); @@ -1926,7 +1958,12 @@ public abstract class GameImpl implements Game, Serializable { } } } else { - SpellAbility spellAbility = perm.getSpellAbility(); + Ability spellAbility = perm.getSpellAbility(); + if (spellAbility == null) { + if (!perm.getAbilities().isEmpty()) { + spellAbility = perm.getAbilities().get(0); // Can happen for created tokens (e.g. Estrid, the Masked) + } + } if (spellAbility.getTargets().isEmpty()) { for (Ability ability : perm.getAbilities(this)) { if ((ability instanceof SpellAbility) @@ -1994,7 +2031,7 @@ public abstract class GameImpl implements Game, Serializable { } else if (target instanceof TargetCard) { Card attachedTo = getCard(perm.getAttachedTo()); if (attachedTo == null - || !((TargetCard) spellAbility.getTargets().get(0)).canTarget(perm.getControllerId(), perm.getAttachedTo(), spellAbility, this)) { + || !(spellAbility.getTargets().get(0)).canTarget(perm.getControllerId(), perm.getAttachedTo(), spellAbility, this)) { if (movePermanentToGraveyardWithInfo(perm)) { if (attachedTo != null) { attachedTo.removeAttachment(perm.getId(), this); @@ -2007,7 +2044,7 @@ public abstract class GameImpl implements Game, Serializable { } } // 704.5s If the number of lore counters on a Saga permanent is greater than or equal to its final chapter number - // and it isn’t the source of a chapter ability that has triggered but not yet left the stack, that Saga’s controller sacrifices it. + // and it isn't the source of a chapter ability that has triggered but not yet left the stack, that Saga's controller sacrifices it. if (perm.hasSubtype(SubType.SAGA, this)) { for (Ability sagaAbility : perm.getAbilities()) { if (sagaAbility instanceof SagaAbility) { @@ -2451,7 +2488,7 @@ public abstract class GameImpl implements Game, Serializable { @Override public boolean canPlaySorcery(UUID playerId) { - return isMainPhase() && getActivePlayerId().equals(playerId) && getStack().isEmpty(); + return isMainPhase() && isActivePlayer(playerId) && getStack().isEmpty(); } /** @@ -2483,7 +2520,7 @@ public abstract class GameImpl implements Game, Serializable { Set toOutside = new HashSet<>(); for (Iterator it = getBattlefield().getAllPermanents().iterator(); it.hasNext();) { Permanent perm = it.next(); - if (perm.getOwnerId().equals(playerId)) { + if (perm.isOwnedBy(playerId)) { if (perm.getAttachedTo() != null) { Permanent attachedTo = getPermanent(perm.getAttachedTo()); if (attachedTo != null) { @@ -2501,7 +2538,7 @@ public abstract class GameImpl implements Game, Serializable { } toOutside.add(perm); // it.remove(); - } else if (perm.getControllerId().equals(player.getId())) { + } else if (perm.isControlledBy(player.getId())) { // and any effects which give that player control of any objects or players end Effects: for (ContinuousEffect effect : getContinuousEffects().getLayeredEffects(this)) { @@ -2534,7 +2571,7 @@ public abstract class GameImpl implements Game, Serializable { } // Then, if that player controlled any objects on the stack not represented by cards, those objects cease to exist. this.getState().getContinuousEffects().removeInactiveEffects(this); - getStack().removeIf(object -> object.getControllerId().equals(playerId)); + getStack().removeIf(object -> object.isControlledBy(playerId)); // Then, if there are any objects still controlled by that player, those objects are exiled. applyEffects(); // to remove control from effects removed meanwhile List permanents = this.getBattlefield().getAllActivePermanents(playerId); @@ -2546,17 +2583,17 @@ public abstract class GameImpl implements Game, Serializable { for (ExileZone exile : this.getExile().getExileZones()) { for (Iterator it = exile.iterator(); it.hasNext();) { Card card = this.getCard(it.next()); - if (card != null && card.getOwnerId().equals(playerId)) { + if (card != null && card.isOwnedBy(playerId)) { it.remove(); } } } - //Remove all emblems/plane the player controls + //Remove all commander/emblems/plane the player controls boolean addPlaneAgain = false; for (Iterator it = this.getState().getCommand().iterator(); it.hasNext();) { CommandObject obj = it.next(); - if ((obj instanceof Emblem || obj instanceof Plane) && obj.getControllerId().equals(playerId)) { + if (obj.getControllerId().equals(playerId)) { if (obj instanceof Emblem) { ((Emblem) obj).discardEffects();// This may not be the best fix but it works } @@ -2580,20 +2617,21 @@ public abstract class GameImpl implements Game, Serializable { } } } - Iterator> it = gameCards.entrySet().iterator(); while (it.hasNext()) { Entry entry = it.next(); Card card = entry.getValue(); - if (card.getOwnerId().equals(playerId)) { + if (card.isOwnedBy(playerId)) { it.remove(); } } + // Make sure effects of no longer existing objects are removed + getContinuousEffects().removeInactiveEffects(this); // If the current monarch leaves the game. When that happens, the player whose turn it is becomes the monarch. // If the monarch leaves the game on their turn, the next player in turn order becomes the monarch. if (playerId.equals(getMonarchId())) { - if (!getActivePlayerId().equals(playerId)) { + if (!isActivePlayer(playerId)) { setMonarchId(null, getActivePlayerId()); } else { Player nextPlayer = getPlayerList().getNext(this); diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index f4516516fa2..e18fc41b72f 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -1,4 +1,3 @@ - package mage.game; import java.io.Serializable; @@ -911,7 +910,7 @@ public class GameState implements Serializable, Copyable { } public List getTriggered(UUID controllerId) { - return triggered.stream().filter(triggeredAbility -> triggeredAbility.getControllerId().equals(controllerId)) + return triggered.stream().filter(triggeredAbility -> controllerId.equals(triggeredAbility.getControllerId())) .collect(Collectors.toList()); } diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index c6478382bee..5b56d49347c 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -1,7 +1,6 @@ + package mage.game.combat; -import java.io.Serializable; -import java.util.*; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.RequirementEffect; @@ -32,6 +31,9 @@ import mage.util.Copyable; import mage.util.trace.TraceUtil; import org.apache.log4j.Logger; +import java.io.Serializable; +import java.util.*; + /** * @author BetaSteward_at_googlemail.com */ @@ -46,7 +48,7 @@ public class Combat implements Serializable, Copyable { protected List groups = new ArrayList<>(); protected Map blockingGroups = new HashMap<>(); - // player and plainswalker ids + // player and planeswalker ids protected Set defenders = new HashSet<>(); // how many creatures attack defending player protected Map> numberCreaturesDefenderAttackedBy = new HashMap<>(); @@ -208,7 +210,7 @@ public class Combat implements Serializable, Copyable { possibleDefenders = new HashSet<>(); for (UUID objectId : defenders) { Permanent planeswalker = game.getPermanent(objectId); - if (planeswalker != null && planeswalker.getControllerId().equals(playerToAttack)) { + if (planeswalker != null && planeswalker.isControlledBy(playerToAttack)) { possibleDefenders.add(objectId); } else if (playerToAttack.equals(objectId)) { possibleDefenders.add(objectId); @@ -309,31 +311,28 @@ public class Combat implements Serializable, Copyable { for (UUID targetId : target.getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { - if (permanent != null) { - for (UUID bandedId : attacker.getBandedCards()) { - permanent.addBandedCard(bandedId); - Permanent banded = game.getPermanent(bandedId); - if (banded != null) { - banded.addBandedCard(targetId); - } - } - permanent.addBandedCard(creatureId); - attacker.addBandedCard(targetId); - if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) { - filter.add(new AbilityPredicate(BandingAbility.class)); + for (UUID bandedId : attacker.getBandedCards()) { + permanent.addBandedCard(bandedId); + Permanent banded = game.getPermanent(bandedId); + if (banded != null) { + banded.addBandedCard(targetId); } } + permanent.addBandedCard(creatureId); + attacker.addBandedCard(targetId); + if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) { + filter.add(new AbilityPredicate(BandingAbility.class)); + } } + } } } if (isBanded) { StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: "); sb.append(attacker.getLogName()); - int i = 0; for (UUID id : attacker.getBandedCards()) { - i++; sb.append(", "); Permanent permanent = game.getPermanent(id); if (permanent != null) { @@ -414,7 +413,6 @@ public class Combat implements Serializable, Copyable { } /** - * * @param player * @param game * @return true if the attack with that set of creatures and attacked @@ -485,7 +483,7 @@ public class Combat implements Serializable, Copyable { * Handle the blocker selection process * * @param blockController player that controlls how to block, if null the - * defender is the controller + * defender is the controller * @param game */ public void selectBlockers(Player blockController, Game game) { @@ -531,7 +529,6 @@ public class Combat implements Serializable, Copyable { /** * Add info about attacker blocked by blocker to the game log - * */ private void logBlockerInfo(Player defender, Game game) { boolean shownDefendingPlayer = game.getPlayers().size() < 3; // only two players no ned to sow the attacked player @@ -694,7 +691,8 @@ public class Combat implements Serializable, Copyable { Set opponents = game.getOpponents(attackingPlayerId); //20101001 - 509.1c // map with attackers (UUID) that must be blocked by at least one blocker and a set of all creatures that can block it and don't block yet - Map> mustBeBlockedByAtLeastOne = new HashMap<>(); + Map> mustBeBlockedByAtLeastX = new HashMap<>(); + Map minNumberOfBlockersMap = new HashMap<>(); // check mustBlock requirements of creatures from opponents of attacking player for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED, player.getId(), game)) { @@ -706,18 +704,22 @@ public class Combat implements Serializable, Copyable { // get all requirement effects that apply to the creature (e.g. is able to block attacker) for (Map.Entry> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, false, game).entrySet()) { RequirementEffect effect = entry.getKey(); - // get possible mustBeBlockedByAtLeastOne blocker + // get possible mustBeBlockedByAtLeastX blocker for (Ability ability : entry.getValue()) { UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game); if (toBeBlockedCreature != null) { - Set potentialBlockers; - if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) { - potentialBlockers = mustBeBlockedByAtLeastOne.get(toBeBlockedCreature); - } else { - potentialBlockers = new HashSet<>(); - mustBeBlockedByAtLeastOne.put(toBeBlockedCreature, potentialBlockers); + CombatGroup toBeBlockedGroup = findGroup(toBeBlockedCreature); + if (toBeBlockedGroup != null && toBeBlockedGroup.getDefendingPlayerId().equals(creature.getControllerId())) { + minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers()); + Set potentialBlockers; + if (mustBeBlockedByAtLeastX.containsKey(toBeBlockedCreature)) { + potentialBlockers = mustBeBlockedByAtLeastX.get(toBeBlockedCreature); + } else { + potentialBlockers = new HashSet<>(); + mustBeBlockedByAtLeastX.put(toBeBlockedCreature, potentialBlockers); + } + potentialBlockers.add(creature.getId()); } - potentialBlockers.add(creature.getId()); } } // check the mustBlockAllAttackers requirement for creatures already blocking (Blaze of Glory) ------------------------------- @@ -800,18 +802,22 @@ public class Combat implements Serializable, Copyable { // get all requirement effects that apply to the creature for (Map.Entry> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, false, game).entrySet()) { RequirementEffect effect = entry.getKey(); - // get possible mustBeBlockedByAtLeastOne blocker + // get possible mustBeBlockedByAtLeastX blocker for (Ability ability : entry.getValue()) { UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game); if (toBeBlockedCreature != null) { - Set potentialBlockers; - if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) { - potentialBlockers = mustBeBlockedByAtLeastOne.get(toBeBlockedCreature); - } else { - potentialBlockers = new HashSet<>(); - mustBeBlockedByAtLeastOne.put(toBeBlockedCreature, potentialBlockers); + CombatGroup toBeBlockedGroup = findGroup(toBeBlockedCreature); + if (toBeBlockedGroup != null && toBeBlockedGroup.getDefendingPlayerId().equals(creature.getControllerId())) { + minNumberOfBlockersMap.put(toBeBlockedCreature, effect.getMinNumberOfBlockers()); + Set potentialBlockers; + if (mustBeBlockedByAtLeastX.containsKey(toBeBlockedCreature)) { + potentialBlockers = mustBeBlockedByAtLeastX.get(toBeBlockedCreature); + } else { + potentialBlockers = new HashSet<>(); + mustBeBlockedByAtLeastX.put(toBeBlockedCreature, potentialBlockers); + } + potentialBlockers.add(creature.getId()); } - potentialBlockers.add(creature.getId()); } } @@ -886,18 +892,19 @@ public class Combat implements Serializable, Copyable { } - // check if for attacking creatures with mustBeBlockedByAtLeastOne requirements are fulfilled - for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) { + // check if for attacking creatures with mustBeBlockedByAtLeastX requirements are fulfilled + for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastX.keySet()) { for (CombatGroup combatGroup : game.getCombat().getGroups()) { if (combatGroup.getAttackers().contains(toBeBlockedCreatureId)) { boolean requirementFulfilled = false; // Check whether an applicable creature is blocking. for (UUID blockerId : combatGroup.getBlockers()) { - if (mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId).contains(blockerId)) { + if (mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId).contains(blockerId)) { requirementFulfilled = true; break; } } + requirementFulfilled &= (combatGroup.getBlockers().size() >= Math.min(minNumberOfBlockersMap.get(toBeBlockedCreatureId), mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId).size())); if (!requirementFulfilled) { // creature is not blocked but has possible blockers if (controller.isHuman()) { @@ -905,9 +912,12 @@ public class Combat implements Serializable, Copyable { if (toBeBlockedCreature != null) { // check if all possible blocker block other creatures they are forced to block // read through all possible blockers - for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { + for (UUID possibleBlockerId : mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId)) { + if (combatGroup.getBlockers().contains(possibleBlockerId)) { + continue; + } String blockRequiredMessage = isCreatureDoingARequiredBlock( - possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game); + possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastX, game); if (blockRequiredMessage != null) { // message means not required removeBlocker(possibleBlockerId, game); game.informPlayer(controller, blockRequiredMessage + " Existing block removed. It's a requirement to block " + toBeBlockedCreature.getIdName() + '.'); @@ -918,9 +928,9 @@ public class Combat implements Serializable, Copyable { } else { // take the first potential blocker from the set to block for the AI - for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { + for (UUID possibleBlockerId : mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId)) { String blockRequiredMessage = isCreatureDoingARequiredBlock( - possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game); + possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastX, game); if (blockRequiredMessage != null) { // set the block Permanent possibleBlocker = game.getPermanent(possibleBlockerId); @@ -931,7 +941,9 @@ public class Combat implements Serializable, Copyable { } defender.declareBlocker(defender.getId(), possibleBlockerId, toBeBlockedCreatureId, game); } - break; + if (combatGroup.getBlockers().size() >= minNumberOfBlockersMap.get(toBeBlockedCreatureId)) { + break; + } } } } @@ -948,7 +960,7 @@ public class Combat implements Serializable, Copyable { if (creatureForcedToBlock == null) { break; } - if (!creatureForcedToBlock.getControllerId().equals(player.getId())) { + if (!creatureForcedToBlock.isControlledBy(player.getId())) { // ignore creatures controlled by other players continue; } @@ -999,8 +1011,8 @@ public class Combat implements Serializable, Copyable { } else // check if the blocker blocks a attacker that must be blocked at least by one and is the only blocker, this block is also valid { if (combatGroup.getBlockers().size() == 1) { - if (mustBeBlockedByAtLeastOne.containsKey(forcingAttackerId)) { - if (mustBeBlockedByAtLeastOne.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) { + if (mustBeBlockedByAtLeastX.containsKey(forcingAttackerId)) { + if (mustBeBlockedByAtLeastX.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) { blockIsValid = true; break CombatGroups; } @@ -1033,11 +1045,11 @@ public class Combat implements Serializable, Copyable { * * @param possibleBlockerId * @param toBeBlockedCreatureId - * @param mustBeBlockedByAtLeastOne + * @param mustBeBlockedByAtLeastX * @param game * @return null block is required otherwise message with reason why not */ - protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, UUID toBeBlockedCreatureId, Map> mustBeBlockedByAtLeastOne, Game game) { + protected String isCreatureDoingARequiredBlock(UUID possibleBlockerId, UUID toBeBlockedCreatureId, Map> mustBeBlockedByAtLeastX, Game game) { Permanent possibleBlocker = game.getPermanent(possibleBlockerId); if (possibleBlocker != null) { if (possibleBlocker.getBlocking() == 0) { @@ -1046,16 +1058,16 @@ public class Combat implements Serializable, Copyable { Set forcingAttackers = creatureMustBlockAttackers.get(possibleBlockerId); if (forcingAttackers == null) { // no other creature forces the blocker to block -> it's available - // check now, if it already blocks a creature that mustBeBlockedByAtLeastOne + // check now, if it already blocks a creature that mustBeBlockedByAtLeastX if (possibleBlocker.getBlocking() > 0) { CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId); if (combatGroupOfPossibleBlocker != null) { for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) { - if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) { + if (mustBeBlockedByAtLeastX.containsKey(blockedAttackerId)) { // blocks a creature that has to be blocked by at least one if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) { - Set blockedSet = mustBeBlockedByAtLeastOne.get(blockedAttackerId); - Set toBlockSet = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId); + Set blockedSet = mustBeBlockedByAtLeastX.get(blockedAttackerId); + Set toBlockSet = mustBeBlockedByAtLeastX.get(toBeBlockedCreatureId); if (toBlockSet == null) { // This should never happen.
 return null; @@ -1175,9 +1187,7 @@ public class Combat implements Serializable, Copyable { } break; case MULTIPLE: - for (UUID opponentId : game.getOpponents(attackingPlayerId)) { - attackablePlayers.add(opponentId); - } + attackablePlayers.addAll(game.getOpponents(attackingPlayerId)); break; } } @@ -1265,10 +1275,10 @@ public class Combat implements Serializable, Copyable { if (defenderAttackedBy.size() >= defendingPlayer.getMaxAttackedBy()) { Player attackingPlayer = game.getPlayer(game.getControllerId(attackerId)); if (attackingPlayer != null && !game.isSimulation()) { - game.informPlayer(attackingPlayer, new StringBuilder("No more than ") - .append(CardUtil.numberToText(defendingPlayer.getMaxAttackedBy())) - .append(" creatures can attack ") - .append(defendingPlayer.getLogName()).toString()); + game.informPlayer(attackingPlayer, "No more than " + + CardUtil.numberToText(defendingPlayer.getMaxAttackedBy()) + + " creatures can attack " + + defendingPlayer.getLogName()); } return false; } @@ -1298,7 +1308,7 @@ public class Combat implements Serializable, Copyable { * @param playerId * @param game * @param solveBanding check whether also add creatures banded with - * attackerId + * attackerId */ public void addBlockingGroup(UUID blockerId, UUID attackerId, UUID playerId, Game game, boolean solveBanding) { Permanent blocker = game.getPermanent(blockerId); @@ -1309,9 +1319,7 @@ public class Combat implements Serializable, Copyable { // add all blocked attackers for (CombatGroup group : groups) { if (group.getBlockers().contains(blockerId)) { - for (UUID attacker : group.attackers) { - newGroup.attackers.add(attacker); - } + newGroup.attackers.addAll(group.attackers); } } blockingGroups.put(blockerId, newGroup); @@ -1407,12 +1415,8 @@ public class Combat implements Serializable, Copyable { } public boolean hasFirstOrDoubleStrike(Game game) { - for (CombatGroup group : groups) { - if (group.hasFirstOrDoubleStrike(game)) { - return true; - } - } - return false; + return groups.stream() + .anyMatch(group -> group.hasFirstOrDoubleStrike(game)); } public CombatGroup findGroup(UUID attackerId) { @@ -1433,7 +1437,7 @@ public class Combat implements Serializable, Copyable { return null; } -// public int totalUnblockedDamage(Game game) { + // public int totalUnblockedDamage(Game game) { // int total = 0; // for (CombatGroup group : groups) { // if (group.getBlockers().isEmpty()) { @@ -1457,7 +1461,7 @@ public class Combat implements Serializable, Copyable { } if (group.defenderIsPlaneswalker) { Permanent permanent = game.getPermanent(group.getDefenderId()); - if (permanent.getControllerId().equals(defenderId)) { + if (permanent.isControlledBy(defenderId)) { return true; } } @@ -1466,7 +1470,6 @@ public class Combat implements Serializable, Copyable { } /** - * * @param attackerId * @return uuid of defending player or planeswalker */ diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java index cf414b96e0a..e357b6df977 100644 --- a/Mage/src/main/java/mage/game/combat/CombatGroup.java +++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java @@ -3,6 +3,8 @@ package mage.game.combat; import java.io.Serializable; import java.util.*; +import java.util.stream.Stream; + import mage.abilities.common.ControllerAssignCombatDamageToBlockersAbility; import mage.abilities.common.ControllerDivideCombatDamageAbility; import mage.abilities.common.DamageAsThoughNotBlockedAbility; @@ -12,6 +14,7 @@ import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TrampleAbility; +import mage.constants.AsThoughEffectType; import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.game.Game; @@ -60,19 +63,11 @@ public class CombatGroup implements Serializable, Copyable { } public boolean hasFirstOrDoubleStrike(Game game) { - for (UUID permId : attackers) { - Permanent attacker = game.getPermanent(permId); - if (attacker != null && hasFirstOrDoubleStrike(attacker)) { - return true; - } - } - for (UUID permId : blockers) { - Permanent blocker = game.getPermanent(permId); - if (blocker != null && hasFirstOrDoubleStrike(blocker)) { - return true; - } - } - return false; + return Stream.concat(attackers.stream(), blockers.stream()) + .map(id -> game.getPermanent(id)) + .filter(Objects::nonNull) + .anyMatch(this::hasFirstOrDoubleStrike); + } public UUID getDefenderId() { @@ -124,11 +119,14 @@ public class CombatGroup implements Serializable, Copyable { return; } else { Player player = game.getPlayer(defenderAssignsCombatDamage(game) ? defendingPlayerId : attacker.getControllerId()); - if (attacker.getAbilities().containsKey(DamageAsThoughNotBlockedAbility.getInstance().getId())) { // for handling creatures like Thorn Elemental - if (player.chooseUse(Outcome.Damage, "Do you wish to assign damage for " + attacker.getLogName() + " as though it weren't blocked?", null, game)) { - blocked = false; - unblockedDamage(first, game); - } + if ((attacker.getAbilities().containsKey(DamageAsThoughNotBlockedAbility.getInstance().getId()) && + player.chooseUse(Outcome.Damage, "Do you wish to assign damage for " + + attacker.getLogName() + " as though it weren't blocked?", null, game)) || + game.getContinuousEffects().asThough(attacker.getId(), AsThoughEffectType.DAMAGE_NOT_BLOCKED + , null, attacker.getControllerId(), game) != null) { + // for handling creatures like Thorn Elemental + blocked = false; + unblockedDamage(first, game); } if (blockers.size() == 1) { singleBlockerDamage(player, first, game); @@ -869,7 +867,7 @@ public class CombatGroup implements Serializable, Copyable { // for handling Butcher Orgg if (creature.getAbilities().containsKey(ControllerDivideCombatDamageAbility.getInstance().getId())) { Player player = game.getPlayer(defenderAssignsCombatDamage(game) ? defendingPlayerId : (!isAttacking && attackerAssignsCombatDamage(game) ? game.getCombat().getAttackingPlayerId() : playerId)); - // 10/4/2004 If it is blocked but then all of its blockers are removed before combat damage is assigned, then it won’t be able to deal combat damage and you won’t be able to use its ability. + // 10/4/2004 If it is blocked but then all of its blockers are removed before combat damage is assigned, then it won't be able to deal combat damage and you won't be able to use its ability. // (same principle should apply if it's blocking and its blocked attacker is removed from combat) if (!((blocked && blockers.isEmpty() && isAttacking) || (attackers.isEmpty() && !isAttacking)) && canDamage(creature, first)) { if (player.chooseUse(Outcome.Damage, "Do you wish to assign " + creature.getLogName() + "'s combat damage divided among defending player and/or any number of defending creatures?", null, game)) { diff --git a/Mage/src/main/java/mage/game/command/emblems/AjaniAdversaryOfTyrantsEmblem.java b/Mage/src/main/java/mage/game/command/emblems/AjaniAdversaryOfTyrantsEmblem.java new file mode 100644 index 00000000000..3a74eac9dd7 --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/AjaniAdversaryOfTyrantsEmblem.java @@ -0,0 +1,25 @@ +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.CatToken2; + +/** + * + * @author TheElk801 + */ +public class AjaniAdversaryOfTyrantsEmblem extends Emblem { + + // −7: You get an emblem with "At the beginning of your end step, create three 1/1 white Cat creature tokens with lifelink." + public AjaniAdversaryOfTyrantsEmblem() { + this.setName("Emblem Ajani"); + this.setExpansionSetCodeForImage("M19"); + this.getAbilities().add(new BeginningOfEndStepTriggeredAbility( + Zone.COMMAND, new CreateTokenEffect(new CatToken2(), 3), + TargetController.YOU, null, false + )); + } +} diff --git a/Mage/src/main/java/mage/game/command/emblems/AjaniSteadfastEmblem.java b/Mage/src/main/java/mage/game/command/emblems/AjaniSteadfastEmblem.java index 40675d7daf9..755291e0392 100644 --- a/Mage/src/main/java/mage/game/command/emblems/AjaniSteadfastEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/AjaniSteadfastEmblem.java @@ -60,7 +60,7 @@ class AjaniSteadfastPreventEffect extends PreventionEffectImpl { if (event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return super.applies(event, source, game); } } diff --git a/Mage/src/main/java/mage/game/command/emblems/DarettiScrapSavantEmblem.java b/Mage/src/main/java/mage/game/command/emblems/DarettiScrapSavantEmblem.java index 8e91c02d57d..246f783855c 100644 --- a/Mage/src/main/java/mage/game/command/emblems/DarettiScrapSavantEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/DarettiScrapSavantEmblem.java @@ -59,7 +59,7 @@ class DarettiScrapSavantTriggeredAbility extends TriggeredAbilityImpl { if (zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getTarget().isArtifact() - && zEvent.getTarget().getOwnerId().equals(this.controllerId)) { + && zEvent.getTarget().isOwnedBy(this.controllerId)) { this.getEffects().setTargetPointer(new FixedTarget(zEvent.getTargetId())); return true; } diff --git a/Mage/src/main/java/mage/game/command/emblems/ElspethSunsChampionEmblem.java b/Mage/src/main/java/mage/game/command/emblems/ElspethSunsChampionEmblem.java index dba80ba4561..72e045663eb 100644 --- a/Mage/src/main/java/mage/game/command/emblems/ElspethSunsChampionEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/ElspethSunsChampionEmblem.java @@ -1,4 +1,3 @@ - package mage.game.command.emblems; import mage.abilities.Ability; @@ -8,7 +7,7 @@ import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.FlyingAbility; import mage.constants.Duration; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.command.Emblem; /** @@ -16,16 +15,24 @@ import mage.game.command.Emblem; * @author spjspj */ public class ElspethSunsChampionEmblem extends Emblem { + // -7: You get an emblem with "Creatures you control get +2/+2 and have flying." - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures"); - public ElspethSunsChampionEmblem() { this.setName("Emblem Elspeth"); this.setExpansionSetCodeForImage("THS"); - Ability ability = new SimpleStaticAbility(Zone.COMMAND, new BoostControlledEffect(2, 2, Duration.EndOfGame, filter, false)); - ability.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfGame, filter)); + Ability ability = new SimpleStaticAbility( + Zone.COMMAND, + new BoostControlledEffect( + 2, 2, Duration.EndOfGame, + StaticFilters.FILTER_PERMANENT_CREATURES, + false + ).setText("creatures you control get +2/+2") + ); + ability.addEffect(new GainAbilityControlledEffect( + FlyingAbility.getInstance(), + Duration.EndOfGame, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and have flying")); this.getAbilities().add(ability); - } } diff --git a/Mage/src/main/java/mage/game/command/emblems/LukeSkywalkerEmblem.java b/Mage/src/main/java/mage/game/command/emblems/LukeSkywalkerEmblem.java new file mode 100644 index 00000000000..037d7c0cdfd --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/LukeSkywalkerEmblem.java @@ -0,0 +1,61 @@ +package mage.game.command.emblems; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; +import mage.abilities.effects.common.PreventAllDamageToPlayersEffect; +import mage.constants.*; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.game.events.GameEvent; +import mage.game.permanent.token.CatToken2; +import mage.game.turn.Phase; +import mage.players.Player; + +/** + * + * @author NinthWorld + */ +public class LukeSkywalkerEmblem extends Emblem { + + // -6: You get an emblem with "Prevent all damage that would be dealt to you during combat." Exile Luke Skywalker, the Last Jedi. + public LukeSkywalkerEmblem() { + this.setName("Emblem Luke Skywalker"); + this.setExpansionSetCodeForImage("SWS"); + this.getAbilities().add(new SimpleStaticAbility(Zone.BATTLEFIELD, new LukeSkywalkerEmblemEffect())); + } +} + +class LukeSkywalkerEmblemEffect extends PreventionEffectImpl { + + public LukeSkywalkerEmblemEffect() { + super(Duration.Custom, Integer.MAX_VALUE, false); + staticText = "Prevent all damage that would be dealt to you during combat"; + } + + public LukeSkywalkerEmblemEffect(final LukeSkywalkerEmblemEffect effect) { + super(effect); + } + + @Override + public LukeSkywalkerEmblemEffect copy() { + return new LukeSkywalkerEmblemEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (game.getPhase().getType() == TurnPhase.COMBAT + && super.applies(event, source, game) + && event.getType() == GameEvent.EventType.DAMAGE_PLAYER) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && game.getState().getPlayersInRange(controller.getId(), game).contains(event.getTargetId())) { + return true; + } + } + return false; + } +} diff --git a/Mage/src/main/java/mage/game/command/emblems/RowanKenrithEmblem.java b/Mage/src/main/java/mage/game/command/emblems/RowanKenrithEmblem.java index 8a34621a24f..46ecdbb4e68 100644 --- a/Mage/src/main/java/mage/game/command/emblems/RowanKenrithEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/RowanKenrithEmblem.java @@ -1,19 +1,18 @@ - package mage.game.command.emblems; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.mana.ManaAbility; +import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.command.Emblem; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; -import mage.game.stack.StackObject; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; /** * @@ -30,14 +29,19 @@ public class RowanKenrithEmblem extends Emblem { class RowanKenrithEmblemTriggeredAbility extends TriggeredAbilityImpl { - public RowanKenrithEmblemTriggeredAbility() { - super(Zone.COMMAND, new RowanKenrithEmblemCopyEffect(), false); + RowanKenrithEmblemTriggeredAbility() { + super(Zone.COMMAND, new RowanKenrithEmblemEffect(), false); } - public RowanKenrithEmblemTriggeredAbility(final RowanKenrithEmblemTriggeredAbility ability) { + RowanKenrithEmblemTriggeredAbility(final RowanKenrithEmblemTriggeredAbility ability) { super(ability); } + @Override + public RowanKenrithEmblemTriggeredAbility copy() { + return new RowanKenrithEmblemTriggeredAbility(this); + } + @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; @@ -45,10 +49,11 @@ class RowanKenrithEmblemTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId().equals(this.getControllerId())) { - StackObject ability = game.getStack().getStackObject(event.getTargetId()); - if (ability != null && !(ability instanceof ManaAbility)) { - this.getEffects().get(0).setTargetPointer(new FixedTarget(ability.getId())); + if (event.getPlayerId().equals(getControllerId())) { + StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); + if (stackAbility != null && !(stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl)) { + Effect effect = this.getEffects().get(0); + effect.setValue("stackAbility", stackAbility); return true; } } @@ -59,40 +64,38 @@ class RowanKenrithEmblemTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever you activate an ability that isn't a mana ability, copy it. You may choose new targets for the copy."; } - - @Override - public RowanKenrithEmblemTriggeredAbility copy() { - return new RowanKenrithEmblemTriggeredAbility(this); - } } -class RowanKenrithEmblemCopyEffect extends OneShotEffect { +class RowanKenrithEmblemEffect extends OneShotEffect { - public RowanKenrithEmblemCopyEffect() { - super(Outcome.Copy); - this.staticText = "copy it. You may choose new targets for the copy."; + RowanKenrithEmblemEffect() { + super(Outcome.Benefit); + this.staticText = ", copy it. You may choose new targets for the copy."; } - public RowanKenrithEmblemCopyEffect(final RowanKenrithEmblemCopyEffect effect) { + RowanKenrithEmblemEffect(final RowanKenrithEmblemEffect effect) { super(effect); } @Override - public boolean apply(Game game, Ability source) { - StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(targetPointer.getFirst(game, source)); - if (stackAbility != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - stackAbility.createCopyOnStack(game, source, source.getControllerId(), true); - return true; - } - } - return false; - + public RowanKenrithEmblemEffect copy() { + return new RowanKenrithEmblemEffect(this); } @Override - public RowanKenrithEmblemCopyEffect copy() { - return new RowanKenrithEmblemCopyEffect(this); + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + StackAbility ability = (StackAbility) getValue("stackAbility"); + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (ability != null && controller != null && sourcePermanent != null) { + ability.createCopyOnStack(game, source, source.getControllerId(), true); + game.informPlayers(sourcePermanent.getIdName() + ": " + controller.getLogName() + " copied activated ability"); + return true; + } + return false; } } diff --git a/Mage/src/main/java/mage/game/command/emblems/TezzeretArtificeMasterEmblem.java b/Mage/src/main/java/mage/game/command/emblems/TezzeretArtificeMasterEmblem.java new file mode 100644 index 00000000000..397aac8c660 --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/TezzeretArtificeMasterEmblem.java @@ -0,0 +1,28 @@ +package mage.game.command.emblems; + +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterPermanentCard; +import mage.game.command.Emblem; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author TheElk801 + */ +public class TezzeretArtificeMasterEmblem extends Emblem { + + // −9: You get an emblem with "At the beginning of your end step, search your library for a permanent card, put it into the battlefield, then shuffle your library." + public TezzeretArtificeMasterEmblem() { + this.setName("Emblem Tezzeret"); + this.setExpansionSetCodeForImage("M19"); + this.getAbilities().add(new BeginningOfEndStepTriggeredAbility( + Zone.COMMAND, + new SearchLibraryPutInPlayEffect( + new TargetCardInLibrary(new FilterPermanentCard()) + ), TargetController.YOU, null, false + )); + } +} diff --git a/Mage/src/main/java/mage/game/command/emblems/VivienReidEmblem.java b/Mage/src/main/java/mage/game/command/emblems/VivienReidEmblem.java new file mode 100644 index 00000000000..c411e581dfd --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/VivienReidEmblem.java @@ -0,0 +1,51 @@ +package mage.game.command.emblems; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.command.Emblem; + +/** + * + * @author spjspj + */ +public class VivienReidEmblem extends Emblem { + // -8: You get an emblem with "Creatures you control get +2/+2 and have vigilance, trample, and indestructible. + + public VivienReidEmblem() { + this.setName("Emblem Vivien"); + this.setExpansionSetCodeForImage("M19"); + Ability ability = new SimpleStaticAbility( + Zone.COMMAND, + new BoostControlledEffect( + 2, 2, Duration.EndOfGame, + StaticFilters.FILTER_PERMANENT_CREATURES, + false + ).setText("creatures you control get +2/+2") + ); + ability.addEffect(new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), + Duration.EndOfGame, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and have vigilance,")); + ability.addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), + Duration.EndOfGame, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("trample,")); + ability.addEffect(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), + Duration.EndOfGame, + StaticFilters.FILTER_PERMANENT_CREATURES + ).setText("and indestructible")); + this.getAbilities().add(ability); + + } +} 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 85fa828de72..0574973f5c8 100644 --- a/Mage/src/main/java/mage/game/command/emblems/WillKenrithEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/WillKenrithEmblem.java @@ -20,7 +20,7 @@ public class WillKenrithEmblem extends Emblem { Zone.COMMAND, new CopyTargetSpellEffect(true) .setText("copy that spell. You may choose new targets for the copy"), - StaticFilters.FILTER_INSTANT_OR_SORCERY_SPELL, + StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false, true )); diff --git a/Mage/src/main/java/mage/game/command/planes/TrailOfTheMageRingsPlane.java b/Mage/src/main/java/mage/game/command/planes/TrailOfTheMageRingsPlane.java index 318f07c375c..1af66697987 100644 --- a/Mage/src/main/java/mage/game/command/planes/TrailOfTheMageRingsPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/TrailOfTheMageRingsPlane.java @@ -115,7 +115,7 @@ class TrailOfTheMageRingsReboundEffect extends ContinuousEffectImpl { } for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { StackObject stackObject = iterator.next(); - if (stackObject instanceof Spell && stackObject.getControllerId().equals(source.getControllerId())) { + if (stackObject instanceof Spell && stackObject.isControlledBy(source.getControllerId())) { Spell spell = (Spell) stackObject; Card card = spell.getCard(); if (card != null) { diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index 9f1f77659b9..958d4e736e2 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -1,4 +1,3 @@ - package mage.game.events; import java.io.Serializable; @@ -72,6 +71,7 @@ public class GameEvent implements Serializable { MIRACLE_CARD_REVEALED, MADNESS_CARD_EXILED, INVESTIGATED, + KICKED, DISCARD_CARD, DISCARDED_CARD, CYCLE_CARD, CYCLED_CARD, @@ -198,6 +198,10 @@ public class GameEvent implements Serializable { */ DECLARING_BLOCKERS, DECLARED_BLOCKERS, + /* DECLARING_BLOCKERS + targetId id of the blocking player + sourceId id of the blocking player + */ DECLARE_BLOCKER, BLOCKER_DECLARED, CREATURE_BLOCKED, UNBLOCKED_ATTACKER, diff --git a/Mage/src/main/java/mage/game/permanent/Battlefield.java b/Mage/src/main/java/mage/game/permanent/Battlefield.java index 58eac0788e4..c9df6b058c6 100644 --- a/Mage/src/main/java/mage/game/permanent/Battlefield.java +++ b/Mage/src/main/java/mage/game/permanent/Battlefield.java @@ -58,7 +58,7 @@ public class Battlefield implements Serializable { public int countAll(FilterPermanent filter, UUID controllerId, Game game) { return (int) field.values() .stream() - .filter(permanent -> permanent.getControllerId().equals(controllerId) + .filter(permanent -> permanent.isControlledBy(controllerId) && filter.match(permanent, game) && permanent.isPhasedIn()) .count(); @@ -124,7 +124,7 @@ public class Battlefield implements Serializable { public boolean contains(FilterPermanent filter, UUID controllerId, int num, Game game) { return field.values() .stream() - .filter(permanent -> permanent.getControllerId().equals(controllerId) + .filter(permanent -> permanent.isControlledBy(controllerId) && filter.match(permanent, game) && permanent.isPhasedIn()) .count() >= num; @@ -213,7 +213,7 @@ public class Battlefield implements Serializable { return field.values() .stream() .filter(perm -> perm.isPhasedIn() - && perm.getControllerId().equals(controllerId)) + && perm.isControlledBy(controllerId)) .collect(Collectors.toList()); } @@ -261,7 +261,7 @@ public class Battlefield implements Serializable { public List getAllActivePermanents(FilterPermanent filter, UUID controllerId, Game game) { return field.values() .stream() - .filter(perm -> perm.isPhasedIn() && perm.getControllerId().equals(controllerId) && filter.match(perm, game)) + .filter(perm -> perm.isPhasedIn() && perm.isControlledBy(controllerId) && filter.match(perm, game)) .collect(Collectors.toList()); } @@ -333,14 +333,14 @@ public class Battlefield implements Serializable { .stream() .filter(perm -> perm.getAbilities().containsKey(PhasingAbility.getInstance().getId()) && perm.isPhasedIn() && - perm.getControllerId().equals(controllerId)) + perm.isControlledBy(controllerId)) .collect(Collectors.toList()); } public List getPhasedOut(UUID controllerId) { return field.values() .stream() - .filter(perm -> !perm.isPhasedIn() && perm.getControllerId().equals(controllerId)) + .filter(perm -> !perm.isPhasedIn() && perm.isControlledBy(controllerId)) .collect(Collectors.toList()); } diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index da6a39a9fac..1e17d0e8a9a 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -353,4 +353,11 @@ public interface Permanent extends Card, Controllable { void setCreateOrder(int createOrder); + default boolean isAttachedTo(UUID otherId){ + if(getAttachedTo() == null){ + return false; + } + return getAttachedTo().equals(otherId); + } + } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index d089ee06d91..eef81055552 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -178,7 +178,7 @@ public class PermanentCard extends PermanentImpl { @Override public int getConvertedManaCost() { if (isTransformed()) { - // 711.4b While a double-faced permanent’s back face is up, it has only the characteristics of its back face. + // 711.4b While a double-faced permanent's back face is up, it has only the characteristics of its back face. // However, its converted mana cost is calculated using the mana cost of its front face. This is a change from previous rules. // If a permanent is copying the back face of a double-faced card (even if the card representing that copy // is itself a double-faced card), the converted mana cost of that permanent is 0. diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index c90b047103b..74739b25a37 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -1,7 +1,6 @@ package mage.game.permanent; -import java.util.*; import mage.MageObject; import mage.MageObjectReference; import mage.ObjectColor; @@ -36,6 +35,8 @@ import mage.util.GameLog; import mage.util.ThreadLocalStringBuilder; import org.apache.log4j.Logger; +import java.util.*; + /** * @author BetaSteward_at_googlemail.com */ @@ -316,7 +317,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public void beginningOfTurn(Game game) { - if (game.getActivePlayerId().equals(this.controllerId)) { + if (game.isActivePlayer(this.controllerId)) { this.controlledFromStartOfControllerTurn = true; } } @@ -493,6 +494,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { attachedPerm.phaseOut(game, true); } } + this.removeFromCombat(game); this.phasedIn = false; this.indirectPhase = indirectPhase; if (!game.isSimulation()) { @@ -630,11 +632,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public List getConnectedCards(String key) { - if (this.connectedCards.containsKey(key)) { - return this.connectedCards.get(key); - } else { - return emptyList; - } + return this.connectedCards.getOrDefault(key, emptyList); } @Override diff --git a/Mage/src/main/java/mage/game/permanent/token/AngelToken2.java b/Mage/src/main/java/mage/game/permanent/token/AngelToken2.java new file mode 100644 index 00000000000..9369b05c36f --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/AngelToken2.java @@ -0,0 +1,29 @@ +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; + +public final class AngelToken2 extends TokenImpl { + + public AngelToken2() { + super("Angel", "4/4 white Angel creature token with flying and vigilance"); + cardType.add(CardType.CREATURE); + color.setWhite(true); + subtype.add(SubType.ANGEL); + power = new MageInt(4); + toughness = new MageInt(4); + addAbility(FlyingAbility.getInstance()); + addAbility(VigilanceAbility.getInstance()); + } + + public AngelToken2(final AngelToken2 token) { + super(token); + } + + public AngelToken2 copy() { + return new AngelToken2(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/AvatarToken2.java b/Mage/src/main/java/mage/game/permanent/token/AvatarToken2.java new file mode 100644 index 00000000000..b63e3e14c5b --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/AvatarToken2.java @@ -0,0 +1,27 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +public final class AvatarToken2 extends TokenImpl { + + public AvatarToken2() { + super("Avatar", "4/4 white Avatar creature token with flying"); + cardType.add(CardType.CREATURE); + color.setWhite(true); + subtype.add(SubType.AVATAR); + power = new MageInt(4); + toughness = new MageInt(4); + addAbility(FlyingAbility.getInstance()); + } + + public AvatarToken2(final AvatarToken2 token) { + super(token); + } + + public AvatarToken2 copy() { + return new AvatarToken2(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/BeastToken4.java b/Mage/src/main/java/mage/game/permanent/token/BeastToken4.java new file mode 100644 index 00000000000..d6b579b4514 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/BeastToken4.java @@ -0,0 +1,45 @@ + +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public final class BeastToken4 extends TokenImpl { + + public BeastToken4() { + this(null, 0); + } + + public BeastToken4(String setCode) { + this(setCode, 0); + } + + public BeastToken4(String setCode, int tokenType) { + super("Beast", "2/2 green Beast creature token"); + setOriginalExpansionSetCode(setCode != null ? setCode : "EXO"); + cardType.add(CardType.CREATURE); + color.setGreen(true); + subtype.add(SubType.BEAST); + power = new MageInt(2); + toughness = new MageInt(2); + + } + + public BeastToken4(final BeastToken4 token) { + super(token); + } + + @Override + public BeastToken4 copy() { + return new BeastToken4(this); + } +} 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 4ba0d93601d..81883c03a14 100644 --- a/Mage/src/main/java/mage/game/permanent/token/BelzenlokDemonToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/BelzenlokDemonToken.java @@ -21,6 +21,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.Player; /** * @@ -94,9 +95,9 @@ class BelzenlokDemonTokenEffect extends OneShotEffect { if (otherCreatures > 0) { new SacrificeControllerEffect(filter, 1, "").apply(game, source); } else { - Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (permanent != null) { - permanent.damage(6, permanent.getId(), game, false, true); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.damage(6, source.getSourceId(), game, false, true); } } return true; diff --git a/Mage/src/main/java/mage/game/permanent/token/BrudicladTelchorMyrToken.java b/Mage/src/main/java/mage/game/permanent/token/BrudicladTelchorMyrToken.java new file mode 100644 index 00000000000..33de29d06fa --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/BrudicladTelchorMyrToken.java @@ -0,0 +1,43 @@ +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; + +public final class BrudicladTelchorMyrToken extends TokenImpl { + + final static private List tokenImageSets = new ArrayList<>(); + + static { + tokenImageSets.addAll(Arrays.asList("C18")); + } + + public BrudicladTelchorMyrToken() { + this((String)null); + } + + public BrudicladTelchorMyrToken(String expansionSetCode) { + super("Myr", "2/1 blue Myr artifact creature token"); + this.setOriginalExpansionSetCode(expansionSetCode); + cardType.add(CardType.CREATURE); + cardType.add(CardType.ARTIFACT); + subtype.add(SubType.MYR); + color.setBlue(true); + power = new MageInt(2); + toughness = new MageInt(1); + + availableImageSetCodes = tokenImageSets; + } + + public BrudicladTelchorMyrToken(final BrudicladTelchorMyrToken token) { + super(token); + } + + public BrudicladTelchorMyrToken copy() { + return new BrudicladTelchorMyrToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/MaskToken.java b/Mage/src/main/java/mage/game/permanent/token/MaskToken.java new file mode 100644 index 00000000000..662ee9e0603 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/MaskToken.java @@ -0,0 +1,44 @@ +package mage.game.permanent.token; + +import mage.abilities.Ability; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TotemArmorAbility; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public final class MaskToken extends TokenImpl { + + public MaskToken() { + super( + "Mask", "white Aura enchantment token named Mask " + + "attached to another target permanent. " + + "The token has enchant permanent and totem armor." + ); + cardType.add(CardType.ENCHANTMENT); + color.setWhite(true); + subtype.add(SubType.AURA); + + TargetPermanent auraTarget = new TargetPermanent(); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + ability.addTarget(auraTarget); + ability.addEffect(new AttachEffect(Outcome.BoostCreature)); + this.addAbility(ability); + + this.addAbility(new TotemArmorAbility()); + } + + public MaskToken(final MaskToken token) { + super(token); + } + + public MaskToken copy() { + return new MaskToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/NestingDragonToken.java b/Mage/src/main/java/mage/game/permanent/token/NestingDragonToken.java new file mode 100644 index 00000000000..e33ce893297 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/NestingDragonToken.java @@ -0,0 +1,45 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * + * @author spjspj + */ +public final class NestingDragonToken extends TokenImpl { + + public NestingDragonToken() { + super( + "Dragon Egg", + "0/2 red Dragon Egg creature token with defender and " + + "\"" + + "When this creature dies, " + + "create a 2/2 red Dragon creature token with flying and " + + "'{R}: This creature gets +1/+0 until end of turn.'" + + "\"" + ); + cardType.add(CardType.CREATURE); + color.setRed(true); + subtype.add(SubType.DRAGON); + subtype.add(SubType.EGG); + power = new MageInt(0); + toughness = new MageInt(2); + addAbility(DefenderAbility.getInstance()); + this.addAbility(new DiesTriggeredAbility( + new CreateTokenEffect(new DragonEggDragonToken()), false + )); + } + + public NestingDragonToken(final NestingDragonToken token) { + super(token); + } + + public NestingDragonToken copy() { + return new NestingDragonToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/OxToken.java b/Mage/src/main/java/mage/game/permanent/token/OxToken.java new file mode 100644 index 00000000000..082fe757927 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/OxToken.java @@ -0,0 +1,32 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public final class OxToken extends TokenImpl { + + public OxToken() { + super("Ox", "2/4 white Ox creature token"); + + cardType.add(CardType.CREATURE); + color.setWhite(true); + subtype.add(SubType.OX); + power = new MageInt(2); + toughness = new MageInt(4); + + } + + public OxToken(final OxToken token) { + super(token); + } + + @Override + public OxToken copy() { + return new OxToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/PorgToken.java b/Mage/src/main/java/mage/game/permanent/token/PorgToken.java new file mode 100644 index 00000000000..fc09a8c7a53 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/PorgToken.java @@ -0,0 +1,39 @@ + + +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.keyword.MonstrosityAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.Collections; + +/** + * + * @author NinthWorld + */ +public final class PorgToken extends TokenImpl { + + public PorgToken() { + super("Porg", "0/1 green Bird creature token named Porg with \"{G}: Monstrosity 1.\""); + availableImageSetCodes.addAll(Collections.singletonList("SWS")); + + cardType.add(CardType.CREATURE); + subtype.add(SubType.BIRD); + + color.setGreen(true); + power = new MageInt(0); + toughness = new MageInt(1); + + this.addAbility(new MonstrosityAbility("{G}", 1)); + } + + public PorgToken(final PorgToken token) { + super(token); + } + + public PorgToken copy() { + return new PorgToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/RetrofitterFoundryToken.java b/Mage/src/main/java/mage/game/permanent/token/RetrofitterFoundryToken.java new file mode 100644 index 00000000000..c413d20bcac --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/RetrofitterFoundryToken.java @@ -0,0 +1,34 @@ +package mage.game.permanent.token; + +import mage.constants.CardType; +import mage.constants.SubType; +import mage.MageInt; + +/** + * + * @author TheElk801 + */ +public final class RetrofitterFoundryToken extends TokenImpl { + + public RetrofitterFoundryToken() { + this("C18"); + } + + public RetrofitterFoundryToken(String setCode) { + super("Construct", "4/4 colorless Construct artifact creature token"); + this.setOriginalExpansionSetCode(setCode); + cardType.add(CardType.ARTIFACT); + cardType.add(CardType.CREATURE); + subtype.add(SubType.CONSTRUCT); + power = new MageInt(4); + toughness = new MageInt(4); + } + + public RetrofitterFoundryToken(final RetrofitterFoundryToken token) { + super(token); + } + + public RetrofitterFoundryToken copy() { + return new RetrofitterFoundryToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/TetraviteToken.java b/Mage/src/main/java/mage/game/permanent/token/TetraviteToken.java index 7ff53e0f125..aef40c90d55 100644 --- a/Mage/src/main/java/mage/game/permanent/token/TetraviteToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/TetraviteToken.java @@ -1,14 +1,17 @@ - - package mage.game.permanent.token; + import mage.constants.CardType; import mage.MageInt; -import mage.MageObject; -import mage.abilities.StaticAbility; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.keyword.FlyingAbility; +import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; +import mage.game.events.GameEvent; /** * @@ -17,7 +20,7 @@ import mage.game.Game; public final class TetraviteToken extends TokenImpl { public TetraviteToken() { - super("Tetravite", "1/1 colorless Tetravite artifact creature token"); + super("Tetravite", "1/1 colorless Tetravite artifact creature token with flying and \"This creature can’t be enchanted.\""); cardType.add(CardType.CREATURE); cardType.add(CardType.ARTIFACT); subtype.add(SubType.TETRAVITE); @@ -25,7 +28,7 @@ public final class TetraviteToken extends TokenImpl { toughness = new MageInt(1); this.addAbility(FlyingAbility.getInstance()); - this.addAbility(new CantBeEnchantedAbility()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TetraviteTokenEffect())); } public TetraviteToken(final TetraviteToken token) { @@ -37,24 +40,30 @@ public final class TetraviteToken extends TokenImpl { } } -class CantBeEnchantedAbility extends StaticAbility { +class TetraviteTokenEffect extends ContinuousRuleModifyingEffectImpl { - public CantBeEnchantedAbility() { - super(Zone.BATTLEFIELD, null); + public TetraviteTokenEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "this creature can't be enchanted"; } - public CantBeEnchantedAbility(final CantBeEnchantedAbility ability) { - super(ability); + public TetraviteTokenEffect(final TetraviteTokenEffect effect) { + super(effect); } @Override - public CantBeEnchantedAbility copy() { - return new CantBeEnchantedAbility(this); + public TetraviteTokenEffect copy() { + return new TetraviteTokenEffect(this); } - public boolean canTarget(MageObject source, Game game) { - return !(source.isEnchantment() - && source.hasSubtype(SubType.AURA, game)); + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ATTACH + || event.getType() == GameEvent.EventType.STAY_ATTACHED; } + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getTargetId().equals(source.getSourceId()); + } } diff --git a/Mage/src/main/java/mage/game/permanent/token/TrooperToken2.java b/Mage/src/main/java/mage/game/permanent/token/TrooperToken2.java new file mode 100644 index 00000000000..6a35e1f3651 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/TrooperToken2.java @@ -0,0 +1,36 @@ + +package mage.game.permanent.token; + +import java.util.Collections; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * + * @author NinthWorld + */ +public final class TrooperToken2 extends TokenImpl { + + public TrooperToken2() { + super("Trooper", "1/1 black Trooper creature token"); + availableImageSetCodes.addAll(Collections.singletonList("SWS")); + this.setTokenType(2); + + cardType.add(CardType.CREATURE); + subtype.add(SubType.TROOPER); + + color.setBlack(true); + power = new MageInt(1); + toughness = new MageInt(1); + } + + public TrooperToken2(final TrooperToken2 token) { + super(token); + } + + public TrooperToken2 copy() { + return new TrooperToken2(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/YoungPyromancerElementalToken.java b/Mage/src/main/java/mage/game/permanent/token/YoungPyromancerElementalToken.java index f304fc3a0f4..a59f93d0694 100644 --- a/Mage/src/main/java/mage/game/permanent/token/YoungPyromancerElementalToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/YoungPyromancerElementalToken.java @@ -1,4 +1,3 @@ - package mage.game.permanent.token; import mage.MageInt; @@ -13,7 +12,7 @@ import mage.util.RandomUtil; public final class YoungPyromancerElementalToken extends TokenImpl { public YoungPyromancerElementalToken() { - super("Elemental", "1/1 red Elemental creature"); + super("Elemental", "1/1 red Elemental creature token"); if (getOriginalExpansionSetCode() != null && getOriginalExpansionSetCode().equals("M14")) { setTokenType(RandomUtil.nextInt(2) + 1); } diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index c729298ce46..281a6485dd7 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -67,6 +67,7 @@ public class Spell extends StackObjImpl implements Card { private boolean faceDown; private boolean countered; private boolean resolving = false; + private UUID commandedBy = null; // for Word of Command private boolean doneActivatingManaAbilities; // if this is true, the player is no longer allowed to pay the spell costs with activating of mana abilies @@ -121,6 +122,7 @@ public class Spell extends StackObjImpl implements Card { this.faceDown = spell.faceDown; this.countered = spell.countered; this.resolving = spell.resolving; + this.commandedBy = spell.commandedBy; this.doneActivatingManaAbilities = spell.doneActivatingManaAbilities; this.targetChanged = spell.targetChanged; @@ -179,6 +181,12 @@ public class Spell extends StackObjImpl implements Card { return false; } this.resolving = true; + if (commandedBy != null && !commandedBy.equals(getControllerId())) { + Player turnController = game.getPlayer(commandedBy); + if (turnController != null) { + turnController.controlPlayersTurn(game, controller.getId()); + } + } if (this.isInstant() || this.isSorcery()) { int index = 0; result = false; @@ -244,7 +252,7 @@ public class Spell extends StackObjImpl implements Card { // card will be copied during putOntoBattlefield, so the card of CardPermanent has to be changed // TODO: Find a better way to prevent bestow creatures from being effected by creature affecting abilities Permanent permanent = game.getPermanent(card.getId()); - if (permanent != null && permanent instanceof PermanentCard) { + if (permanent instanceof PermanentCard) { permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set if (!card.getCardType().contains(CardType.CREATURE)) { card.addCardType(CardType.CREATURE); @@ -264,7 +272,7 @@ public class Spell extends StackObjImpl implements Card { updateOptionalCosts(0); if (controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null)) { Permanent permanent = game.getPermanent(card.getId()); - if (permanent != null && permanent instanceof PermanentCard) { + if (permanent instanceof PermanentCard) { ((PermanentCard) permanent).getCard().addCardType(CardType.CREATURE); ((PermanentCard) permanent).getCard().getSubtype(game).remove(SubType.AURA); return true; @@ -1024,4 +1032,12 @@ public class Spell extends StackObjImpl implements Card { throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates. } + public void setCommandedBy(UUID playerId) { + this.commandedBy = playerId; + } + + public UUID getCommandedBy() { + return commandedBy; + } + } diff --git a/Mage/src/main/java/mage/game/stack/SpellStack.java b/Mage/src/main/java/mage/game/stack/SpellStack.java index 71ad426f8bb..40b5c963883 100644 --- a/Mage/src/main/java/mage/game/stack/SpellStack.java +++ b/Mage/src/main/java/mage/game/stack/SpellStack.java @@ -37,10 +37,11 @@ public class SpellStack extends ArrayDeque { try { top = this.peek(); top.resolve(game); + game.resetControlAfterSpellResolve(top.getId()); } finally { if (top != null) { if (contains(top)) { - logger.warn("StackObject was still on the stack after resoving" + top.getName()); + logger.warn("StackObject was still on the stack after resolving" + top.getName()); this.remove(top, game); } } @@ -89,10 +90,10 @@ public class SpellStack extends ArrayDeque { game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName()); } game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); + return true; } else if (!game.isSimulation()) { game.informPlayers(counteredObjectName + " could not be countered by " + sourceObject.getLogName()); } - return true; } return false; } diff --git a/Mage/src/main/java/mage/players/Library.java b/Mage/src/main/java/mage/players/Library.java index 5841a85ce91..3c896d5b837 100644 --- a/Mage/src/main/java/mage/players/Library.java +++ b/Mage/src/main/java/mage/players/Library.java @@ -101,7 +101,7 @@ public class Library implements Serializable { } public void putOnTop(Card card, Game game) { - if (card.getOwnerId().equals(playerId)) { + if (card.isOwnedBy(playerId)) { card.setZone(Zone.LIBRARY, game); library.addFirst(card.getId()); } else { @@ -125,7 +125,7 @@ public class Library implements Serializable { } public void putOnBottom(Card card, Game game) { - if (card.getOwnerId().equals(playerId)) { + if (card.isOwnedBy(playerId)) { card.setZone(Zone.LIBRARY, game); library.remove(card.getId()); library.add(card.getId()); diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index cb099ddebd9..f95b01e1361 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -1,4 +1,3 @@ - package mage.players; import java.io.Serializable; @@ -36,6 +35,8 @@ public class ManaPool implements Serializable { private boolean autoPayment; // auto payment from mana pool: true - mode is active private boolean autoPaymentRestricted; // auto payment from mana pool: true - if auto Payment is on, it will only pay if one kind of mana is in the pool private ManaType unlockedManaType; // type of mana that was selected to pay manually + private boolean forcedToPay; // for Word of Command + private final List poolBookmark = new ArrayList<>(); // mana pool bookmark for rollback purposes private final Set doNotEmptyManaTypes = new HashSet<>(); @@ -44,6 +45,7 @@ public class ManaPool implements Serializable { autoPayment = true; autoPaymentRestricted = true; unlockedManaType = null; + forcedToPay = false; } public ManaPool(final ManaPool pool) { @@ -54,6 +56,10 @@ public class ManaPool implements Serializable { this.autoPayment = pool.autoPayment; this.autoPaymentRestricted = pool.autoPaymentRestricted; this.unlockedManaType = pool.unlockedManaType; + this.forcedToPay = pool.forcedToPay; + for (ManaPoolItem item : pool.poolBookmark) { + poolBookmark.add(item.copy()); + } this.doNotEmptyManaTypes.addAll(pool.doNotEmptyManaTypes); } @@ -88,12 +94,12 @@ public class ManaPool implements Serializable { * @return */ public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, Mana usedManaToPay) { - if (!autoPayment && manaType != unlockedManaType) { + if (!isAutoPayment() && manaType != unlockedManaType) { // if manual payment and the needed mana type was not unlocked, nothing will be paid return false; } ManaType possibleAsThoughtPoolManaType = null; - if (autoPayment && autoPaymentRestricted && !wasManaAddedBeyondStock() && manaType != unlockedManaType) { + if (isAutoPayment() && isAutoPaymentRestricted() && !wasManaAddedBeyondStock() && manaType != unlockedManaType) { // if automatic restricted payment and there is already mana in the pool // and the needed mana type was not unlocked, nothing will be paid if (unlockedManaType != null) { @@ -112,6 +118,7 @@ public class ManaPool implements Serializable { lockManaType(); // pay only one mana if mana payment is set to manually return true; } + for (ManaPoolItem mana : manaItems) { if (filter != null) { if (!filter.match(mana.getSourceObject(), game)) { @@ -121,7 +128,7 @@ public class ManaPool implements Serializable { } } } - if (possibleAsThoughtPoolManaType == null && manaType != unlockedManaType && autoPayment && autoPaymentRestricted && mana.count() == mana.getStock()) { + if (possibleAsThoughtPoolManaType == null && manaType != unlockedManaType && isAutoPayment() && isAutoPaymentRestricted() && mana.count() == mana.getStock()) { // no mana added beyond the stock so don't auto pay this continue; } @@ -366,25 +373,27 @@ public class ManaPool implements Serializable { } public void addMana(Mana manaToAdd, Game game, Ability source, boolean emptyOnTurnsEnd) { - Mana mana = manaToAdd.copy(); - if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source.getSourceId(), playerId, mana))) { - if (mana instanceof ConditionalMana) { - ManaPoolItem item = new ManaPoolItem((ConditionalMana) mana, source.getSourceObject(game), - ((ConditionalMana) mana).getManaProducerOriginalId() != null ? ((ConditionalMana) mana).getManaProducerOriginalId() : source.getOriginalId()); - if (emptyOnTurnsEnd) { - item.setDuration(Duration.EndOfTurn); + if (manaToAdd != null) { + Mana mana = manaToAdd.copy(); + if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source.getSourceId(), playerId, mana))) { + if (mana instanceof ConditionalMana) { + ManaPoolItem item = new ManaPoolItem((ConditionalMana) mana, source.getSourceObject(game), + ((ConditionalMana) mana).getManaProducerOriginalId() != null ? ((ConditionalMana) mana).getManaProducerOriginalId() : source.getOriginalId()); + if (emptyOnTurnsEnd) { + item.setDuration(Duration.EndOfTurn); + } + this.manaItems.add(item); + } else { + ManaPoolItem item = new ManaPoolItem(mana.getRed(), mana.getGreen(), mana.getBlue(), mana.getWhite(), mana.getBlack(), mana.getGeneric() + mana.getColorless(), source.getSourceObject(game), source.getOriginalId(), mana.getFlag()); + if (emptyOnTurnsEnd) { + item.setDuration(Duration.EndOfTurn); + } + this.manaItems.add(item); } - this.manaItems.add(item); - } else { - ManaPoolItem item = new ManaPoolItem(mana.getRed(), mana.getGreen(), mana.getBlue(), mana.getWhite(), mana.getBlack(), mana.getGeneric() + mana.getColorless(), source.getSourceObject(game), source.getOriginalId(), mana.getFlag()); - if (emptyOnTurnsEnd) { - item.setDuration(Duration.EndOfTurn); - } - this.manaItems.add(item); + ManaEvent manaEvent = new ManaEvent(EventType.MANA_ADDED, source.getId(), source.getSourceId(), playerId, mana); + manaEvent.setData(mana.toString()); + game.fireEvent(manaEvent); } - ManaEvent manaEvent = new ManaEvent(EventType.MANA_ADDED, source.getId(), source.getSourceId(), playerId, mana); - manaEvent.setData(mana.toString()); - game.fireEvent(manaEvent); } } @@ -435,19 +444,19 @@ public class ManaPool implements Serializable { } public boolean isAutoPayment() { - return autoPayment; + return autoPayment || forcedToPay; } public void setAutoPayment(boolean autoPayment) { this.autoPayment = autoPayment; } - public void setAutoPaymentRestricted(boolean autoPaymentRestricted) { - this.autoPaymentRestricted = autoPaymentRestricted; + public boolean isAutoPaymentRestricted() { + return autoPaymentRestricted || forcedToPay; } - public boolean isAutoPaymentRestricted() { - return autoPaymentRestricted; + public void setAutoPaymentRestricted(boolean autoPaymentRestricted) { + this.autoPaymentRestricted = autoPaymentRestricted; } public ManaType getUnlockedManaType() { @@ -489,4 +498,39 @@ public class ManaPool implements Serializable { return itemsCopy; } + public void setForcedToPay(boolean forcedToPay) { + this.forcedToPay = forcedToPay; + } + + public boolean isForcedToPay() { + return forcedToPay; + } + + public UUID getPlayerId() { + return playerId; + } + + public void storeMana() { + poolBookmark.clear(); + poolBookmark.addAll(getManaItems()); + } + + public List getPoolBookmark() { + List itemsCopy = new ArrayList<>(); + for (ManaPoolItem manaItem : poolBookmark) { + itemsCopy.add(manaItem.copy()); + } + return itemsCopy; + } + + public void restoreMana(List manaList) { + manaItems.clear(); + if (!manaList.isEmpty()) { + List itemsCopy = new ArrayList<>(); + for (ManaPoolItem manaItem : manaList) { + itemsCopy.add(manaItem.copy()); + } + manaItems.addAll(itemsCopy); + } + } } diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 6a51f097456..415dfec7c14 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -1,4 +1,3 @@ - package mage.players; import java.io.Serializable; @@ -279,6 +278,8 @@ public interface Player extends MageItem, Copyable { */ void setTurnControlledBy(UUID playerId); + List getTurnControllers(); + UUID getTurnControlledBy(); /** @@ -306,6 +307,8 @@ public interface Player extends MageItem, Copyable { */ void setGameUnderYourControl(boolean value); + void setGameUnderYourControl(boolean value, boolean fullRestore); + boolean isTestMode(); void setTestMode(boolean value); @@ -352,14 +355,19 @@ public interface Player extends MageItem, Copyable { boolean searchLibrary(TargetCardInLibrary target, Game game); + boolean searchLibrary(TargetCardInLibrary target, Game game, boolean triggerEvents); + + boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId); + /** * * @param target * @param game * @param targetPlayerId player whose library will be searched + * @param triggerEvents whether searching will trigger any game events * @return true if search was successful */ - boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId); + boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents); boolean canPlayLand(); @@ -852,6 +860,8 @@ public interface Player extends MageItem, Copyable { Set getUsersAllowedToSeeHandCards(); + void setPayManaMode(boolean payManaMode); + boolean isInPayManaMode(); void setMatchPlayer(MatchPlayer matchPlayer); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index a21a497df72..b6167fa2142 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1,4 +1,3 @@ - package mage.players; import java.io.Serializable; @@ -156,6 +155,7 @@ public abstract class PlayerImpl implements Player, Serializable { protected boolean isGameUnderControl = true; protected UUID turnController; + protected List turnControllers = new ArrayList<>(); protected Set playersUnderYourControl = new HashSet<>(); protected Set usersAllowedToSeeHandCards = new HashSet<>(); @@ -263,6 +263,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.isGameUnderControl = player.isGameUnderControl; this.turnController = player.turnController; + this.turnControllers.clear(); + this.turnControllers.addAll(player.turnControllers); this.passed = player.passed; this.passedTurn = player.passedTurn; @@ -343,6 +345,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.isGameUnderControl = player.isGameUnderControl(); this.turnController = player.getTurnControlledBy(); + this.turnControllers.clear(); + this.turnControllers.addAll(player.getTurnControllers()); this.reachedNextTurnAfterLeaving = player.hasReachedNextTurnAfterLeaving(); this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana(); this.castSourceIdManaCosts = player.getCastSourceIdManaCosts(); @@ -390,7 +394,7 @@ public abstract class PlayerImpl implements Player, Serializable { this.draws = false; this.loses = false; this.left = false; - // reset is neccessary because in tournament player will be used for each round + // reset is necessary because in tournament player will be used for each round this.quit = false; this.timerTimeout = false; this.idleTimeout = false; @@ -398,6 +402,7 @@ public abstract class PlayerImpl implements Player, Serializable { this.turns = 0; this.isGameUnderControl = true; this.turnController = this.getId(); + this.turnControllers.clear(); this.playersUnderYourControl.clear(); this.passed = false; @@ -492,18 +497,22 @@ public abstract class PlayerImpl implements Player, Serializable { PlayerList players = game.getState().getPlayerList(playerId); for (int i = 0; i < range.getRange(); i++) { Player player = players.getNext(game); - while (player.hasLeft()) { - player = players.getNext(game); + if (player != null) { + while (player.hasLeft()) { + player = players.getNext(game); + } + inRange.add(player.getId()); } - inRange.add(player.getId()); } players = game.getState().getPlayerList(playerId); for (int i = 0; i < range.getRange(); i++) { Player player = players.getPrevious(game); - while (player.hasLeft()) { - player = players.getPrevious(game); + if (player != null) { + while (player.hasLeft()) { + player = players.getPrevious(game); + } + inRange.add(player.getId()); } - inRange.add(player.getId()); } } } @@ -520,13 +529,13 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void controlPlayersTurn(Game game, UUID playerId) { + Player player = game.getPlayer(playerId); + player.setTurnControlledBy(this.getId()); + game.informPlayers(getLogName() + " controls the turn of " + player.getLogName()); if (!playerId.equals(this.getId())) { this.playersUnderYourControl.add(playerId); - Player player = game.getPlayer(playerId); if (!player.hasLeft() && !player.hasLost()) { player.setGameUnderYourControl(false); - player.setTurnControlledBy(this.getId()); - game.informPlayers(getLogName() + " controls the turn of " + player.getLogName()); } DelayedTriggeredAbility ability = new AtTheEndOfTurnStepPostDelayedTriggeredAbility(new LoseControlOnOtherPlayersControllerEffect(this.getLogName(), player.getLogName())); ability.setSourceId(getId()); @@ -538,6 +547,12 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void setTurnControlledBy(UUID playerId) { this.turnController = playerId; + this.turnControllers.add(playerId); + } + + @Override + public List getTurnControllers() { + return this.turnControllers; } @Override @@ -563,9 +578,27 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void setGameUnderYourControl(boolean value) { + setGameUnderYourControl(value, true); + } + + @Override + public void setGameUnderYourControl(boolean value, boolean fullRestore) { this.isGameUnderControl = value; if (isGameUnderControl) { - this.turnController = getId(); + if (fullRestore) { + this.turnControllers.clear(); + this.turnController = getId(); + } else { + if (turnControllers.size() > 0) { + this.turnControllers.remove(turnControllers.size() - 1); + } + if (turnControllers.isEmpty()) { + this.turnController = getId(); + } else { + this.turnController = turnControllers.get(turnControllers.size() - 1); + isGameUnderControl = false; + } + } } } @@ -642,7 +675,7 @@ public abstract class PlayerImpl implements Player, Serializable { */ @Override public boolean putInHand(Card card, Game game) { - if (card.getOwnerId().equals(playerId)) { + if (card.isOwnedBy(playerId)) { card.setZone(Zone.HAND, game); this.hand.add(card); } else { @@ -831,7 +864,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean putInGraveyard(Card card, Game game) { - if (card.getOwnerId().equals(playerId)) { + if (card.isOwnedBy(playerId)) { this.graveyard.add(card); } else { return game.getPlayer(card.getOwnerId()).putInGraveyard(card, game); @@ -882,7 +915,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop) { - if (card.getOwnerId().equals(getId())) { + if (card.isOwnedBy(getId())) { if (library.size() + 1 < xFromTheTop) { putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, true); } else { @@ -980,6 +1013,11 @@ public abstract class PlayerImpl implements Player, Serializable { return castSourceIdManaCosts; } + @Override + public void setPayManaMode(boolean payManaMode) { + this.payManaMode = payManaMode; + } + @Override public boolean isInPayManaMode() { return payManaMode; @@ -1007,6 +1045,10 @@ public abstract class PlayerImpl implements Player, Serializable { if (game == null || ability == null) { return false; } + + // Use ability copy to avoid problems with targets and costs on recast (issue https://github.com/magefree/mage/issues/5189). + ability = ability.copy(); + ability.setControllerId(getId()); if (ability.getSpellAbilityType() != SpellAbilityType.BASE) { ability = chooseSpellAbilityForCast(ability, game, noMana); @@ -1117,12 +1159,12 @@ public abstract class PlayerImpl implements Player, Serializable { resetStoredBookmark(game); // prevent undo after playing a land return true; } - // putOntoBattlefield retured false if putOntoBattlefield was replaced by replacement effect (e.g. Kjeldorian Outpost). + // putOntoBattlefield returned false if putOntoBattlefield was replaced by replacement effect (e.g. Kjeldoran Outpost). // But that would undo the effect completely, - // what makes no real sense. So it makes no sense to generally do a restorState here. + // what makes no real sense. So it makes no sense to generally do a restoreState here. // restoreState(bookmark, card.getName(), game); } - // if the to play the land is replaced (e.g. Kjeldoran Outpos and don't sacrificing a Plains) it's a valid state so returning true here + // if the to play the land is replaced (e.g. Kjeldoran Outpost and don't sacrificing a Plains) it's a valid state so returning true here return true; } @@ -1132,7 +1174,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (ability.activate(game, false)) { if (ability.resolve(game)) { if (ability.isUndoPossible()) { - if (storedBookmark == -1 || storedBookmark > bookmark) { // e.g. usefull for undo Nykthos, Shrine to Nyx + if (storedBookmark == -1 || storedBookmark > bookmark) { // e.g. useful for undo Nykthos, Shrine to Nyx setStoredBookmark(bookmark); } } else { @@ -1229,7 +1271,7 @@ public abstract class PlayerImpl implements Player, Serializable { result = playManaAbility((ActivatedManaAbilityImpl) ability.copy(), game); break; case SPELL: - result = cast((SpellAbility) ability.copy(), game, false, activationStatus.getPermittingObject()); + result = cast((SpellAbility) ability, game, false, activationStatus.getPermittingObject()); break; default: result = playAbility(ability.copy(), game); @@ -1381,7 +1423,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, Game game) { LinkedHashMap useable = new LinkedHashMap<>(); - if (object instanceof StackAbility) { // It may not be possible to activate abilities of stack actilities + if (object instanceof StackAbility) { // It may not be possible to activate abilities of stack abilities return useable; } if (object instanceof SplitCard) { @@ -1397,7 +1439,7 @@ public abstract class PlayerImpl implements Player, Serializable { return useable; } - // Adds special abilities that are given to non permanants by continuous effects + // Adds special abilities that are given to non permanents by continuous effects private void getOtherUseableActivatedAbilities(MageObject object, Zone zone, Game game, Map useable) { Abilities otherAbilities = game.getState().getActivatedOtherAbilities(object.getId(), zone); if (otherAbilities != null) { @@ -1467,7 +1509,7 @@ public abstract class PlayerImpl implements Player, Serializable { } protected boolean isActivePlayer(Game game) { - return game.getActivePlayerId().equals(this.playerId); + return game.isActivePlayer(this.playerId); } @Override @@ -1553,7 +1595,7 @@ public abstract class PlayerImpl implements Player, Serializable { // that phased out indirectly won't phase in by itself, but instead phases in // along with the card it's attached to. Permanent attachedTo = game.getPermanent(permanent.getAttachedTo()); - if (!(attachedTo != null && attachedTo.getControllerId().equals(this.getId()))) { + if (!(attachedTo != null && attachedTo.isControlledBy(this.getId()))) { permanent.phaseOut(game, false); } } @@ -1587,7 +1629,7 @@ public abstract class PlayerImpl implements Player, Serializable { // selected permanents to untap List selectedToUntap = new ArrayList<>(); - // player can cancel the seletion of an effect to use a prefered order of restriction effects + // player can cancel the selection of an effect to use a preferred order of restriction effects boolean playerCanceledSelection; do { playerCanceledSelection = false; @@ -1601,7 +1643,7 @@ public abstract class PlayerImpl implements Player, Serializable { FilterControlledPermanent filter = handledEntry.getKey().getKey().getFilter().copy(); String message = filter.getMessage(); - // omitt already from other untap effects selected permanents + // omit already from other untap effects selected permanents for (Permanent permanent : selectedToUntap) { filter.add(Predicates.not(new PermanentIdPredicate(permanent.getId()))); } @@ -1702,7 +1744,7 @@ public abstract class PlayerImpl implements Player, Serializable { for (Permanent permanent : canBeUntapped) { if (handledEffect.getFilter().match(permanent, game)) { // matches the restricted permanents of handled entry boolean canBeSelected = true; - // check if the permanent is restriced by another restriction that has left no permanent + // check if the permanent is restricted by another restriction that has left no permanent for (Entry>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) { if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game) && notMoreThanEffect.getValue() == 0) { canBeSelected = false; @@ -1815,7 +1857,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public int loseLife(int amount, Game game, boolean atCombat) { - if (!canLoseLife) { + if (!canLoseLife || !this.isInGame()) { return 0; } GameEvent event = new GameEvent(GameEvent.EventType.LOSE_LIFE, playerId, playerId, playerId, amount, atCombat); @@ -1850,7 +1892,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public int gainLife(int amount, Game game, UUID sourceId) { - if (!canGainLife || amount == 0) { + if (!canGainLife || amount <= 0) { return 0; } GameEvent event = new GameEvent(GameEvent.EventType.GAIN_LIFE, playerId, playerId, playerId, amount, false); @@ -2322,7 +2364,7 @@ public abstract class PlayerImpl implements Player, Serializable { setStoredBookmark(game.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda } Permanent attacker = game.getPermanent(attackerId); - if (attacker != null && attacker.canAttack(defenderId, game) && attacker.getControllerId().equals(playerId)) { + if (attacker != null && attacker.canAttack(defenderId, game) && attacker.isControlledBy(playerId)) { if (!game.getCombat().declareAttacker(attackerId, defenderId, playerId, game)) { game.undo(playerId); } @@ -2351,11 +2393,21 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean searchLibrary(TargetCardInLibrary target, Game game) { - return searchLibrary(target, game, playerId); + return searchLibrary(target, game, playerId, true); + } + + @Override + public boolean searchLibrary(TargetCardInLibrary target, Game game, boolean triggerEvents) { + return searchLibrary(target, game, playerId, triggerEvents); } @Override public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId) { + return searchLibrary(target, game, targetPlayerId, true); + } + + @Override + public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents) { //20091005 - 701.14c Library searchedLibrary = null; String searchInfo = null; @@ -2411,7 +2463,9 @@ public abstract class PlayerImpl implements Player, Serializable { for (UUID targetId : newTarget.getTargets()) { target.add(targetId, game); } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SEARCHED, targetPlayerId, playerId)); + if (triggerEvents) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SEARCHED, targetPlayerId, playerId)); + } } else if (targetPlayerId.equals(playerId) && handleLibraryCastableCards(library, game, targetPlayerId)) { // for handling Panglacial Wurm newTarget.clearChosen(); continue; @@ -2632,10 +2686,11 @@ public abstract class PlayerImpl implements Player, Serializable { available.addMana(manaAbilities, game); } for (Abilities manaAbilities : sourceWithCosts) { + available.removeDuplicated(); available.addManaWithCost(manaAbilities, game); } - // remove duplicated variants (see ManaOptionsTest for info - when thats rises) + // remove duplicated variants (see ManaOptionsTest for info - when that rises) available.removeDuplicated(); return available; @@ -2940,9 +2995,7 @@ public abstract class PlayerImpl implements Player, Serializable { // Other activated abilities LinkedHashMap useable = new LinkedHashMap<>(); getOtherUseableActivatedAbilities(card, Zone.GRAVEYARD, game, useable); - for (Ability ability : useable.values()) { - playable.add(ability); - } + playable.addAll(useable.values()); } for (ExileZone exile : game.getExile().getExileZones()) { for (Card card : exile.getCards(game)) { @@ -3009,7 +3062,7 @@ public abstract class PlayerImpl implements Player, Serializable { // activated abilities from objects in the command zone (emblems or commanders) for (CommandObject commandObject : game.getState().getCommand()) { for (ActivatedAbility ability : commandObject.getAbilities().getActivatedAbilities(Zone.COMMAND)) { - if (ability.getControllerId().equals(getId()) && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) { + if (ability.isControlledBy(getId()) && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) { playableActivated.put(ability.toString(), ability); } @@ -3564,7 +3617,7 @@ public abstract class PlayerImpl implements Player, Serializable { game.informPlayers(getLogName() + " puts " + (withName ? card.getLogName() : (card.isFaceDown(game) ? "a face down card" : "a card")) + " from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + ' ' - + (card.getOwnerId().equals(this.getId()) ? "into their hand" : "into its owner's hand") + + (card.isOwnedBy(this.getId()) ? "into their hand" : "into its owner's hand") ); } result = true; @@ -3587,7 +3640,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (cards.isEmpty()) { ownerId = card.getOwnerId(); } - if (card.getOwnerId().equals(ownerId)) { + if (card.isOwnedBy(ownerId)) { it.remove(); cards.add(card); } @@ -3658,7 +3711,7 @@ public abstract class PlayerImpl implements Player, Serializable { StringBuilder sb = new StringBuilder(this.getLogName()) .append(" puts ").append(card.getLogName()).append(' ').append(card.isCopy() ? "(Copy) " : "") .append(fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + ' ' : ""); - if (card.getOwnerId().equals(getId())) { + if (card.isOwnedBy(getId())) { sb.append("into their graveyard"); } else { sb.append("it into its owner's graveyard"); @@ -3690,7 +3743,7 @@ public abstract class PlayerImpl implements Player, Serializable { sb.append("from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(' '); } sb.append("to the ").append(toTop ? "top" : "bottom"); - if (card.getOwnerId().equals(getId())) { + if (card.isOwnedBy(getId())) { sb.append(" of their library"); } else { Player player = game.getPlayer(card.getOwnerId()); diff --git a/Mage/src/main/java/mage/target/TargetObject.java b/Mage/src/main/java/mage/target/TargetObject.java index 6936f78acd6..575ad44873d 100644 --- a/Mage/src/main/java/mage/target/TargetObject.java +++ b/Mage/src/main/java/mage/target/TargetObject.java @@ -1,21 +1,19 @@ - - package mage.target; -import mage.constants.Zone; +import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; +import mage.constants.Zone; import mage.game.Game; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com */ public abstract class TargetObject extends TargetImpl { - protected TargetObject() {} + protected TargetObject() { + } public TargetObject(Zone zone) { this(1, 1, zone, false); @@ -40,7 +38,7 @@ public abstract class TargetObject extends TargetImpl { @Override public String getTargetedName(Game game) { StringBuilder sb = new StringBuilder(); - for (UUID targetId: getTargets()) { + for (UUID targetId : getTargets()) { MageObject object = game.getObject(targetId); if (object != null) { sb.append(object.getLogName()).append(' '); @@ -52,7 +50,9 @@ public abstract class TargetObject extends TargetImpl { @Override public boolean canTarget(UUID id, Game game) { MageObject object = game.getObject(id); - return object != null && game.getState().getZone(id).match(zone) && getFilter().match(object, game); + return object != null + && zone != null && zone.match(game.getState().getZone(id)) + && getFilter() != null && getFilter().match(object, game); } @Override diff --git a/Mage/src/main/java/mage/target/TargetPermanent.java b/Mage/src/main/java/mage/target/TargetPermanent.java index 310badaf7de..9114df0019b 100644 --- a/Mage/src/main/java/mage/target/TargetPermanent.java +++ b/Mage/src/main/java/mage/target/TargetPermanent.java @@ -1,4 +1,3 @@ - package mage.target; import java.util.HashSet; @@ -8,6 +7,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -20,11 +20,11 @@ public class TargetPermanent extends TargetObject { protected FilterPermanent filter; public TargetPermanent() { - this(1, 1, new FilterPermanent(), false); + this(StaticFilters.FILTER_PERMANENT); } public TargetPermanent(FilterPermanent filter) { - this(1, 1, filter, false); + this(1, filter); } public TargetPermanent(int numTargets, FilterPermanent filter) { diff --git a/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java b/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java index 22d16d8f340..64bbbe36112 100644 --- a/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java +++ b/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java @@ -10,6 +10,7 @@ import mage.constants.AbilityType; import mage.constants.Zone; import mage.filter.Filter; import mage.filter.FilterAbility; +import mage.filter.FilterStackObject; import mage.game.Game; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; @@ -21,13 +22,13 @@ import mage.target.TargetObject; */ public class TargetActivatedAbility extends TargetObject { - protected final FilterAbility filter; + protected final FilterStackObject filter; public TargetActivatedAbility() { - this(new FilterAbility("activated ability")); + this(new FilterStackObject("activated ability")); } - public TargetActivatedAbility(FilterAbility filter) { + public TargetActivatedAbility(FilterStackObject filter) { this.minNumberOfTargets = 1; this.maxNumberOfTargets = 1; this.zone = Zone.STACK; @@ -46,8 +47,10 @@ public class TargetActivatedAbility extends TargetObject { return false; } StackObject stackObject = game.getStack().getStackObject(id); - return stackObject != null && stackObject.getStackAbility() != null && stackObject.getStackAbility().getAbilityType() == AbilityType.ACTIVATED - && filter.match(((ActivatedAbility) stackObject.getStackAbility()), game); + return stackObject != null + && stackObject.getStackAbility() != null + && stackObject.getStackAbility().getAbilityType() == AbilityType.ACTIVATED + && filter.match(stackObject, source.getSourceId(), source.getControllerId(), game); } @Override diff --git a/Mage/src/main/java/mage/target/common/TargetAnyTargetAmount.java b/Mage/src/main/java/mage/target/common/TargetAnyTargetAmount.java index c566675203e..37c8d4f8fb4 100644 --- a/Mage/src/main/java/mage/target/common/TargetAnyTargetAmount.java +++ b/Mage/src/main/java/mage/target/common/TargetAnyTargetAmount.java @@ -1,4 +1,3 @@ - package mage.target.common; import java.util.HashSet; @@ -178,7 +177,9 @@ public class TargetAnyTargetAmount extends TargetAmount { sb.append(permanent.getLogName()).append('(').append(getTargetAmount(targetId)).append(") "); } else { Player player = game.getPlayer(targetId); - sb.append(player.getLogName()).append('(').append(getTargetAmount(targetId)).append(") "); + if (player != null) { + sb.append(player.getLogName()).append('(').append(getTargetAmount(targetId)).append(") "); + } } } return sb.toString(); diff --git a/Mage/src/main/java/mage/target/common/TargetCardInASingleGraveyard.java b/Mage/src/main/java/mage/target/common/TargetCardInASingleGraveyard.java index b2a4e937e3b..86721777d32 100644 --- a/Mage/src/main/java/mage/target/common/TargetCardInASingleGraveyard.java +++ b/Mage/src/main/java/mage/target/common/TargetCardInASingleGraveyard.java @@ -34,7 +34,7 @@ public class TargetCardInASingleGraveyard extends TargetCard { Card card = game.getCard(firstTarget); Card targetCard = game.getCard(id); if (card == null || targetCard == null - || !card.getOwnerId().equals(targetCard.getOwnerId())) { + || !card.isOwnedBy(targetCard.getOwnerId())) { return false; } } diff --git a/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java b/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java index 9eb50d187fa..71ae125321f 100644 --- a/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java +++ b/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java @@ -41,8 +41,8 @@ public class TargetCardInLibrary extends TargetCard { public TargetCardInLibrary(int minNumTargets, int maxNumTargets, FilterCard filter) { super(minNumTargets, maxNumTargets, Zone.LIBRARY, filter); // 701.15b If a player is searching a hidden zone for cards with a stated quality, such as a card - // with a certain card type or color, that player isn’t required to find some or all of those cards - // even if they’re present in that zone. + // with a certain card type or color, that player isn't required to find some or all of those cards + // even if they're present in that zone. this.setRequired(!filter.hasPredicates()); this.setNotTarget(true); this.librarySearchLimit = Integer.MAX_VALUE; diff --git a/Mage/src/main/java/mage/target/common/TargetCardInOpponentsGraveyard.java b/Mage/src/main/java/mage/target/common/TargetCardInOpponentsGraveyard.java index 13676b8da12..4ebbfa167fd 100644 --- a/Mage/src/main/java/mage/target/common/TargetCardInOpponentsGraveyard.java +++ b/Mage/src/main/java/mage/target/common/TargetCardInOpponentsGraveyard.java @@ -40,7 +40,7 @@ public class TargetCardInOpponentsGraveyard extends TargetCard { if (game.getPlayer(source.getControllerId()).hasOpponent(card.getOwnerId(), game)) { if (allFromOneOpponent && !targets.isEmpty()) { Card firstCard = game.getCard(targets.keySet().iterator().next()); - if (firstCard != null && !card.getOwnerId().equals(firstCard.getOwnerId())) { + if (firstCard != null && !card.isOwnedBy(firstCard.getOwnerId())) { return false; } } diff --git a/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java b/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java index 595880577b2..935d811d0a0 100644 --- a/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java @@ -1,6 +1,6 @@ - package mage.target.common; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; /** @@ -10,19 +10,19 @@ import mage.filter.common.FilterControlledCreaturePermanent; public class TargetControlledCreaturePermanent extends TargetControlledPermanent { public TargetControlledCreaturePermanent() { - this(1, 1, new FilterControlledCreaturePermanent(), false); + this(1); } public TargetControlledCreaturePermanent(int numTargets) { - this(numTargets, numTargets, new FilterControlledCreaturePermanent(), false); + this(numTargets, numTargets); } public TargetControlledCreaturePermanent(int minNumTargets, int maxNumTargets) { - this(minNumTargets, maxNumTargets, new FilterControlledCreaturePermanent(), false); + this(minNumTargets, maxNumTargets, StaticFilters.FILTER_CONTROLLED_CREATURE, false); } public TargetControlledCreaturePermanent(FilterControlledCreaturePermanent filter) { - super(1, 1, filter, false); + this(1, 1, filter, false); } public TargetControlledCreaturePermanent(int minNumTargets, int maxNumTargets, FilterControlledCreaturePermanent filter, boolean notTarget) { diff --git a/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java b/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java index ce3eb7a0392..cbc3e687ab0 100644 --- a/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java @@ -1,7 +1,6 @@ - - package mage.target.common; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; @@ -12,11 +11,11 @@ import mage.target.TargetPermanent; public class TargetControlledPermanent extends TargetPermanent { public TargetControlledPermanent() { - this(1, 1, new FilterControlledPermanent(), false); + this(1, 1, StaticFilters.FILTER_CONTROLLED_PERMANENT, false); } public TargetControlledPermanent(int numTargets) { - this(numTargets, numTargets, new FilterControlledPermanent(), false); + this(numTargets, numTargets, StaticFilters.FILTER_CONTROLLED_PERMANENT, false); } public TargetControlledPermanent(FilterControlledPermanent filter) { diff --git a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentSameController.java b/Mage/src/main/java/mage/target/common/TargetCreaturePermanentSameController.java index 107a65d47f6..642440373a3 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentSameController.java +++ b/Mage/src/main/java/mage/target/common/TargetCreaturePermanentSameController.java @@ -31,7 +31,7 @@ public class TargetCreaturePermanentSameController extends TargetCreaturePermane Permanent targetPermanent = game.getPermanent(targetId); if (targetPermanent != null) { if (!firstTargetPermanent.getId().equals(targetPermanent.getId())) { - if (!firstTargetPermanent.getControllerId().equals(targetPermanent.getOwnerId())) { + if (!firstTargetPermanent.isControlledBy(targetPermanent.getOwnerId())) { return false; } } diff --git a/Mage/src/main/java/mage/target/common/TargetPermanentOrSuspendedCard.java b/Mage/src/main/java/mage/target/common/TargetPermanentOrSuspendedCard.java index 470472c4955..1575dcc4bad 100644 --- a/Mage/src/main/java/mage/target/common/TargetPermanentOrSuspendedCard.java +++ b/Mage/src/main/java/mage/target/common/TargetPermanentOrSuspendedCard.java @@ -69,7 +69,7 @@ public class TargetPermanentOrSuspendedCard extends TargetImpl { } @Override - public Filter getFilter() { + public Filter getFilter() { return this.filter; } diff --git a/Mage/src/main/java/mage/target/common/TargetSpellOrPermanent.java b/Mage/src/main/java/mage/target/common/TargetSpellOrPermanent.java index 50ced1b860e..f2a846ba375 100644 --- a/Mage/src/main/java/mage/target/common/TargetSpellOrPermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetSpellOrPermanent.java @@ -248,10 +248,12 @@ public class TargetSpellOrPermanent extends TargetImpl { sb.append(permanent.getLogName()).append(' '); } else { Spell spell = game.getStack().getSpell(targetId); - if (spell.isFaceDown(game)) { - sb.append(GameLog.getNeutralColoredText("face down spell")); - } else { - sb.append(spell.getLogName()).append(' '); + if (spell != null) { + if (spell.isFaceDown(game)) { + sb.append(GameLog.getNeutralColoredText("face down spell")); + } else { + sb.append(spell.getLogName()).append(' '); + } } } } diff --git a/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java b/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java index b0bad5fe749..5efeb3552d5 100644 --- a/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java +++ b/Mage/src/main/java/mage/target/common/TargetTriggeredAbility.java @@ -40,7 +40,7 @@ public class TargetTriggeredAbility extends TargetObject { return stackObject.getStackAbility() != null && (stackObject.getStackAbility() instanceof TriggeredAbility) && source != null - && stackObject.getStackAbility().getControllerId().equals(source.getControllerId()); + && stackObject.getStackAbility().isControlledBy(source.getControllerId()); } @Override @@ -53,7 +53,7 @@ public class TargetTriggeredAbility extends TargetObject { for (StackObject stackObject : game.getStack()) { if (stackObject.getStackAbility() != null && stackObject.getStackAbility() instanceof TriggeredAbility - && stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) { + && stackObject.getStackAbility().isControlledBy(sourceControllerId)) { return true; } } @@ -71,7 +71,7 @@ public class TargetTriggeredAbility extends TargetObject { for (StackObject stackObject : game.getStack()) { if (stackObject.getStackAbility() != null && stackObject.getStackAbility() instanceof TriggeredAbility - && stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) { + && stackObject.getStackAbility().isControlledBy(sourceControllerId)) { possibleTargets.add(stackObject.getStackAbility().getId()); } } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index d2addea1b12..ac9a02f558f 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -2,6 +2,8 @@ package mage.util; import java.util.UUID; +import java.util.stream.Stream; + import mage.MageObject; import mage.Mana; import mage.abilities.Ability; @@ -354,13 +356,8 @@ public final class CardUtil { } public static boolean checkNumeric(String s) { + return s.chars().allMatch(Character::isDigit); - for (int i = 0; i < s.length(); i++) { - if (!Character.isDigit(s.charAt(i))) { - return false; - } - } - return true; } /** @@ -442,9 +439,9 @@ public final class CardUtil { public static String getObjectZoneString(String text, MageObject mageObject, Game game) { int zoneChangeCounter = 0; if (mageObject instanceof Permanent) { - zoneChangeCounter = ((Permanent) mageObject).getZoneChangeCounter(game); + zoneChangeCounter = mageObject.getZoneChangeCounter(game); } else if (mageObject instanceof Card) { - zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter(game); + zoneChangeCounter = mageObject.getZoneChangeCounter(game); } return getObjectZoneString(text, mageObject.getId(), game, zoneChangeCounter, false); } diff --git a/Mage/src/main/java/mage/util/RandomUtil.java b/Mage/src/main/java/mage/util/RandomUtil.java index aa08d609386..29307983419 100644 --- a/Mage/src/main/java/mage/util/RandomUtil.java +++ b/Mage/src/main/java/mage/util/RandomUtil.java @@ -26,4 +26,8 @@ public final class RandomUtil { public static boolean nextBoolean() { return ThreadLocalRandom.current().nextBoolean(); } + + public static double nextDouble() { + return ThreadLocalRandom.current().nextDouble(); + } } diff --git a/Mage/src/main/java/mage/watchers/common/AttackedLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/AttackedLastTurnWatcher.java index 78eb6c67180..b8ca0dd44a4 100644 --- a/Mage/src/main/java/mage/watchers/common/AttackedLastTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/AttackedLastTurnWatcher.java @@ -30,13 +30,11 @@ public class AttackedLastTurnWatcher extends Watcher { public AttackedLastTurnWatcher(final AttackedLastTurnWatcher watcher) { super(watcher); for (Entry> entry : watcher.attackedLastTurnCreatures.entrySet()) { - Set allAttackersCopy = new HashSet<>(); - allAttackersCopy.addAll(entry.getValue()); + Set allAttackersCopy = new HashSet<>(entry.getValue()); attackedLastTurnCreatures.put(entry.getKey(), allAttackersCopy); } for (Entry> entry : watcher.attackedThisTurnCreatures.entrySet()) { - Set allAttackersCopy = new HashSet<>(); - allAttackersCopy.addAll(entry.getValue()); + Set allAttackersCopy = new HashSet<>(entry.getValue()); attackedThisTurnCreatures.put(entry.getKey(), allAttackersCopy); } } diff --git a/Mage/src/main/java/mage/watchers/common/CommanderInfoWatcher.java b/Mage/src/main/java/mage/watchers/common/CommanderInfoWatcher.java index 14c22b7f5a8..22f3fc3ba59 100644 --- a/Mage/src/main/java/mage/watchers/common/CommanderInfoWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CommanderInfoWatcher.java @@ -16,7 +16,7 @@ import mage.players.Player; import mage.watchers.Watcher; /* 20130711 - *903.14a A player that’s been dealt 21 or more combat damage by the same commander + *903.14a A player that's been dealt 21 or more combat damage by the same commander * over the course of the game loses the game. (This is a state-based action. See rule 704.) * * diff --git a/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java index 04db06ff031..331602e3f1f 100644 --- a/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/PermanentsEnteredBattlefieldYourLastTurnWatcher.java @@ -76,7 +76,7 @@ public class PermanentsEnteredBattlefieldYourLastTurnWatcher extends Watcher { } public List getPermanentsEnteringOnPlayersLastTurn(Game game, UUID playerId) { - if (game.getActivePlayerId().equals(playerId)) { + if (game.isActivePlayer(playerId)) { return enteringBattlefield.get(playerId); } return enteringBattlefieldLastTurn.get(playerId); diff --git a/Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java new file mode 100644 index 00000000000..2c7300286c1 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/PlayerLostLifeNonCombatWatcher.java @@ -0,0 +1,84 @@ + +package mage.watchers.common; + +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +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; + +/* + * Counts amount of life lost from noncombat sources current or last turn by players. + * This watcher is automatically started in gameImpl.init for each game + * + * @author NinthWorld + */ +public class PlayerLostLifeNonCombatWatcher extends Watcher { + + private final Map amountOfLifeLostThisTurn = new HashMap<>(); + private final Map amountOfLifeLostLastTurn = new HashMap<>(); + + public PlayerLostLifeNonCombatWatcher() { + super(PlayerLostLifeNonCombatWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public PlayerLostLifeNonCombatWatcher(final PlayerLostLifeNonCombatWatcher watcher) { + super(watcher); + for (Entry entry : watcher.amountOfLifeLostThisTurn.entrySet()) { + amountOfLifeLostThisTurn.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.LOST_LIFE && !event.getFlag()) { + UUID playerId = event.getPlayerId(); + if (playerId != null) { + Integer amount = amountOfLifeLostThisTurn.get(playerId); + if (amount == null) { + amount = event.getAmount(); + } else { + amount = amount + event.getAmount(); + } + amountOfLifeLostThisTurn.put(playerId, amount); + } + } + } + + public int getLiveLost(UUID playerId) { + return amountOfLifeLostThisTurn.getOrDefault(playerId, 0); + } + + public int getAllOppLifeLost(UUID playerId, Game game) { + int amount = 0; + for (UUID opponentId : this.amountOfLifeLostThisTurn.keySet()) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null && opponent.hasOpponent(playerId, game)) { + amount += this.amountOfLifeLostThisTurn.getOrDefault(opponentId, 0); + } + } + return amount; + } + + public int getLiveLostLastTurn(UUID playerId) { + return amountOfLifeLostLastTurn.getOrDefault(playerId, 0); + } + + @Override + public void reset() { + amountOfLifeLostLastTurn.clear(); + amountOfLifeLostLastTurn.putAll(amountOfLifeLostThisTurn); + amountOfLifeLostThisTurn.clear(); + } + + @Override + public PlayerLostLifeNonCombatWatcher copy() { + return new PlayerLostLifeNonCombatWatcher(this); + } +} diff --git a/Mage/src/main/java/mage/watchers/common/WasBlockedThisTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/WasBlockedThisTurnWatcher.java new file mode 100644 index 00000000000..65e44a07afc --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/WasBlockedThisTurnWatcher.java @@ -0,0 +1,53 @@ + +package mage.watchers.common; + +import mage.MageObjectReference; +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author noahg + */ +public class WasBlockedThisTurnWatcher extends Watcher { + + private final Set wasBlockedThisTurnCreatures; + + public WasBlockedThisTurnWatcher() { + super(WasBlockedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + wasBlockedThisTurnCreatures = new HashSet<>(); + } + + public WasBlockedThisTurnWatcher(final WasBlockedThisTurnWatcher watcher) { + super(watcher); + wasBlockedThisTurnCreatures = new HashSet<>(watcher.wasBlockedThisTurnCreatures); + } + + @Override + public Watcher copy() { + return new WasBlockedThisTurnWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { + this.wasBlockedThisTurnCreatures.add(new MageObjectReference(event.getTargetId(), game)); + } + } + + public Set getWasBlockedThisTurnCreatures() { + return this.wasBlockedThisTurnCreatures; + } + + @Override + public void reset() { + super.reset(); + wasBlockedThisTurnCreatures.clear(); + } + +} diff --git a/Utils/known-sets.txt b/Utils/known-sets.txt index 0534ba49503..896efb1671f 100644 --- a/Utils/known-sets.txt +++ b/Utils/known-sets.txt @@ -25,7 +25,9 @@ Commander 2014 Edition|Commander2014| Commander 2015 Edition|Commander2015| Commander 2016 Edition|Commander2016| Commander 2017 Edition|Commander2017| +Commander 2018|Commander2018| Commander Anthology|CommanderAnthology| +Commander Anthology 2018|CommanderAnthology2018| Commander's Arsenal|CommandersArsenal| Conflux|Conflux| Conspiracy: Take the Crown|ConspiracyTakeTheCrown| diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 80ec6b76bd5..2266d8210e0 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -1719,7 +1719,7 @@ Kitsune Healer|Champions of Kamigawa|27|C|{3}{W}|Creature - Fox Cleric|2|2|{T}: Tatsumasa, the Dragon's Fang|Champions of Kamigawa|270|R|{6}|Legendary Artifact - Equipment|||Equipped creature gets +5/+5.${6}, Exile Tatsumasa, the Dragon's Fang: Put a 5/5 blue Dragon Spirit creature token with flying onto the battlefield. Return Tatsumasa to the battlefield under its owner's control when that token dies.$Equip {3}| Tenza, Godo's Maul|Champions of Kamigawa|271|U|{3}|Legendary Artifact - Equipment|||Equipped creature gets +1/+1. As long as it's legendary, it gets an additional +2/+2. As long as it's red, it has trample.$Equip {1} ({1}: Attach to target creature you control. Equip only as a sorcery.)| Uba Mask|Champions of Kamigawa|272|R|{4}|Artifact|||If a player would draw a card, that player exiles that card face up instead.$Each player may play cards he or she exiled with Uba Mask this turn.| -Boseiju, Who Shelters All|Champions of Kamigawa|273|R||Legendary Land|||Boseiju, Who Shelters All enters the battlefield tapped.${T}, Pay 2 life: Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered by spells or abilities.| +Boseiju, Who Shelters All|Champions of Kamigawa|273|R||Legendary Land|||Boseiju, Who Shelters All enters the battlefield tapped.${T}, Pay 2 life: Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered.| Cloudcrest Lake|Champions of Kamigawa|274|U||Land|||{T}: Add {C}.${T}: Add {W} or {U}. Cloudcrest Lake doesn't untap during your next untap step.| Eiganjo Castle|Champions of Kamigawa|275|R||Legendary Land|||{T}: Add {W}.${W}, {T}: Prevent the next 2 damage that would be dealt to target legendary creature this turn.| Forbidden Orchard|Champions of Kamigawa|276|R||Land|||{T}: Add one mana of any color.$Whenever you tap Forbidden Orchard for mana, put a 1/1 colorless Spirit creature token onto the battlefield under target opponent's control.| @@ -3279,7 +3279,7 @@ Sedraxis Alchemist|Conflux|54|C|{2}{B}|Creature - Zombie Wizard|2|2|When Sedraxi Voices from the Void|Conflux|55|U|{4}{B}|Sorcery|||Domain - Target player discards a card for each basic land type among lands you control.| Wretched Banquet|Conflux|56|C|{B}|Sorcery|||Destroy target creature if it has the least power or is tied for least power among creatures on the battlefield.| Yoke of the Damned|Conflux|57|C|{1}{B}|Enchantment - Aura|||Enchant creature$When a creature dies, destroy enchanted creature.| -Banefire|Conflux|58|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented.| +Banefire|Conflux|58|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, Banefire can't be countered and the damage can't be prevented.| Bloodhall Ooze|Conflux|59|R|{R}|Creature - Ooze|1|1|At the beginning of your upkeep, if you control a black permanent, you may put a +1/+1 counter on Bloodhall Ooze.$At the beginning of your upkeep, if you control a green permanent, you may put a +1/+1 counter on Bloodhall Ooze.| Court Homunculus|Conflux|6|C|{W}|Artifact Creature - Homunculus|1|1|Court Homunculus gets +1/+1 as long as you control another artifact.| Canyon Minotaur|Conflux|60|C|{3}{R}|Creature - Minotaur Warrior|3|3|| @@ -3798,7 +3798,7 @@ Echoing Calm|Darksteel|2|C|{1}{W}|Instant|||Destroy target enchantment and all o Chromescale Drake|Darksteel|20|R|{6}{U}{U}{U}|Creature - Drake|3|4|Affinity for artifacts (This spell costs {1} less to cast for each artifact you control.)$Flying$When Chromescale Drake enters the battlefield, reveal the top three cards of your library. Put all artifact cards revealed this way into your hand and the rest into your graveyard.| Echoing Truth|Darksteel|21|C|{1}{U}|Instant|||Return target nonland permanent and all other permanents with the same name as that permanent to their owners' hands.| Hoverguard Observer|Darksteel|22|U|{2}{U}{U}|Creature - Drone|3|3|Flying$Hoverguard Observer can block only creatures with flying.| -Last Word|Darksteel|23|R|{2}{U}{U}|Instant|||Last Word can't be countered by spells or abilities.$Counter target spell.| +Last Word|Darksteel|23|R|{2}{U}{U}|Instant|||Last Word can't be countered.$Counter target spell.| Machinate|Darksteel|24|C|{1}{U}{U}|Instant|||Look at the top X cards of your library, where X is the number of artifacts you control. Put one of those cards into your hand and the rest on the bottom of your library in any order.| Magnetic Flux|Darksteel|25|C|{2}{U}|Instant|||Artifact creatures you control gain flying until end of turn.| Neurok Prodigy|Darksteel|26|C|{2}{U}|Creature - Human Wizard|2|1|Flying$Discard an artifact card: Return Neurok Prodigy to its owner's hand.| @@ -3938,7 +3938,7 @@ Riot Spikes|Dissension|146|C|{BR}|Enchantment - Aura|||({BR} can be paid with Shielding Plax|Dissension|147|C|{2}{GU}|Enchantment - Aura|||({GU} can be paid with either {G} or {U}.)$Enchant creature$When Shielding Plax enters the battlefield, draw a card.$Enchanted creature can't be the target of spells or abilities your opponents control.| Simic Guildmage|Dissension|148|U|{GU}{GU}|Creature - Elf Wizard|2|2|({GU} can be paid with either {G} or {U}.)${1}{G}: Move a +1/+1 counter from target creature onto another target creature with the same controller.${1}{U}: Attach target Aura enchanting a permanent to another permanent with the same controller.| Bound|Dissension|149a|R|{3}{B}{G}|Instant|||Sacrifice a creature. Return up to X cards from your graveyard to your hand, where X is the number of colors that creature was. Exile this card.$| -Determined|Dissension|149b|R|{G}{U}|Instant|||$Other spells you control can't be countered by spells or abilities this turn.$Draw a card.| +Determined|Dissension|149b|R|{G}{U}|Instant|||$Other spells you control can't be countered this turn.$Draw a card.| Proclamation of Rebirth|Dissension|15|R|{2}{W}|Sorcery|||Return up to three target creature cards with converted mana cost 1 or less from your graveyard to the battlefield.$Forecast - {5}{W}, Reveal Proclamation of Rebirth from your hand: Return target creature card with converted mana cost 1 or less from your graveyard to the battlefield. (Activate this ability only during your upkeep and only once each turn.)| Crime|Dissension|150a|R|{3}{W}{B}|Sorcery|||Put target creature or enchantment card from an opponent's graveyard onto the battlefield under your control.$| Punishment|Dissension|150b|R|{X}{B}{G}|Sorcery|||$Destroy each artifact, creature, and enchantment with converted mana cost X.| @@ -4029,7 +4029,7 @@ Vesper Ghoul|Dissension|57|C|{2}{B}|Creature - Zombie Druid|1|1|{tap}, Pay 1 lif Wit's End|Dissension|58|R|{5}{B}{B}|Sorcery|||Target player discards his or her hand.| Cackling Flames|Dissension|59|C|{3}{R}|Instant|||Cackling Flames deals 3 damage to any target.$Hellbent - Cackling Flames deals 5 damage to that creature or player instead if you have no cards in hand.| Carom|Dissension|6|C|{1}{W}|Instant|||The next 1 damage that would be dealt to target creature this turn is dealt to another target creature instead.$Draw a card.| -Demonfire|Dissension|60|R|{X}{R}|Sorcery|||Demonfire deals X damage to any target. If a creature dealt damage this way would die this turn, exile it instead.$Hellbent - If you have no cards in hand, Demonfire can't be countered by spells or abilities and the damage can't be prevented.| +Demonfire|Dissension|60|R|{X}{R}|Sorcery|||Demonfire deals X damage to any target. If a creature dealt damage this way would die this turn, exile it instead.$Hellbent - If you have no cards in hand, Demonfire can't be countered and the damage can't be prevented.| Flame-Kin War Scout|Dissension|61|U|{3}{R}|Creature - Elemental Scout|2|4|When another creature enters the battlefield, sacrifice Flame-Kin War Scout. If you do, Flame-Kin War Scout deals 4 damage to that creature.| Flaring Flame-Kin|Dissension|62|U|{2}{R}|Creature - Elemental Warrior|2|2|As long as Flaring Flame-Kin is enchanted, it gets +2/+2, has trample, and has "{R}: Flaring Flame-Kin gets +1/+0 until end of turn."| Gnat Alley Creeper|Dissension|63|U|{2}{R}|Creature - Human Rogue|3|1|Gnat Alley Creeper can't be blocked by creatures with flying.| @@ -4392,7 +4392,7 @@ Lightning Berserker|Dragons of Tarkir|146|U|{R}|Creature - Human Berserker|1|1|{ Lose Calm|Dragons of Tarkir|147|C|{3}{R}|Sorcery|||Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn and can't be blocked this turn except by two or more creatures.| Magmatic Chasm|Dragons of Tarkir|148|C|{1}{R}|Sorcery|||Creature without flying can't block this turn.| Qal Sisma Behemoth|Dragons of Tarkir|149|U|{2}{R}|Creature - Ogre Warrior|5|5|Qal Sisma Behemoth can't attack or block unless you pay {2}.| -Rending Volley|Dragons of Tarkir|150|U|{R}|Instant|||Rending Volley can't be countered by spells or abilities.$Rending Volley deals 4 damage to target white or blue creature.| +Rending Volley|Dragons of Tarkir|150|U|{R}|Instant|||Rending Volley can't be countered.$Rending Volley deals 4 damage to target white or blue creature.| Roast|Dragons of Tarkir|151|U|{1}{R}|Sorcery|||Roast deals 5 damage to target creature without flying.| Sabertooth Outrider|Dragons of Tarkir|152|C|{3}{R}|Creature - Human Warrior|4|2|Trample$Formidable — Whenever Sabertooth Outrider attacks, if creatures you control have total power 8 or greater, Sabertooth Outrider gains first strike until end of turn.| Sarkhan's Rage|Dragons of Tarkir|153|C|{4}{R}|Instant|||Sarkhan's Rage deals 5 damage to any target. If you control no Dragons, Sarkhan's Rage deals 2 damage to you.| @@ -4829,7 +4829,7 @@ Flame Javelin|Duel Decks: Anthology, Jace vs. Chandra|53|U|{2R}{2R}{2R}|Instant| Cone of Flame|Duel Decks: Anthology, Jace vs. Chandra|54|U|{3}{R}{R}|Sorcery|||Cone of Flame deals 1 damage to any target, 2 damage to another any target, and 3 damage to a third any target.| Fireblast|Duel Decks: Anthology, Jace vs. Chandra|55|C|{4}{R}{R}|Instant|||You may sacrifice two Mountains rather than pay Fireblast's mana cost.$Fireblast deals 4 damage to any target.| Fireball|Duel Decks: Anthology, Jace vs. Chandra|56|U|{X}{R}|Sorcery|||Fireball deals X damage divided evenly, rounded down, among any number of target creatures and/or players.$Fireball costs {1} more to cast for each target beyond the first.| -Demonfire|Duel Decks: Anthology, Jace vs. Chandra|57|R|{X}{R}|Sorcery|||Demonfire deals X damage to any target. If a creature dealt damage this way would die this turn, exile it instead.$Hellbent - If you have no cards in hand, Demonfire can't be countered by spells or abilities and the damage can't be prevented.| +Demonfire|Duel Decks: Anthology, Jace vs. Chandra|57|R|{X}{R}|Sorcery|||Demonfire deals X damage to any target. If a creature dealt damage this way would die this turn, exile it instead.$Hellbent - If you have no cards in hand, Demonfire can't be countered and the damage can't be prevented.| Keldon Megaliths|Duel Decks: Anthology, Jace vs. Chandra|58|U||Land|||Keldon Megaliths enters the battlefield tapped.${tap}: Add {R}.$Hellbent - {1}{R}, {tap}: Keldon Megaliths deals 1 damage to any target. Activate this ability only if you have no cards in hand.| Mountain|Duel Decks: Anthology, Jace vs. Chandra|59|L||Basic Land - Mountain|||R| Willbender|Duel Decks: Anthology, Jace vs. Chandra|6|U|{1}{U}|Creature - Human Wizard|1|2|Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)$When Willbender is turned face up, change the target of target spell or ability with a single target.| @@ -5395,7 +5395,7 @@ Flame Javelin|Duel Decks: Jace vs. Chandra|53|U|{2R}{2R}{2R}|Instant|||({2R} Cone of Flame|Duel Decks: Jace vs. Chandra|54|U|{3}{R}{R}|Sorcery|||Cone of Flame deals 1 damage to any target, 2 damage to another any target, and 3 damage to a third any target.| Fireblast|Duel Decks: Jace vs. Chandra|55|C|{4}{R}{R}|Instant|||You may sacrifice two Mountains rather than pay Fireblast's mana cost.$Fireblast deals 4 damage to any target.| Fireball|Duel Decks: Jace vs. Chandra|56|U|{X}{R}|Sorcery|||Fireball deals X damage divided evenly, rounded down, among any number of target creatures and/or players.$Fireball costs {1} more to cast for each target beyond the first.| -Demonfire|Duel Decks: Jace vs. Chandra|57|R|{X}{R}|Sorcery|||Demonfire deals X damage to any target. If a creature dealt damage this way would die this turn, exile it instead.$Hellbent - If you have no cards in hand, Demonfire can't be countered by spells or abilities and the damage can't be prevented.| +Demonfire|Duel Decks: Jace vs. Chandra|57|R|{X}{R}|Sorcery|||Demonfire deals X damage to any target. If a creature dealt damage this way would die this turn, exile it instead.$Hellbent - If you have no cards in hand, Demonfire can't be countered and the damage can't be prevented.| Keldon Megaliths|Duel Decks: Jace vs. Chandra|58|U||Land|||Keldon Megaliths enters the battlefield tapped.${tap}: Add {R}.$Hellbent - {1}{R}, {tap}: Keldon Megaliths deals 1 damage to any target. Activate this ability only if you have no cards in hand.| Mountain|Duel Decks: Jace vs. Chandra|59|L||Basic Land - Mountain|||R| Willbender|Duel Decks: Jace vs. Chandra|6|U|{1}{U}|Creature - Human Wizard|1|2|Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)$When Willbender is turned face up, change the target of target spell or ability with a single target.| @@ -5673,7 +5673,7 @@ Swamp|Duel Decks: Phyrexia vs. the Coalition|32|L||Basic Land - Swamp|||B| Swamp|Duel Decks: Phyrexia vs. the Coalition|33|L||Basic Land - Swamp|||B| Swamp|Duel Decks: Phyrexia vs. the Coalition|34|L||Basic Land - Swamp|||B| Swamp|Duel Decks: Phyrexia vs. the Coalition|35|L||Basic Land - Swamp|||B| -Urza's Rage|Duel Decks: Phyrexia vs. the Coalition|36|M|{2}{R}|Instant|||Kicker {8}{R} (You may pay an additional {8}{R} as you cast this spell.)$Urza's Rage can't be countered by spells or abilities.$Urza's Rage deals 3 damage to any target. If Urza's Rage was kicked, instead it deals 10 damage to that creature or player and the damage can't be prevented.| +Urza's Rage|Duel Decks: Phyrexia vs. the Coalition|36|M|{2}{R}|Instant|||Kicker {8}{R} (You may pay an additional {8}{R} as you cast this spell.)$Urza's Rage can't be countered.$Urza's Rage deals 3 damage to any target. If Urza's Rage was kicked, instead it deals 10 damage to that creature or player and the damage can't be prevented.| Thornscape Apprentice|Duel Decks: Phyrexia vs. the Coalition|37|C|{G}|Creature - Human Wizard|1|1|{R}, {tap}: Target creature gains first strike until end of turn.${W}, {tap}: Tap target creature.| Nomadic Elf|Duel Decks: Phyrexia vs. the Coalition|38|C|{1}{G}|Creature - Elf Nomad|2|2|{1}{G}: Add one mana of any color.| Quirion Elves|Duel Decks: Phyrexia vs. the Coalition|39|C|{1}{G}|Creature - Elf Druid|1|1|As Quirion Elves enters the battlefield, choose a color.${tap}: Add {G}.${tap}: Add one mana of the chosen color.| @@ -5819,7 +5819,7 @@ Orcish Cannonade|Duel Decks: Speed vs. Cunning|28|C|{1}{R}{R}|Instant|||Orcish C Fiery Fall|Duel Decks: Speed vs. Cunning|29|C|{5}{R}|Instant|||Fiery Fall deals 5 damage to target creature.$Basic landcycling {1}{R} ({1}{R}, Discard this card: Search your library for a basic land card, reveal it, and put it into your hand. Then shuffle your library.)| Infantry Veteran|Duel Decks: Speed vs. Cunning|3|C|{W}|Creature - Human Soldier|1|1|{tap}: Target attacking creature gets +1/+1 until end of turn.| Fury of the Horde|Duel Decks: Speed vs. Cunning|30|R|{5}{R}{R}|Sorcery|||You may exile two red cards from your hand rather than pay Fury of the Horde's mana cost.$Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase.| -Banefire|Duel Decks: Speed vs. Cunning|31|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented.| +Banefire|Duel Decks: Speed vs. Cunning|31|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, Banefire can't be countered and the damage can't be prevented.| Evolving Wilds|Duel Decks: Speed vs. Cunning|32|C||Land|||{tap}, Sacrifice Evolving Wilds: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library.| Ghitu Encampment|Duel Decks: Speed vs. Cunning|33|U||Land|||Ghitu Encampment enters the battlefield tapped.${tap}: Add {R}.${1}{R}: Ghitu Encampment becomes a 2/1 red Warrior creature with first strike until end of turn. It's still a land. (It deals combat damage before creatures without first strike.)| Nomad Outpost|Duel Decks: Speed vs. Cunning|34|U||Land|||Nomad Outpost enters the battlefield tapped.${tap}: Add {R}, {W}, or {B}.| @@ -8188,7 +8188,7 @@ Tolaria West|From the Vault: Lore|13|M||Land|||Tolaria West enters the battlefie Umezawa's Jitte|From the Vault: Lore|14|M|{2}|Legendary Artifact - Equipment|||Whenever equipped creature deals combat damage, put two charge counters on Umezawa's Jitte.$Remove a charge counter from Umezawa's Jitte: Choose one Equipped creature gets +2/+2 until end of turn; or target creature gets -1/-1 until end of turn; or you gain 2 life.$Equip {2}| Unmask|From the Vault: Lore|15|M|{3}{B}|Sorcery|||You may exile a black card from your hand rather than pay Unmask's mana cost.$Target player reveals his or her hand. You choose a nonland card from it. That player discards that card.| Ancient Tomb|From the Vault: Realms|1|M||Land|||{T}: Add {C}{C}. Ancient Tomb deals 2 damage to you.| -Boseiju, Who Shelters All|From the Vault: Realms|2|M||Legendary Land|||Boseiju, Who Shelters All enters the battlefield tapped.${T}, Pay 2 life: Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered by spells or abilities.| +Boseiju, Who Shelters All|From the Vault: Realms|2|M||Legendary Land|||Boseiju, Who Shelters All enters the battlefield tapped.${T}, Pay 2 life: Add {C}. If that mana is spent on an instant or sorcery spell, that spell can't be countered.| Cephalid Coliseum|From the Vault: Realms|3|M||Land|||{T}: Add {U}. Cephalid Coliseum deals 1 damage to you.$Threshold {U}, {T}, Sacrifice Cephalid Coliseum: Target player draws three cards, then discards three cards. Activate this ability only if seven or more cards are in your graveyard.| Desert|From the Vault: Realms|4|M||Land - Desert|||{T}: Add {C}.${T}: Desert deals 1 damage to target attacking creature. Activate this ability only during the end of combat step.| Dryad Arbor|From the Vault: Realms|5|M||Land Creature - Forest Dryad|||(Dryad Arbor isn't a spell, it's affected by summoning sickness, and it has "{T}: Add {G}.")| @@ -8723,7 +8723,7 @@ Tibor and Lumia|Guildpact|135|R|{2}{U}{R}|Legendary Creature - Human Wizard|3|3| Ulasht, the Hate Seed|Guildpact|136|R|{2}{R}{G}|Legendary Creature - Hellion Hydra|0|0|Ulasht, the Hate Seed enters the battlefield with a +1/+1 counter on it for each other red creature you control and a +1/+1 counter on it for each other green creature you control.${1}, Remove a +1/+1 counter from Ulasht: Choose one - Ulasht deals 1 damage to target creature; or put a 1/1 green Saproling creature token onto the battlefield.| Wee Dragonauts|Guildpact|137|C|{1}{U}{R}|Creature - Faerie Wizard|1|3|Flying$Whenever you cast an instant or sorcery spell, Wee Dragonauts gets +2/+0 until end of turn.| Witch-Maw Nephilim|Guildpact|138|R|{G}{W}{U}{B}|Creature - Nephilim|1|1|Whenever you cast a spell, you may put two +1/+1 counters on Witch-Maw Nephilim.$Whenever Witch-Maw Nephilim attacks, it gains trample until end of turn if its power is 10 or greater.| -Wreak Havoc|Guildpact|139|U|{2}{R}{G}|Sorcery|||Wreak Havoc can't be countered by spells or abilities.$Destroy target artifact or land.| +Wreak Havoc|Guildpact|139|U|{2}{R}{G}|Sorcery|||Wreak Havoc can't be countered.$Destroy target artifact or land.| Shadow Lance|Guildpact|14|U|{W}|Enchantment - Aura|||Enchant creature$Enchanted creature has first strike.${1}{B}: Enchanted creature gets +2/+2 until end of turn.| Yore-Tiller Nephilim|Guildpact|140|R|{W}{U}{B}{R}|Creature - Nephilim|2|2|Whenever Yore-Tiller Nephilim attacks, return target creature card from your graveyard to the battlefield tapped and attacking.| Debtors' Knell|Guildpact|141|R|{4}{WB}{WB}{WB}|Enchantment|||({WB} can be paid with either {W} or {B}.)$At the beginning of your upkeep, put target creature card from a graveyard onto the battlefield under your control.| @@ -9738,7 +9738,7 @@ Thunderscape Apprentice|Invasion|174|C|{R}|Creature - Human Wizard|1|1|{B}, {tap Thunderscape Master|Invasion|175|R|{2}{R}{R}|Creature - Human Wizard|2|2|{B}{B}, {tap}: Target player loses 2 life and you gain 2 life.${G}{G}, {tap}: Creatures you control get +2/+2 until end of turn.| Tribal Flames|Invasion|176|C|{1}{R}|Sorcery|||Domain - Tribal Flames deals X damage to any target, where X is the number of basic land types among lands you control.| Turf Wound|Invasion|177|C|{2}{R}|Instant|||Target player can't play land cards this turn.$$Draw a card.| -Urza's Rage|Invasion|178|R|{2}{R}|Instant|||Kicker {8}{R} (You may pay an additional {8}{R} as you cast this spell.)$Urza's Rage can't be countered by spells or abilities.$Urza's Rage deals 3 damage to any target. If Urza's Rage was kicked, instead it deals 10 damage to that creature or player and the damage can't be prevented.| +Urza's Rage|Invasion|178|R|{2}{R}|Instant|||Kicker {8}{R} (You may pay an additional {8}{R} as you cast this spell.)$Urza's Rage can't be countered.$Urza's Rage deals 3 damage to any target. If Urza's Rage was kicked, instead it deals 10 damage to that creature or player and the damage can't be prevented.| Viashino Grappler|Invasion|179|C|{2}{R}|Creature - Viashino|3|1|{G}: Viashino Grappler gains trample until end of turn.| Global Ruin|Invasion|18|R|{4}{W}|Sorcery|||Each player chooses from the lands he or she controls a land of each basic land type, then sacrifices the rest.| Zap|Invasion|180|C|{2}{R}|Instant|||Zap deals 1 damage to any target.$$Draw a card.| @@ -10706,7 +10706,7 @@ Arc Lightning|Khans of Tarkir|97|U|{2}{R}|Sorcery|||Arc Lightning deals 3 damage Arrow Storm|Khans of Tarkir|98|C|{3}{R}{R}|Sorcery|||Arrow Storm deals 4 damage to any target.$Raid - If you attacked with a creature this turn, instead Arrow Storm deals 5 damage to that creature or player and the damage can't be prevented.| Ashcloud Phoenix|Khans of Tarkir|99|M|{2}{R}{R}|Creature - Phoenix|4|1|Flying$When Ashcloud Phoenix dies, return it to the battlefield face down.$Morph {4}{R}{R} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)$When Ashcloud Phoenix is turned face up, it deals 2 damage to each player.| Earwig Squad|Launch Party|1|R|{3}{B}{B}|Creature - Goblin Rogue|5|3|Prowl {2}{B} (You may cast this for its prowl cost if you dealt combat damage to a player this turn with a Goblin or Rogue.)$When Earwig Squad enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles his or her library.| -Vexing Shusher|Launch Party|2|R|{RG}{RG}|Creature - Goblin Shaman|2|2|Vexing Shusher can't be countered.${RG}: Target spell can't be countered by spells or abilities.| +Vexing Shusher|Launch Party|2|R|{RG}{RG}|Creature - Goblin Shaman|2|2|Vexing Shusher can't be countered.${RG}: Target spell can't be countered.| Figure of Destiny|Launch Party|3|R|{RW}|Creature - Kithkin|1|1|{RW}: Figure of Destiny becomes a Kithkin Spirit with base power and toughness 2/2.${RW}{RW}{RW}: If Figure of Destiny is a Spirit, it becomes a Kithkin Spirit Warrior with base power and toughness 4/4.${RW}{RW}{RW}{RW}{RW}{RW}: If Figure of Destiny is a Warrior, it becomes a Kithkin Spirit Warrior Avatar with base power and toughness 8/8, flying, and first strike.| Ajani Vengeant|Launch Party|4|M|{2}{W}{R}|Legendary Planeswalker - Ajani|||+1: Target permanent doesn't untap during its controller's next untap step.$-2: Ajani Vengeant deals 3 damage to any target and you gain 3 life.$-7: Destroy all lands target player controls.| Obelisk of Alara|Launch Party|5|R|{6}|Artifact|||{1}{W}, {T}: You gain 5 life.${1}{U}, {T}: Draw a card, then discard a card.${1}{B}, {T}: Target creature gets -2/-2 until end of turn.${1}{R}, {T}: Obelisk of Alara deals 3 damage to target player.${1}{G}, {T}: Target creature gets +4/+4 until end of turn.| @@ -10839,7 +10839,7 @@ Divine Offering|Legends|178|C|{1}{W}|Instant|||Destroy target artifact. You gain Divine Transformation|Legends|179|R|{2}{W}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +3/+3.| Hellfire|Legends|18|R|{2}{B}{B}{B}|Sorcery|||Destroy all nonblack creatures. Hellfire deals X plus 3 damage to you, where X is the number of creatures that died this way.| Elder Land Wurm|Legends|180|R|{4}{W}{W}{W}|Creature - Dragon Wurm|5|5|Defender, trample$When Elder Land Wurm blocks, it loses defender.| -Silhouette|Legends|181|U|{1}{U}|Instant|||Prevent all damage that would be dealt to target creature this turn by spells or abilities that target it.| +Silhouette|Legends|181|U|{1}{U}|Instant|||Prevent all damage that would be dealt to target creature this turn that target it.| Enchanted Being|Legends|181|C|{1}{W}{W}|Creature - Human|2|2|Prevent all combat damage that would be dealt to Enchanted Being by enchanted creatures.| Equinox|Legends|182|C|{W}|Enchantment - Aura|||Enchant land$Enchanted land has "{tap}: Counter target spell if it would destroy a land you control."| Fortified Area|Legends|183|U|{1}{W}{W}|Enchantment|||Wall creatures you control get +1/+0 and have banding. (Any creatures with banding, and up to one without, can attack in a band. Bands are blocked as a group. If any creatures with banding you control are blocking or being blocked by a creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking.)| @@ -11100,7 +11100,7 @@ Needleshot Gourna|Legions|133|C|{4}{G}{G}|Creature - Beast|3|6|Reach (This cr Patron of the Wild|Legions|134|C|{G}|Creature - Elf|1|1|Morph {2}{G} You may cast this card face downn as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)$When Patron of the Wild is turned face up, target creature gets +3/+3 until end of turn.| Primal Whisperer|Legions|135|R|{4}{G}|Creature - Elf Soldier|2|2|Primal Whisperer gets +2/+2 for each face-down creature on the battlefield.$Morph {3}{G} You may cast this card face downn as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)| Quick Sliver|Legions|136|C|{1}{G}|Creature - Sliver|1|1|Flash$Any player may play Sliver cards as though they had flash.| -Root Sliver|Legions|137|U|{3}{G}|Creature - Sliver|2|2|Root Sliver can't be countered.$Sliver spells can't be countered by spells or abilities.| +Root Sliver|Legions|137|U|{3}{G}|Creature - Sliver|2|2|Root Sliver can't be countered.$Sliver spells can't be countered.| Seedborn Muse|Legions|138|R|{3}{G}{G}|Creature - Spirit|2|4|Untap all permanents you control during each other player's untap step.| Stonewood Invoker|Legions|139|C|{1}{G}|Creature - Elf Mutant|2|2|{7}{G}: Stonewood Invoker gets +5/+5 until end of turn.| Gempalm Avenger|Legions|14|C|{5}{W}|Creature - Human Soldier|3|5|Cycling {2}{W} ({2}{W}, Discard this card: Draw a card.)$When you cycle Gempalm Avenger, Soldier creatures get +1/+1 and gain first strike until end of turn.| @@ -12385,7 +12385,7 @@ Chandra Nalaar|Magic 2011|127|M|{3}{R}{R}|Legendary Planeswalker - Chandra|||+1: Chandra's Outrage|Magic 2011|128|C|{2}{R}{R}|Instant|||Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller.| Chandra's Spitfire|Magic 2011|129|U|{2}{R}|Creature - Elemental|1|3|Flying$Whenever an opponent is dealt noncombat damage, Chandra's Spitfire gets +3/+0 until end of turn.| Elite Vanguard|Magic 2011|13|U|{W}|Creature - Human Soldier|2|1|| -Combust|Magic 2011|130|U|{1}{R}|Instant|||Combust can't be countered by spells or abilities.$Combust deals 5 damage to target white or blue creature. The damage can't be prevented.| +Combust|Magic 2011|130|U|{1}{R}|Instant|||Combust can't be countered.$Combust deals 5 damage to target white or blue creature. The damage can't be prevented.| Cyclops Gladiator|Magic 2011|131|R|{1}{R}{R}{R}|Creature - Cyclops Warrior|4|4|Whenever Cyclops Gladiator attacks, you may have it deal damage equal to its power to target creature defending player controls. If you do, that creature deals damage equal to its power to Cyclops Gladiator.| Demolish|Magic 2011|132|C|{3}{R}|Sorcery|||Destroy target artifact or land.| Destructive Force|Magic 2011|133|R|{5}{R}{R}|Sorcery|||Each player sacrifices five lands. Destructive Force deals 5 damage to each creature.| @@ -12631,7 +12631,7 @@ Chandra, the Firebrand|Magic 2012|124|M|{3}{R}|Legendary Planeswalker - Chandra| Chandra's Outrage|Magic 2012|125|C|{2}{R}{R}|Instant|||Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller.| Chandra's Phoenix|Magic 2012|126|R|{1}{R}{R}|Creature - Phoenix|2|2|Flying$Haste (This creature can attack and {tap} as soon as it comes under your control.)$Whenever an opponent is dealt damage by a red instant or sorcery spell you control or by a red planeswalker you control, return Chandra's Phoenix from your graveyard to your hand.| Circle of Flame|Magic 2012|127|U|{1}{R}|Enchantment|||Whenever a creature without flying attacks you or a planeswalker you control, Circle of Flame deals 1 damage to that creature.| -Combust|Magic 2012|128|U|{1}{R}|Instant|||Combust can't be countered by spells or abilities.$Combust deals 5 damage to target white or blue creature. The damage can't be prevented.| +Combust|Magic 2012|128|U|{1}{R}|Instant|||Combust can't be countered.$Combust deals 5 damage to target white or blue creature. The damage can't be prevented.| Crimson Mage|Magic 2012|129|U|{1}{R}|Creature - Human Shaman|2|1|{R}: Target creature you control gains haste until end of turn. (It can attack and {tap} this turn.)| Demystify|Magic 2012|13|C|{W}|Instant|||Destroy target enchantment.| Fiery Hellhound|Magic 2012|130|C|{1}{R}{R}|Creature - Elemental Hound|2|2|{R}: Fiery Hellhound gets +1/+0 until end of turn.| @@ -13776,7 +13776,7 @@ Demolish|Magic Origins|139|C|{3}{R}|Sorcery|||Destroy target artifact or land.| Dragon Fodder|Magic Origins|140|C|{1}{R}|Sorcery|||Put two 1/1 red Goblin creature tokens onto the battlefield.| Embermaw Hellion|Magic Origins|141|R|{3}{R}{R}|Creature - Hellion|4|5|Trample$If another red source you control would deal damage to a permanent or player, it deals that much damage plus 1 to that permanent or player instead.| Enthralling Victor|Magic Origins|142|U|{3}{R}|Creature - Human Warrior|3|2|When Enthralling Victor enters the battlefield, gain control of target creature an opponent controls with power 2 or less until end of turn. Untap that creature. It gains haste until end of turn.| -Exquisite Firecraft|Magic Origins|143|R|{1}{R}{R}|Sorcery|||Exquisite Firecraft deals 4 damage to any target. $Spell mastery � If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered by spells or abilities.| +Exquisite Firecraft|Magic Origins|143|R|{1}{R}{R}|Sorcery|||Exquisite Firecraft deals 4 damage to any target. $Spell mastery � If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered.| Fiery Conclusion|Magic Origins|144|U|{1}{R}|Instant|||As an additional cost to cast Fiery Conclusion, sacrifice a creature.$Fiery Conclusion deals 5 damage to target creature.| Fiery Impulse|Magic Origins|145|C|{R}|Instant|||Fiery Impulse deals 2 damage to target creature.$Spell mastery � If there are two or more instant and/or sorcery cards in your graveyard, Fiery Impulse deals 3 damage to that creature instead.| Firefiend Elemental|Magic Origins|146|C|{3}{R}|Creature - Elemental|3|2|Haste$Renown 1 (When this creature deals combat damage to a player, if it isn't renowned, put a +1/+1 counter on it and it becomes renowned.)| @@ -16821,14 +16821,14 @@ Thief of Hope|Modern Masters 2015|100|C|{2}{B}|Creature - Spirit|2|2|Whenever yo Vampire Lacerator|Modern Masters 2015|101|C|{B}|Creature - Vampire Warrior|2|2|At the beginning of your upkeep, you lose 1 life unless an opponent has 10 or less life.| Vampire Outcasts|Modern Masters 2015|102|U|{2}{B}{B}|Creature - Vampire|2|2|Bloodthirst 2 (If an opponent was dealt damage this turn, this creature enters the battlefield with two +1/+1 counters on it.)$Lifelink (Damage dealt by this creature also causes you to gain that much life.)| Waking Nightmare|Modern Masters 2015|103|C|{2}{B}|Sorcery - Arcane|||Target player discards two cards.| -Banefire|Modern Masters 2015|104|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, Banefire can't be countered by spells or abilities and the damage can't be prevented.| +Banefire|Modern Masters 2015|104|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, Banefire can't be countered and the damage can't be prevented.| Blades of Velis Vel|Modern Masters 2015|105|C|{1}{R}|Tribal Instant - Shapeshifter|||Changeling (This card is every creature type at all times.)$Up to two target creatures each get +2/+0 and gain all creature types until end of turn.| Blood Ogre|Modern Masters 2015|106|C|{2}{R}|Creature - Ogre Warrior|2|2|Bloodthirst 1 (If an opponent was dealt damage this turn, this creature enters the battlefield with a +1/+1 counter on it.)$First strike (This creature deals combat damage before creatures without first strike.)| Bloodshot Trainee|Modern Masters 2015|107|U|{3}{R}|Creature - Goblin Warrior|2|3|{tap}: Bloodshot Trainee deals 4 damage to target creature. Activate this ability only if Bloodshot Trainee's power is 4 or greater.| Brute Force|Modern Masters 2015|108|C|{R}|Instant|||Target creature gets +3/+3 until end of turn.| Burst Lightning|Modern Masters 2015|109|C|{R}|Instant|||Kicker {4} (You may pay an additional {4} as you cast this spell.)$Burst Lightning deals 2 damage to any target. If Burst Lightning was kicked, it deals 4 damage to that creature or player instead.| Celestial Purge|Modern Masters 2015|11|U|{1}{W}|Instant|||Exile target black or red permanent.| -Combust|Modern Masters 2015|110|U|{1}{R}|Instant|||Combust can't be countered by spells or abilities.$Combust deals 5 damage to target white or blue creature. The damage can't be prevented.| +Combust|Modern Masters 2015|110|U|{1}{R}|Instant|||Combust can't be countered.$Combust deals 5 damage to target white or blue creature. The damage can't be prevented.| Comet Storm|Modern Masters 2015|111|M|{X}{R}{R}|Instant|||Multikicker {1} (You may pay an additional {1} any number of times as you cast this spell.)$Choose any target, then choose another any target for each time Comet Storm was kicked. Comet Storm deals X damage to each of them.| Dragonsoul Knight|Modern Masters 2015|112|C|{2}{R}|Creature - Human Knight|2|2|First strike${W}{U}{B}{R}{G}: Until end of turn, Dragonsoul Knight becomes a Dragon, gets +5/+3, and gains flying and trample.| Fiery Fall|Modern Masters 2015|113|C|{5}{R}|Instant|||Fiery Fall deals 5 damage to target creature.$Basic landcycling {1}{R} ({1}{R}, Discard this card: Search your library for a basic land card, reveal it, and put it into your hand. Then shuffle your library.)| @@ -20099,7 +20099,7 @@ Despoiler of Souls|Prerelease Events|203|R|{B}{B}|Creature - Horror|3|1|Despoile Dwynen, Gilt-Leaf Daen|Prerelease Events|204|R|{2}{G}{G}|Legendary Creature - Elf Warrior|3|4|Reach$Other Elf creatures you control get +1/+1.$Whenever Dwynen, Gilt-Leaf Daen attacks, you gain 1 life for each attacking Elf you control.| Embermaw Hellion|Prerelease Events|205|R|{3}{R}{R}|Creature - Hellion|4|5|Trample$If another red source you control would deal damage to a permanent or player, it deals that much damage plus 1 to that permanent or player instead.| Evolutionary Leap|Prerelease Events|206|R|{1}{G}|Enchantment|||{G}, Sacrifice a creature: Reveal cards from the top of your library until you reveal a creature card. Put that card into your hand and the rest on the bottom of your library in a random order.| -Exquisite Firecraft|Prerelease Events|207|R|{1}{R}{R}|Sorcery|||Exquisite Firecraft deals 4 damage to any target. $Spell mastery � If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered by spells or abilities.| +Exquisite Firecraft|Prerelease Events|207|R|{1}{R}{R}|Sorcery|||Exquisite Firecraft deals 4 damage to any target. $Spell mastery � If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered.| Gaea's Revenge|Prerelease Events|208|R|{5}{G}{G}|Creature - Elemental|8|5|Gaea's Revenge can't be countered.$Haste$Gaea's Revenge can't be the target of nongreen spells or abilities from nongreen sources.| Gideon's Phalanx|Prerelease Events|209|R|{5}{W}{W}|Instant|||Put four 2/2 white Knight creature tokens with vigilance onto the battlefield.$Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, creatures you control gain indestructible until end of turn.| Gilt-Leaf Winnower|Prerelease Events|210|R|{3}{B}{B}|Creature - Elf Warrior|4|3|Menace (This creature can't be blocked except by two or more creatures.)$When Gilt-Leaf Winnower enters the battlefield, you may destroy target non-Elf creature whose power and toughness aren't equal.| @@ -20694,7 +20694,7 @@ Urban Burgeoning|Return to Ravnica|138|C|{G}|Enchantment - Aura|||Enchant land$E Wild Beastmaster|Return to Ravnica|139|R|{2}{G}|Creature - Human Shaman|1|1|Whenever Wild Beastmaster attacks, each other creature you control gets +X/+X until end of turn, where X is Wild Beastmaster's power.| Martial Law|Return to Ravnica|14|R|{2}{W}{W}|Enchantment|||At the beginning of your upkeep, detain target creature an opponent controls. (Until your next turn, that creature can't attack or block and its activated abilities can't be activated.)| Worldspine Wurm|Return to Ravnica|140|M|{8}{G}{G}{G}|Creature - Wurm|15|15|Trample$When Worldspine Wurm dies, put three 5/5 green Wurm creature tokens with trample onto the battlefield.$When Worldspine Wurm is put into a graveyard from anywhere, shuffle it into its owner's library.| -Abrupt Decay|Return to Ravnica|141|R|{B}{G}|Instant|||Abrupt Decay can't be countered by spells or abilities.$Destroy target nonland permanent with converted mana cost 3 or less.| +Abrupt Decay|Return to Ravnica|141|R|{B}{G}|Instant|||Abrupt Decay can't be countered.$Destroy target nonland permanent with converted mana cost 3 or less.| Archon of the Triumvirate|Return to Ravnica|142|R|{5}{W}{U}|Creature - Archon|4|5|Flying$Whenever Archon of the Triumvirate attacks, detain up to two target nonland permanents your opponents control. (Until your next turn, those permanents can't attack or block and their activated abilities can't be activated.)| Armada Wurm|Return to Ravnica|143|M|{2}{G}{G}{W}{W}|Creature - Wurm|5|5|Trample$When Armada Wurm enters the battlefield, put a 5/5 green Wurm creature token with trample onto the battlefield.| Auger Spree|Return to Ravnica|144|C|{1}{B}{R}|Instant|||Target creature gets +4/-4 until end of turn.| @@ -20707,7 +20707,7 @@ Palisade Giant|Return to Ravnica|15|R|{4}{W}{W}|Creature - Giant Soldier|2|7|All Collective Blessing|Return to Ravnica|150|R|{3}{G}{G}{W}|Enchantment|||Creatures you control get +3/+3.| Common Bond|Return to Ravnica|151|C|{1}{G}{W}|Instant|||Put a +1/+1 counter on target creature.$Put a +1/+1 counter on target creature.| Corpsejack Menace|Return to Ravnica|152|R|{2}{B}{G}|Creature - Fungus|4|4|If one or more +1/+1 counters would be placed on a creature you control, twice that many +1/+1 counters are placed on it instead.| -Counterflux|Return to Ravnica|153|R|{U}{U}{R}|Instant|||Counterflux can't be countered by spells or abilities.$Counter target spell you don't control.$Overload {1}{U}{U}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")| +Counterflux|Return to Ravnica|153|R|{U}{U}{R}|Instant|||Counterflux can't be countered.$Counter target spell you don't control.$Overload {1}{U}{U}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")| Coursers' Accord|Return to Ravnica|154|C|{4}{G}{W}|Sorcery|||Put a 3/3 green Centaur creature token onto the battlefield, then populate. (Put a token onto the battlefield that's a copy of a creature token you control.)| Detention Sphere|Return to Ravnica|155|R|{1}{W}{U}|Enchantment|||When Detention Sphere enters the battlefield, you may exile target nonland permanent not named Detention Sphere and all other permanents with the same name as that permanent.$When Detention Sphere leaves the battlefield, return the exiled cards to the battlefield under their owner's control.| Dramatic Rescue|Return to Ravnica|156|C|{W}{U}|Instant|||Return target creature to its owner's hand. You gain 2 life.| @@ -20755,7 +20755,7 @@ Search Warrant|Return to Ravnica|193|C|{W}{U}|Sorcery|||Target player reveals hi Selesnya Charm|Return to Ravnica|194|U|{G}{W}|Instant|||Choose one - Target creature gets +2/+2 and gains trample until end of turn; or exile target creature with power 5 or greater; or put a 2/2 white Knight creature token with vigilance onto the battlefield.| Skull Rend|Return to Ravnica|195|C|{3}{B}{R}|Sorcery|||Skull Rend deals 2 damage to each opponent. Those players each discard two cards at random.| Skymark Roc|Return to Ravnica|196|U|{2}{W}{U}|Creature - Bird|3|3|Flying$Whenever Skymark Roc attacks, you may return target creature defending player controls with toughness 2 or less to its owner's hand.| -Slaughter Games|Return to Ravnica|197|R|{2}{B}{R}|Sorcery|||Slaughter Games can't be countered by spells or abilities.$Name a nonland card. Search target opponent's graveyard, hand, and library for any number of cards with that name and exile them. Then that player shuffles his or her library.| +Slaughter Games|Return to Ravnica|197|R|{2}{B}{R}|Sorcery|||Slaughter Games can't be countered.$Name a nonland card. Search target opponent's graveyard, hand, and library for any number of cards with that name and exile them. Then that player shuffles his or her library.| Sluiceway Scorpion|Return to Ravnica|198|C|{2}{B}{G}|Creature - Scorpion|2|2|Deathtouch (Any amount of damage this deals to a creature is enough to destroy it.)$Scavenge {1}{B}{G} ({1}{B}{G}, Exile this card from your graveyard: Put a number of +1/+1 counters equal to this card's power on target creature. Scavenge only as a sorcery.)| Spawn of Rix Maadi|Return to Ravnica|199|C|{3}{B}{R}|Creature - Horror|5|3|Unleash (You may have this creature enter the battlefield with a +1/+1 counter on it. It can't block as long as it has a +1/+1 counter on it.)| Armory Guard|Return to Ravnica|2|C|{3}{W}|Creature - Giant Soldier|2|5|Armory Guard has vigilance as long as you control a Gate.| @@ -22514,7 +22514,7 @@ Tattermunge Maniac|Shadowmoor|219|U|{RG}|Creature - Goblin Warrior|2|1|Tattermun Safehold Sentry|Shadowmoor|22|C|{1}{W}|Creature - Elf Warrior|2|2|{2}{W}, {untap}: Safehold Sentry gets +0/+2 until end of turn. ({untap} is the untap symbol.)| Tattermunge Witch|Shadowmoor|220|U|{1}{RG}|Creature - Goblin Shaman|2|1|{R}{G}: Each blocked creature gets +1/+0 and gains trample until end of turn.| Valleymaker|Shadowmoor|221|R|{5}{RG}|Creature - Giant Shaman|5|5|{tap}, Sacrifice a Mountain: Valleymaker deals 3 damage to target creature.${tap}, Sacrifice a Forest: Choose a player. That player adds {G}{G}{G} to his or her mana pool.| -Vexing Shusher|Shadowmoor|222|R|{RG}{RG}|Creature - Goblin Shaman|2|2|Vexing Shusher can't be countered.${RG}: Target spell can't be countered by spells or abilities.| +Vexing Shusher|Shadowmoor|222|R|{RG}{RG}|Creature - Goblin Shaman|2|2|Vexing Shusher can't be countered.${RG}: Target spell can't be countered.| Wort, the Raidmother|Shadowmoor|223|R|{4}{RG}{RG}|Legendary Creature - Goblin Shaman|3|3|When Wort, the Raidmother enters the battlefield, put two 1/1 red and green Goblin Warrior creature tokens onto the battlefield.$Each red or green instant or sorcery spell you cast has conspire. (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.)| Barkshell Blessing|Shadowmoor|224|C|{GW}|Instant|||Target creature gets +2/+2 until end of turn.$Conspire (As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose a new target for the copy.)| Dawnglow Infusion|Shadowmoor|225|U|{X}{GW}|Sorcery|||You gain X life if {G} was spent to cast Dawnglow Infusion and X life if {W} was spent to cast it. (Do both if {G}{W} was spent.)| @@ -25094,7 +25094,7 @@ Grim Lavamancer|Torment|100|R|{R}|Creature - Human Wizard|1|1|{R}, {tap}, Exile Hell-Bent Raider|Torment|101|R|{1}{R}{R}|Creature - Human Barbarian|2|2|First strike, haste$Discard a card at random: Hell-Bent Raider gains protection from white until end of turn.| Kamahl's Sledge|Torment|102|C|{5}{R}{R}|Sorcery|||Kamahl's Sledge deals 4 damage to target creature.$Threshold - If seven or more cards are in your graveyard, instead Kamahl's Sledge deals 4 damage to that creature and 4 damage to that creature's controller.| Longhorn Firebeast|Torment|103|C|{2}{R}|Creature - Elemental Ox Beast|3|2|When Longhorn Firebeast enters the battlefield, any opponent may have it deal 5 damage to him or her. If a player does, sacrifice Longhorn Firebeast.| -Overmaster|Torment|104|R|{R}|Sorcery|||The next instant or sorcery spell you cast this turn can't be countered by spells or abilities.$Draw a card.| +Overmaster|Torment|104|R|{R}|Sorcery|||The next instant or sorcery spell you cast this turn can't be countered.$Draw a card.| Pardic Arsonist|Torment|105|U|{2}{R}{R}|Creature - Human Barbarian|3|3|Threshold - As long as seven or more cards are in your graveyard, Pardic Arsonist has "When Pardic Arsonist enters the battlefield, it deals 3 damage to any target."| Pardic Collaborator|Torment|106|U|{3}{R}|Creature - Human Barbarian|2|2|First strike${B}: Pardic Collaborator gets +1/+1 until end of turn.| Pardic Lancer|Torment|107|C|{4}{R}|Creature - Human Barbarian|3|2|Discard a card at random: Pardic Lancer gets +1/+0 and gains first strike until end of turn.| @@ -25119,7 +25119,7 @@ Centaur Veteran|Torment|123|C|{5}{G}|Creature - Centaur|3|3|Trample${G}, Discard Dwell on the Past|Torment|124|U|{G}|Sorcery|||Target player shuffles up to four target cards from his or her graveyard into his or her library.| Far Wanderings|Torment|125|C|{2}{G}|Sorcery|||Search your library for a basic land card, put that card onto the battlefield tapped, then shuffle your library.$Threshold - If seven or more cards are in your graveyard, instead search your library for up to three basic land cards, put them onto the battlefield tapped, then shuffle your library.| Gurzigost|Torment|126|R|{3}{G}{G}|Creature - Beast|6|8|At the beginning of your upkeep, sacrifice Gurzigost unless you put two cards from your graveyard on the bottom of your library.${G}{G}, Discard a card: You may have Gurzigost assign its combat damage this turn as though it weren't blocked.| -Insist|Torment|127|R|{G}|Sorcery|||The next creature spell you cast this turn can't be countered by spells or abilities.$Draw a card.| +Insist|Torment|127|R|{G}|Sorcery|||The next creature spell you cast this turn can't be countered.$Draw a card.| Invigorating Falls|Torment|128|C|{2}{G}{G}|Sorcery|||You gain life equal to the number of creature cards in all graveyards.| Krosan Constrictor|Torment|129|C|{3}{G}|Creature - Snake|2|2|Swampwalk${tap}: Target black creature gets -2/-0 until end of turn.| Possessed Nomad|Torment|13|R|{2}{W}{W}|Creature - Human Nomad Horror|3|3|Vigilance$Threshold - As long as seven or more cards are in your graveyard, Possessed Nomad gets +1/+1, is black, and has "{2}{B}, {tap}: Destroy target white creature."| @@ -26834,7 +26834,7 @@ Thalia, Guardian of Thraben|World Magic Cup Qualifier|3|R|{1}{W}|Legendary Creat Liliana of the Veil|World Magic Cup Qualifier|4|M|{1}{B}{B}|Legendary Planeswalker - Liliana|||+1: Each player discards a card.$-2: Target player sacrifices a creature.$-6: Separate all permanents target player controls into two piles. That player sacrifices all permanents in the pile of his or her choice.| Snapcaster Mage|World Magic Cup Qualifier|5|R|{1}{U}|Creature - Human Wizard|2|1|Flash$When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. (You may cast that card from your graveyard for its flashback cost. Then exile it.)| Inkmoth Nexus|World Magic Cup Qualifier|6|Special||Land|||{tap}: Add {C}.${1}: Blinkmoth Nexus becomes a 1/1 Blinkmoth artifact creature with flying until end of turn. It's still a land.${1}, {tap}: Target Blinkmoth creature gets +1/+1 until end of turn.| -Abrupt Decay|World Magic Cup Qualifier|6|R|{B}{G}|Instant|||Abrupt Decay can't be countered by spells or abilities.$Destroy target nonland permanent with converted mana cost 3 or less.| +Abrupt Decay|World Magic Cup Qualifier|6|R|{B}{G}|Instant|||Abrupt Decay can't be countered.$Destroy target nonland permanent with converted mana cost 3 or less.| Admonition Angel|Worldwake|1|M|{3}{W}{W}{W}|Creature - Angel|6|6|Flying$Landfall - Whenever a land enters the battlefield under your control, you may exile target nonland permanent other than Admonition Angel.$When Admonition Angel leaves the battlefield, return all cards exiled with it to the battlefield under their owners' control.| Kitesail Apprentice|Worldwake|10|C|{W}|Creature - Kor Soldier|1|1|As long as Kitesail Apprentice is equipped, it gets +1/+1 and has flying.| Feral Contest|Worldwake|100|C|{3}{G}|Sorcery|||Put a +1/+1 counter on target creature you control. Another target creature blocks it this turn if able.| @@ -27720,7 +27720,7 @@ Stoneshock Giant|Commander 2015 Edition|165|U|{3}{R}{R}|Creature - Giant|5|4|{6} Sunrise Sovereign|Commander 2015 Edition|166|R|{5}{R}|Creature - Giant Warrior|5|5|Other Giant creatures you control get +2/+2 and have trample.| Taurean Mauler|Commander 2015 Edition|167|R|{2}{R}|Creature - Shapeshifter|2|2|Changeling (This card is every creature type at all times.)$Whenever an opponent casts a spell, you may put a +1/+1 counter on Taurean Mauler.| Thundercloud Shaman|Commander 2015 Edition|168|U|{3}{R}{R}|Creature - Giant Shaman|4|4|When Thundercloud Shaman enters the battlefield, it deals damage equal to the number of Giants you control to each non-Giant creature.| -Urza's Rage|Commander 2015 Edition|169|R|{2}{R}|Instant|||Kicker {8}{R} (You may pay an additional {8}{R} as you cast this spell.)$Urza's Rage can't be countered by spells or abilities.$Urza's Rage deals 3 damage to any target. If Urza's Rage was kicked, instead it deals 10 damage to that creature or player and the damage can't be prevented.| +Urza's Rage|Commander 2015 Edition|169|R|{2}{R}|Instant|||Kicker {8}{R} (You may pay an additional {8}{R} as you cast this spell.)$Urza's Rage can't be countered.$Urza's Rage deals 3 damage to any target. If Urza's Rage was kicked, instead it deals 10 damage to that creature or player and the damage can't be prevented.| Corpse Augur|Commander 2015 Edition|17|U|{3}{B}|Creature - Zombie Wizard|4|2|When Corpse Augur dies, you draw X cards and you lose X life, where X is the number of creature cards in target player's graveyard.| Vandalblast|Commander 2015 Edition|170|U|{R}|Sorcery|||Destroy target artifact you don't control.$Overload {4}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")| Warstorm Surge|Commander 2015 Edition|171|R|{5}{R}|Enchantment|||Whenever a creature enters the battlefield under your control, it deals damage equal to its power to any target.| @@ -27771,7 +27771,7 @@ Viridian Zealot|Commander 2015 Edition|210|R|{G}{G}|Creature - Elf Warrior|2|1|{ Wall of Blossoms|Commander 2015 Edition|211|U|{1}{G}|Creature - Plant Wall|0|4|Defender$When Wall of Blossoms enters the battlefield, draw a card.| Wood Elves|Commander 2015 Edition|212|C|{2}{G}|Creature - Elf Scout|1|1|When Wood Elves enters the battlefield, search your library for a Forest card and put that card onto the battlefield. Then shuffle your library.| Coiling Oracle|Commander 2015 Edition|213|C|{G}{U}|Creature - Snake Elf Druid|1|1|When Coiling Oracle enters the battlefield, reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put that card into your hand.| -Counterflux|Commander 2015 Edition|214|R|{U}{U}{R}|Instant|||Counterflux can't be countered by spells or abilities.$Counter target spell you don't control.$Overload {1}{U}{U}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")| +Counterflux|Commander 2015 Edition|214|R|{U}{U}{R}|Instant|||Counterflux can't be countered.$Counter target spell you don't control.$Overload {1}{U}{U}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")| Death Grasp|Commander 2015 Edition|215|R|{X}{W}{B}|Sorcery|||Death Grasp deals X damage to any target. You gain X life.| Epic Experiment|Commander 2015 Edition|216|M|{X}{U}{R}|Sorcery|||Exile the top X cards of your library. For each instant and sorcery card with converted mana cost X or less among them, you may cast that card without paying its mana cost. Then put all cards exiled this way that weren't cast into your graveyard.| Etherium-Horn Sorcerer|Commander 2015 Edition|217|R|{4}{U}{R}|Artifact Creature - Minotaur Wizard|3|6|{1}{U}{R}: Return Etherium-Horn Sorcerer to its owner's hand.$Cascade (When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom in a random order.)| @@ -28284,7 +28284,7 @@ Negate|Oath of the Gatewatch|59|C|{1}{U}|Instant|||Counter target noncreature sp Oath of Jace|Oath of the Gatewatch|60|R|{2}{U}|Legendary Enchantment|||When Oath of Jace enters the battlefield, draw three cards, then discard two cards.$At the beginning of your upkeep, scry X, where X is the number of planeswalkers you control.| Overwhelming Denial|Oath of the Gatewatch|61|R|{2}{U}{U}|Instant|||Surge {U}{U} (You may cast this spell for its surge cost if you or a teammate has cast another spell this turn.)$Overwhelming Denial can't be countered by spell or abilities.$Counter target spell.| Roiling Waters|Oath of the Gatewatch|62|U|{5}{U}{U}|Sorcery|||Return up to two target creatures your opponents control to their owners' hands. Target player draws two cards.| -Sphinx of the Final Word|Oath of the Gatewatch|63|M|{5}{U}{U}|Creature - Sphinx|5|5|Sphinx of the Final Word can't be countered.$Flying, hexproof$Instant and sorcery spells you control can't be countered by spells or abilities.| +Sphinx of the Final Word|Oath of the Gatewatch|63|M|{5}{U}{U}|Creature - Sphinx|5|5|Sphinx of the Final Word can't be countered.$Flying, hexproof$Instant and sorcery spells you control can't be countered.| Sweep Away|Oath of the Gatewatch|64|C|{2}{U}|Instant|||Return target creature to its owner's hand. If that creature is attacking, you may put it on top of its owner's library instead.| Umara Entangler|Oath of the Gatewatch|65|C|{1}{U}|Creature - Merfolk Rogue Ally|2|1|Prowess (Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn.)| Unity of Purpose|Oath of the Gatewatch|66|U|{3}{U}|Instant|||Support 2. (Put a +1/+1 counter on each of up to two target creatures.)$Untap each creature you control with a +1/+1 counter on it.| @@ -28339,7 +28339,7 @@ Press into Service|Oath of the Gatewatch|114|U|{4}{R}|Sorcery|||Support 2. (P Pyromancer's Assault|Oath of the Gatewatch|115|U|{3}{R}|Enchantment|||Whenever you cast your second spell each turn, Pyromancer's Assault deals 2 damage to any target.| Reckless Bushwhacker|Oath of the Gatewatch|116|U|{2}{R}|Creature - Goblin Warrior Ally|2|1|Surge {1}{R} (You may cast this spell for its surge cost if you or a teammate has cast another spell this turn.)$Haste$When Reckless Bushwhacker enters the battlefield, if its surge cost was paid, other creatures you control get +1/+0 and gain haste until end of turn.| Sparkmage's Gambit|Oath of the Gatewatch|117|C|{1}{R}|Sorcery|||Sparkmage's Gambit deals 1 damage to each of up to two target creatures. Those creatures can't block this turn.| -Tears of Valakut|Oath of the Gatewatch|118|U|{1}{R}|Instant|||Tears of Valakut can't be countered by spells or abilities.$Tears of Valakut deals 5 damage to target creature with flying.| +Tears of Valakut|Oath of the Gatewatch|118|U|{1}{R}|Instant|||Tears of Valakut can't be countered.$Tears of Valakut deals 5 damage to target creature with flying.| Tyrant of Valakut|Oath of the Gatewatch|119|R|{5}{R}{R}|Creature - Dragon|5|4|Surge {3}{R}{R} (You may cast this spell for its surge cost if you or a teammate has cast another spell this turn.)$Flying$When Tyrant of Valakut enters the battlefield, if its surge cost was paid, it deals 3 damage to any target.| Zada's Commando|Oath of the Gatewatch|120|C|{1}{R}|Creature - Goblin Archer Ally|2|1|First strike$Cohort — {T}, Tap an untapped Ally you control: Zada's Commando deals 1 damage to target opponent.| Birthing Hulk|Oath of the Gatewatch|121|U|{6}{G}|Creature - Eldrazi Drone|5|4|Devoid (This card has no color.)When Birthing Hulk enters the battlefield, put two 1/1 colorless Eldrazi Scion creature tokens onto the battlefield. They have "Sacrifice this creature: Add {C}."${1}{C}: Regenerate Birthing Hulk.| @@ -28510,7 +28510,7 @@ Chalice of Death|Dark Ascension|146b|U||Artifact|||{tap}: Target player loses 5 Elbrus, the Binding Blade|Dark Ascension|147a|M|{7}|Legendary Artifact - Equipment|||Equipped creature gets +1/+0.$When equipped creature deals combat damage to a player, unattach Elbrus, the Binding Blade, then transform it.$Equip {1}| Ghastly Haunting|Dark Ascension|50b|U||Enchantment - Aura|||Enchant creature$You control enchanted creature.| Bound|Dissension|149a|R|{3}{B}{G}|Instant|||Sacrifice a creature. Return up to X cards from your graveyard to your hand, where X is the number of colors that creature was. Exile this card.$| -Determined|Dissension|149b|R|{G}{U}|Instant|||$Other spells you control can't be countered by spells or abilities this turn.$Draw a card.| +Determined|Dissension|149b|R|{G}{U}|Instant|||$Other spells you control can't be countered this turn.$Draw a card.| Crime|Dissension|150a|R|{3}{W}{B}|Sorcery|||Put target creature or enchantment card from an opponent's graveyard onto the battlefield under your control.$| Punishment|Dissension|150b|R|{X}{B}{G}|Sorcery|||$Destroy each artifact, creature, and enchantment with converted mana cost X.| Hide|Dissension|151a|R|{R}{W}|Instant|||Put target artifact or enchantment on the bottom of its owner's library.$| @@ -29584,7 +29584,7 @@ Wailing Ghoul|Eldritch Moon|112|C|{1}{B}|Creature - Zombie|1|3|When Wailing Ghou Weirded Vampire|Eldritch Moon|113|C|{3}{B}|Creature - Vampire Horror|3|3|Madness {2}{B} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)| Whispers of Emrakul|Eldritch Moon|114|U|{1}{B}|Sorcery|||Target opponent discards a card at random.$Delirium — If there are four or more card types among cards in your graveyard, that player discards two cards at random instead.| Abandon Reason|Eldritch Moon|115|U|{2}{R}|Instant|||Up to two target creatures each get +1/+0 and gain first strike until end of turn.$Madness {1}{R} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)| -Alchemist's GreetinG|Eldritch Moon|116|C|{4}{R}|Sorcery|||Alchemist's Greeting deals 4 damage to target creature.$Madness {1}{R} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)| +Alchemist's Greeting|Eldritch Moon|116|C|{4}{R}|Sorcery|||Alchemist's Greeting deals 4 damage to target creature.$Madness {1}{R} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)| Assembled Alphas|Eldritch Moon|117|R|{5}{R}|Creature - Wolf|5|5|Whenever Assembled Alphas blocks or becomes blocked by a creature, Assembled Alphas deals 3 damage to that creature and 3 damage to that creature's controller.| Bedlam Reveler|Eldritch Moon|118|R|{6}{R}{R}|Creature - Devil Horror|3|4|Bedlam Reveler costs {1} less to cast for each instant or sorcery card in your graveyard.$Prowess (Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn.)$When Bedlam Reveler enters the battlefield, discard your hand, then draw three cards.| Blood Mist|Eldritch Moon|119|U|{3}{R}|Enchantment|||At the beginning of combat on your turn, target creature you control gains double strike until end of turn.| @@ -30466,7 +30466,7 @@ Skyship Plunderer|Aether Revolt|46|U|{1}{U}|Creature - Human Pirate|2|1|Flying$W Take into Custody|Aether Revolt|47|C|{U}|Instant|||Tap target creature. It doesn't untap during its controller's next untap step.| Trophy Mage|Aether Revolt|48|U|{2}{U}|Creature - Human Wizard|2|2|When Trophy Mage enters the battlefield, you may search your library for an artifact card with converted mana cost 3, reveal it, put it into your hand, then shuffle your library.| Whir of Invention|Aether Revolt|49|R|{X}{U}{U}{U}|Instant|||Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}.)$Search your library for an artifact card with converted mana cost X or less, put it onto the battlefield, then shuffle your library.| -Wind-King Raiders|Aether Revolt|50|U|{4}{U}{U}|Creature - Human Artificer|4|3|Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}.)$Flying| +Wind-Kin Raiders|Aether Revolt|50|U|{4}{U}{U}|Creature - Human Artificer|4|3|Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}.)$Flying| Aether Poisoner|Aether Revolt|51|C|{1}{B}|Creature - Human Artificer|1|1|Deathtouch (Any amount of damage this deals to a creature is enough to destroy it.)$When Aether Poisoner enters the battlefield, you get {E}{E} (two energy counters).$Whenever Aether Poisoner attacks, you may pay {E}{E}. If you do, create a 1/1 colorless Servo artifact creature token.| Alley Strangler|Aether Revolt|52|C|{2}{B}|Creature - Aetherborn Rogue|2|3|Menace| Battle at the Bridge|Aether Revolt|53|R|{X}{B}|Sorcery|||Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}.)$Target creature gets -X/-X until end of turn. You gain X life.| @@ -30757,7 +30757,7 @@ Thornscape Battlemage|Modern Masters 2017|142|U|{2}{G}|Creature - Elf Wizard|2|2 Thragtusk|Modern Masters 2017|143|R|{4}{G}|Creature - Beast|5|3|When Thragtusk enters the battlefield, you gain 5 life.$When Thragtusk leaves the battlefield, create a 3/3 green Beast creature token.| Ulvenwald Tracker|Modern Masters 2017|144|R|{G}|Creature - Human Shaman|1|1|{1}{G}, {T}: Target creature you control fights another target creature.| Vital Splicer|Modern Masters 2017|145|U|{3}{G}|Creature - Human Artificer|1|1|When Vital Splicer enters the battlefield, create a 3/3 colorless Golem artifact creature token.${1}: Regenerate target Golem you control.| -Abrupt Decay|Modern Masters 2017|146|R|{B}{G}|Instant|||Abrupt Decay can't be countered by spells or abilities.$Destroy target nonland permanent with converted mana cost 3 or less.| +Abrupt Decay|Modern Masters 2017|146|R|{B}{G}|Instant|||Abrupt Decay can't be countered.$Destroy target nonland permanent with converted mana cost 3 or less.| Advent of the Wurm|Modern Masters 2017|147|R|{1}{G}{G}{W}|Instant|||Create a 5/5 green Wurm creature token with trample.| Aethermage's Touch|Modern Masters 2017|148|R|{2}{W}{U}|Instant|||Reveal the top four cards of your library. You may put a creature card from among them onto the battlefield. It gains "At the beginning of your end step, return this creature to its owner's hand." Then put the rest of the cards revealed this way on the bottom of your library in any order.| Agent of Masks|Modern Masters 2017|149|U|{3}{W}{B}|Creature - Human Advisor|2|3|At the beginning of your upkeep, each opponent loses 1 life. You gain life equal to the life lost this way.| @@ -30874,7 +30874,7 @@ Djeru's Resolve|Amonkhet|11|C|{W}|Instant|||Untap target creature. Prevent all d Fan Bearer|Amonkhet|12|C|{W}|Creature - Zombie|1|2|{2}, {T}: Tap target creature.| Forsake the Worldly|Amonkhet|13|C|{2}{W}|Instant|||Exile target artifact or enchantment.$Cycling {2}| Gideon of the Trials|Amonkhet|14|M|{1}{W}{W}|Legendary Planeswalker - Gideon|||+1: Until your next turn, prevent all damage target permanent would deal.$0: Until end of turn, Gideon of the Trials becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn.$0: You get an emblem with "As long as you control a Gideon planeswalker, you can't lose the game and your opponent can't win the game."| -Gideon's Intervention|Amonkhet|15|R|{2}{W}{W}|Enchantment|||As Gideon’s Intervention enters the battlefield, choose a card name.$Your opponents can’t cast spells with the chosen name.$Prevent all damage that would be dealt to you and permanents you control by sources with the chosen name.| +Gideon's Intervention|Amonkhet|15|R|{2}{W}{W}|Enchantment|||As Gideon's Intervention enters the battlefield, choose a card name.$Your opponents can't cast spells with the chosen name.$Prevent all damage that would be dealt to you and permanents you control by sources with the chosen name.| Glory-Bound Initiate|Amonkhet|16|R|{1}{W}|Creature - Human Warrior|3|1|You may exert Glory-Bound Initiate as it attacks. When you do, it gets +1/+3 and gains lifelink until end of turn.| Gust Walker|Amonkhet|17|C|{1}{W}|Creature - Human Wizard|2|2|You may exert Gust Walker as it attacks. When you do, it gets +1/+1 and gains flying until end of turn.| Impeccable Timing|Amonkhet|18|C|{1}{W}|Instant|||Impeccable Timing deals 3 damage to target attacking or blocking creature.| @@ -31706,7 +31706,7 @@ Mathas, Fiend Seeker|Commander 2017 Edition|42|M|{R}{W}{B}|Legendary Creature - Mirri, Weatherlight Duelist|Commander 2017 Edition|43|M|{1}{G}{W}|Legendary Creature - Cat Warrior|3|2|First Strike$Whenever Mirri, Weatherlight Duelist attacks, each opponent can't block with more than one creature this combat.$As long as Mirri, Weatherlight Duelist is tapped, no more than one creature can attack you each combat.| Nazahn, Revered Bladesmith|Commander 2017 Edition|44|M|{4}{G}{W}|Legendary Creature - Cat Artificer|5|4|When Nazahn, Revered Bladesmith enters the battlefield, search your library for an Equipment card and reveal it. If you reveal a card named Hammer of Nazahn this way, put it onto the battlefield. Otherwise, put that card into your hand. Then shuffle your library.$Whenever an equipped creature you control attacks, you may tap target creature defending player controls.| O-Kagachi, Vengeful Kami|Commander 2017 Edition|45|M|{1}{W}{U}{B}{R}{G}|Legendary Creature - Dragon Spirit|6|6|Flying, Trample$Whenever O-Kagachi, Vengeful Kami deals combat damage to a player, if that player attacked you during his or her last turn, exile target nonland permanent that player controls| -Taigam, Ojutai Master|Commander 2017 Edition|46|R|{2}{W}{U}|Legendary Creature - Human Monk|3|4|Instant, sorcery, and Dragon spells you control can't be countered by spells or abilities.$Whenever you cast an instant or sorcery spell from your hand, if Taigam, Ojutai Master attacked this turn, that spell gains rebound. (Exile the spell as it resolves. At the beginning of your next upkeep, you may cast that card from exile without paying its mana cost.)| +Taigam, Ojutai Master|Commander 2017 Edition|46|R|{2}{W}{U}|Legendary Creature - Human Monk|3|4|Instant, sorcery, and Dragon spells you control can't be countered.$Whenever you cast an instant or sorcery spell from your hand, if Taigam, Ojutai Master attacked this turn, that spell gains rebound. (Exile the spell as it resolves. At the beginning of your next upkeep, you may cast that card from exile without paying its mana cost.)| Taigam, Sidisi's Hand|Commander 2017 Edition|47|R|{3}{U}{B}|Legendary Creature - Human Wizard|3|4|Skip your draw step.$At the beginning of your upkeep, look at the top three cards of your library. Put one of them into your hand and the rest into your graveyard.$B, T, Exile X cards from your graveyard: Target creature gets -X/-X until end of turn.| The Ur-Dragon|Commander 2017 Edition|48|M|{4}{W}{U}{B}{R}{G}|Legendary Creature - Dragon Avatar|10|10|Eminence — As long as The Ur-Dragon is in the command zone or on the battlefield, other Dragon spells you cast cost {1} less to cast.$Flying$Whenever one or more Dragons you control attack, draw that many cards, then you may put a permanent card from your hand onto the battlefield| Wasitora, Nekoru Queen|Commander 2017 Edition|49|M|{2}{B}{R}{G}|Legendary Creature - Cat Dragon|5|4|Flying, trample$Whenever Wasitora, Nekoru Queen deals combat damage to a player, that player sacrifices a creature. If the player can't, you create a 3/3 black, red, and green Cat Dragon creature token with flying| @@ -32680,7 +32680,7 @@ Famished Paladin|Rivals of Ixalan|8|U|{1}{W}|Creature - Vampire Knight|3|3|Famis Forerunner of the Legion|Rivals of Ixalan|9|U|{2}{W}|Creature - Vampire Knight|2|2|When Forerunner of the Legion enters the battlefield, you may search your library for a Vampire card, reveal it, then shuffle your library and put that card on top of it.$Whenever another Vampire enters the battlefield under your control, target creature gets +1/+1 until end of turn.| Imperial Ceratops|Rivals of Ixalan|10|U|{4}{W}|Creature - Dinosaur|3|5|Enrage - Whenever Imperial Ceratops is dealt damage, you gain 2 life.| Legion Conquistador|Rivals of Ixalan|11|C|{2}{W}|Creature - Vampire Soldier|2|2|When Legion Conquistador enters the battlefield, you may search your library for any number of cards named Legion Conquistador, reveal them, put them into your hand, then shuffle your library.| -Luminous Bond|Rivals of Ixalan|12|C|{2}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature can't attack or block.| +Luminous Bonds|Rivals of Ixalan|12|C|{2}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature can't attack or block.| Majestic Heliopterus|Rivals of Ixalan|13|U|{3}{W}|Creature - Dinosaur|2|2|Flying$Whenever Majestic Heliopterus attacks, another target Dinosaur you control gains flying until end of turn.| Martyr of Dusk|Rivals of Ixalan|14|C|{1}{W}|Creature - Vampire Soldier|2|1|When Martyr of Dusk dies, create a 1/1 white Vampire creature token with lifelink.| Moment of Triumph|Rivals of Ixalan|15|C|{W}|Instant|||Target creature gets +2/+2 until end of turn. You gain 2 life.| @@ -32711,10 +32711,10 @@ Hornswoggle|Rivals of Ixalan|39|U|{2}{U}|Instant|||Counter target creature spell Induced Amnesia|Rivals of Ixalan|40|R|{2}{U}|Enchantment|||When Induced Amnesia enters the battlefield, target player exiles all the cards in his or her hand face down, then draws that many cards.$When Induced Amnesia is put into a graveyard from the battlefield, return the exiled cards to their owner's hand.| Kitesail Corsair|Rivals of Ixalan|41|C|{1}{U}|Creature - Human Pirate|2|1|Kitesail Corsair has flying as long as it's attacking.| Kumena's Awakening|Rivals of Ixalan|42|R|{2}{U}{U}|Enchantment|||Ascend (If you control ten or more permenants, you get the city's blessing for the rest of the game.)$At the beginning of your upkeep, each player draws a card. If you have the city's blessing, instead only you draw a card.| -Mist-Cloacked Herald|Rivals of Ixalan|43|C|{U}|Creature - Merfolk Warrior|1|1|Mist-Cloaked Herald can't be blocked.| +Mist-Cloaked Herald|Rivals of Ixalan|43|C|{U}|Creature - Merfolk Warrior|1|1|Mist-Cloaked Herald can't be blocked.| Negate|Rivals of Ixalan|44|C|{1}{U}|Instant|||Counter target noncreature spell.| Nezahal, Primal Tide|Rivals of Ixalan|45|M|{5}{U}{U}|Legendary Creature - Elder Dinosaur|7|7|Nezahal, Primal Tide can't be countered.$You have no maximum hand size.$Whenever an opponent casts a noncreature spell, draw a card.$Discard three cards: Exile Nezahal. Return it to the battlefield tapped under its owner's control at the beginning of the next end step.| -Return to the Wind|Rivals of Ixalan|46|R|{2}{U}|Instant|||Exile target nonland permanent. For as long as that card remains exiled, its owner may cast it without paying its mana cost.| +Release to the Wind|Rivals of Ixalan|46|R|{2}{U}|Instant|||Exile target nonland permanent. For as long as that card remains exiled, its owner may cast it without paying its mana cost.| River Darter|Rivals of Ixalan|47|C|{2}{U}|Creature - Merfolk Warrior|2|3|River Darter can't be blocked by Dinosaurs.| Riverwise Augur|Rivals of Ixalan|48|U|{3}{U}|Creature - Merfolk Wizard|2|2|When Riverwise Augur enters the battlefield, draw three cards, then put two cards from your hand on top of your library in any order. | Sailor of Means|Rivals of Ixalan|49|C|{2}{U}|Creature - Human Pirate|1|4|When Sailor of Means enters the battlefield, create a colorless Treasure artifact token with "{t}, Sacrifice this artifact: Add one mana of any color." | @@ -32726,7 +32726,7 @@ Siren Reaver|Rivals of Ixalan|54|U|{3}{U}|Creature - Siren Pirate|3|2|Raid(If you control ten or more permanents, you get the city's blessing for the rest of the game.)$As long as you have the city's blessing Slippery Scoundrel has Hexproof and can't be blocked.| Soul of the Rapids|Rivals of Ixalan|56|C|{3}{U}{U}|Creature - Elemental|3|2|Flying$Hexproof (This creature can't be the target of spells or abilities your opponents control.)| Spire Winder|Rivals of Ixalan|57|C|{3}{U}|Creature - snake|2|3|Flying$Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)$Spire Winder gets +1/+1 as long as you have the city's blessing.| -Sworn Gaurdian|Rivals of Ixalan|58|C|{1}{U}|Creature - Merfolk Warrior|1|3|| +Sworn Guardian|Rivals of Ixalan|58|C|{1}{U}|Creature - Merfolk Warrior|1|3|| Timestream Navigator|Rivals of Ixalan|59|M|{1}{U}|Creature - Human Pirate Wizard|1|1|Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)${2}{U}{U}, {T}, Put Timestream Navigator on the bottom of its owner's library: Take an extra turn after this one. Activate this ability only if you have the city's blessing.| Warkite Marauder|Rivals of Ixalan|60|R|{1}{U}|Creature - Human Pirate|2|1|Flying$Whenever Warkite Marauder attacks, target creature defending player controls loses all abilities and has base power and toughness 0/1 until end of turn.| Waterknot|Rivals of Ixalan|61|C|{1}{U}{U}|Enchantment - Aura|||Enchant Crerature$When Waterknot enters the battlefield, tap enchanted creature.$Enchanted creature doesn't untap during it's controller's untap step.| @@ -32788,7 +32788,7 @@ Stampeding Horncrest|Rivals of Ixalan|116|C|{4}{R}|Creature - Dinosaur|4|4|Stamp Storm Fleet Swashbuckler|Rivals of Ixalan|117|U|{1}{R}|Creature - Human Pirate|2|2|Ascend (If you control 10 or more permanents, you gain the city's blessing for the rest of the game.)$Storm Fleet Swashbuckler has double strike as long as you have the city's blessing.| Sun-Collared Raptor|Rivals of Ixalan|118|C|{1}{R}|Creature - Dinosaur|1|2|Trample${2}{R}: Sun-Collared Raptor gets +3/+0 until end of turn.| Swaggering Corsair|Rivals of Ixalan|119|C|{2}{R}|Creature - Human Pirate|2|2|Raid — Swaggering Corsair enters the battlefield with a +1/+1 counter on it if you attacked with a creature this turn.| -Tilonali's Crown|Rivals of Ixalan|120|C|{1}{R}|Enchantment - Aura|||Enchant creature$When Tilonali's Crown enters the battlefield, it deals 1 damage to enchanted creature.$Enchanted creature gets +3/+0 and has trample.| +Tilonalli's Crown|Rivals of Ixalan|120|C|{1}{R}|Enchantment - Aura|||Enchant creature$When Tilonali's Crown enters the battlefield, it deals 1 damage to enchanted creature.$Enchanted creature gets +3/+0 and has trample.| Tilonalli's Summoner|Rivals of Ixalan|121|R|{1}{R}|Creature - Human Shaman|1|1|Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)$Whenever Tilonalli's Summoner attacks, you may pay {X}{R}. If you do, create X 1/1 Elemental creature tokens that are tapped and attacking. At the beginning of the next end step, exile those tokens unless you have the city's blessing.| Aggressive Urge|Rivals of Ixalan|122|C|{1}{G}|Instant|||Target creature gets +1/+1 until end of turn.$Draw a card.| Cacophodon|Rivals of Ixalan|123|U|{3}{G}|Creature - Dinosaur|2|5|Enrage — Whenever Cacophodon is dealt damage, untap target permanent.| @@ -32810,7 +32810,7 @@ Knight of the Stampede|Rivals of Ixalan|138|C|{3}{G}|Creature - Human Knight|2|4 Naturalize|Rivals of Ixalan|139|C|{1}{G}|Instant|||Destroy target artifact or enchantment.| Orazca Frillback|Rivals of Ixalan|140|C|{2}{G}|Creature - Dinosaur|4|2|| Overgrown Armasaur|Rivals of Ixalan|141|C|{3}{G}{G}|Creature - Dinosaur|4|4|Enrage — Whenever Overgrown Armasaur is dealt damage, create a 1/1 green Saproling creature token.| -Path to Discovery|Rivals of Ixalan|142|R|{3}{G}|Enchantment|||Whenever a creature enters the battlefield under your control, it explores. (Reveal the top card of your library. Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on the creature, then put the card back or put it into your graveyard.)| +Path of Discovery|Rivals of Ixalan|142|R|{3}{G}|Enchantment|||Whenever a creature enters the battlefield under your control, it explores. (Reveal the top card of your library. Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on the creature, then put the card back or put it into your graveyard.)| Plummet|Rivals of Ixalan|143|C|{1}{G}|Instant|||Destroy target creature with flying.| Polyraptor|Rivals of Ixalan|144|M|{6}{G}{G}|Creature - Dinosaur|5|5|Enrage — Whenever Polyraptor is dealt damage, create a token that is a copy of Polyraptor.| Strength of the Pack|Rivals of Ixalan|145|U|{4}{G}{G}|Sorcery|||Put two +1/+1 counters on each creature you control.| @@ -33585,40 +33585,716 @@ Island|Battlebond|251|C||Basic Land - Island|||({T}: Add {U}.)| Swamp|Battlebond|252|C||Basic Land - Swamp|||({T}: Add {B}.)| Mountain|Battlebond|253|C||Basic Land - Mountain|||({T}: Add {R}.)| Forest|Battlebond|254|C||Basic Land - Forest|||({T}: Add {G}.)| +Aegis of the Heavens|Core Set 2019|1|U|{1}{W}|Instant|||Target creature gets +1/+7 until end of turn.| +Aethershield Artificer|Core Set 2019|2|U|{3}{W}|Creature - Dwarf Artificer|3|3|At the beginning of combat on your turn, target artifact creature you control gets +2/+2 and gains indestructible until end of turn.| +Ajani, Adversary of Tyrants|Core Set 2019|3|M|{2}{W}{W}|Legendary Planeswalker - Ajani|4|+1: Put a +1/+1 counter on each of up to two target creatures.$−2: Return target creature card with converted mana cost 2 or less from your graveyard to the battlefield.$−7: You get an emblem with "At the beginning of your end step, create three 1/1 white Cat creature tokens with lifelink."| +Ajani's Last Stand|Core Set 2019|4|R|{2}{W}{W}|Enchantment|||Whenever a creature or planeswalker you control dies, you may sacrifice Ajani's Last Stand. If you do, create a 4/4 white Avatar creature token with flying.$When a spell or ability an opponent controls causes you to discard this card, if you control a Plains, create a 4/4 white Avatar creature token with flying.| +Ajani's Pridemate|Core Set 2019|5|U|{1}{W}|Creature - Cat Soldier|2|2|Whenever you gain life, you may put a +1/+1 counter on Ajani's Pridemate.| +Ajani's Welcome|Core Set 2019|6|U|{W}|Enchantment|||Whenever a creature enters the battlefield under your control, you gain 1 life.| +Angel of the Dawn|Core Set 2019|7|C|{4}{W}|Creature - Angel|3|3|Flying$When Angel of the Dawn enters the battlefield, creatures you control get +1/+1 and gain vigilance until end of turn.| +Cavalry Drillmaster|Core Set 2019|8|C|{1}{W}|Creature - Human Knight|2|1|When Cavalry Drillmaster enters the battlefield, target creature gets +2/+0 and gains first strike until end of turn.| +Cleansing Nova|Core Set 2019|9|R|{3}{W}{W}|Sorcery|||Choose one —$• Destroy all creatures.$• Destroy all artifacts and enchantments.| Daybreak Chaplain|Core Set 2019|10|C|{1}{W}|Creature - Human Cleric|1|3|Lifelink| Dwarven Priest|Core Set 2019|11|C|{3}{W}|Creature - Dwarf Cleric|2|4|When Dwarven Priest enters the battlefield, you gain 1 life for each creature you control.| +Gallant Cavalry|Core Set 2019|12|C|{3}{W}|Creature - Human Knight|2|2|Vigilance$When Gallant Cavalry enters the battlefield, create a 2/2 white Knight creature token with vigilance.| +Herald of Faith|Core Set 2019|13|U|{3}{W}{W}|Creature - Angel|4|3|Flying$Whenever Herald of Faith attacks, you gain 2 life.| +Hieromancer's Cage|Core Set 2019|14|U|{3}{W}|Enchantment|||When Hieromancer's Cage enters the battlefield, exile target nonland permanent an opponent controls until Hieromancer's Cage leaves the battlefield.| Inspired Charge|Core Set 2019|15|C|{2}{W}{W}|Instant|||Creatures you control get +2/+1 until end of turn.| +Invoke the Divine|Core Set 2019|16|C|{2}{W}|Instant|||Destroy target artifact or enchantment. You gain 4 life.| +Isolate|Core Set 2019|17|R|{W}|Instant|||Exile target permanent with converted mana cost 1.| Knight of the Tusk|Core Set 2019|18|C|{4}{W}{W}|Creature - Human Knight|3|7|Vigilance| Knight's Pledge|Core Set 2019|19|C|{1}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +2/+2.| +Knightly Valor|Core Set 2019|20|U|{4}{W}|Enchantment - Aura|||Enchant creature$When Knightly Valor enters the battlefield, create a 2/2 white Knight creature token with vigilance.$Enchanted creature gets +2/+2 and has vigilance.| +Lena, Selfless Champion|Core Set 2019|21|R|{4}{W}{W}|Legendary Creature - Human Knight|3|3|When Lena, Selfless Champion enters the battlefield, create a 1/1 white Soldier creature token for each nontoken creature you control.$Sacrifice Lena: Creatures you control with power less than Lena's power gain indestructible until end of turn.| +Leonin Vanguard|Core Set 2019|22|U|{W}|Creature - Cat Soldier|1|1|At the beginning of combat on your turn, if you control three or more creatures, Leonin Vanguard gets +1/+1 until end of turn and you gain 1 life.| +Leonin Warleader|Core Set 2019|23|R|{2}{W}{W}|Creature - Cat Soldier|4|4|Whenever Leonin Warleader attacks, create two 1/1 white Cat creature tokens with lifelink that are tapped and attacking.| Loxodon Line Breaker|Core Set 2019|24|C|{2}{W}|Creature - Elephant Soldier|3|2|| +Luminous Bonds|Core Set 2019|25|C|{2}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature can't attack or block.| +Make a Stand|Core Set 2019|26|U|{2}{W}|Instant|||Creatures you control get +1/+0 and gain indestructible until end of turn.| +Mentor of the Meek|Core Set 2019|27|R|{2}{W}|Creature - Human Soldier|2|2|Whenever another creature with power 2 or less enters the battlefield under your control, you may pay {1}. If you do, draw a card.| Mighty Leap|Core Set 2019|28|C|{1}{W}|Instant|||Target creature gets +2/+2 and gains flying until end of turn.| +Militia Bugler|Core Set 2019|29|U|{2}{W}|Creature - Human Soldier|2|3|Vigilance$When Militia Bugler enters the battlefield, look at the top four cards of your library. You may reveal a creature card with power 2 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Novice Knight|Core Set 2019|30|U|{W}|Creature - Human Knight|2|3|Defender$As long as Novice Knight is enchanted or equipped, it can attack as though it didn't have defender.| Oreskos Swiftclaw|Core Set 2019|31|C|{1}{W}|Creature - Cat Warrior|3|1|| +Pegasus Courser|Core Set 2019|32|C|{2}{W}|Creature - Pegasus|1|3|Flying$Whenever Pegasus Courser attacks, another target attacking creature gains flying until end of turn.| +Remorseful Cleric|Core Set 2019|33|R|{1}{W}|Creature - Spirit Cleric|2|1|Flying$Sacrifice Remorseful Cleric: Exile all cards from target player's graveyard.| +Resplendent Angel|Core Set 2019|34|M|{1}{W}{W}|Creature - Angel|3|3|Flying$At the beginning of each end step, if you gained 5 or more life this turn, create a 4/4 white Angel creature token with flying and vigilance.${3}{W}{W}{W}: Until end of turn, Resplendent Angel gets +2/+2 and gains lifelink.| Revitalize|Core Set 2019|35|C|{1}{W}|Instant|||You gain 3 life.$Draw a card.| Rustwing Falcon|Core Set 2019|36|C|{W}|Creature - Bird|1|2|Flying| +Shield Mare|Core Set 2019|37|U|{1}{W}{W}|Creature - Horse|2|3|Shield Mare can't be blocked by red creatures.$When Shield Mare enters the battlefield or becomes the target of a spell or ability an opponent controls, you gain 3 life.| +Star-Crowned Stag|Core Set 2019|38|C|{3}{W}|Creature - Elk|3|3|Whenever Star-Crowned Stag attacks, tap target creature defending player controls.| +Suncleanser|Core Set 2019|39|R|{1}{W}|Creature - Human Cleric|1|4|When Suncleanser enters the battlefield, choose one —$• Remove all counters from target creature. It can't have counters put on it for as long as Suncleanser remains on the battlefield.$• Target opponent loses all counters. That player can't get counters for as long as Suncleanser remains on the battlefield.| +Take Vengeance|Core Set 2019|40|C|{1}{W}|Sorcery|||Destroy target tapped creature.| Trusty Packbeast|Core Set 2019|41|C|{2}{W}|Creature - Beast|2|3|When Trusty Packbeast enters the battlefield, return target artifact card from your graveyard to your hand.| +Valiant Knight|Core Set 2019|42|R|{3}{W}|Creature - Human Knight|3|4|Other Knights you control get +1/+1.${3}{W}{W}: Knights you control gain double strike until end of turn.| +Aether Tunnel|Core Set 2019|43|U|{1}{U}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+0 and can't be blocked.| Anticipate|Core Set 2019|44|C|{1}{U}|Instant|||Look at the top three cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.| +Aven Wind Mage|Core Set 2019|45|C|{2}{U}|Creature - Bird Wizard|2|2|Flying$Whenever you cast an instant or sorcery spell, Aven Wind Mage gets +1/+1 until end of turn.| +Aviation Pioneer|Core Set 2019|46|C|{2}{U}|Creature - Human Artificer|1|2|When Aviation Pioneer enters the battlefield, create a 1/1 colorless Thopter artifact creature token with flying.| +Bone to Ash|Core Set 2019|47|U|{2}{U}{U}|Instant|||Counter target creature spell.$Draw a card.| Cancel|Core Set 2019|48|C|{1}{U}{U}|Instant|||Counter target spell.| +Departed Deckhand|Core Set 2019|49|U|{1}{U}|Creature - Spirit Pirate|2|2|When Departed Deckhand becomes the target of a spell, sacrifice it.$Departed Deckhand can't be blocked except by Spirits.${3}{U}: Another target creature you control can't be blocked this turn except by Spirits.| Disperse|Core Set 2019|50|C|{1}{U}|Instant|||Return target nonland permanent to its owner's hand.| +Divination|Core Set 2019|51|C|{2}{U}|Sorcery|||Draw two cards.| +Djinn of Wishes|Core Set 2019|52|R|{3}{U}{U}|Creature - Djinn|4|4|Flying$Djinn of Wishes enters the battlefield with three wish counters on it.${2}{U}{U}, Remove a wish counter from Djinn of Wishes: Reveal the top card of your library. You may play that card without paying its mana cost. If you don't, exile it.| Dwindle|Core Set 2019|53|C|{2}{U}|Enchantment - Aura|||Enchant creature$Enchanted creature gets -6/-0.$When enchanted creature blocks, destroy it.| +Essence Scatter|Core Set 2019|54|C|{1}{U}|Instant|||Counter target creature spell.| +Exclusion Mage|Core Set 2019|55|U|{2}{U}|Creature - Human Wizard|2|2|When Exclusion Mage enters the battlefield, return target creature an opponent controls to its owner's hand.| Frilled Sea Serpent|Core Set 2019|56|C|{4}{U}{U}|Creature - Serpent|4|6|{5}{U}{U}: Frilled Sea Serpent can't be blocked this turn.| Gearsmith Prodigy|Core Set 2019|57|C|{U}|Creature - Human Artificer|1|2|Gearsmith Prodigy gets +1/+0 as long as you control an artifact.| +Ghostform|Core Set 2019|58|C|{1}{U}|Sorcery|||Up to two target creatures can't be blocked this turn.| +Horizon Scholar|Core Set 2019|59|U|{5}{U}|Creature - Sphinx|4|4|Flying$When Horizon Scholar enters the battlefield, scry 2.| +Metamorphic Alteration|Core Set 2019|60|R|{1}{U}|Enchantment - Aura|||Enchant creature$As Metamorphic Alteration enters the battlefield, choose a creature.$Enchanted creature is a copy of the chosen creature.| +Mirror Image|Core Set 2019|61|U|{2}{U}|Creature - Shapeshifter|0|0|You may have Mirror Image enter the battlefield as a copy of any creature you control.| +Mistcaller|Core Set 2019|62|R|{U}|Creature - Merfolk Wizard|1|1|Sacrifice Mistcaller: Until end of turn, if a nontoken creature would enter the battlefield and it wasn't cast, exile it instead.| +Mystic Archaeologist|Core Set 2019|63|R|{1}{U}|Creature - Human Wizard|2|1|{3}{U}{U}: Draw two cards.| Omenspeaker|Core Set 2019|64|C|{1}{U}|Creature - Human Wizard|1|3|When Omenspeaker enters the battlefield, scry 2.| +Omniscience|Core Set 2019|65|M|{7}{U}{U}{U}|Enchantment|||You may cast spells from your hand without paying their mana costs.| +One with the Machine|Core Set 2019|66|R|{3}{U}|Sorcery|||Draw cards equal to the highest converted mana cost among artifacts you control.| +Patient Rebuilding|Core Set 2019|67|R|{3}{U}{U}|Enchantment|||At the beginning of your upkeep, target opponent puts the top three cards of their library into their graveyard, then you draw a card for each land card put into that graveyard this way.| +Psychic Corrosion|Core Set 2019|68|U|{2}{U}|Enchantment|||Whenever you draw a card, each opponent puts the top two cards of their library into their graveyard.| +Sai, Master Thopterist|Core Set 2019|69|R|{2}{U}|Legendary Creature - Human Artificer|1|4|Whenever you cast an artifact spell, create a 1/1 colorless Thopter artifact creature token with flying.${1}{U}, Sacrifice two artifacts: Draw a card.| Salvager of Secrets|Core Set 2019|70|C|{3}{U}{U}|Creature - Merfolk Wizard|2|2|When Salvager of Secrets enters the battlefield, return target instant or sorcery card from your graveyard to your hand.| Scholar of Stars|Core Set 2019|71|C|{3}{U}|Creature - Human Artificer|3|2|When Scholar of Stars enters the battlefield, if you control an artifact, draw a card.| +Sift|Core Set 2019|72|U|{3}{U}|Sorcery|||Draw three cards, then discard a card.| +Skilled Animator|Core Set 2019|73|U|{2}{U}|Creature - Human Artificer|1|3|When Skilled Animator enters the battlefield, target artifact you control becomes an artifact creature with base power and toughness 5/5 for as long as Skilled Animator remains on the battlefield.| +Sleep|Core Set 2019|74|U|{2}{U}{U}|Sorcery|||Tap all creatures target player controls. Those creatures don't untap during that player's next untap step.| +Snapping Drake|Core Set 2019|75|C|{3}{U}|Creature - Drake|3|2|Flying| +Supreme Phantom|Core Set 2019|76|R|{1}{U}|Creature - Spirit|1|3|Flying$Other Spirits you control get +1/+1.| +Surge Mare|Core Set 2019|77|U|{U}{U}|Creature - Horse Fish|0|5|Surge Mare can't be blocked by green creatures.$Whenever Surge Mare deals damage to an opponent, you may draw a card. If you do, discard a card.${1}{U}: Surge Mare gets +2/-2 until end of turn.| +Switcheroo|Core Set 2019|78|U|{4}{U}|Sorcery|||Exchange control of two target creatures.| +Tezzeret, Artifice Master|Core Set 2019|79|M|{3}{U}{U}|Legendary Planeswalker - Tezzeret|5|+1: Create a 1/1 colorless Thopter artifact creature token with flying.$0: Draw a card. If you control three or more artifacts, draw two cards instead.$−9: You get an emblem with "At the beginning of your end step, search your library for a permanent card, put it onto the battlefield, then shuffle your library."| Tolarian Scholar|Core Set 2019|80|C|{2}{U}|Creature - Human Wizard|2|3|| +Totally Lost|Core Set 2019|81|C|{4}{U}|Instant|||Put target nonland permanent on top of its owner's library.| Uncomfortable Chill|Core Set 2019|82|C|{2}{U}|Instant|||Creatures your opponents control get -2/-0 until end of turn.$Draw a card.| Wall of Mist|Core Set 2019|83|C|{1}{U}|Creature - Wall|0|5|Defender| +Windreader Sphinx|Core Set 2019|84|R|{5}{U}{U}|Creature - Sphinx|3|7|Flying$Whenever a creature with flying attacks, you may draw a card.| +Abnormal Endurance|Core Set 2019|85|C|{1}{B}|Instant|||Until end of turn, target creature gets +2/+0 and gains "When this creature dies, return it to the battlefield tapped under its owner's control."| +Blood Divination|Core Set 2019|86|U|{3}{B}|Sorcery|||As an additional cost to cast this spell, sacrifice a creature.$Draw three cards.| +Bogstomper|Core Set 2019|87|C|{4}{B}{B}|Creature - Beast|6|5|| +Bone Dragon|Core Set 2019|88|M|{3}{B}{B}|Creature - Dragon Skeleton|5|4|Flying${3}{B}{B}, Exile seven other cards from your graveyard: Return Bone Dragon from your graveyard to the battlefield tapped.| +Child of Night|Core Set 2019|89|C|{1}{B}|Creature - Vampire|2|1|Lifelink| +Death Baron|Core Set 2019|90|R|{1}{B}{B}|Creature - Zombie Wizard|2|2|Skeleton creatures you control and other Zombie creatures you control get +1/+1 and have deathtouch.| +Demon of Catastrophes|Core Set 2019|91|R|{2}{B}{B}|Creature - Demon|6|6|As an additional cost to cast this spell, sacrifice a creature.$Flying, trample| +Diregraf Ghoul|Core Set 2019|92|U|{B}|Creature - Zombie|2|2|Diregraf Ghoul enters the battlefield tapped.| +Doomed Dissenter|Core Set 2019|93|C|{1}{B}|Creature - Human|1|1|When Doomed Dissenter dies, create a 2/2 black Zombie creature token.| +Duress|Core Set 2019|94|C|{B}|Sorcery|||Target opponent reveals their hand. You choose a noncreature, nonland card from it. That player discards that card.| +Epicure of Blood|Core Set 2019|95|C|{4}{B}|Creature - Vampire|4|4|Whenever you gain life, each opponent loses 1 life.| +Fell Specter|Core Set 2019|96|U|{3}{B}|Creature - Specter|1|3|Flying$When Fell Specter enters the battlefield, target opponent discards a card.$Whenever an opponent discards a card, that player loses 2 life.| +Fraying Omnipotence|Core Set 2019|97|R|{3}{B}{B}|Sorcery|||Each player loses half their life, then discards half the cards in their hand, then sacrifices half the creatures they control. Round up each time.| +Gravedigger|Core Set 2019|98|U|{3}{B}|Creature - Zombie|2|2|When Gravedigger enters the battlefield, you may return target creature card from your graveyard to your hand.| +Graveyard Marshal|Core Set 2019|99|R|{B}{B}|Creature - Zombie Soldier|3|2|{2}{B}, Exile a creature card from your graveyard: Create a tapped 2/2 black Zombie creature token.| +Hired Blade|Core Set 2019|100|C|{2}{B}|Creature - Human Assassin|3|2|Flash| +Infectious Horror|Core Set 2019|101|C|{3}{B}|Creature - Zombie Horror|2|2|Whenever Infectious Horror attacks, each opponent loses 2 life.| +Infernal Reckoning|Core Set 2019|102|R|{B}|Instant|||Exile target colorless creature. You gain life equal to its power.| +Infernal Scarring|Core Set 2019|103|C|{1}{B}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +2/+0 and has "When this creature dies, draw a card."| +Isareth the Awakener|Core Set 2019|104|R|{1}{B}{B}|Legendary Creature - Human Wizard|3|3|Deathtouch$Whenever Isareth the Awakener attacks, you may pay {X}. When you do, return target creature card with converted mana cost X from your graveyard to the battlefield with a corpse counter on it. If that creature would leave the battlefield, exile it instead of putting it anywhere else.| +Lich's Caress|Core Set 2019|105|C|{3}{B}{B}|Sorcery|||Destroy target creature. You gain 3 life.| +Liliana, Untouched by Death|Core Set 2019|106|M|{2}{B}{B}|Legendary Planeswalker - Liliana|4|+1: Put the top three cards of your library into your graveyard. If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life.$−2: Target creature gets -X/-X until end of turn, where X is the number of Zombies you control.$−3: You may cast Zombie cards from your graveyard this turn.| +Liliana's Contract|Core Set 2019|107|R|{3}{B}{B}|Enchantment|||When Liliana's Contract enters the battlefield, you draw four cards and you lose 4 life.$At the beginning of your upkeep, if you control four or more Demons with different names, you win the game.| +Macabre Waltz|Core Set 2019|108|C|{1}{B}|Sorcery|||Return up to two target creature cards from your graveyard to your hand, then discard a card.| +Mind Rot|Core Set 2019|109|C|{2}{B}|Sorcery|||Target player discards two cards.| +Murder|Core Set 2019|110|U|{1}{B}{B}|Instant|||Destroy target creature.| +Nightmare's Thirst|Core Set 2019|111|U|{B}|Instant|||You gain 1 life. Target creature gets -X/-X until end of turn, where X is the amount of life you gained this turn.| +Open the Graves|Core Set 2019|112|R|{3}{B}{B}|Enchantment|||Whenever a nontoken creature you control dies, create a 2/2 black Zombie creature token.| +Phylactery Lich|Core Set 2019|113|R|{B}{B}{B}|Creature - Zombie|5|5|Indestructible$As Phylactery Lich enters the battlefield, put a phylactery counter on an artifact you control.$When you control no permanents with phylactery counters on them, sacrifice Phylactery Lich.| +Plague Mare|Core Set 2019|114|U|{1}{B}{B}|Creature - Nightmare Horse|2|2|Plague Mare can't be blocked by white creatures.$When Plague Mare enters the battlefield, creatures your opponents control get -1/-1 until end of turn.| +Ravenous Harpy|Core Set 2019|115|U|{2}{B}|Creature - Harpy|1|2|Flying${1}, Sacrifice another creature: Put a +1/+1 counter on Ravenous Harpy.| +Reassembling Skeleton|Core Set 2019|116|U|{1}{B}|Creature - Skeleton Warrior|1|1|{1}{B}: Return Reassembling Skeleton from your graveyard to the battlefield tapped.| +Rise from the Grave|Core Set 2019|117|U|{4}{B}|Sorcery|||Put target creature card from a graveyard onto the battlefield under your control. That creature is a black Zombie in addition to its other colors and types.| +Skeleton Archer|Core Set 2019|118|C|{3}{B}|Creature - Skeleton Archer|3|3|When Skeleton Archer enters the battlefield, it deals 1 damage to any target.| +Skymarch Bloodletter|Core Set 2019|119|C|{2}{B}|Creature - Vampire Soldier|2|2|Flying$When Skymarch Bloodletter enters the battlefield, target opponent loses 1 life and you gain 1 life.| Sovereign's Bite|Core Set 2019|120|C|{1}{B}|Sorcery|||Target player loses 3 life and you gain 3 life.| +Stitcher's Supplier|Core Set 2019|121|U|{B}|Creature - Zombie|1|1|When Stitcher's Supplier enters the battlefield or dies, put the top three cards of your library into your graveyard.| +Strangling Spores|Core Set 2019|122|C|{3}{B}|Instant|||Target creature gets -3/-3 until end of turn.| +Two-Headed Zombie|Core Set 2019|123|C|{3}{B}|Creature - Zombie|4|2|Menace| +Vampire Neonate|Core Set 2019|124|C|{B}|Creature - Vampire|0|3|{2}, {T}: Each opponent loses 1 life and you gain 1 life.| +Vampire Sovereign|Core Set 2019|125|U|{3}{B}{B}|Creature - Vampire|3|4|Flying$When Vampire Sovereign enters the battlefield, target opponent loses 3 life and you gain 3 life.| +Walking Corpse|Core Set 2019|126|C|{1}{B}|Creature - Zombie|2|2|| Act of Treason|Core Set 2019|127|C|{2}{R}|Sorcery|||Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.| +Alpine Moon|Core Set 2019|128|R|{R}|Enchantment|||As Alpine Moon enters the battlefield, choose a nonbasic land card name.$Lands your opponents control with the chosen name lose all land types and abilities, and they gain "{T}: Add one mana of any color."| Apex of Power|Core Set 2019|129|M|{7}{R}{R}{R}|Sorcery|||Exile the top seven cards of your library. Until end of turn, you may cast nonland cards exiled this way.$If this spell was cast from your hand, add ten mana of any one color.| +Banefire|Core Set 2019|130|R|{X}{R}|Sorcery|||Banefire deals X damage to any target.$If X is 5 or more, this spell can't be countered and the damage can't be prevented.| +Boggart Brute|Core Set 2019|131|C|{2}{R}|Creature - Goblin Warrior|3|2|Menace| Catalyst Elemental|Core Set 2019|132|C|{2}{R}|Creature - Elemental|2|2|Sacrifice Catalyst Elemental: Add {R}{R}.| +Crash Through|Core Set 2019|133|C|{R}|Sorcery|||Creatures you control gain trample until end of turn.$Draw a card.| +Dark-Dweller Oracle|Core Set 2019|134|R|{1}{R}|Creature - Goblin Shaman|2|2|{1}, Sacrifice a creature: Exile the top card of your library. You may play that card this turn.| +Demanding Dragon|Core Set 2019|135|R|{3}{R}{R}|Creature - Dragon|5|5|Flying$When Demanding Dragon enters the battlefield, it deals 5 damage to target opponent unless that player sacrifices a creature.| +Dismissive Pyromancer|Core Set 2019|136|R|{1}{R}|Creature - Human Wizard|2|2|{R}, {T}, Discard a card: Draw a card.${2}{R}, {T}, Sacrifice Dismissive Pyromancer: It deals 4 damage to target creature.| +Doublecast|Core Set 2019|137|U|{R}{R}|Sorcery|||When you cast your next instant or sorcery spell this turn, copy that spell. You may choose new targets for the copy.| +Dragon Egg|Core Set 2019|138|U|{2}{R}|Creature - Dragon|0|2|Defender$When Dragon Egg dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn."| +Electrify|Core Set 2019|139|C|{3}{R}|Instant|||Electrify deals 4 damage to target creature.| +Fiery Finish|Core Set 2019|140|U|{4}{R}{R}|Sorcery|||Fiery Finish deals 7 damage to target creature.| Fire Elemental|Core Set 2019|141|C|{3}{R}{R}|Creature - Elemental|5|4|| Goblin Instigator|Core Set 2019|142|C|{1}{R}|Creature - Goblin Rogue|1|1|When Goblin Instigator enters the battlefield, create a 1/1 red Goblin creature token.| Goblin Motivator|Core Set 2019|143|C|{R}|Creature - Goblin Warrior|1|1|{T}: Target creature gains haste until end of turn.| +Goblin Trashmaster|Core Set 2019|144|R|{2}{R}{R}|Creature - Goblin Warrior|3|3|Other Goblins you control get +1/+1.$Sacrifice a Goblin: Destroy target artifact.| +Guttersnipe|Core Set 2019|145|U|{2}{R}|Creature - Goblin Shaman|2|2|Whenever you cast an instant or sorcery spell, Guttersnipe deals 2 damage to each opponent.| +Havoc Devils|Core Set 2019|146|C|{2}{R}{R}|Creature - Devil|4|3|Trample| Hostile Minotaur|Core Set 2019|147|C|{3}{R}|Creature - Minotaur|3|3|Haste| +Inferno Hellion|Core Set 2019|148|U|{3}{R}|Creature - Hellion|7|3|Trample$At the beginning of each end step, if Inferno Hellion attacked or blocked this turn, its owner shuffles it into their library.| +Lathliss, Dragon Queen|Core Set 2019|149|R|{4}{R}{R}|Legendary Creature - Dragon|6|6|Flying$Whenever another nontoken Dragon enters the battlefield under your control, create a 5/5 red Dragon creature token with flying.${1}{R}: Dragons you control get +1/+0 until end of turn.| Lava Axe|Core Set 2019|150|C|{4}{R}|Sorcery|||Lava Axe deals 5 damage to target player or planeswalker.| +Lightning Mare|Core Set 2019|151|U|{R}{R}|Creature - Elemental Horse|3|1|This spell can't be countered.$Lightning Mare can't be blocked by blue creatures.${1}{R}: Lightning Mare gets +1/+0 until end of turn.| +Lightning Strike|Core Set 2019|152|U|{1}{R}|Instant|||Lightning Strike deals 3 damage to any target.| Onakke Ogre|Core Set 2019|153|C|{2}{R}|Creature - Ogre Warrior|4|2|| +Sarkhan, Fireblood|Core Set 2019|154|M|{1}{R}{R}|Legendary Planeswalker - Sarkhan|3|+1: You may discard a card. If you do, draw a card.$+1: Add two mana of any combination of colors. Spend this mana only to cast Dragon spells.$−7: Create four 5/5 red Dragon creature tokens with flying.| +Sarkhan's Unsealing|Core Set 2019|155|R|{3}{R}|Enchantment|||Whenever you cast a creature spell with power 4, 5, or 6, Sarkhan's Unsealing deals 4 damage to any target.$Whenever you cast a creature spell with power 7 or greater, Sarkhan's Unsealing deals 4 damage to each opponent and each creature and planeswalker they control.| +Shock|Core Set 2019|156|C|{R}|Instant|||Shock deals 2 damage to any target.| +Siegebreaker Giant|Core Set 2019|157|U|{3}{R}{R}|Creature - Giant Warrior|6|3|Trample${3}{R}: Target creature can't block this turn.| +Smelt|Core Set 2019|158|C|{R}|Instant|||Destroy target artifact.| +Sparktongue Dragon|Core Set 2019|159|C|{3}{R}{R}|Creature - Dragon|3|3|Flying$When Sparktongue Dragon enters the battlefield, you may pay {2}{R}. When you do, it deals 3 damage to any target.| +Spit Flame|Core Set 2019|160|R|{2}{R}|Instant|||Spit Flame deals 4 damage to target creature.$Whenever a Dragon enters the battlefield under your control, you may pay {R}. If you do, return Spit Flame from your graveyard to your hand.| Sure Strike|Core Set 2019|161|C|{1}{R}|Instant|||Target creature gets +3/+0 and gains first strike until end of turn.| +Tectonic Rift|Core Set 2019|162|U|{3}{R}|Sorcery|||Destroy target land. Creatures without flying can't block this turn.| +Thud|Core Set 2019|163|U|{R}|Sorcery|||As an additional cost to cast this spell, sacrifice a creature.$Thud deals damage equal to the sacrificed creature's power to any target.| Tormenting Voice|Core Set 2019|164|C|{1}{R}|Sorcery|||As an additional cost to cast this spell, discard a card.$Draw two cards.| Trumpet Blast|Core Set 2019|165|C|{2}{R}|Instant|||Attacking creatures get +2/+0 until end of turn.| +Viashino Pyromancer|Core Set 2019|166|C|{1}{R}|Creature - Viashino Wizard|2|1|When Viashino Pyromancer enters the battlefield, it deals 2 damage to target player or planeswalker.| +Volcanic Dragon|Core Set 2019|167|U|{4}{R}{R}|Creature - Dragon|4|4|Flying$Haste| +Volley Veteran|Core Set 2019|168|U|{3}{R}|Creature - Goblin Warrior|4|2|When Volley Veteran enters the battlefield, it deals damage to target creature an opponent controls equal to the number of Goblins you control.| +Blanchwood Armor|Core Set 2019|169|U|{2}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 for each Forest you control.| +Bristling Boar|Core Set 2019|170|C|{3}{G}|Creature - Boar|4|3|Bristling Boar can't be blocked by more than one creature.| +Centaur Courser|Core Set 2019|171|C|{2}{G}|Creature - Centaur Warrior|3|3|| +Colossal Dreadmaw|Core Set 2019|172|C|{4}{G}{G}|Creature - Dinosaur|6|6|Trample| +Colossal Majesty|Core Set 2019|173|U|{2}{G}|Enchantment|||At the beginning of your upkeep, if you control a creature with power 4 or greater, draw a card.| +Daggerback Basilisk|Core Set 2019|174|C|{2}{G}|Creature - Basilisk|2|2|Deathtouch| +Declare Dominance|Core Set 2019|175|U|{3}{G}{G}|Sorcery|||Target creature gets +3/+3 until end of turn. All creatures able to block it this turn do so.| +Druid of Horns|Core Set 2019|176|U|{3}{G}|Creature - Human Druid|2|3|Whenever you cast an Aura spell that targets Druid of Horns, create a 3/3 green Beast creature token.| +Druid of the Cowl|Core Set 2019|177|C|{1}{G}|Creature - Elf Druid|1|3|{T}: Add {G}.| +Dryad Greenseeker|Core Set 2019|178|U|{1}{G}|Creature - Dryad|1|3|{T}: Look at the top card of your library. If it's a land card, you may reveal it and put it into your hand.| +Elvish Clancaller|Core Set 2019|179|R|{G}{G}|Creature - Elf Druid|1|1|Other Elves you control get +1/+1.${4}{G}{G}, {T}: Search your library for a card named Elvish Clancaller, put it onto the battlefield, then shuffle your library.| +Elvish Rejuvenator|Core Set 2019|180|C|{2}{G}|Creature - Elf Druid|1|1|Whenever Elvish Rejuvenator enters the battlefield, look at the top five cards of your library. You may put a land card from among them onto the battlefield tapped. Put the rest on the bottom of your library in a random order.| +Ghastbark Twins|Core Set 2019|181|U|{5}{G}{G}|Creature - Treefolk|7|7|Trample$Ghastbark Twins can block an additional creature each combat.| +Ghirapur Guide|Core Set 2019|182|U|{2}{G}|Creature - Elf Scout|3|2|{2}{G}: Target creature you control can't be blocked by creatures with power 2 or less this turn.| +Giant Spider|Core Set 2019|183|C|{3}{G}|Creature - Spider|2|4|Reach| +Gift of Paradise|Core Set 2019|184|U|{2}{G}|Enchantment - Aura|||Enchant land$When Gift of Paradise enters the battlefield, you gain 3 life.$Enchanted land has "{T}: Add two mana of any one color."| +Gigantosaurus|Core Set 2019|185|R|{G}{G}{G}{G}{G}|Creature - Dinosaur|10|10|| +Goreclaw, Terror of Qal Sisma|Core Set 2019|186|R|{3}{G}|Legendary Creature - Bear|4|3|Creature spells you cast with power 4 or greater cost {2} less to cast.$Whenever Goreclaw, Terror of Qal Sisma attacks, each creature you control with power 4 or greater gets +1/+1 and gains trample until end of turn.| +Greenwood Sentinel|Core Set 2019|187|C|{1}{G}|Creature - Elf Scout|2|2|Vigilance| +Highland Game|Core Set 2019|188|C|{1}{G}|Creature - Elk|2|1|When Highland Game dies, you gain 2 life.| +Hungering Hydra|Core Set 2019|189|R|{X}{G}|Creature - Hydra|0|0|Hungering Hydra enters the battlefield with X +1/+1 counters on it.$Hungering Hydra can't be blocked by more than one creature.$Whenever Hungering Hydra is dealt damage, put that many +1/+1 counters on it.| +Naturalize|Core Set 2019|190|C|{1}{G}|Instant|||Destroy target artifact or enchantment.| +Oakenform|Core Set 2019|191|C|{2}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +3/+3.| +Pelakka Wurm|Core Set 2019|192|R|{4}{G}{G}{G}|Creature - Wurm|7|7|Trample$When Pelakka Wurm enters the battlefield, you gain 7 life.$When Pelakka Wurm dies, draw a card.| +Plummet|Core Set 2019|193|C|{1}{G}|Instant|||Destroy target creature with flying.| +Prodigious Growth|Core Set 2019|194|R|{4}{G}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +7/+7 and has trample.| +Rabid Bite|Core Set 2019|195|C|{1}{G}|Sorcery|||Target creature you control deals damage equal to its power to target creature you don't control.| +Reclamation Sage|Core Set 2019|196|U|{2}{G}|Creature - Elf Shaman|2|1|When Reclamation Sage enters the battlefield, you may destroy target artifact or enchantment.| +Recollect|Core Set 2019|197|U|{2}{G}|Sorcery|||Return target card from your graveyard to your hand.| +Rhox Oracle|Core Set 2019|198|C|{4}{G}|Creature - Rhino Monk|4|2|When Rhox Oracle enters the battlefield, draw a card.| +Root Snare|Core Set 2019|199|C|{1}{G}|Instant|||Prevent all combat damage that would be dealt this turn.| +Runic Armasaur|Core Set 2019|200|R|{1}{G}{G}|Creature - Dinosaur|2|5|Whenever an opponent activates an ability of a creature or land that isn't a mana ability, you may draw a card.| +Scapeshift|Core Set 2019|201|M|{2}{G}{G}|Sorcery|||Sacrifice any number of lands. Search your library for up to that many land cards, put them onto the battlefield tapped, then shuffle your library.| +Talons of Wildwood|Core Set 2019|202|C|{1}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 and has trample.${2}{G}: Return Talons of Wildwood from your graveyard to your hand.| +Thorn Lieutenant|Core Set 2019|203|R|{1}{G}|Creature - Elf Warrior|2|3|Whenever Thorn Lieutenant becomes the target of a spell or ability an opponent controls, create a 1/1 green Elf Warrior creature token.${5}{G}: Thorn Lieutenant gets +4/+4 until end of turn.| +Thornhide Wolves|Core Set 2019|204|C|{4}{G}|Creature - Wolf|4|5|| +Titanic Growth|Core Set 2019|205|C|{1}{G}|Instant|||Target creature gets +4/+4 until end of turn.| +Vigilant Baloth|Core Set 2019|206|U|{3}{G}{G}|Creature - Beast|5|5|Vigilance| +Vine Mare|Core Set 2019|207|U|{2}{G}{G}|Creature - Elemental Horse|5|3|Hexproof$Vine Mare can't be blocked by black creatures.| +Vivien Reid|Core Set 2019|208|M|{3}{G}{G}|Legendary Planeswalker - Vivien|5|+1: Look at the top four cards of your library. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.$−3: Destroy target artifact, enchantment, or creature with flying.$−8: You get an emblem with "Creatures you control get +2/+2 and have vigilance, trample, and indestructible."| +Vivien's Invocation|Core Set 2019|209|R|{5}{G}{G}|Sorcery|||Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in a random order. When a creature is put onto the battlefield this way, it deals damage equals to its power to target creature an opponent controls.| +Wall of Vines|Core Set 2019|210|C|{G}|Creature - Plant Wall|0|3|Defender| +Aerial Engineer|Core Set 2019|211|U|{2}{W}{U}|Creature - Human Artificer|2|4|As long as you control an artifact, Aerial Engineer gets +2/+0 and has flying.| +Arcades, the Strategist|Core Set 2019|212|M|{1}{G}{W}{U}|Legendary Creature - Elder Dragon|3|5|Flying, vigilance$Whenever a creature with defender enters the battlefield under your control, draw a card.$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.| +Brawl-Bash Ogre|Core Set 2019|213|U|{2}{B}{R}|Creature - Ogre Warrior|3|3|Menace$Whenever Brawl-Bash Ogre attacks, you may sacrifice another creature. If you do, Brawl-Bash Ogre gets +2/+2 until end of turn.| +Chromium, the Mutable|Core Set 2019|214|M|{4}{W}{U}{B}|Legendary Creature - Elder Dragon|7|7|Flash$This spell can't be countered.$Flying$Discard a card: Until end of turn, Chromium, the Mutable becomes a Human with base power and toughness 1/1, loses all abilities, and gains hexproof. It can't be blocked this turn.| +Draconic Disciple|Core Set 2019|215|U|{1}{R}{G}|Creature - Human Shaman|2|2|{T}: Add one mana of any color.${7}, {T}, Sacrifice Draconic Disciple: Create a 5/5 red Dragon creature token with flying.| +Enigma Drake|Core Set 2019|216|U|{1}{U}{R}|Creature - Drake|*|4|Flying$Enigma Drake's power is equal to the number of instant and sorcery cards in your graveyard.| +Heroic Reinforcements|Core Set 2019|217|U|{2}{R}{W}|Sorcery|||Create two 1/1 white Soldier creature tokens. Until end of turn, creatures you control get +1/+1 and gain haste.| +Nicol Bolas, the Arisen|Core Set 2019|218|M||Legendary Planeswalker - Bolas|7|+2: Draw two cards.$−3: Nicol Bolas, the Arisen deals 10 damage to target creature or planeswalker.$−4: Put target creature or planeswalker card from a graveyard onto the battlefield under your control.$−12: Exile all but the bottom card of target player's library.| +Nicol Bolas, the Ravager|Core Set 2019|218|M|{1}{U}{B}{R}|Legendary Creature - Elder Dragon|4|4|Flying$When Nicol Bolas, the Ravager enters the battlefield, each opponent discards a card.${4}{U}{B}{R}: Exile Nicol Bolas, the Ravager, then return him to the battlefield transformed under his owner's control. Activate this ability only any time you could cast a sorcery.| +Palladia-Mors, the Ruiner|Core Set 2019|219|M|{3}{W}{R}{G}|Legendary Creature - Elder Dragon|6|6|Flying, vigilance, trample$Palladia-Mors, the Ruiner has hexproof if it hasn't dealt damage yet.| +Poison-Tip Archer|Core Set 2019|220|U|{2}{B}{G}|Creature - Elf Archer|2|3|Reach$Whenever another creature dies, each opponent loses 1 life.| +Psychic Symbiont|Core Set 2019|221|U|{4}{U}{B}|Creature - Nightmare Horror|3|3|Flying$When Psychic Symbiont enters the battlefield, target opponent discards a card and you draw a card.| +Regal Bloodlord|Core Set 2019|222|U|{3}{W}{B}|Creature - Vampire Soldier|2|4|Flying$At the beginning of each end step, if you gained life this turn, create a 1/1 black Bat creature token with flying.| +Satyr Enchanter|Core Set 2019|223|U|{1}{G}{W}|Creature - Satyr Druid|2|2|Whenever you cast an enchantment spell, draw a card.| +Skyrider Patrol|Core Set 2019|224|U|{2}{G}{U}|Creature - Elf Scout|2|3|Flying$At the beginning of combat on your turn, you may pay {G}{U}. When you do, put a +1/+1 counter on another target creature you control, and that creature gains flying until end of turn.| +Vaevictis Asmadi, the Dire|Core Set 2019|225|M|{3}{B}{R}{G}|Legendary Creature - Elder Dragon|6|6|Flying$Whenever Vaevictis Asmadi, the Dire attacks, for each player, choose target permanent that player controls. Those players sacrifice those permanents. Each player who sacrificed a permanent this way reveals the top card of their library, then puts it onto the battlefield if it's a permanent card.| +Amulet of Safekeeping|Core Set 2019|226|R|{2}|Artifact|||Whenever you become the target of a spell or ability an opponent controls, counter that spell or ability unless its controller pays {1}.$Creature tokens get -1/-0.| +Arcane Encyclopedia|Core Set 2019|227|U|{3}|Artifact|||{3}, {T}: Draw a card.| +Chaos Wand|Core Set 2019|228|R|{3}|Artifact|||{4}, {T}: Target opponent exiles cards from the top of their library until they exile an instant or sorcery card. You may cast that card without paying its mana cost. Then put the exiled cards that weren't cast this way on the bottom of that library in a random order.| +Crucible of Worlds|Core Set 2019|229|M|{3}|Artifact|||You may play land cards from your graveyard.| +Desecrated Tomb|Core Set 2019|230|R|{3}|Artifact|||Whenever one or more creature cards leave your graveyard, create a 1/1 black Bat creature token with flying.| +Diamond Mare|Core Set 2019|231|U|{2}|Artifact Creature - Horse|1|3|As Diamond Mare enters the battlefield, choose a color.$Whenever you cast a spell of the chosen color, you gain 1 life.| +Dragon's Hoard|Core Set 2019|232|R|{3}|Artifact|||Whenever a Dragon enters the battlefield under your control, put a gold counter on Dragon's Hoard.${T}, Remove a gold counter from Dragon's Hoard: Draw a card.${T}: Add one mana of any color.| +Explosive Apparatus|Core Set 2019|233|C|{1}|Artifact|||{3}, {T}, Sacrifice Explosive Apparatus: It deals 2 damage to any target.| +Field Creeper|Core Set 2019|234|C|{2}|Artifact Creature - Scarecrow|2|1|| +Fountain of Renewal|Core Set 2019|235|U|{1}|Artifact|||At the beginning of your upkeep, you gain 1 life.${3}, Sacrifice Fountain of Renewal: Draw a card.| +Gargoyle Sentinel|Core Set 2019|236|U|{3}|Artifact Creature - Gargoyle|3|3|Defender${3}: Until end of turn, Gargoyle Sentinel loses defender and gains flying.| +Gearsmith Guardian|Core Set 2019|237|C|{5}|Artifact Creature - Construct|3|5|Gearsmith Guardian gets +2/+0 as long as you control a blue creature.| +Magistrate's Scepter|Core Set 2019|238|R|{3}|Artifact|||{4}, {T}: Put a charge counter on Magistrate's Scepter.${T}, Remove three charge counters from Magistrate's Scepter: Take an extra turn after this one.| +Manalith|Core Set 2019|239|C|{3}|Artifact|||{T}: Add one mana of any color.| +Marauder's Axe|Core Set 2019|240|C|{2}|Artifact - Equipment|||Equipped creature gets +2/+0.$Equip {2}| +Meteor Golem|Core Set 2019|241|U|{7}|Artifact Creature - Golem|3|3|When Meteor Golem enters the battlefield, destroy target nonland permanent an opponent controls.| +Millstone|Core Set 2019|242|U|{2}|Artifact|||{2}, {T}: Target player puts the top two cards of their library into their graveyard.| +Rogue's Gloves|Core Set 2019|243|U|{2}|Artifact - Equipment|||Whenever equipped creature deals combat damage to a player, you may draw a card.$Equip {2}| +Sigiled Sword of Valeron|Core Set 2019|244|R|{3}|Artifact - Equipment|||Equipped creature gets +2/+0, has vigilance, and is a Knight in addition to its other types.$Whenever equipped creature attacks, create a 2/2 white Knight creature token with vigilance that's attacking.$Equip {3}| Skyscanner|Core Set 2019|245|C|{3}|Artifact Creature - Thopter|1|1|Flying$When Skyscanner enters the battlefield, draw a card.| +Suspicious Bookcase|Core Set 2019|246|U|{2}|Artifact Creature - Wall|0|4|Defender${3}, {T}: Target creature can't be blocked this turn.| +Transmogrifying Wand|Core Set 2019|247|R|{3}|Artifact|||Transmogrifying Wand enters the battlefield with three charge counters on it.${1}, {T}, Remove a charge counter from Transmogrifying Wand: Destroy target creature. Its controller creates a 2/4 white Ox creature token. Activate this ability only any time you could cast a sorcery.| +Cinder Barrens|Core Set 2019|248|C||Land|||Cinder Barrens enters the battlefield tapped.${T}: Add {B} or {R}.| +Detection Tower|Core Set 2019|249|R||Land|||{T}: Add {C}.${1}, {T}: Until end of turn, your opponents and creatures your opponents control with hexproof can be the targets of spells and abilities you control as though they didn't have hexproof.| +Forsaken Sanctuary|Core Set 2019|250|C||Land|||Forsaken Sanctuary enters the battlefield tapped.${T}: Add {W} or {B}.| +Foul Orchard|Core Set 2019|251|C||Land|||Foul Orchard enters the battlefield tapped.${T}: Add {B} or {G}.| +Highland Lake|Core Set 2019|252|C||Land|||Highland Lake enters the battlefield tapped.${T}: Add {U} or {R}.| +Meandering River|Core Set 2019|253|C||Land|||Meandering River enters the battlefield tapped.${T}: Add {W} or {U}.| +Reliquary Tower|Core Set 2019|254|U||Land|||You have no maximum hand size.${T}: Add {C}.| +Rupture Spire|Core Set 2019|255|U||Land|||Rupture Spire enters the battlefield tapped.$When Rupture Spire enters the battlefield, sacrifice it unless you pay {1}.${T}: Add one mana of any color.| +Stone Quarry|Core Set 2019|256|C||Land|||Stone Quarry enters the battlefield tapped.${T}: Add {R} or {W}.| +Submerged Boneyard|Core Set 2019|257|C||Land|||Submerged Boneyard enters the battlefield tapped.${T}: Add {U} or {B}.| +Timber Gorge|Core Set 2019|258|C||Land|||Timber Gorge enters the battlefield tapped.${T}: Add {R} or {G}.| +Tranquil Expanse|Core Set 2019|259|C||Land|||Tranquil Expanse enters the battlefield tapped.${T}: Add {G} or {W}.| +Woodland Stream|Core Set 2019|260|C||Land|||Woodland Stream enters the battlefield tapped.${T}: Add {G} or {U}.| +Plains|Core Set 2019|261|C||Basic Land - Plains|||({T}: Add {W}.)| +Island|Core Set 2019|265|C||Basic Land - Island|||({T}: Add {U}.)| +Swamp|Core Set 2019|269|C||Basic Land - Swamp|||({T}: Add {B}.)| +Mountain|Core Set 2019|273|C||Basic Land - Mountain|||({T}: Add {R}.)| +Forest|Core Set 2019|277|C||Basic Land - Forest|||({T}: Add {G}.)| +Ajani, Wise Counselor|Core Set 2019|281|M|{3}{W}{W}|Legendary Planeswalker - Ajani|5|+2: You gain 1 life for each creature you control.$−3: Creatures you control get +2/+2 until end of turn.$−9: Put X +1/+1 counters on target creature, where X is your life total.| +Ajani's Influence|Core Set 2019|282|R|{2}{W}{W}|Sorcery|||Put two +1/+1 counters on target creature.$Look at the top five cards of your library. You may reveal a white card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Court Cleric|Core Set 2019|283|U|{W}|Creature - Human Cleric|1|1|Lifelink$Court Cleric gets +1/+1 as long as you control an Ajani planeswalker.| +Serra's Guardian|Core Set 2019|284|R|{4}{W}{W}|Creature - Angel|5|5|Flying$Vigilance$Other creatures you control have vigilance.| +Silverbeak Griffin|Core Set 2019|285|C|{W}{W}|Creature - Griffin|2|2|Flying| +Tezzeret, Cruel Machinist|Core Set 2019|286|M|{4}{U}{U}|Legendary Planeswalker - Tezzeret|4|+1: Draw a card.$0: Until your next turn, target artifact you control becomes a 5/5 creature in addition to its other types.$−7: Put any number of cards from your hand onto the battlefield face down. They're 5/5 artifact creatures.| +Riddlemaster Sphinx|Core Set 2019|287|R|{4}{U}{U}|Creature - Sphinx|5|5|Flying$When Riddlemaster Sphinx enters the battlefield, you may return target creature an opponent controls to its owner's hand.| +Pendulum of Patterns|Core Set 2019|288|C|{2}|Artifact|||When Pendulum of Patterns enters the battlefield, you gain 3 life.${5}, {T}, Sacrifice Pendulum of Patterns: Draw a card.| +Tezzeret's Gatebreaker|Core Set 2019|289|R|{4}|Artifact|||When Tezzeret's Gatebreaker enters the battlefield, look at the top five cards of your library. You may reveal a blue or artifact card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.${5}{U}, {T}, Sacrifice Tezzeret's Gatebreaker: Creatures you control can't be blocked this turn.| +Tezzeret's Strider|Core Set 2019|290|U|{3}|Artifact Creature - Golem|3|1|As long as you control a Tezzeret planeswalker, Tezzeret's Strider has menace.| +Liliana, the Necromancer|Core Set 2019|291|M|{3}{B}{B}|Legendary Planeswalker - Liliana|4|+1: Target player loses 2 life.$−1: Return target creature card from your graveyard to your hand.$−7: Destroy up to two target creatures. Put up to two creature cards from graveyards onto the battlefield under your control.| +Arisen Gorgon|Core Set 2019|292|U|{1}{B}{B}|Creature - Zombie Gorgon|3|3|Arisen Gorgon has deathtouch as long as you control a Liliana planeswalker.| +Gravewaker|Core Set 2019|293|R|{4}{B}{B}|Creature - Bird Spirit|5|5|Flying${5}{B}{B}: Return target creature card from your graveyard to the battlefield tapped.| +Liliana's Spoils|Core Set 2019|294|R|{3}{B}|Sorcery|||Target opponent discards a card.$Look at the top five cards of your library. You may reveal a black card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Tattered Mummy|Core Set 2019|295|C|{1}{B}|Creature - Zombie Jackal|1|2|When Tattered Mummy dies, each opponent loses 2 life.| +Sarkhan, Dragonsoul|Core Set 2019|296|M|{4}{R}{R}|Legendary Planeswalker - Sarkhan|5|+2: Sarkhan, Dragonsoul deals 1 damage to each opponent and each creature your opponents control.$−3: Sarkhan, Dragonsoul deals 4 damage to target player or planeswalker.$−9: Search your library for any number of Dragon creature cards, put them onto the battlefield, then shuffle your library.| +Kargan Dragonrider|Core Set 2019|297|C|{1}{R}|Creature - Human Warrior|2|2|As long as you control a Dragon, Kargan Dragonrider has flying.| +Sarkhan's Dragonfire|Core Set 2019|298|R|{3}{R}{R}|Sorcery|||Sarkhan's Dragonfire deals 3 damage to any target.$Look at the top five cards of your library. You may reveal a red card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Sarkhan's Whelp|Core Set 2019|299|U|{2}{R}|Creature - Dragon|2|2|Flying$Whenever you activate an ability of a Sarkhan planeswalker, Sarkhan's Whelp deals 1 damage to any target.| +Shivan Dragon|Core Set 2019|300|R|{4}{R}{R}|Creature - Dragon|5|5|Flying${R}: Shivan Dragon gets +1/+0 until end of turn.| +Vivien of the Arkbow|Core Set 2019|301|M|{4}{G}{G}|Legendary Planeswalker - Vivien|5|+2: Put two +1/+1 counters on up to one target creature.$−3: Target creature you control deals damage equal to its power to target creature you don't control.$−9: Creatures you control get +4/+4 and gain trample until end of turn.| +Aggressive Mammoth|Core Set 2019|302|R|{3}{G}{G}{G}|Creature - Elephant|8|8|Trample$Other creatures you control have trample.| +Skalla Wolf|Core Set 2019|303|R|{3}{G}{G}|Creature - Wolf Spirit|3|3|When Skalla Wolf enters the battlefield, look at the top five cards of your library. You may reveal a green card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Ursine Champion|Core Set 2019|304|C|{1}{G}|Creature - Human Berserker|2|2|{5}{G}: Ursine Champion gets +3/+3 and becomes a Bear Berserker until end of turn. Activate this ability only once each turn.| +Vivien's Jaguar|Core Set 2019|305|U|{2}{G}|Creature - Cat Spirit|3|2|Reach${2}{G}: Return Vivien's Jaguar from your graveyard to your hand. Activate this ability only if you control a Vivien planeswalker.| +Nexus of Fate|Core Set 2019|306|M|{5}{U}{U}|Instant|||Take an extra turn after this one.$If Nexus of Fate would be put into a graveyard from anywhere, reveal Nexus of Fate and shuffle it into its owner's library instead.| +Sun Sentinel|Core Set 2019|307|C|{1}{W}|Creature - Human Soldier|2|2|Vigilance| +Air Elemental|Core Set 2019|308|U|{3}{U}{U}|Creature - Elemental|4|4|Flying| +Befuddle|Core Set 2019|309|C|{2}{U}|Instant|||Target creature gets -4/-0 until end of turn.$Draw a card.| +Mist-Cloaked Herald|Core Set 2019|310|C|{U}|Creature - Merfolk Warrior|1|1|Mist-Cloaked Herald can't be blocked.| +Waterknot|Core Set 2019|311|C|{1}{U}{U}|Enchantment - Aura|||Enchant creature$When Waterknot enters the battlefield, tap enchanted creature.$Enchanted creature doesn't untap during its controller's untap step.| +Grasping Scoundrel|Core Set 2019|312|C|{B}|Creature - Human Pirate|1|1|Grasping Scoundrel gets +1/+0 as long as it's attacking.| +Radiating Lightning|Core Set 2019|313|C|{3}{R}|Instant|||Radiating Lightning deals 3 damage to target player and 1 damage to each creature that player controls.| +Llanowar Elves|Core Set 2019|314|C|{G}|Creature - Elf Druid|1|1|{T}: Add {G}.| +Mu Yanling|Global Series: Jiang Yanggu & Mu Yanling|1|M|{4}{U}{U}|Legendary Planeswalker - Yanling|||+2: Target creature can't be blocked this turn.$−3: Draw two cards.$−10: Tap all creatures your opponents control. You take an extra turn after this one.| +Colorful Feiyi Sparrow|Global Series: Jiang Yanggu & Mu Yanling|2|C|{1}{W}|Creature - Bird|1|3|Flying| +Purple-Crystal Crab|Global Series: Jiang Yanggu & Mu Yanling|3|C|{1}{U}|Creature - Crab|1|1|When Purple-Crystal Crab dies, draw card.| +Vivid Flying Fish|Global Series: Jiang Yanggu & Mu Yanling|4|C|{1}{U}|Creature - Fish Lizard|1|1|Vivid Flying Fish has flying as long as it's attacking.| +Welkin Tern|Global Series: Jiang Yanggu & Mu Yanling|5|C|{1}{U}|Creature - Bird|2|1|Flying$Welkin Tern can block only creatures with flying.| +Heavenly Qilin|Global Series: Jiang Yanggu & Mu Yanling|6|C|{2}{W}|Creature - Kirin|2|2|Flying$Whenenver Heavenly Qilin attacks, another target creature you control gains flying until end of turn.| +Armored Whirl Turtle|Global Series: Jiang Yanggu & Mu Yanling|7|C|{2}{U}|Creature - Turtle|0|5|| +Nine-Tail White Fox|Global Series: Jiang Yanggu & Mu Yanling|8|C|{2}{U}|Creature - Fox Spirit|2|2|Whenever Nine-Tail White Fox deals combat damage to a player, draw a card.| +Earth-Origin Yak|Global Series: Jiang Yanggu & Mu Yanling|9|C|{3}{W}|Creature - Ox|2|4|When Earth-Origin Yak enters the battlefield, creatures you control get +1/+1 until end of turn.| +Moon-Eating Dog|Global Series: Jiang Yanggu & Mu Yanling|10|U|{3}{U}|Creature - Hound|3|3|As long as you control a Yanling planeswalker, Moon-Eating Dog has flying.| +Stormcloud Spirit|Global Series: Jiang Yanggu & Mu Yanling|11|U|{3}{U}{U}|Creature - Spirit|4|4|Flying| +Ancestor Dragon|Global Series: Jiang Yanggu & Mu Yanling|12|R|{4}{W}{W}|Creature - Dragon|5|6|Flying$Whenever one or more creatures you control attack, you gain 1 life for each attacking creature.| +Cloak of Mists|Global Series: Jiang Yanggu & Mu Yanling|13|C|{1}{U}|Enchantment - Aura|||Enchant creature$Enchanted creature can't be blocked.| +Qilin's Blessing|Global Series: Jiang Yanggu & Mu Yanling|14|C|{W}|Instant|||Target creature gets +2/+2 until end of turn.| +Drown in Shapelessness|Global Series: Jiang Yanggu & Mu Yanling|15|C|{1}{U}|Instant|||Return target creature to its owner's hand.| +Dragon's Presence|Global Series: Jiang Yanggu & Mu Yanling|16|C|{2}{W}|Instant|||Dragon's Presence deals 5 damage to target attacking or blocking creature.| +Brilliant Plan|Global Series: Jiang Yanggu & Mu Yanling|17|U|{4}{U}|Sorcery|||Draw three cards.| +Rhythmic Water Vortex|Global Series: Jiang Yanggu & Mu Yanling|18|R|{3}{U}{U}|Sorcery|||Return up to two target creatures to their owner's hand.$Search your library and/or graveyard for a card named Mu Yanling, reveal it, and put it into your hand. If you searched your library this way, shuffle it.| +Meandering River|Global Series: Jiang Yanggu & Mu Yanling|19|C||Land|||Meandering River enters the battlefield tapped.${T}: Add {W} or {U}.| +Plains|Global Series: Jiang Yanggu & Mu Yanling|20|C||Basic Land - Plains|||({T}: Add {W}.)| +Island|Global Series: Jiang Yanggu & Mu Yanling|21|C||Basic Land - Island|||({T}: Add {U}.)| +Jiang Yanggu|Global Series: Jiang Yanggu & Mu Yanling|22|M|{4}{G}|Legendary Planeswalker - Yanggu|||+1: Target creature gets +2/+2 until end of turn.$−1: If you don't control a creature named Mowu, create a legendary 3/3 green Hound creature token named Mowu.$−5: Until end of turn, target creature gains trample and gets +X/+X, where X is the number of lands you control.| +Leopard-Spotted Jiao|Global Series: Jiang Yanggu & Mu Yanling|23|C|{1}{R}|Creature - Beast|3|1|| +Feiyi Snake|Global Series: Jiang Yanggu & Mu Yanling|24|C|{1}{G}|Creature - Snake|2|1|Reach| +Sacred White Deer|Global Series: Jiang Yanggu & Mu Yanling|25|U|{1}{G}|Creature - Elk|2|2|{3}{G}, {T}: You gain 4 life. Activate this ability only if you control a Yanggu planeswalker.| +Reckless Pangolin|Global Series: Jiang Yanggu & Mu Yanling|26|C|{2}{G}|Creature - Pangolin|2|2|Whenever Reckless Pangolin attacks, it gets +1/+1 until end of turn.| +Giant Spider|Global Series: Jiang Yanggu & Mu Yanling|27|C|{3}{G}|Creature - Spider|2|4|Reach| +Ferocious Zheng|Global Series: Jiang Yanggu & Mu Yanling|28|C|{2}{G}{G}|Creature - Cat Beast|4|4|| +Fire-Omen Crane|Global Series: Jiang Yanggu & Mu Yanling|29|U|{3}{R}{R}|Creature - Bird Spirit|3|3|Flying$Whenever Fire-Omen Crane attacks, it deals 1 damage to target creature an opponent controls.| +Screeching Phoenix|Global Series: Jiang Yanggu & Mu Yanling|30|R|{4}{R}{R}|Creature - Phoenix|4|4|Flying${2}{R}: Creatures you control get +1/+0 until end of turn.| +Earthshaking Si|Global Series: Jiang Yanggu & Mu Yanling|31|C|{5}{G}|Creature - Beast|5|5|Trample| +Hardened-Scale Armor|Global Series: Jiang Yanggu & Mu Yanling|32|C|{2}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +3/3.| +Breath of Fire|Global Series: Jiang Yanggu & Mu Yanling|33|C|{1}{R}|Instant|||Breath of Fire deals 2 damage to target creature.| +Aggressive Instinct|Global Series: Jiang Yanggu & Mu Yanling|34|C|{1}{G}|Sorcery|||Target creature you control deals damage equal to its power to target creature you don't control.| +Confidence from Strength|Global Series: Jiang Yanggu & Mu Yanling|35|C|{2}{G}|Sorcery|||Target creature gets +4/+4 until and gains trample until end of turn.| +Journey for the Elixir|Global Series: Jiang Yanggu & Mu Yanling|36|R|{2}{G}|Sorcery|||Search your library and graveyard for a basic land card and a card named Jiang Yanggu, reveal them, put them into your hand, then shuffle your library.| +Cleansing Screech|Global Series: Jiang Yanggu & Mu Yanling|37|C|{4}{R}|Sorcery|||Cleansing Screech deals 4 damage to any target.| +Timber Gorge|Global Series: Jiang Yanggu & Mu Yanling|38|C||Land|||Timber Gorge enters the battlefield tapped.${T}: Add {R} or {G}.| +Mountain|Global Series: Jiang Yanggu & Mu Yanling|39|C||Basic Land - Mountain|||({T}: Add {R}.)| +Forest|Global Series: Jiang Yanggu & Mu Yanling|40|C||Basic Land - Forest|||({T}: Add {G}.)| +Boreas Charger|Commander 2018|1|R|{2}{W}|Creature - Pegasus|2|1|Flying$When Boreas Charger leaves the battlefield, choose an opponent who controls more lands than you. Search your library for a number of Plains cards equal to the difference and reveal them. Put one of them onto the battlefield tapped and the rest into your hand. Then shuffle your library.| +Empyrial Storm|Commander 2018|2|R|{4}{W}{W}|Sorcery|||When you cast this spell, copy it for each time you've cast your commander from the command zone this game.$Create a 4/4 white Angel creature token with flying.| +Heavenly Blademaster|Commander 2018|3|R|{5}{W}|Creature - Angel|3|6|Flying, double strike$When Heavenly Blademaster enters the battlefield, you may attach any number of Auras and Equipment you control to it.$Other creatures you control get +1/+1 for each Aura and Equipment attached to Heavenly Blademaster.| +Loyal Unicorn|Commander 2018|4|U|{3}{W}|Creature - Unicorn|3|4|Vigilance$Lieutenant — At the beginning of combat on your turn, if you control your commander, prevent all combat damage that would be dealt to creatures you control this turn. Other creatures you control gain vigilance until end of turn.| +Magus of the Balance|Commander 2018|5|R|{1}{W}|Creature - Human Wizard|2|2|{4}{W}, {T}, Sacrifice Magus of the Balance: Each player chooses a number of lands they control equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players discard cards and sacrifice creatures the same way.| +Aminatou's Augury|Commander 2018|6|R|{6}{U}{U}|Sorcery|||Exile the top eight cards of your library. You may put a land card from among them onto the battlefield. Until end of turn, for each nonland card type, you may cast a card of that type from among the exiled cards without paying its mana cost.| +Echo Storm|Commander 2018|7|R|{3}{U}{U}|Sorcery|||When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.$Create a token that's a copy of target artifact.| +Estrid's Invocation|Commander 2018|8|R|{2}{U}|Enchantment|||You may have Estrid's Invocation enter the battlefield as a copy of any enchantment you control, except it gains "At the beginning of your upkeep, you may exile this enchantment. If you do, return it to the battlefield under its owner's control."| +Ever-Watching Threshold|Commander 2018|9|R|{2}{U}|Enchantment|||Whenever an opponent attacks you and/or a planeswalker you control with one or more creatures, draw a card.| +Loyal Drake|Commander 2018|10|U|{2}{U}|Creature - Drake|2|2|Flying$Lieutenant — At the beginning of combat on your turn, if you control your commander, draw a card.| +Octopus Umbra|Commander 2018|11|R|{3}{U}{U}|Enchantment - Aura|||Enchant creature$Enchanted creature has base power and toughness 8/8 and has "Whenever this creature attacks, you may tap target creature with power 8 or less."$Totem armor| +Primordial Mist|Commander 2018|12|R|{4}{U}|Enchantment|||At the beginning of your end step, you may manifest the top card of your library.| +Vedalken Humiliator|Commander 2018|13|R|{3}{U}|Creature - Vedalken Wizard|3|4|Metalcraft — Whenever Vedalken Humiliator attacks, if you control three or more artifacts, creatures your opponents control lose all abilities and have base power and toughness 1/1 until end of turn.| +Bloodtracker|Commander 2018|14|R|{3}{B}|Creature - Vampire Wizard|2|2|Flying${B}, Pay 2 life: Put a +1/+1 counter on Bloodtracker.$When Bloodtracker leaves the battlefield, draw a card for each +1/+1 counter on it.| +Entreat the Dead|Commander 2018|15|R|{X}{X}{B}{B}{B}|Sorcery|||Return X target creature cards from your graveyard to the battlefield.$Miracle {X}{B}{B}| +Loyal Subordinate|Commander 2018|16|U|{2}{B}|Creature - Zombie|3|1|Menace$Lieutenant — At the beginning of combat on your turn, if you control your commander, each opponent loses 3 life.| +Night Incarnate|Commander 2018|17|R|{4}{B}|Creature - Elemental|3|4|Deathtouch$When Night Incarnate leaves the battlefield, all creatures get -3/-3 until end of turn.$Evoke {3}{B}| +Skull Storm|Commander 2018|18|R|{7}{B}{B}|Sorcery|||When you cast this spell, copy it for each time you've cast your commander from the command zone this game.$Each opponent sacrifices a creature. Each opponent who can't loses half their life, rounded up.| +Sower of Discord|Commander 2018|19|R|{4}{B}{B}|Creature - Demon|6|6|Flying$As Sower of Discord enters the battlefield, choose two players.$Whenever damage is dealt to one of the chosen players, the other chosen player also loses that much life.| +Emissary of Grudges|Commander 2018|20|R|{5}{R}|Creature - Efreet|6|5|Flying, haste$As Emissary of Grudges enters the battlefield, secretly choose an opponent.$Reveal the player you chose: Choose new targets for target spell or ability if it's controlled by the chosen player and if it targets you or a permanent you control. Activate this ability only once.| +Enchanter's Bane|Commander 2018|21|R|{1}{R}|Enchantment|||At the beginning of your end step, target enchantment deals damage equal to its converted mana cost to its controller unless that player sacrifices it.| +Fury Storm|Commander 2018|22|R|{2}{R}{R}|Instant|||When you cast this spell, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies.$Copy target instant or sorcery spell. You may choose new targets for the copy.| +Loyal Apprentice|Commander 2018|23|U|{1}{R}|Creature - Human Artificer|2|1|Haste$Lieutenant — At the beginning of combat on your turn, if you control your commander, create a 1/1 colorless Thopter artifact creature token with flying. That token gains haste until end of turn.| +Nesting Dragon|Commander 2018|24|R|{3}{R}{R}|Creature - Dragon|5|4|Flying$Landfall — Whenever a land enters the battlefield under your control, create a 0/2 red Dragon Egg creature token with defender and "When this creature dies, create a 2/2 red Dragon creature token with flying and '{R}: This creature gets +1/+0 until end of turn.'"| +Reality Scramble|Commander 2018|25|R|{2}{R}{R}|Sorcery|||Put target permanent you own on the bottom of your library. Reveal cards from the top of your library until you reveal a card that shares a card type with that permanent. Put that card onto the battlefield and the rest on the bottom of your library in a random order.$Retrace| +Saheeli's Directive|Commander 2018|26|R|{X}{R}{R}{R}|Sorcery|||Improvise$Reveal the top X cards of your library. You may put any number of artifact cards with converted mana cost X or less from among them onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield into your graveyard.| +Treasure Nabber|Commander 2018|27|R|{2}{R}|Creature - Goblin Rogue|3|2|Whenever an opponent taps an artifact for mana, gain control of that artifact until the end of your next turn.| +Varchild, Betrayer of Kjeldor|Commander 2018|28|R|{2}{R}|Legendary Creature - Human Knight|3|3|Whenever Varchild, Betrayer of Kjeldor deals combat damage to a player, that player creates that many 1/1 red Survivor creature tokens.$Survivors your opponents control can't block, and they can't attack you or a planeswalker you control.$When Varchild leaves the battlefield, gain control of all Survivors.| +Crash of Rhino Beetles|Commander 2018|29|R|{4}{G}|Creature - Insect|5|5|Trample$Crash of Rhino Beetles gets +10/+10 as long as you control ten or more lands.| +Genesis Storm|Commander 2018|30|R|{4}{G}{G}|Sorcery|||When you cast this spell, copy it for each time you've cast your commander from the command zone this game.$Reveal cards from the top of your library until you reveal a nonland permanent card. You may put that card onto the battlefield. Then put all cards revealed this way that weren't put onto the battlefield on the bottom of your library in a random order.| +Loyal Guardian|Commander 2018|31|U|{4}{G}|Creature - Rhino|4|4|Trample$Lieutenant — At the beginning of combat on your turn, if you control your commander, put a +1/+1 counter on each creature you control.| +Myth Unbound|Commander 2018|32|R|{2}{G}|Enchantment|||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.| +Nylea's Colossus|Commander 2018|33|R|{6}{G}|Enchantment Creature - Giant|6|6|Constellation — Whenever Nylea's Colossus or another enchantment enters the battlefield under your control, double target creature's power and toughness until end of turn.| +Ravenous Slime|Commander 2018|34|R|{2}{G}|Creature - Ooze|1|1|Ravenous Slime can't be blocked by creatures with power 2 or less.$If a creature an opponent controls would die, instead exile it and put a number of +1/+1 counters equal to that creature's power on Ravenous Slime.| +Turntimber Sower|Commander 2018|35|R|{2}{G}|Creature - Elf Druid|3|3|Whenever one or more land cards are put into your graveyard from anywhere, create a 0/1 green Plant creature token.${G}, Sacrifice three creatures: Return target land card from your graveyard to your hand.| +Whiptongue Hydra|Commander 2018|36|R|{5}{G}|Creature - Lizard Hydra|4|4|Reach$When Whiptongue Hydra enters the battlefield, destroy all creatures with flying. Put a +1/+1 counter on Whiptongue Hydra for each creature destroyed this way.| +Aminatou, the Fateshifter|Commander 2018|37|M|{W}{U}{B}|Legendary Planeswalker - Aminatou|3|+1: Draw a card, then put a card from your hand on top of your library.$-1: Exile another target permanent you own, then return it to the battlefield under your control.$-6: Choose left or right. Each player gains control of all nonland permanents other than Aminatou, the Fateshifter controlled by the next player in the chosen direction.$Aminatou, the Fateshifter can be your commander.| +Arixmethes, Slumbering Isle|Commander 2018|38|R|{2}{G}{U}|Legendary Creature - Kraken|12|12|Arixmethes, Slumbering Isle enters the battlefield tapped with five slumber counters on it.$As long as Arixmethes has a slumber counter on it, it's a land.$Whenever you cast a spell, you may remove a slumber counter from Arixmethes.${T}: Add {G}{U}.| +Brudiclad, Telchor Engineer|Commander 2018|39|M|{4}{U}{R}|Legendary Artifact Creature - Artificer|4|4|Creature tokens you control have haste.$At the beginning of combat on your turn, create a 2/1 blue Myr artifact creature token. Then you may choose a token you control. If you do, each other token you control becomes a copy of that token.| +Estrid, the Masked|Commander 2018|40|M|{1}{G}{W}{U}|Legendary Planeswalker - Estrid|3|+2: Untap each enchanted permanent you control.$-1: Create a white Aura enchantment token named Mask attached to another target permanent. The token has enchant permanent and totem armor.$-7: Put the top seven cards of your library into your graveyard. Return all non-Aura enchantment cards from your graveyard to the battlefield, then do the same for Aura cards.$Estrid, the Masked can be your commander.| +Gyrus, Waker of Corpses|Commander 2018|41|M|{X}{B}{R}{G}|Legendary Creature - Hydra|0|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.$Whenever Gyrus attacks, you may exile target creature card with lesser power from your graveyard. If you do, create a token that's a copy of that card and that's tapped and attacking. Exile the token at the end of combat.| +Kestia, the Cultivator|Commander 2018|42|M|{1}{G}{W}{U}|Legendary Enchantment Creature - Nymph|4|4|Bestow {3}{G}{W}{U}$Enchanted creature gets +4/+4.$Whenever an enchanted creature or enchantment creature you control attacks, draw a card.| +Lord Windgrace|Commander 2018|43|M|{2}{B}{R}{G}|Legendary Planeswalker - Windgrace|5|+2: Discard a card, then draw a card. If a land card is discarded this way, draw an additional card.$-3: Return up to two target land cards from your graveyard to the battlefield.$-11: Destroy up to six target nonland permanents, then create six 2/2 green Cat Warrior creature tokens with forestwalk.$Lord Windgrace can be your commander.| +Saheeli, the Gifted|Commander 2018|44|M|{2}{U}{R}|Legendary Planeswalker - Saheeli|4|+1: Create a 1/1 colorless Servo artifact creature token.$+1: The next spell you cast this turn costs {1} less to cast for each artifact you control as you cast it.$-7: For each artifact you control, create a token that's a copy of it. Those tokens gain haste. Exile those tokens at the beginning of the next end step.$Saheeli, the Gifted can be your commander.| +Tawnos, Urza's Apprentice|Commander 2018|45|M|{U}{R}|Legendary Creature - Human Artificer|1|3|Haste${U}{R}, {T}: Copy target activated or triggered ability you control from an artifact source. You may choose new targets for the copy.| +Thantis the Warweaver|Commander 2018|46|M|{3}{B}{R}{G}|Legendary Creature - Spider|5|5|Vigilance, reach$All creatures attack each combat if able.$Whenever a creature attacks you or a planeswalker you control, put a +1/+1 counter on Thantis the Warweaver.| +Tuvasa the Sunlit|Commander 2018|47|M|{G}{W}{U}|Legendary Creature - Merfolk Shaman|1|1|Tuvasa the Sunlit gets +1/+1 for each enchantment you control.$Whenever you cast your first enchantment spell each turn, draw a card.| +Varina, Lich Queen|Commander 2018|48|M|{1}{W}{U}{B}|Legendary Creature - Zombie Wizard|4|4|Whenever you attack with one or more Zombies, draw that many cards, then discard that many cards. You gain that much life.${2}, Exile two cards from your graveyard: Create a tapped 2/2 black Zombie creature token.| +Windgrace's Judgment|Commander 2018|49|R|{3}{B}{G}|Instant|||For any number of opponents, destroy target nonland permanent that player controls.| +Xantcha, Sleeper Agent|Commander 2018|50|R|{1}{B}{R}|Legendary Creature - Minion|5|5|As Xantcha, Sleeper Agent enters the battlefield, an opponent of your choice gains control of it.$Xantcha attacks each combat if able and can't attack its owner or planeswalkers its owner controls.${3}: Xantcha's controller loses 2 life and you draw a card. Any player may activate this ability.| +Yennet, Crypt Sovereign|Commander 2018|51|M|{2}{W}{U}{B}|Legendary Creature - Sphinx|3|5|Flying, vigilance, menace$Whenever Yennet, Crypt Sovereign attacks, reveal the top card of your library. If that card's converted mana cost is odd, you may cast it without paying its mana cost. Otherwise, draw a card.| +Yuriko, the Tiger's Shadow|Commander 2018|52|R|{1}{U}{B}|Legendary Creature - Human Ninja|1|3|Commander ninjutsu {U}{B}$Whenever a Ninja you control deals combat damage to a player, reveal the top card of your library and put that card into your hand. Each opponent loses life equal to that card's converted mana cost.| +Ancient Stone Idol|Commander 2018|53|R|{10}|Artifact Creature - Golem|12|12|Flash$This spell costs {1} less to cast for each attacking creature.$Trample$When Ancient Stone Idol dies, create a 6/12 colorless Construct artifact creature token with trample.| +Coveted Jewel|Commander 2018|54|R|{6}|Artifact|||When Coveted Jewel enters the battlefield, draw three cards.${T}: Add three mana of any one color.$Whenever one or more creatures an opponent controls attack you and aren't blocked, that player draws three cards and gains control of Coveted Jewel. Untap it.| +Endless Atlas|Commander 2018|55|R|{2}|Artifact|||{2}, {T}: Draw a card. Activate this ability only if you control three or more lands with the same name.| +Geode Golem|Commander 2018|56|U|{5}|Artifact Creature - Golem|5|3|Trample$Whenever Geode Golem deals combat damage to a player, you may cast your commander from the command zone without paying its mana cost.| +Retrofitter Foundry|Commander 2018|57|R|{1}|Artifact|||{3}: Untap Retrofitter Foundry.${2}, {T}: Create a 1/1 colorless Servo artifact creature token.${1}, {T}, Sacrifice a Servo: Create a 1/1 colorless Thopter artifact creature token with flying.${T}, Sacrifice a Thopter: Create a 4/4 colorless Construct artifact creature token.| +Forge of Heroes|Commander 2018|58|C||Land|||{T}: Add {C}.${T}: Choose target commander that entered the battlefield this turn. Put a +1/+1 counter on it if it's a creature and a loyalty counter on it if it's a planeswalker.| +Isolated Watchtower|Commander 2018|59|R||Land|||{T}: Add {C}.${2}, {T}: Scry 1, then you may reveal the top card of your library. If a basic land card is revealed this way, put it onto the battlefield tapped. Activate this ability only if an opponent controls at least two more lands than you.| +Adarkar Valkyrie|Commander 2018|60|R|{4}{W}{W}|Snow Creature - Angel|4|5|Flying, vigilance${T}: When target creature other than Adarkar Valkyrie dies this turn, return that card to the battlefield under your control.| +Ajani's Chosen|Commander 2018|61|R|{2}{W}{W}|Creature - Cat Soldier|3|3|Whenever an enchantment enters the battlefield under your control, create a 2/2 white Cat creature token. If that enchantment is an Aura, you may attach it to the token.| +Akroma's Vengeance|Commander 2018|62|R|{4}{W}{W}|Sorcery|||Destroy all artifacts, creatures, and enchantments.$Cycling {3}| +Banishing Stroke|Commander 2018|63|U|{5}{W}|Instant|||Put target artifact, creature, or enchantment on the bottom of its owner's library.$Miracle {W}| +Celestial Archon|Commander 2018|64|R|{3}{W}{W}|Enchantment Creature - Archon|4|4|Bestow {5}{W}{W}$Flying, first strike$Enchanted creature gets +4/+4 and has flying and first strike.| +Crib Swap|Commander 2018|65|U|{2}{W}|Tribal Instant - Shapeshifter|||Changeling$Exile target creature. Its controller creates a 1/1 colorless Shapeshifter creature token with changeling.| +Dismantling Blow|Commander 2018|66|C|{2}{W}|Instant|||Kicker {2}{U}$Destroy target artifact or enchantment. If this spell was kicked, draw two cards.| +Entreat the Angels|Commander 2018|67|M|{X}{X}{W}{W}{W}|Sorcery|||Create X 4/4 white Angel creature tokens with flying.$Miracle {X}{W}{W}| +Lightform|Commander 2018|68|U|{1}{W}{W}|Enchantment|||When Lightform enters the battlefield, it becomes an Aura with enchant creature. Manifest the top card of your library and attach Lightform to it.$Enchanted creature has flying and lifelink.| +Martial Coup|Commander 2018|69|R|{X}{W}{W}|Sorcery|||Create X 1/1 white Soldier creature tokens. If X is 5 or more, destroy all other creatures.| +Phyrexian Rebirth|Commander 2018|70|R|{4}{W}{W}|Sorcery|||Destroy all creatures, then create an X/X colorless Horror artifact creature token, where X is the number of creatures destroyed this way.| +Return to Dust|Commander 2018|71|U|{2}{W}{W}|Instant|||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.| +Sage's Reverie|Commander 2018|72|U|{3}{W}|Enchantment - Aura|||Enchant creature$When Sage's Reverie enters the battlefield, draw a card for each Aura you control that's attached to a creature.$Enchanted creature gets +1/+1 for each Aura you control that's attached to a creature.| +Serra Avatar|Commander 2018|73|M|{4}{W}{W}{W}|Creature - Avatar|*|*|Serra Avatar's power and toughness are each equal to your life total.$When Serra Avatar is put into a graveyard from anywhere, shuffle it into its owner's library.| +Sigil of the Empty Throne|Commander 2018|74|R|{3}{W}{W}|Enchantment|||Whenever you cast an enchantment spell, create a 4/4 white Angel creature token with flying.| +Silent Sentinel|Commander 2018|75|R|{5}{W}{W}|Creature - Archon|4|6|Flying$Whenever Silent Sentinel attacks, you may return target enchantment card from your graveyard to the battlefield.| +Soul Snare|Commander 2018|76|U|{W}|Enchantment|||{W}, Sacrifice Soul Snare: Exile target creature that's attacking you or a planeswalker you control.| +Terminus|Commander 2018|77|R|{4}{W}{W}|Sorcery|||Put all creatures on the bottom of their owners' libraries.$Miracle {W}| +Unquestioned Authority|Commander 2018|78|U|{2}{W}|Enchantment - Aura|||Enchant creature$When Unquestioned Authority enters the battlefield, draw a card.$Enchanted creature has protection from creatures.| +Winds of Rath|Commander 2018|79|R|{3}{W}{W}|Sorcery|||Destroy all creatures that aren't enchanted. They can't be regenerated.| +Aether Gale|Commander 2018|80|R|{3}{U}{U}|Sorcery|||Return six target nonland permanents to their owners' hands.| +Archetype of Imagination|Commander 2018|81|U|{4}{U}{U}|Enchantment Creature - Human Wizard|3|2|Creatures you control have flying.$Creatures your opponents control lose flying and can't have or gain flying.| +Brainstorm|Commander 2018|82|U|{U}|Instant|||Draw three cards, then put two cards from your hand on top of your library in any order.| +Cloudform|Commander 2018|83|U|{1}{U}{U}|Enchantment|||When Cloudform enters the battlefield, it becomes an Aura with enchant creature. Manifest the top card of your library and attach Cloudform to it.$Enchanted creature has flying and hexproof.| +Conundrum Sphinx|Commander 2018|84|R|{2}{U}{U}|Creature - Sphinx|4|4|Flying$Whenever Conundrum Sphinx attacks, each player chooses a card name. Then each player reveals the top card of their library. If the card a player revealed has the name they chose, that player puts it into their hand. If it doesn't, that player puts it on the bottom of their library.| +Devastation Tide|Commander 2018|85|R|{3}{U}{U}|Sorcery|||Return all nonland permanents to their owners' hands.$Miracle {1}{U}| +Dictate of Kruphix|Commander 2018|86|R|{1}{U}{U}|Enchantment|||Flash$At the beginning of each player's draw step, that player draws an additional card.| +Djinn of Wishes|Commander 2018|87|R|{3}{U}{U}|Creature - Djinn|4|4|Flying$Djinn of Wishes enters the battlefield with three wish counters on it.${2}{U}{U}, Remove a wish counter from Djinn of Wishes: Reveal the top card of your library. You may play that card without paying its mana cost. If you don't, exile it.| +Dream Cache|Commander 2018|88|C|{2}{U}|Sorcery|||Draw three cards, then put two cards from your hand both on top of your library or both on the bottom of your library.| +Eel Umbra|Commander 2018|89|C|{1}{U}|Enchantment - Aura|||Flash| +Etherium Sculptor|Commander 2018|90|C|{1}{U}|Artifact Creature - Vedalken Artificer|1|2|Artifact spells you cast cost {1} less to cast.| +Inkwell Leviathan|Commander 2018|91|R|{7}{U}{U}|Artifact Creature - Leviathan|7|11|Islandwalk| +Into the Roil|Commander 2018|92|C|{1}{U}|Instant|||Kicker {1}{U}$Return target nonland permanent to its owner's hand. If this spell was kicked, draw a card.| +Jeskai Infiltrator|Commander 2018|93|R|{2}{U}|Creature - Human Monk|2|3|Jeskai Infiltrator can't be blocked as long as you control no other creatures.$When Jeskai Infiltrator deals combat damage to a player, exile it and the top card of your library in a face-down pile, shuffle that pile, then manifest those cards.| +Mulldrifter|Commander 2018|94|U|{4}{U}|Creature - Elemental|2|2|Flying$When Mulldrifter enters the battlefield, draw two cards.$Evoke {2}{U}| +Ninja of the Deep Hours|Commander 2018|95|C|{3}{U}|Creature - Human Ninja|2|2|Ninjutsu {1}{U}$Whenever Ninja of the Deep Hours deals combat damage to a player, you may draw a card.| +Ponder|Commander 2018|96|C|{U}|Sorcery|||Look at the top three cards of your library, then put them back in any order. You may shuffle your library.$Draw a card.| +Portent|Commander 2018|97|C|{U}|Sorcery|||Look at the top three cards of target player's library, then put them back in any order. You may have that player shuffle their library.$Draw a card at the beginning of the next turn's upkeep.| +Predict|Commander 2018|98|U|{1}{U}|Instant|||Choose a card name, then target player puts the top card of their library into their graveyard. If that card has the chosen name, you draw two cards. Otherwise, you draw a card.| +Reverse Engineer|Commander 2018|99|U|{3}{U}{U}|Sorcery|||Improvise$Draw three cards.| +Saheeli's Artistry|Commander 2018|100|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except it's an artifact in addition to its other types.| +Sharding Sphinx|Commander 2018|101|R|{4}{U}{U}|Artifact Creature - Sphinx|4|4|Flying$Whenever an artifact creature you control deals combat damage to a player, you may create a 1/1 blue Thopter artifact creature token with flying.| +Sigiled Starfish|Commander 2018|102|C|{1}{U}|Creature - Starfish|0|3|{T}: Scry 1.| +Sphinx of Jwar Isle|Commander 2018|103|R|{4}{U}{U}|Creature - Sphinx|5|5|Flying$Shroud| +Sphinx of Uthuun|Commander 2018|104|R|{5}{U}{U}|Creature - Sphinx|5|6|Flying$When Sphinx of Uthuun enters the battlefield, reveal the top five cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other into your graveyard.| +Telling Time|Commander 2018|105|C|{1}{U}|Instant|||Look at the top three cards of your library. Put one of those cards into your hand, one on top of your library, and one on the bottom of your library.| +Thirst for Knowledge|Commander 2018|106|U|{2}{U}|Instant|||Draw three cards. Then discard two cards unless you discard an artifact card.| +Thopter Spy Network|Commander 2018|107|R|{2}{U}{U}|Enchantment|||At the beginning of your upkeep, if you control an artifact, create a 1/1 colorless Thopter artifact creature token with flying.$Whenever one or more artifact creatures you control deal combat damage to a player, draw a card.| +Tidings|Commander 2018|108|U|{3}{U}{U}|Sorcery|||Draw four cards.| +Treasure Hunt|Commander 2018|109|C|{1}{U}|Sorcery|||Reveal cards from the top of your library until you reveal a nonland card, then put all cards revealed this way into your hand.| +Vow of Flight|Commander 2018|110|U|{2}{U}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +2/+2, has flying, and can't attack you or a planeswalker you control.| +Whirler Rogue|Commander 2018|111|U|{2}{U}{U}|Creature - Human Rogue Artificer|2|2|When Whirler Rogue enters the battlefield, create two 1/1 colorless Thopter artifact creature tokens with flying.$Tap two untapped artifacts you control: Target creature can't be blocked this turn.| +Whitewater Naiads|Commander 2018|112|U|{3}{U}{U}|Enchantment Creature - Nymph|4|4|Constellation — Whenever Whitewater Naiads or another enchantment enters the battlefield under your control, target creature can't be blocked this turn.| +Army of the Damned|Commander 2018|113|M|{5}{B}{B}{B}|Sorcery|||Create thirteen tapped 2/2 black Zombie creature tokens.$Flashback {7}{B}{B}{B}| +Moonlight Bargain|Commander 2018|114|R|{3}{B}{B}|Instant|||Look at the top five cards of your library. For each card, put that card into your graveyard unless you pay 2 life. Then put the rest into your hand.| +Phyrexian Delver|Commander 2018|115|R|{3}{B}{B}|Creature - Zombie|3|2|When Phyrexian Delver enters the battlefield, return target creature card from your graveyard to the battlefield. You lose life equal to that card's converted mana cost.| +Retreat to Hagra|Commander 2018|116|U|{2}{B}|Enchantment|||Landfall — Whenever a land enters the battlefield under your control, choose one —$• Target creature gets +1/+0 and gains deathtouch until end of turn.$• Each opponent loses 1 life and you gain 1 life.| +Ruinous Path|Commander 2018|117|R|{1}{B}{B}|Sorcery|||Destroy target creature or planeswalker.$Awaken 4—{5}{B}{B}| +Soul of Innistrad|Commander 2018|118|M|{4}{B}{B}|Creature - Avatar|6|6|Deathtouch${3}{B}{B}: Return up to three target creature cards from your graveyard to your hand.${3}{B}{B}, Exile Soul of Innistrad from your graveyard: Return up to three target creature cards from your graveyard to your hand.| +Stitch Together|Commander 2018|119|U|{B}{B}|Sorcery|||Return target creature card from your graveyard to your hand.$Threshold — Return that card from your graveyard to the battlefield instead if seven or more cards are in your graveyard.| +Blasphemous Act|Commander 2018|120|R|{8}{R}|Sorcery|||This spell costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| +Chain Reaction|Commander 2018|121|R|{2}{R}{R}|Sorcery|||Chain Reaction deals X damage to each creature, where X is the number of creatures on the battlefield.| +Chaos Warp|Commander 2018|122|R|{2}{R}|Instant|||The owner of target permanent shuffles it into their library, then reveals the top card of their library. If it's a permanent card, they put it onto the battlefield.| +Flameblast Dragon|Commander 2018|123|R|{4}{R}{R}|Creature - Dragon|5|5|Flying$Whenever Flameblast Dragon attacks, you may pay {X}{R}. If you do, Flameblast Dragon deals X damage to any target.| +Hellkite Igniter|Commander 2018|124|R|{5}{R}{R}|Creature - Dragon|5|5|Flying, haste${1}{R}: Hellkite Igniter gets +X/+0 until end of turn, where X is the number of artifacts you control.| +Magmaquake|Commander 2018|125|R|{X}{R}{R}|Instant|||Magmaquake deals X damage to each creature without flying and each planeswalker.| +Thopter Engineer|Commander 2018|126|U|{2}{R}|Creature - Human Artificer|1|3|When Thopter Engineer enters the battlefield, create a 1/1 colorless Thopter artifact creature token with flying.$Artifact creatures you control have haste.| +Acidic Slime|Commander 2018|127|U|{3}{G}{G}|Creature - Ooze|2|2|Deathtouch$When Acidic Slime enters the battlefield, destroy target artifact, enchantment, or land.| +Aura Gnarlid|Commander 2018|128|C|{2}{G}|Creature - Beast|2|2|Creatures with power less than Aura Gnarlid's power can't block it.$Aura Gnarlid gets +1/+1 for each Aura on the battlefield.| +Avenger of Zendikar|Commander 2018|129|M|{5}{G}{G}|Creature - Elemental|5|5|When Avenger of Zendikar enters the battlefield, create a 0/1 green Plant creature token for each land you control.$Landfall — Whenever a land enters the battlefield under your control, you may put a +1/+1 counter on each Plant creature you control.| +Baloth Woodcrasher|Commander 2018|130|U|{4}{G}{G}|Creature - Beast|4|4|Landfall — Whenever a land enters the battlefield under your control, Baloth Woodcrasher gets +4/+4 and gains trample until end of turn.| +Bear Umbra|Commander 2018|131|R|{2}{G}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +2/+2 and has "Whenever this creature attacks, untap all lands you control."$Totem armor| +Boon Satyr|Commander 2018|132|R|{1}{G}{G}|Enchantment Creature - Satyr|4|2|Flash$Bestow {3}{G}{G}$Enchanted creature gets +4/+2.| +Borderland Explorer|Commander 2018|133|C|{1}{G}|Creature - Elf Scout|3|1|When Borderland Explorer enters the battlefield, each player may discard a card. Each player who discarded a card this way may search their library for a basic land card, reveal it, put it into their hand, then shuffle their library.| +Budoka Gardener|Commander 2018|134|R|{1}{G}|Creature - Human Monk|2|1|{T}: You may put a land card from your hand onto the battlefield. If you control ten or more lands, flip Budoka Gardener.| +Centaur Vinecrasher|Commander 2018|135|R|{3}{G}|Creature - Plant Centaur|1|1|Trample$Centaur Vinecrasher enters the battlefield with a number of +1/+1 counters on it equal to the number of land cards in all graveyards.$Whenever a land card is put into a graveyard from anywhere, you may pay {G}{G}. If you do, return Centaur Vinecrasher from your graveyard to your hand.| +Consign to Dust|Commander 2018|136|U|{2}{G}|Instant|||Strive — This spell costs {2}{G} more to cast for each target beyond the first.$Destroy any number of target artifacts and/or enchantments.| +Creeping Renaissance|Commander 2018|137|R|{3}{G}{G}|Sorcery|||Choose a permanent type. Return all cards of the chosen type from your graveyard to your hand.$Flashback {5}{G}{G}| +Cultivate|Commander 2018|138|C|{2}{G}|Sorcery|||Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library.| +Dawn's Reflection|Commander 2018|139|C|{3}{G}|Enchantment - Aura|||Enchant land$Whenever enchanted land is tapped for mana, its controller adds an additional two mana in any combination of colors.| +Eidolon of Blossoms|Commander 2018|140|R|{2}{G}{G}|Enchantment Creature - Spirit|2|2|Constellation — Whenever Eidolon of Blossoms or another enchantment enters the battlefield under your control, draw a card.| +Enchantress's Presence|Commander 2018|141|R|{2}{G}|Enchantment|||Whenever you cast an enchantment spell, draw a card.| +Epic Proportions|Commander 2018|142|R|{4}{G}{G}|Enchantment - Aura|||Flash$Enchant creature$Enchanted creature gets +5/+5 and has trample.| +Explore|Commander 2018|143|C|{1}{G}|Sorcery|||You may play an additional land this turn.$Draw a card.| +Explosive Vegetation|Commander 2018|144|U|{3}{G}|Sorcery|||Search your library for up to two basic land cards and put them onto the battlefield tapped. Then shuffle your library.| +Far Wanderings|Commander 2018|145|C|{2}{G}|Sorcery|||Search your library for a basic land card, put that card onto the battlefield tapped, then shuffle your library.$Threshold — If seven or more cards are in your graveyard, instead search your library for up to three basic land cards, put them onto the battlefield tapped, then shuffle your library.| +Farhaven Elf|Commander 2018|146|C|{2}{G}|Creature - Elf Druid|1|1|When Farhaven Elf enters the battlefield, you may search your library for a basic land card and put it onto the battlefield tapped. If you do, shuffle your library.| +Fertile Ground|Commander 2018|147|C|{1}{G}|Enchantment - Aura|||Enchant land$Whenever enchanted land is tapped for mana, its controller adds an additional one mana of any color.| +Grapple with the Past|Commander 2018|148|C|{1}{G}|Instant|||Put the top three cards of your library into your graveyard, then you may return a creature or land card from your graveyard to your hand.| +Ground Seal|Commander 2018|149|R|{1}{G}|Enchantment|||When Ground Seal enters the battlefield, draw a card.$Cards in graveyards can't be the targets of spells or abilities.| +Harrow|Commander 2018|150|C|{2}{G}|Instant|||As an additional cost to cast this spell, sacrifice a land.$Search your library for up to two basic land cards and put them onto the battlefield. Then shuffle your library.| +Herald of the Pantheon|Commander 2018|151|R|{1}{G}|Creature - Centaur Shaman|2|2|Enchantment spells you cast cost {1} less to cast.$Whenever you cast an enchantment spell, you gain 1 life.| +Hunting Wilds|Commander 2018|152|U|{3}{G}|Sorcery|||Kicker {3}{G}$Search your library for up to two Forest cards and put them onto the battlefield tapped. Then shuffle your library.$If this spell was kicked, untap all Forests put onto the battlefield this way. They become 3/3 green creatures with haste that are still lands.| +Hydra Omnivore|Commander 2018|153|M|{4}{G}{G}|Creature - Hydra|8|8|Whenever Hydra Omnivore deals combat damage to an opponent, it deals that much damage to each other opponent.| +Khalni Heart Expedition|Commander 2018|154|C|{1}{G}|Enchantment|||Landfall — Whenever a land enters the battlefield under your control, you may put a quest counter on Khalni Heart Expedition.$Remove three quest counters from Khalni Heart Expedition and sacrifice it: Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle your library.| +Kruphix's Insight|Commander 2018|155|C|{2}{G}|Sorcery|||Reveal the top six cards of your library. Put up to three enchantment cards from among them into your hand and the rest of the revealed cards into your graveyard.| +Moldgraf Monstrosity|Commander 2018|156|R|{4}{G}{G}{G}|Creature - Insect|8|8|Trample$When Moldgraf Monstrosity dies, exile it, then return two creature cards at random from your graveyard to the battlefield.| +Overgrowth|Commander 2018|157|C|{2}{G}|Enchantment - Aura|||Enchant land$Whenever enchanted land is tapped for mana, its controller adds an additional {G}{G}.| +Rampaging Baloths|Commander 2018|158|R|{4}{G}{G}|Creature - Beast|6|6|Trample$Landfall — Whenever a land enters the battlefield under your control, you may create a 4/4 green Beast creature token.| +Reclamation Sage|Commander 2018|159|U|{2}{G}|Creature - Elf Shaman|2|1|When Reclamation Sage enters the battlefield, you may destroy target artifact or enchantment.| +Sakura-Tribe Elder|Commander 2018|160|C|{1}{G}|Creature - Snake Shaman|1|1|Sacrifice Sakura-Tribe Elder: Search your library for a basic land card, put that card onto the battlefield tapped, then shuffle your library.| +Scute Mob|Commander 2018|161|R|{G}|Creature - Insect|1|1|At the beginning of your upkeep, if you control five or more lands, put four +1/+1 counters on Scute Mob.| +Snake Umbra|Commander 2018|162|C|{2}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 and has "Whenever this creature deals damage to an opponent, you may draw a card."$Totem armor| +Spawning Grounds|Commander 2018|163|R|{6}{G}{G}|Enchantment - Aura|||Enchant land$Enchanted land has "{T}: Create a 5/5 green Beast creature token with trample."| +Vow of Wildness|Commander 2018|164|U|{2}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +3/+3, has trample, and can't attack you or a planeswalker you control.| +Wild Growth|Commander 2018|165|C|{G}|Enchantment - Aura|||Enchant land$Whenever enchanted land is tapped for mana, its controller adds an additional {G}.| +Yavimaya Elder|Commander 2018|166|C|{1}{G}{G}|Creature - Human Druid|2|1|When Yavimaya Elder dies, you may search your library for up to two basic land cards, reveal them, and put them into your hand. If you do, shuffle your library.${2}, Sacrifice Yavimaya Elder: Draw a card.| +Yavimaya Enchantress|Commander 2018|167|C|{2}{G}|Creature - Human Druid|2|2|Yavimaya Enchantress gets +1/+1 for each enchantment on the battlefield.| +Aethermage's Touch|Commander 2018|168|R|{2}{W}{U}|Instant|||Reveal the top four cards of your library. You may put a creature card from among them onto the battlefield. It gains "At the beginning of your end step, return this creature to its owner's hand." Then put the rest of the cards revealed this way on the bottom of your library in any order.| +Bant Charm|Commander 2018|169|U|{G}{W}{U}|Instant|||Choose one —$• Destroy target artifact.$• Put target creature on the bottom of its owner's library.$• Counter target instant spell.| +Bruna, Light of Alabaster|Commander 2018|170|M|{3}{W}{W}{U}|Legendary Creature - Angel|5|5|Flying, vigilance$Whenever Bruna, Light of Alabaster attacks or blocks, you may attach to it any number of Auras on the battlefield and you may put onto the battlefield attached to it any number of Aura cards that could enchant it from your graveyard and/or hand.| +Charnelhoard Wurm|Commander 2018|171|R|{4}{B}{R}{G}|Creature - Wurm|6|6|Trample$Whenever Charnelhoard Wurm deals damage to an opponent, you may return target card from your graveyard to your hand.| +Cold-Eyed Selkie|Commander 2018|172|R|{1}{G/U}{G/U}|Creature - Merfolk Rogue|1|1|Islandwalk$Whenever Cold-Eyed Selkie deals combat damage to a player, you may draw that many cards.| +Daxos of Meletis|Commander 2018|173|R|{1}{W}{U}|Legendary Creature - Human Soldier|2|2|Daxos of Meletis can't be blocked by creatures with power 3 or greater.$Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library. You gain life equal to that card's converted mana cost. Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast that spell.| +Deathreap Ritual|Commander 2018|174|U|{2}{B}{G}|Enchantment|||Morbid — At the beginning of each end step, if a creature died this turn, you may draw a card.| +Decimate|Commander 2018|175|R|{2}{R}{G}|Sorcery|||Destroy target artifact, target creature, target enchantment, and target land.| +Duskmantle Seer|Commander 2018|176|R|{2}{U}{B}|Creature - Vampire Wizard|4|4|Flying$At the beginning of your upkeep, each player reveals the top card of their library, loses life equal to that card's converted mana cost, then puts it into their hand.| +Elderwood Scion|Commander 2018|177|R|{3}{G}{W}|Creature - Elemental|4|4|Trample, lifelink$Spells you cast that target Elderwood Scion cost {2} less to cast.$Spells your opponents cast that target Elderwood Scion cost {2} more to cast.| +Enigma Sphinx|Commander 2018|178|R|{4}{W}{U}{B}|Artifact Creature - Sphinx|5|4|Flying$When Enigma Sphinx is put into your graveyard from the battlefield, put it into your library third from the top.$Cascade| +Esper Charm|Commander 2018|179|U|{W}{U}{B}|Instant|||Choose one —$• Destroy target enchantment.$• Draw two cards.$• Target player discards two cards.| +Finest Hour|Commander 2018|180|R|{2}{G}{W}{U}|Enchantment|||Exalted$Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that creature. After this phase, there is an additional combat phase.| +Gaze of Granite|Commander 2018|181|R|{X}{B}{B}{G}|Sorcery|||Destroy each nonland permanent with converted mana cost X or less.| +Grisly Salvage|Commander 2018|182|C|{B}{G}|Instant|||Reveal the top five cards of your library. You may put a creature or land card from among them into your hand. Put the rest into your graveyard.| +High Priest of Penance|Commander 2018|183|R|{W}{B}|Creature - Human Cleric|1|1|Whenever High Priest of Penance is dealt damage, you may destroy target nonland permanent.| +Lavalanche|Commander 2018|184|R|{X}{B}{R}{G}|Sorcery|||Lavalanche deals X damage to target player or planeswalker and each creature that player or that planeswalker's controller controls.| +Maverick Thopterist|Commander 2018|185|U|{3}{U}{R}|Creature - Human Artificer|2|2|Improvise$When Maverick Thopterist enters the battlefield, create two 1/1 colorless Thopter artifact creature tokens with flying.| +Mortify|Commander 2018|186|U|{1}{W}{B}|Instant|||Destroy target creature or enchantment.| +Putrefy|Commander 2018|187|U|{1}{B}{G}|Instant|||Destroy target artifact or creature. It can't be regenerated.| +Righteous Authority|Commander 2018|188|R|{3}{W}{U}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 for each card in its controller's hand.$At the beginning of the draw step of enchanted creature's controller, that player draws an additional card.| +Rubblehulk|Commander 2018|189|R|{4}{R}{G}|Creature - Elemental|*|*|Rubblehulk's power and toughness are each equal to the number of lands you control.$Bloodrush — {1}{R}{G}, Discard Rubblehulk: Target attacking creature gets +X/+X until end of turn, where X is the number of lands you control.| +Savage Twister|Commander 2018|190|U|{X}{R}{G}|Sorcery|||Savage Twister deals X damage to each creature.| +Silent-Blade Oni|Commander 2018|191|R|{3}{U}{U}{B}{B}|Creature - Demon Ninja|6|5|Ninjutsu {4}{U}{B}$Whenever Silent-Blade Oni deals combat damage to a player, look at that player's hand. You may cast a nonland card in it without paying that card's mana cost.| +Unflinching Courage|Commander 2018|192|U|{1}{G}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +2/+2 and has trample and lifelink.| +Utter End|Commander 2018|193|R|{2}{W}{B}|Instant|||Exile target nonland permanent.| +Worm Harvest|Commander 2018|194|R|{2}{B/G}{B/G}{B/G}|Sorcery|||Create a 1/1 black and green Worm creature token for each land card in your graveyard.$Retrace| +Zendikar Incarnate|Commander 2018|195|U|{2}{R}{G}|Creature - Elemental|*|4|Zendikar Incarnate's power is equal to the number of lands you control.| +Azorius Signet|Commander 2018|196|U|{2}|Artifact|||{1}, {T}: Add {W}{U}.| +Blinkmoth Urn|Commander 2018|197|R|{5}|Artifact|||At the beginning of each player's precombat main phase, if Blinkmoth Urn is untapped, that player adds {C} for each artifact they control.| +Bosh, Iron Golem|Commander 2018|198|R|{8}|Legendary Artifact Creature - Golem|6|7|Trample${3}{R}, Sacrifice an artifact: Bosh, Iron Golem deals damage equal to the sacrificed artifact's converted mana cost to any target.| +Chief of the Foundry|Commander 2018|199|U|{3}|Artifact Creature - Construct|2|3|Other artifact creatures you control get +1/+1.| +Commander's Sphere|Commander 2018|200|C|{3}|Artifact|||{T}: Add one mana of any color in your commander's color identity.$Sacrifice Commander's Sphere: Draw a card.| +Crystal Ball|Commander 2018|201|U|{3}|Artifact|||{1}, {T}: Scry 2.| +Darksteel Juggernaut|Commander 2018|202|R|{5}|Artifact Creature - Juggernaut|*|*|Indestructible$Darksteel Juggernaut's power and toughness are each equal to the number of artifacts you control.$Darksteel Juggernaut attacks each combat if able.| +Dimir Signet|Commander 2018|203|U|{2}|Artifact|||{1}, {T}: Add {U}{B}.| +Dreamstone Hedron|Commander 2018|204|U|{6}|Artifact|||{T}: Add {C}{C}{C}.${3}, {T}, Sacrifice Dreamstone Hedron: Draw three cards.| +Duplicant|Commander 2018|205|R|{6}|Artifact Creature - Shapeshifter|2|4|Imprint — When Duplicant enters the battlefield, you may exile target nontoken creature.$As long as a card exiled with Duplicant is a creature card, Duplicant has the power, toughness, and creature types of the last creature card exiled with Duplicant. It's still a Shapeshifter.| +Hedron Archive|Commander 2018|206|U|{4}|Artifact|||{T}: Add {C}{C}.${2}, {T}, Sacrifice Hedron Archive: Draw two cards.| +Izzet Signet|Commander 2018|207|U|{2}|Artifact|||{1}, {T}: Add {U}{R}.| +Magnifying Glass|Commander 2018|208|U|{3}|Artifact|||{T}: Add {C}.${4}, {T}: Investigate.| +Mimic Vat|Commander 2018|209|R|{3}|Artifact|||Imprint — Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with Mimic Vat to its owner's graveyard.${3}, {T}: Create a token that's a copy of a card exiled with Mimic Vat. It gains haste. Exile it at the beginning of the next end step.| +Mind Stone|Commander 2018|210|C|{2}|Artifact|||{T}: Add {C}.${1}, {T}, Sacrifice Mind Stone: Draw a card.| +Mirrorworks|Commander 2018|211|R|{5}|Artifact|||Whenever another nontoken artifact enters the battlefield under your control, you may pay {2}. If you do, create a token that's a copy of that artifact.| +Myr Battlesphere|Commander 2018|212|R|{7}|Artifact Creature - Myr Construct|4|7|When Myr Battlesphere enters the battlefield, create four 1/1 colorless Myr artifact creature tokens.$Whenever Myr Battlesphere attacks, you may tap X untapped Myr you control. If you do, Myr Battlesphere gets +X/+0 until end of turn and deals X damage to the player or planeswalker it's attacking.| +Orzhov Signet|Commander 2018|213|U|{2}|Artifact|||{1}, {T}: Add {W}{B}.| +Pilgrim's Eye|Commander 2018|214|C|{3}|Artifact Creature - Thopter|1|1|Flying$When Pilgrim's Eye enters the battlefield, you may search your library for a basic land card, reveal it, put it into your hand, then shuffle your library.| +Prismatic Lens|Commander 2018|215|U|{2}|Artifact|||{T}: Add {C}.${1}, {T}: Add one mana of any color.| +Prototype Portal|Commander 2018|216|R|{4}|Artifact|||Imprint — When Prototype Portal enters the battlefield, you may exile an artifact card from your hand.${X}, {T}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card.| +Psychosis Crawler|Commander 2018|217|R|{5}|Artifact Creature - Horror|*|*|Psychosis Crawler's power and toughness are each equal to the number of cards in your hand.$Whenever you draw a card, each opponent loses 1 life.| +Scrabbling Claws|Commander 2018|218|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.| +Scuttling Doom Engine|Commander 2018|219|R|{6}|Artifact Creature - Construct|6|6|Scuttling Doom Engine can't be blocked by creatures with power 2 or less.$When Scuttling Doom Engine dies, it deals 6 damage to target opponent or planeswalker.| +Seer's Lantern|Commander 2018|220|C|{3}|Artifact|||{T}: Add {C}.| +Seer's Sundial|Commander 2018|221|R|{4}|Artifact|||Landfall — Whenever a land enters the battlefield under your control, you may pay {2}. If you do, draw a card.| +Sol Ring|Commander 2018|222|U|{1}|Artifact|||{T}: Add {C}{C}.| +Soul of New Phyrexia|Commander 2018|223|M|{6}|Artifact Creature - Avatar|6|6|Trample${5}: Permanents you control gain indestructible until end of turn.${5}, Exile Soul of New Phyrexia from your graveyard: Permanents you control gain indestructible until end of turn.| +Steel Hellkite|Commander 2018|224|R|{6}|Artifact Creature - Dragon|5|5|Flying${2}: Steel Hellkite gets +1/+0 until end of turn.${X}: Destroy each nonland permanent with converted mana cost X whose controller was dealt combat damage by Steel Hellkite this turn. Activate this ability only once each turn.| +Swiftfoot Boots|Commander 2018|225|U|{2}|Artifact - Equipment|||Equipped creature has hexproof and haste.$Equip {1}| +Thopter Assembly|Commander 2018|226|R|{6}|Artifact Creature - Thopter|5|5|Flying$At the beginning of your upkeep, if you control no Thopters other than Thopter Assembly, return Thopter Assembly to its owner's hand and create five 1/1 colorless Thopter artifact creature tokens with flying.| +Unstable Obelisk|Commander 2018|227|U|{3}|Artifact|||{T}: Add {C}.${7}, {T}, Sacrifice Unstable Obelisk: Destroy target permanent.| +Unwinding Clock|Commander 2018|228|R|{4}|Artifact|||Untap all artifacts you control during each other player's untap step.| +Vessel of Endless Rest|Commander 2018|229|U|{3}|Artifact|||When Vessel of Endless Rest enters the battlefield, put target card from a graveyard on the bottom of its owner's library.${T}: Add one mana of any color.| +Worn Powerstone|Commander 2018|230|U|{3}|Artifact|||Worn Powerstone enters the battlefield tapped.${T}: Add {C}{C}.| +Akoum Refuge|Commander 2018|231|U||Land|||Akoum Refuge enters the battlefield tapped.$When Akoum Refuge enters the battlefield, you gain 1 life.${T}: Add {B} or {R}.| +Arcane Sanctum|Commander 2018|232|U||Land|||Arcane Sanctum enters the battlefield tapped.${T}: Add {W}, {U}, or {B}.| +Azorius Chancery|Commander 2018|233|U||Land|||Azorius Chancery enters the battlefield tapped.$When Azorius Chancery enters the battlefield, return a land you control to its owner's hand.${T}: Add {W}{U}.| +Azorius Guildgate|Commander 2018|234|C||Land - Gate|||Azorius Guildgate enters the battlefield tapped.${T}: Add {W} or {U}.| +Barren Moor|Commander 2018|235|C||Land|||Barren Moor enters the battlefield tapped.${T}: Add {B}.$Cycling {B}| +Blighted Woodland|Commander 2018|236|U||Land|||{T}: Add {C}.${3}{G}, {T}, Sacrifice Blighted Woodland: Search your library for up to two basic land cards and put them onto the battlefield tapped. Then shuffle your library.| +Blossoming Sands|Commander 2018|237|C||Land|||Blossoming Sands enters the battlefield tapped.$When Blossoming Sands enters the battlefield, you gain 1 life.${T}: Add {G} or {W}.| +Bojuka Bog|Commander 2018|238|C||Land|||Bojuka Bog enters the battlefield tapped.$When Bojuka Bog enters the battlefield, exile all cards from target player's graveyard.${T}: Add {B}.| +Buried Ruin|Commander 2018|239|U||Land|||{T}: Add {C}.${2}, {T}, Sacrifice Buried Ruin: Return target artifact card from your graveyard to your hand.| +Command Tower|Commander 2018|240|C||Land|||{T}: Add one mana of any color in your commander's color identity.| +Darksteel Citadel|Commander 2018|241|U||Artifact Land|||Indestructible${T}: Add {C}.| +Dimir Aqueduct|Commander 2018|242|U||Land|||Dimir Aqueduct enters the battlefield tapped.$When Dimir Aqueduct enters the battlefield, return a land you control to its owner's hand.${T}: Add {U}{B}.| +Dimir Guildgate|Commander 2018|243|C||Land - Gate|||Dimir Guildgate enters the battlefield tapped.${T}: Add {U} or {B}.| +Dismal Backwater|Commander 2018|244|C||Land|||Dismal Backwater enters the battlefield tapped.$When Dismal Backwater enters the battlefield, you gain 1 life.${T}: Add {U} or {B}.| +Evolving Wilds|Commander 2018|245|C||Land|||{T}, Sacrifice Evolving Wilds: Search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library.| +Forgotten Cave|Commander 2018|246|C||Land|||Forgotten Cave enters the battlefield tapped.${T}: Add {R}.$Cycling {R}| +Forsaken Sanctuary|Commander 2018|247|U||Land|||Forsaken Sanctuary enters the battlefield tapped.${T}: Add {W} or {B}.| +Foundry of the Consuls|Commander 2018|248|U||Land|||{T}: Add {C}.${5}, {T}, Sacrifice Foundry of the Consuls: Create two 1/1 colorless Thopter artifact creature tokens with flying.| +Golgari Rot Farm|Commander 2018|249|U||Land|||Golgari Rot Farm enters the battlefield tapped.$When Golgari Rot Farm enters the battlefield, return a land you control to its owner's hand.${T}: Add {B}{G}.| +Great Furnace|Commander 2018|250|C||Artifact Land|||{T}: Add {R}.| +Grim Backwoods|Commander 2018|251|R||Land|||{T}: Add {C}.${2}{B}{G}, {T}, Sacrifice a creature: Draw a card.| +Gruul Turf|Commander 2018|252|U||Land|||Gruul Turf enters the battlefield tapped.$When Gruul Turf enters the battlefield, return a land you control to its owner's hand.${T}: Add {R}{G}.| +Halimar Depths|Commander 2018|253|C||Land|||Halimar Depths enters the battlefield tapped.$When Halimar Depths enters the battlefield, look at the top three cards of your library, then put them back in any order.${T}: Add {U}.| +Haunted Fengraf|Commander 2018|254|C||Land|||{T}: Add {C}.${3}, {T}, Sacrifice Haunted Fengraf: Return a creature card at random from your graveyard to your hand.| +Highland Lake|Commander 2018|255|U||Land|||Highland Lake enters the battlefield tapped.${T}: Add {U} or {R}.| +Izzet Boilerworks|Commander 2018|256|U||Land|||Izzet Boilerworks enters the battlefield tapped.$When Izzet Boilerworks enters the battlefield, return a land you control to its owner's hand.${T}: Add {U}{R}.| +Izzet Guildgate|Commander 2018|257|C||Land - Gate|||Izzet Guildgate enters the battlefield tapped.${T}: Add {U} or {R}.| +Jund Panorama|Commander 2018|258|C||Land|||{T}: Add {C}.${1}, {T}, Sacrifice Jund Panorama: Search your library for a basic Swamp, Mountain, or Forest card and put it onto the battlefield tapped. Then shuffle your library.| +Jungle Hollow|Commander 2018|259|C||Land|||Jungle Hollow enters the battlefield tapped.$When Jungle Hollow enters the battlefield, you gain 1 life.${T}: Add {B} or {G}.| +Jwar Isle Refuge|Commander 2018|260|U||Land|||Jwar Isle Refuge enters the battlefield tapped.$When Jwar Isle Refuge enters the battlefield, you gain 1 life.${T}: Add {U} or {B}.| +Kazandu Refuge|Commander 2018|261|U||Land|||Kazandu Refuge enters the battlefield tapped.$When Kazandu Refuge enters the battlefield, you gain 1 life.${T}: Add {R} or {G}.| +Khalni Garden|Commander 2018|262|C||Land|||Khalni Garden enters the battlefield tapped.$When Khalni Garden enters the battlefield, create a 0/1 green Plant creature token.${T}: Add {G}.| +Krosan Verge|Commander 2018|263|U||Land|||Krosan Verge enters the battlefield tapped.${T}: Add {C}.${2}, {T}, Sacrifice Krosan Verge: Search your library for a Forest card and a Plains card and put them onto the battlefield tapped. Then shuffle your library.| +Lonely Sandbar|Commander 2018|264|C||Land|||Lonely Sandbar enters the battlefield tapped.${T}: Add {U}.$Cycling {U}| +Meandering River|Commander 2018|265|U||Land|||Meandering River enters the battlefield tapped.${T}: Add {W} or {U}.| +Mortuary Mire|Commander 2018|266|C||Land|||Mortuary Mire enters the battlefield tapped.$When Mortuary Mire enters the battlefield, you may put target creature card from your graveyard on top of your library.${T}: Add {B}.| +Mosswort Bridge|Commander 2018|267|R||Land|||Hideaway${T}: Add {G}.${G}, {T}: You may play the exiled card without paying its mana cost if creatures you control have total power 10 or greater.| +Mountain Valley|Commander 2018|268|U||Land|||Mountain Valley enters the battlefield tapped.${T}, Sacrifice Mountain Valley: Search your library for a Mountain or Forest card and put it onto the battlefield. Then shuffle your library.| +Myriad Landscape|Commander 2018|269|U||Land|||Myriad Landscape enters the battlefield tapped.${T}: Add {C}.${2}, {T}, Sacrifice Myriad Landscape: Search your library for up to two basic land cards that share a land type, put them onto the battlefield tapped, then shuffle your library.| +New Benalia|Commander 2018|270|U||Land|||New Benalia enters the battlefield tapped.$When New Benalia enters the battlefield, scry 1.${T}: Add {W}.| +Orzhov Basilica|Commander 2018|271|U||Land|||Orzhov Basilica enters the battlefield tapped.$When Orzhov Basilica enters the battlefield, return a land you control to its owner's hand.${T}: Add {W}{B}.| +Orzhov Guildgate|Commander 2018|272|C||Land - Gate|||Orzhov Guildgate enters the battlefield tapped.${T}: Add {W} or {B}.| +Rakdos Carnarium|Commander 2018|273|C||Land|||Rakdos Carnarium enters the battlefield tapped.$When Rakdos Carnarium enters the battlefield, return a land you control to its owner's hand.${T}: Add {B}{R}.| +Rocky Tar Pit|Commander 2018|274|U||Land|||Rocky Tar Pit enters the battlefield tapped.${T}, Sacrifice Rocky Tar Pit: Search your library for a Swamp or Mountain card and put it onto the battlefield. Then shuffle your library.| +Savage Lands|Commander 2018|275|U||Land|||Savage Lands enters the battlefield tapped.${T}: Add {B}, {R}, or {G}.| +Scoured Barrens|Commander 2018|276|C||Land|||Scoured Barrens enters the battlefield tapped.$When Scoured Barrens enters the battlefield, you gain 1 life.${T}: Add {W} or {B}.| +Seaside Citadel|Commander 2018|277|U||Land|||Seaside Citadel enters the battlefield tapped.${T}: Add {G}, {W}, or {U}.| +Seat of the Synod|Commander 2018|278|C||Artifact Land|||(Seat of the Synod isn't a spell.)${T}: Add {U}.| +Secluded Steppe|Commander 2018|279|C||Land|||Secluded Steppe enters the battlefield tapped.${T}: Add {W}.$Cycling {W}| +Sejiri Refuge|Commander 2018|280|U||Land|||Sejiri Refuge enters the battlefield tapped.$When Sejiri Refuge enters the battlefield, you gain 1 life.${T}: Add {W} or {U}.| +Selesnya Sanctuary|Commander 2018|281|C||Land|||Selesnya Sanctuary enters the battlefield tapped.$When Selesnya Sanctuary enters the battlefield, return a land you control to its owner's hand.${T}: Add {G}{W}.| +Simic Growth Chamber|Commander 2018|282|U||Land|||Simic Growth Chamber enters the battlefield tapped.$When Simic Growth Chamber enters the battlefield, return a land you control to its owner's hand.${T}: Add {G}{U}.| +Submerged Boneyard|Commander 2018|283|U||Land|||Submerged Boneyard enters the battlefield tapped.${T}: Add {U} or {B}.| +Swiftwater Cliffs|Commander 2018|284|C||Land|||Swiftwater Cliffs enters the battlefield tapped.$When Swiftwater Cliffs enters the battlefield, you gain 1 life.${T}: Add {U} or {R}.| +Temple of the False God|Commander 2018|285|U||Land|||{T}: Add {C}{C}. Activate this ability only if you control five or more lands.| +Terramorphic Expanse|Commander 2018|286|C||Land|||{T}, Sacrifice Terramorphic Expanse: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library.| +Thornwood Falls|Commander 2018|287|C||Land|||Thornwood Falls enters the battlefield tapped.$When Thornwood Falls enters the battlefield, you gain 1 life.${T}: Add {G} or {U}.| +Tranquil Cove|Commander 2018|288|C||Land|||Tranquil Cove enters the battlefield tapped.$When Tranquil Cove enters the battlefield, you gain 1 life.${T}: Add {W} or {U}.| +Tranquil Expanse|Commander 2018|289|U||Land|||Tranquil Expanse enters the battlefield tapped.${T}: Add {G} or {W}.| +Tranquil Thicket|Commander 2018|290|C||Land|||Tranquil Thicket enters the battlefield tapped.${T}: Add {G}.$Cycling {G}| +Warped Landscape|Commander 2018|291|C||Land|||{T}: Add {C}.${2}, {T}, Sacrifice Warped Landscape: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library.| +Woodland Stream|Commander 2018|292|C||Land|||Woodland Stream enters the battlefield tapped.${T}: Add {G} or {U}.| +Plains|Commander 2018|293|C||Basic Land - Plains|||({T}: Add {W}.)| +Plains|Commander 2018|294|C||Basic Land - Plains|||({T}: Add {W}.)| +Plains|Commander 2018|295|C||Basic Land - Plains|||({T}: Add {W}.)| +Island|Commander 2018|296|C||Basic Land - Island|||({T}: Add {U}.)| +Island|Commander 2018|297|C||Basic Land - Island|||({T}: Add {U}.)| +Island|Commander 2018|298|C||Basic Land - Island|||({T}: Add {U}.)| +Swamp|Commander 2018|299|C||Basic Land - Swamp|||({T}: Add {B}.)| +Swamp|Commander 2018|300|C||Basic Land - Swamp|||({T}: Add {B}.)| +Swamp|Commander 2018|301|C||Basic Land - Swamp|||({T}: Add {B}.)| +Mountain|Commander 2018|302|C||Basic Land - Mountain|||({T}: Add {R}.)| +Mountain|Commander 2018|303|C||Basic Land - Mountain|||({T}: Add {R}.)| +Mountain|Commander 2018|304|C||Basic Land - Mountain|||({T}: Add {R}.)| +Forest|Commander 2018|305|C||Basic Land - Forest|||({T}: Add {G}.)| +Forest|Commander 2018|306|C||Basic Land - Forest|||({T}: Add {G}.)| +Forest|Commander 2018|307|C||Basic Land - Forest|||({T}: Add {G}.)| +Bludgeoning Pain|Star Wars|300|C|{1}{B}|Instant|||Target creature gets -2/-2 until end of turn. Tap that creature.| +Bor Gullet|Star Wars|301|U|{3}{U}{B}|Creature - Horror Cephalid|4|4|When Bor Gullet enters the battlefield, target opponent reveals his or her hand. You choose a card from it. That player discards that card.| +Chirrut Imwe|Star Wars|302|R|{G}{W}{U}|Legendary Creature - Human Monk|3|3|Chirrut Imwe can block up to two additional creatures.${1}{W}: Prevent all combat damage that would be dealt to Chirrut Imwe until end of turn.| +Director Krennic|Star Wars|303|R|{3}{B}{B}|Legendary Creature - Human Advisor|3|4|When Director Krennic enters the battlefield, create two 1/1 black Trooper creature tokens.$When Director Krennic leaves the battlefield, destroy target basic land.| +Force Protection|Star Wars|304|C|{W}|Instant|||Target creature you control gains protection from color of your choice until end of turn. Scry 1.| +Gerrera's Revolutionary|Star Wars|305|C|{R}|Creature - Barabel Rebel|2|1|Gerrera's Revolutionary attacks each turn if able.| +Hammerhead Corvette|Star Wars|306|U|{3}{G}|Artifact Creature - Rebel Starship|3|3|Spaceflight$Whenever Hammerhead Corvette attacks, you may untap target Starship creature defending player controls and have that creature block Hammerhead Corvette this turn if able.| +Imperial Hovertank|Star Wars|307|U|{4}{W}{B}|Artifact Creature - Trooper Construct|4|4|Whenever a Trooper creature you control attacks, defending player loses 1 life and you gain 1 life.| +Jyn Erso and Cassian Andor|Star Wars|308|R|{2}{R}{W}|Legendary Creature - Human Rebel|4|4|At the beginning of combat on your turn, target creature gets +1/+0 and gains haste until end of turn.| +Occupation|Star Wars|309|U|{W}{B}|Enchantment|||Creatures your opponents control enter the battlefield tapped.${W}{B}: Target creature can't attack or block this turn, and its activated abilities can't be activated until end of turn.| +Resistance|Star Wars|310|U|{R}{W}|Enchantment|||Whenever a creature enters the battlefield under your control, Resistance deals 1 damage to each opponent.${R}{W}: Target creature gains haste until end of turn and must attack or block this turn if able.| +Thermal Detonator|Star Wars|311|C|{1}|Artifact|||{2}, Sacrifice Thermal Detonator: Thermal Detonator deals 2 damage to target creature without spaceflight or target player.| +TIE Striker|Star Wars|312|C|{1}{B}|Artifact Creature - Starship|2|1|Spaceflight| +U-Wing|Star Wars|313|U|{2}{U}|Artifact Creature - Rebel Starship|2|2|Spaceflight$As long as U-Wing is tapped, it gets +1/+0.$As long as U-Wing is untapped, it gets +0/+1.| +Vader's Command|Star Wars|314|R|{2}{B}{B}|Instant|||Choose two -$ Counter target spell unless its controller pays 5 life.$ Destroy target planeswalker.$ Destroy target nonartifact creature.$ Gain 5 life.| +Astromech Droid|Star Wars|400|C|{W}|Artifact Creature - Droid|0|1|{T}: Target starship creature you control gets +1/+1 and gains vigilance until end of turn.$Repair 4| +Buried Ruin|Star Wars|401|C||Land|||{T}: Add {1} to your mana pool.${2}, {T}, Sacrifice Buried Ruin: Return target artifact card from your graveyard to your hand.| +Finn|Star Wars|402|U|{3}{G}|Legendary Creature - Human Trooper Soldier|3|3|Whenever Finn or another nontoken creature you control enters the battlefield under your control, you gain 1 life for each nontoken creature you control.| +Flame Trooper|Star Wars|403|C|{2}{R}|Creature - Human Trooper|2|2|Trooper creatures you control have menace.| +Force Stasis|Star Wars|404|C|{1}{U}|Instant|||Choose one -$ Tap target creature. It doesn't untap during its controller's next untap step.$ Return target instant or sorcery spell you don't control to its owner's hand.| +General Hux|Star Wars|405|U|{3}{B}|Legendary Creature - Human Advisor|3|3|Whenever General Hux or another nontoken creature enters the battlefield under your control, until end of turn, target creature gains "{B}: This creature gets +1/+1 until end of turn."| +Kylo Ren|Star Wars|406|M|{1}{U}{B}{R}|Legendary Creature - Human Sith|3|3|Haste, first strike$Kylo Ren attacks each turn if able.$Whenever Kylo Ren attacks, it gets +1/+0 for each creature in your graveyard and you may tap target creature defending player controls.| +Outer Rim Gang|Star Wars|407|C|{2}{B}{R}{G}|Creature - Human Rogue Hunter|4|4|When Outer Rim Gang enters the battlefield, each creature with a bounty counter on it gets -2/-2 until end of turn.| +Poe Dameron|Star Wars|408|U|{3}{W}|Legendary Creature - Human Soldier|3|3|Whenever Poe Dameron or another nontoken creature enters the battlefield under your control, starship creatures you control get +1/+1 until end of turn.| +Rathtar|Star Wars|409|C|{2}{R}{G}|Creature - Beast|4|4|{5}{G}{G}: Monstrosity 2.$When Rathtar becomes monstrous, any number of target creatures must block it this turn if able.| +Rey|Star Wars|410|R|{G}{W}{U}|Legendary Creature - Human Knight|3|3|Vigilance, first strike$Whenever Rey enters or leaves the battlefield, reveal the top card of target player's library. You gain life equal to that card's converted mana cost.| +Riot Trooper|Star Wars|411|C|{2}{W}|Creature - Human Trooper|2|2|Each trooper creature you control can block an additional creature each combat.| +Salvage Trader|Star Wars|412|C|{3}{U}|Creature - Crolute|2|3|{T}: Exchange control of target artifact you control and target artifact an opponent controls with the same converted mana cost.| +Sins of the Father|Star Wars|413|C|{1}{B}|Sorcery|||Exile target player's graveyard. That player loses 1 life for each instant or sorcery card exiled this way.| +Upsilon-class Shuttle|Star Wars|414|C|{5}|Artifact Creature - Starship|2|3|Spaceflight$Whenever Upsilon-class Shuttle attacks, target creature you control gains spaceflight until end of turn.| +Canto Bight Enforcer|Star Wars|500|U|{1}{B}|Creature - Human Hunter|2|2|When Canto Bight Enforcer enters the battlefield, you may put a bounty counter on target creature.$Bounty - Whenever a creature an opponent controls with a bounty counter on it dies, put a +1/+1 counter on Canto Bight Enforcer.| +Cantonica Casino|Star Wars|501|R|{2}|Artifact|||{T}: Roll two six-sided dice. If you roll doubles, gain 10 life. Otherwise, lose 1 life.| +Captain Phasma|Star Wars|502|R|{4}{W}|Legendary Creature - Human Trooper|4|4|Nontoken Trooper creatures you control have "When this creature enters the battlefield, creature 1/1/ white Trooper creature token."${W}{U}{B}{R}{G}: Search your library for a Trooper creature card, reveal it, put it into your hand, then shuffle your library.| +Code Slice|Star Wars|503|C|{R}|Sorcery|||Put a bounty counter on target creature.$Artifact creatures with bounty counters on them can't block this turn.| +Delay Tactic|Star Wars|504|C|{1}{U}|Instant|||Choose one -$ Creatures you control gain hexproof until end of turn.$ Creatures target opponent controls don't untap during his or her next untap step.| +Fathier|Star Wars|505|C|{2}{R}{R}|Creature - Beast|3|3|Haste${4}{R}{R}: Monstrosity 2.| +First Order Dreadnought|Star Wars|506|M|{4}{B}{B}|Artifact Creature - Starship|5|6|Spaceflight${2}{B}, {T}: Destroy target creature.| +Force Projection|Star Wars|507|R|{1}{U}{U}|Sorcery|||Create a token that is a copy of target creature except that it is an Illusion in addition to its other types and gains "When this creature becomes the target of a spell, sacrifice it."$Scry 2.| +Force Telepathy|Star Wars|508|C|{UB}|Instant|||Target player reveals his or her hand.$Scry 2| +Glorious Charge|Star Wars|509|C|{1}{W}|Instant|||Creatures you control get +1/+1 until end of turn.| +Inspire|Star Wars|510|C|{1}{U}|Instant|||Untap target creature.$Draw a card.| +Luke Skywalker, the Last Jedi|Star Wars|511|M|{2}{G}{W}|Legendary Planeswalker - Luke|||+1: Put two +1/+1 counters on up to one target creature.$-3: Put target noncreature permanent on top of its owner's library.$-6: You get an emblem with "Prevent all damage that would be dealt to you during combat." Exile Luke Skywalker, the Last Jedi.| +Mouse Droid|Star Wars|512|C|{1}{U}|Artifact Creature - Droid|0|1|When Mouse Droid dies, draw a card.$Repair 3| +Porg Nest|Star Wars|513|U|{2}{G}|Creature - Bird|0|2|Defender$At the beginning of your upkeep, create a 0/1 green Bird creature token named Porg with "{G}: Monstrosity 1."| +Praetorian Trooper|Star Wars|514|R|{3}{R}|Creature - Human Trooper|2|2|Trooper creatures you control have double strike.| +Resistance Bomber|Star Wars|515|U|{3}{R}|Artifact Creature - Rebel Starship|2|2|Spaceflight$Resistance Bomber enters the battlefield with a charge counter on it.$Remove a charge counter from Resistance Bomber: Resistance Bomber deals 5 damage to target creature. Activate this ability only if Resistance Bomber is attacking.| +Sai Tok|Star Wars|516|U|{B}{B}|Instant|||Destroy target creature or planeswalker if it has converted mana cost 4 or less.| +Supreme Leader Snoke|Star Wars|517|M|{U}{B}{R}|Legendary Planeswalker - Snoke|||+1: Put a loyalty counter on Supreme Leader Snoke for each life lost by all opponents from noncombat sources this turn.$-1: Draw a card and lose 1 life.$-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.| +TIE Silencer|Star Wars|518|R|{1}{B}{R}|Artifact Creature - Starship|2|2|Haste$Spaceflight$Whenever TIE Silencer attacks, it deals 1 damage to defending player and 1 damage to up to one target creature that player controls.| +Vulptex|Star Wars|519|C|{1}{W}|Creature - Fox|1|1|When Vulptex enters the battlefield, put a +1/+1 counter on target creature.| +Afterburn|Star Wars|600|C|{R}|Instant|||Choose One -$ Target creature gains haste and first strike until end of turn.$ Remove target creature from combat.| +Chewbacca, the Beast|Star Wars|601|R|{1}{G}{G}|Legendary Creature - Wookie Warrior|3|3|Partner with Han Solo, Scrumrat$Whenever Chewbacca, the Beast attacks, another target attacking creature you control gains indestructible until end of turn.| +Conscription|Star Wars|602|U|{2}{U}{U}|Sorcery|||Gain control of target creature with power 2 or less. It becomes a Trooper in addition to its other types.| +Corellian Gunship|Star Wars|603|C|{R}|Artifact Creature - Starship|1|1|Spaceflight$When Corellian Gunship enters the battlefield, it deals 1 damage to target player or planeswalker.| +Despair|Star Wars|604|U|{B}{B}|Instant|||Each opponent sacrifices a creature.| +Droid Uprising|Star Wars|605|U|{2}{W}{W}|Instant|||Tap all nonartifact creatures.$Create two colorless 1/1 Droid artifact creature tokens.| +Dryden Vos|Star Wars|606|R|{1}{B}{R}|Legendary Creature - Human Rogue|2|3|Menace$When Dryden Vos enters the battlefield, put a bounty counter on target creature.$Bounty - Whenever a creature an opponent controls with a bounty counter on it dies, Dryden Vos deals 2 damage to any target.| +Enfys Nest|Star Wars|607|M|{G}{W}|Legendary Creature - Human Rebel|2|1|Vigilance$Whenever Enfys Nest enters the battlefield, you may exile target creature an opponent controls. If you do, that player gains life equal to that creature's power.| +Gamble|Star Wars|608|R|{R}|Sorcery|||Search you library for a card, put that card into your hand, discard a card at random, then shuffle your library.| +Han Solo, Scrumrat|Star Wars|609|R|{2}{W}|Legendary Creature - Human Rogue|2|2|Partner with Chewbacca, the Beast$R: Han Solo, Scrumrat gains first strike until end of turn.$Whenever Han Solo, Scrumrat deals damage during your turn, put a +1/+1 counter on another target creature you control.| +Kalevan Star Yacht|Star Wars|610|U|{3}{B}|Artifact Creature - Starship|2|3|Spaceflight$When Kalevan Star Yacht enters the battlefield, lose 1 life, draw a card, and put a bounty counter on up to one target creature.| +Maelstrom Blockade|Star Wars|611|C|{2}{WB}|Instant|||Exile target attacking creature.| +Mud Trooper|Star Wars|612|U|{B}|Creature - Human Trooper|1|1|Trooper creatures you control have "2: This creature gets +1/+1 until end of turn."| +Range Trooper|Star Wars|613|U|{3}{W}|Creature - Human Trooper|2|2|Trooper creatures you control have "When this creature enters that battlefield, you may exile target creature. Return that creature to the battlefield at the beginning of the next end step."| +Tobias Beckett|Star Wars|614|R|{3}{B}|Legendary Creature - Human Hunter|4|3|When Tobias Becket enters the battlefield, put a bounty counter on target creature an opponent controls.$Bounty - Whenever a creature an opponent controls with a bounty counter on it dies, exile the top card of that player's library. You may cast cards exiled this way and spend mana as though it were mana of any type to cast that spell.| +Underground Forum|Star Wars|615|U||Land|||T: Add {1}.${1}, {T}: Add {B}, {R}, or {G}.${2}, {T}: Put a bounty counter on target creature.| diff --git a/Utils/mtg-sets-data.txt b/Utils/mtg-sets-data.txt index 06444e06953..6cbde344ad8 100644 --- a/Utils/mtg-sets-data.txt +++ b/Utils/mtg-sets-data.txt @@ -32,10 +32,12 @@ Commander 2014 Edition|C14| Commander 2015 Edition|C15| Commander 2016 Edition|C16| Commander 2017 Edition|C17| +Commander 2018 Edition|C18| Champions of Kamigawa|CHK| Chronicles|CHR| Clash Pack|CLASH| Commander Anthology|CMA| +Commander Anthology 2018|CM2| Commander's Arsenal|CM1| Conspiracy: Take the Crown|CN2| Conflux|CON| diff --git a/pom.xml b/pom.xml index 75753c635b3..39d6abf21b4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.mage mage-root - 1.4.30 + 1.4.31 pom Mage Root Mage Root POM @@ -84,7 +84,7 @@ - 1.4.30 + 1.4.31 UTF-8