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 c232330d94d..e964ed8d417 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 @@ -40,6 +40,7 @@ import java.util.HashMap; import java.util.Map; import java.util.prefs.Preferences; import mage.client.MageFrame; +import mage.client.dialog.PreferencesDialog; import mage.remote.Connection; import mage.remote.Connection.ProxyType; import org.jsoup.Jsoup; @@ -56,6 +57,7 @@ public class WizardCardsImageSource implements CardImageSource { private static CardImageSource instance; private static Map setsAliases; + private static Map languageAliases; private final Map> sets; public static CardImageSource getInstance() { @@ -236,42 +238,30 @@ public class WizardCardsImageSource implements CardImageSource { setsAliases.put("WTH", "Weatherlight"); setsAliases.put("WWK", "Worldwake"); setsAliases.put("ZEN", "Zendikar"); + + languageAliases = new HashMap<>(); + languageAliases.put("es", "Spanish"); + languageAliases.put("jp", "Japanese"); + languageAliases.put("it", "Italian"); + languageAliases.put("fr", "French"); + languageAliases.put("cn", "Chinese Simplified"); + languageAliases.put("de", "German"); + } private Map getSetLinks(String cardSet) { Map setLinks = new HashMap<>(); try { String setNames = setsAliases.get(cardSet); - Preferences prefs = MageFrame.getPreferences(); - Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None")); + String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); for (String setName : setNames.split("\\^")) { String URLSetName = URLEncoder.encode(setName, "UTF-8"); - String urlDocument; int page = 0; int firstMultiverseIdLastPage = 0; Pages: while (page < 999) { - Document doc; - if (proxyType.equals(ProxyType.NONE)) { - urlDocument = "http://gatherer.wizards.com/Pages/Search/Default.aspx?page=" + page +"&output=spoiler&method=visual&action=advanced&set=+[%22" + URLSetName + "%22]"; - doc = Jsoup.connect(urlDocument).get(); - } else { - String proxyServer = prefs.get("proxyAddress", ""); - int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0")); - URL url = new URL("http://gatherer.wizards.com/Pages/Search/Default.aspx?page=" + page +"&output=spoiler&method=visual&action=advanced&set=+[%22" + URLSetName + "%22]"); - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort)); - HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy); - - 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)); - } + String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?page=" + page +"&output=spoiler&method=visual&action=advanced&set=+[%22" + URLSetName + "%22]"; + Document doc = getDocument(searchUrl); Elements cardsImages = doc.select("img[src^=../../Handlers/]"); if (cardsImages.isEmpty()) { @@ -279,8 +269,8 @@ public class WizardCardsImageSource implements CardImageSource { } for (int i = 0; i < cardsImages.size(); i++) { + Integer multiverseId = Integer.parseInt(cardsImages.get(i).attr("src").replaceAll("[^\\d]", "")); if (i == 0) { - Integer multiverseId = Integer.parseInt(cardsImages.get(i).attr("src").replaceAll("[^\\d]", "")); if (multiverseId == firstMultiverseIdLastPage) { break Pages; } @@ -289,23 +279,10 @@ public class WizardCardsImageSource implements CardImageSource { String cardName = normalizeName(cardsImages.get(i).attr("alt")); if (cardName != null && !cardName.isEmpty()) { if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island") || cardName.equals("Plains")) { - Integer multiverseId = Integer.parseInt(cardsImages.get(i).attr("src").replaceAll("[^\\d]", "")); - String urlLandDocument = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId; - Document landDoc = Jsoup.connect(urlLandDocument).get(); - Elements variations = landDoc.select("a.variationlink"); - if(!variations.isEmpty()) { - int landNumber = 1; - for (Element variation : variations) { - Integer landMultiverseId = Integer.parseInt(variation.attr("onclick").replaceAll("[^\\d]", "")); - // "" - setLinks.put((cardName + landNumber).toLowerCase(), "/Handlers/Image.ashx?multiverseid=" +landMultiverseId + "&type=card"); - landNumber++; - } - } else { - setLinks.put(cardName.toLowerCase(), cardsImages.get(i).attr("src").substring(5)); - } + setLinks.putAll(getLandVariations(multiverseId, cardName)); } else { - setLinks.put(cardName.toLowerCase(), cardsImages.get(i).attr("src").substring(5)); + Integer preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId); + setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId)); } } } @@ -318,6 +295,85 @@ public class 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.equals(ProxyType.NONE)) { + doc = Jsoup.connect(urlString).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.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 Map getLandVariations(Integer multiverseId, String cardName) throws IOException, NumberFormatException { + String urlLandDocument = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId; + Document landDoc = getDocument(urlLandDocument); + Elements variations = landDoc.select("a.variationlink"); + Map links = new HashMap<>(); + if(!variations.isEmpty()) { + int landNumber = 1; + for (Element variation : variations) { + Integer landMultiverseId = Integer.parseInt(variation.attr("onclick").replaceAll("[^\\d]", "")); + links.put((cardName + landNumber).toLowerCase(), generateLink(landMultiverseId)); + landNumber++; + } + } else { + links.put(cardName.toLowerCase(), generateLink(multiverseId)); + } + + return links; + } + + private static String generateLink(Integer landMultiverseId) { + return "/Handlers/Image.ashx?multiverseid=" +landMultiverseId + "&type=card"; + } + + private Integer getLocalizedMultiverseId(String preferedLanguage, Integer multiverseId) throws IOException { + if (preferedLanguage.equals("en")) { + return multiverseId; + } + + String languageName = languageAliases.get(preferedLanguage); + HashMap localizedLanguageIds = getlocalizedMultiverseIds(multiverseId); + if (localizedLanguageIds.containsKey(languageName)) { + return localizedLanguageIds.get(languageName); + } else { + return multiverseId; + } + } + + private HashMap getlocalizedMultiverseIds(Integer englishMultiverseId) throws IOException { + String cardLanguagesUrl = "http://gatherer.wizards.com/Pages/Card/Languages.aspx?multiverseid=" + englishMultiverseId; + Document cardLanguagesDoc = getDocument(cardLanguagesUrl); + Elements languageTableRows = cardLanguagesDoc.select("tr.cardItem"); + HashMap localizedIds = new HashMap<>(); + if(!languageTableRows.isEmpty()) { + for (Element languageTableRow : languageTableRows) { + Elements languageTableColumns = languageTableRow.select("td"); + Integer localizedId = Integer.parseInt(languageTableColumns.get(0).select("a").first().attr("href").replaceAll("[^\\d]", "")); + String languageName = languageTableColumns.get(1).text().trim(); + localizedIds.put(languageName, localizedId); + } + } + return localizedIds; + } + private String normalizeName(String name) { //Split card if(name.contains("//")) { 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 c4ffa94f69b..0c61f379f4f 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 @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.imageio.IIOImage; @@ -572,7 +573,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab // Logger.getLogger(this.getClass()).info(url.toString()); URLConnection httpConn = url.openConnection(p); // images download from magiccards.info may not work with default 'User-Agent: Java/1.x.x' request header - httpConn.setRequestProperty("User-Agent", ""); + httpConn.setRequestProperty("User-Agent", UUID.randomUUID().toString()); httpConn.connect(); int responseCode = ((HttpURLConnection) httpConn).getResponseCode(); if (responseCode == 200) { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Eternal.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Eternal.java new file mode 100644 index 00000000000..85094dceb64 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Eternal.java @@ -0,0 +1,662 @@ +/* +* Copyright 2011 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.deck; + +import mage.cards.decks.Constructed; + +/** + * This class implements the new casual format "Eternal", which is legacy with no reserved list cards legal. + * Banlist taken from + * + * @author marthinwurer@gmail.com + */ +public class Eternal extends Constructed { + + public Eternal() { + super("Constructed - Eternal"); + + banned.add("Abeyance"); + banned.add("Aboroth"); + banned.add("Academy Rector"); + banned.add("Acid Rain"); + banned.add("Acidic Dagger"); + banned.add("Adun Oakenshield"); + banned.add("Advantageous Proclamation"); + banned.add("Aegis of the Meek"); + banned.add("Aeolipile"); + banned.add("Afiya Grove"); + banned.add("Aku Djinn"); + banned.add("Al-abara's Carpet"); + banned.add("Alchor's Tomb"); + banned.add("Ali from Cairo"); + banned.add("All Hallow's Eve"); + banned.add("Altar of Bone"); + banned.add("Aluren"); + banned.add("Amulet of Quoz"); + banned.add("Amulet of Unmaking"); + banned.add("An-Zerrin Ruins"); + banned.add("Anaba Ancestor"); + banned.add("Anaba Spirit Crafter"); + banned.add("Ancestral Knowledge"); + banned.add("Ancestral Recall"); + banned.add("Angus Mackenzie"); + banned.add("Anvil of Bogardan"); + banned.add("Apocalypse Chime"); + banned.add("Apocalypse"); + banned.add("Argivian Archaeologist"); + banned.add("Argothian Wurm"); + banned.add("Ashnod's Cylix"); + banned.add("Asmira, Holy Avenger"); + banned.add("Auspicious Ancestor"); + banned.add("Autumn Willow"); + banned.add("Avenging Angel"); + banned.add("Avizoa"); + banned.add("Aysen Crusader"); + banned.add("Aysen Highway"); + banned.add("Backup Plan"); + banned.add("Badlands"); + banned.add("Baki's Curse"); + banned.add("Balance"); + banned.add("Balduvian Hydra"); + banned.add("Balduvian Trading Post"); + banned.add("Balm of Restoration"); + banned.add("Baron Sengir"); + banned.add("Barreling Attack"); + banned.add("Barrin, Master Wizard"); + banned.add("Bartel Runeaxe"); + banned.add("Bayou"); + banned.add("Bazaar of Baghdad"); + banned.add("Bazaar of Wonders"); + banned.add("Beast Walkers"); + banned.add("Benthic Djinn"); + banned.add("Black Carriage"); + banned.add("Black Lotus"); + banned.add("Blaze of Glory"); + banned.add("Blizzard"); + banned.add("Bogardan Phoenix"); + banned.add("Bone Dancer"); + banned.add("Bone Mask"); + banned.add("Boris Devilboon"); + banned.add("Bosium Strip"); + banned.add("Brago's Favor"); + banned.add("Braingeyser"); + banned.add("Brand of Ill Omen"); + banned.add("Breathstealer's Crypt"); + banned.add("Bronze Tablet"); + banned.add("Brushwagg"); + banned.add("Bubble Matrix"); + banned.add("Cadaverous Bloom"); + banned.add("Call to Arms"); + banned.add("Candelabra of Tawnos"); + banned.add("Canopy Dragon"); + banned.add("Carnival of Souls"); + banned.add("Carrion"); + banned.add("Catacomb Dragon"); + banned.add("Caverns of Despair"); + banned.add("Chain Stasis"); + banned.add("Chains of Mephistopheles"); + banned.add("Channel"); + banned.add("Chaos Harlequin"); + banned.add("Chaos Orb"); + banned.add("Chaosphere"); + banned.add("Chromatic Armor"); + banned.add("Chronatog"); + banned.add("Circle of Despair"); + banned.add("Citanul Centaurs"); + banned.add("Citanul Druid"); + banned.add("City in a Bottle"); + banned.add("City of Shadows"); + banned.add("City of Solitude"); + banned.add("City of Traitors"); + banned.add("Cleanse"); + banned.add("Cleansing"); + banned.add("Commander Greven il-Vec"); + banned.add("Conch Horn"); + banned.add("Contract from Below"); + banned.add("Copy Artifact"); + banned.add("Corpse Dance"); + banned.add("Corrosion"); + banned.add("Covetous Dragon"); + banned.add("Crovax the Cursed"); + banned.add("Cursed Scroll"); + banned.add("Cycle of Life"); + banned.add("Cyclopean Tomb"); + banned.add("Damping Field"); + banned.add("Darkpact"); + banned.add("Daughter of Autumn"); + banned.add("Debt of Loyalty"); + banned.add("Delif's Cube"); + banned.add("Demonic Attorney"); + banned.add("Demonic Consultation"); + banned.add("Demonic Hordes"); + banned.add("Demonic Tutor"); + banned.add("Deranged Hermit"); + banned.add("Diamond Kaleidoscope"); + banned.add("Diamond Valley"); + banned.add("Didgeridoo"); + banned.add("Dig Through Time"); + banned.add("Discordant Spirit"); + banned.add("Disharmony"); + banned.add("Divine Intervention"); + banned.add("Divine Retribution"); + banned.add("Dominating Licid"); + banned.add("Donate"); + banned.add("Double Stroke"); + banned.add("Draconian Cylix"); + banned.add("Dream Halls"); + banned.add("Drop of Honey"); + banned.add("Dwarven Armorer"); + banned.add("Dwarven Pony"); + banned.add("Dwarven Sea Clan"); + banned.add("Dwarven Thaumaturgist"); + banned.add("Dystopia"); + banned.add("Earthcraft"); + banned.add("Earthlink"); + banned.add("Ebon Praetor"); + banned.add("Eladamri, Lord of Leaves"); + banned.add("Elder Spawn"); + banned.add("Elephant Graveyard"); + banned.add("Elkin Lair"); + banned.add("Elven Lyre"); + banned.add("Elvish Farmer"); + banned.add("Emberwilde Caliph"); + banned.add("Emberwilde Djinn"); + banned.add("Energy Bolt"); + banned.add("Energy Storm"); + banned.add("Energy Vortex"); + banned.add("Equipoise"); + banned.add("Ertai's Familiar"); + banned.add("Ertai, Wizard Adept"); + banned.add("Escaped Shapeshifter"); + banned.add("Eternal Flame"); + banned.add("Eureka"); + banned.add("Exalted Dragon"); + banned.add("Exorcist"); + banned.add("Eye of Singularity"); + banned.add("Faerie Noble"); + banned.add("Falling Star"); + banned.add("Farmstead"); + banned.add("Fastbond"); + banned.add("Fatal Lore"); + banned.add("Femeref Enchantress"); + banned.add("Field of Dreams"); + banned.add("Firestorm Hellkite"); + banned.add("Firestorm Phoenix"); + banned.add("Firestorm"); + banned.add("Flash"); + banned.add("Flooded Shoreline"); + banned.add("Floodwater Dam"); + banned.add("Flow of Maggots"); + banned.add("Forbidden Ritual"); + banned.add("Forcefield"); + banned.add("Forethought Amulet"); + banned.add("Fork"); + banned.add("Formation"); + banned.add("Forsaken Wastes"); + banned.add("Frankenstein's Monster"); + banned.add("Frantic Search"); + banned.add("Frenetic Efreet"); + banned.add("Fungal Bloom"); + banned.add("Fungus Elemental"); + banned.add("Fyndhorn Pollen"); + banned.add("Gaea's Avenger"); + banned.add("Gaea's Cradle"); + banned.add("Gallowbraid"); + banned.add("Gargantuan Gorilla"); + banned.add("Gate to Phyrexia"); + banned.add("Gauntlet of Might"); + banned.add("General Jarkeld"); + banned.add("Gilded Drake"); + banned.add("Glacial Crevasses"); + banned.add("Goblin Bomb"); + banned.add("Goblin Flotilla"); + banned.add("Goblin Recruiter"); + banned.add("Goblin Wizard"); + banned.add("Golgothian Sylex"); + banned.add("Gosta Dirk"); + banned.add("Grandmother Sengir"); + banned.add("Granite Gargoyle"); + banned.add("Grave Robbers"); + banned.add("Gravebind"); + banned.add("Gravity Sphere"); + banned.add("Great Whale"); + banned.add("Griffin Canyon"); + banned.add("Grim Feast"); + banned.add("Grim Monolith"); + banned.add("Guardian Beast"); + banned.add("Guiding Spirit"); + banned.add("Gush"); + banned.add("Gustha's Scepter"); + banned.add("Gwendlyn Di Corci"); + banned.add("Hakim, Loreweaver"); + banned.add("Halfdane"); + banned.add("Hall of Gemstone"); + banned.add("Halls of Mist"); + banned.add("Hand of Justice"); + banned.add("Harbinger of Night"); + banned.add("Hatred"); + banned.add("Haunting Wind"); + banned.add("Hazduhr the Abbot"); + banned.add("Hazezon Tamar"); + banned.add("Heart Wolf"); + banned.add("Heart of Bogardan"); + banned.add("Heart of Yavimaya"); + banned.add("Heat Stroke"); + banned.add("Hellfire"); + banned.add("Helm of Obedience"); + banned.add("Herald of Serra"); + banned.add("Hermit Druid"); + banned.add("Hidden Path"); + banned.add("Hivis of the Scale"); + banned.add("Homarid Shaman"); + banned.add("Hot Springs"); + banned.add("Humility"); + banned.add("Icatian Lieutenant"); + banned.add("Icatian Skirmishers"); + banned.add("Ice Cauldron"); + banned.add("Ifh-Biff Efreet"); + banned.add("Illusionary Mask"); + banned.add("Illusionary Presence"); + banned.add("Illusions of Grandeur"); + banned.add("Immediate Action"); + banned.add("Imperial Seal"); + banned.add("Implements of Sacrifice"); + banned.add("Imprison"); + banned.add("In the Eye of Chaos"); + banned.add("Infernal Denizen"); + banned.add("Infernal Tribute"); + banned.add("Infinite Authority"); + banned.add("Inner Sanctum"); + banned.add("Intuition"); + banned.add("Invoke Prejudice"); + banned.add("Island of Wak-Wak"); + banned.add("Iterative Analysis"); + banned.add("Ivory Gargoyle"); + banned.add("Jabari's Influence"); + banned.add("Jacques le Vert"); + banned.add("Jester's Mask"); + banned.add("Jeweled Bird"); + banned.add("Jihad"); + banned.add("Jovial Evil"); + banned.add("Jungle Patrol"); + banned.add("Juzam Djinn"); + banned.add("Kaervek's Spite"); + banned.add("Karn, Silver Golem"); + banned.add("Katabatic Winds"); + banned.add("Kaysa"); + banned.add("Keeper of Tresserhorn"); + banned.add("Khabal Ghoul"); + banned.add("King Suleiman"); + banned.add("Kjeldoran Knight"); + banned.add("Kjeldoran Outpost"); + banned.add("Kjeldoran Phalanx"); + banned.add("Knights of Thorn"); + banned.add("Knowledge Vault"); + banned.add("Kobold Overlord"); + banned.add("Kookus"); + banned.add("Koskun Falls"); + banned.add("Krovikan Horror"); + banned.add("Kudzu"); + banned.add("Kukemssa Pirates"); + banned.add("Lady Caleria"); + banned.add("Lady Evangela"); + banned.add("Lake of the Dead"); + banned.add("Land Cap"); + banned.add("Land Equilibrium"); + banned.add("Lava Tubes"); + banned.add("Leeches"); + banned.add("Leering Gargoyle"); + banned.add("Library of Alexandria"); + banned.add("Lich"); + banned.add("Lichenthrope"); + banned.add("Liege of the Hollows"); + banned.add("Life Matrix"); + banned.add("Lifeblood"); + banned.add("Lifeline"); + banned.add("Lightning Blow"); + banned.add("Lightning Cloud"); + banned.add("Lightning Dragon"); + banned.add("Lion's Eye Diamond"); + banned.add("Living Plane"); + banned.add("Livonya Silone"); + banned.add("Lodestone Bauble"); + banned.add("Lord of Tresserhorn"); + banned.add("Lotus Vale"); + banned.add("Lure of Prey"); + banned.add("Lurker"); + banned.add("Malignant Growth"); + banned.add("Mammoth Harness"); + banned.add("Mana Crypt"); + banned.add("Mana Drain"); + banned.add("Mana Matrix"); + banned.add("Mana Vault"); + banned.add("Mana Vortex"); + banned.add("Mana Web"); + banned.add("Mangara's Tome"); + banned.add("Maraxus of Keld"); + banned.add("Marjhan"); + banned.add("Marton Stromgald"); + banned.add("Martyr's Cry"); + banned.add("Martyrs of Korlis"); + banned.add("Master of the Hunt"); + banned.add("Masticore"); + banned.add("Meditate"); + banned.add("Memory Jar"); + banned.add("Mental Misstep"); + banned.add("Mercenaries"); + banned.add("Merchant Ship"); + banned.add("Mesmeric Trance"); + banned.add("Metalworker"); + banned.add("Mightstone"); + banned.add("Mind Over Matter"); + banned.add("Mind Twist"); + banned.add("Mind's Desire"); + banned.add("Mindbender Spores"); + banned.add("Minion of Tevesh Szat"); + banned.add("Mirror Universe"); + banned.add("Misers' Cage"); + banned.add("Misfortune"); + banned.add("Mishra's Workshop"); + banned.add("Mist Dragon"); + banned.add("Moat"); + banned.add("Mold Demon"); + banned.add("Morinfen"); + banned.add("Morphling"); + banned.add("Mountain Titan"); + 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("Mudslide"); + banned.add("Multani, Maro-Sorcerer"); + banned.add("Musician"); + banned.add("Muzzio's Preparations"); + banned.add("Mwonvuli Ooze"); + banned.add("Mystic Decree"); + banned.add("Mystic Might"); + banned.add("Mystical Tutor"); + banned.add("Nameless Race"); + banned.add("Narwhal"); + banned.add("Natural Balance"); + banned.add("Natural Selection"); + banned.add("Nature's Wrath"); + banned.add("Necropotence"); + banned.add("Nether Void"); + banned.add("Niall Silvain"); + banned.add("North Star"); + banned.add("Nova Pentacle"); + banned.add("Null Chamber"); + banned.add("Null Rod"); + banned.add("Oath of Druids"); + banned.add("Oath of Ghouls"); + banned.add("Ogre Enforcer"); + banned.add("Old Man of the Sea"); + banned.add("Omen of Fire"); + banned.add("Opal Archangel"); + banned.add("Opalescence"); + banned.add("Orim, Samite Healer"); + banned.add("Palinchron"); + banned.add("Paradigm Shift"); + banned.add("Paupers' Cage"); + banned.add("Peacekeeper"); + banned.add("Pendrell Mists"); + banned.add("Phantasmal Sphere"); + banned.add("Phelddagrif"); + banned.add("Phyrexian Devourer"); + banned.add("Phyrexian Dreadnought"); + banned.add("Phyrexian Marauder"); + banned.add("Phyrexian Negator"); + banned.add("Phyrexian Portal"); + banned.add("Phyrexian Purge"); + banned.add("Phyrexian Tribute"); + banned.add("Pillar Tombs of Aku"); + banned.add("Pixie Queen"); + banned.add("Planar Gate"); + banned.add("Plateau (Brudi)"); + banned.add("Plateau (Tucker)"); + banned.add("Polar Kraken"); + banned.add("Political Trickery"); + banned.add("Powder Keg"); + banned.add("Power Artifact"); + banned.add("Power Play"); + banned.add("Powerleech"); + banned.add("Preacher"); + banned.add("Preferred Selection"); + banned.add("Prismatic Lace"); + banned.add("Psychic Allergy"); + banned.add("Psychic Vortex"); + banned.add("Purgatory"); + banned.add("Purraj of Urborg"); + banned.add("Pygmy Hippo"); + banned.add("Pyramids"); + banned.add("Quarum Trench Gnomes"); + banned.add("Quirion Druid"); + banned.add("Radiant, Archangel"); + banned.add("Raging River"); + banned.add("Ragnar"); + banned.add("Rainbow Efreet"); + banned.add("Rainbow Vale"); + banned.add("Ramses Overdark"); + banned.add("Rapid Fire"); + banned.add("Rashida Scalebane"); + banned.add("Rasputin Dreamweaver"); + banned.add("Razor Pendulum"); + banned.add("Reality Twist"); + banned.add("Rebirth"); + banned.add("Recurring Nightmare"); + banned.add("Recycle"); + banned.add("Reflect Damage"); + banned.add("Reparations"); + banned.add("Replenish"); + banned.add("Retribution of the Meek"); + banned.add("Reveka, Wizard Savant"); + banned.add("Reverberation"); + banned.add("Righteous War"); + banned.add("Ring of Gix"); + banned.add("Ring of Immortals"); + banned.add("Ring of Ma'ruf"); + banned.add("Ring of Renewal"); + banned.add("Ritual of Subdual"); + banned.add("Ritual of the Machine"); + banned.add("River Delta"); + banned.add("River Merfolk"); + banned.add("Roc of Kher Ridges"); + banned.add("Rock Basilisk"); + banned.add("Rock Hydra"); + banned.add("Rofellos, Llanowar Emissary"); + banned.add("Rogue Skycaptain"); + banned.add("Rohgahh of Kher Keep"); + banned.add("Royal Decree"); + banned.add("Rysorian Badger"); + banned.add("Sandals of Abdallah"); + banned.add("Sands of Time"); + banned.add("Sarcomancy"); + banned.add("Savannah"); + banned.add("Sawback Manticore"); + banned.add("Scarwood Bandits"); + banned.add("Scorched Ruins"); + banned.add("Scrubland"); + banned.add("Season of the Witch"); + banned.add("Second Chance"); + banned.add("Secret Summoning"); + banned.add("Secrets of Paradise"); + banned.add("Sedge Troll"); + banned.add("Seeds of Innocence"); + banned.add("Selenia, Dark Angel"); + banned.add("Sentinel Dispatch"); + banned.add("Serendib Djinn"); + banned.add("Serra Aviary"); + banned.add("Serra's Sanctum"); + banned.add("Shahrazad"); + banned.add("Shallow Grave"); + banned.add("Shauku, Endbringer"); + banned.add("Sheltered Valley"); + banned.add("Shimmer"); + banned.add("Sidar Jabari"); + banned.add("Silver Wyvern"); + banned.add("Singing Tree"); + banned.add("Skeleton Ship"); + banned.add("Skullclamp"); + banned.add("Sliver Queen"); + banned.add("Snowblind"); + banned.add("Sol Ring"); + banned.add("Soldevi Digger"); + banned.add("Soldevi Excavations"); + banned.add("Soldevi Golem"); + banned.add("Soraya the Falconer"); + banned.add("Sorrow's Path"); + banned.add("Soul Echo"); + banned.add("Spectral Guardian"); + banned.add("Spinal Villain"); + banned.add("Spirit Shield"); + banned.add("Spirit of the Night"); + banned.add("Spiritual Sanctuary"); + banned.add("Splintering Wind"); + banned.add("Spoils of Evil"); + banned.add("Spoils of War"); + banned.add("Squandered Resources"); + banned.add("Stone Calendar"); + banned.add("Storm Spirit"); + banned.add("Storm World"); + banned.add("Strip Mine"); + banned.add("Su-Chi"); + banned.add("Subterranean Spirit"); + banned.add("Suleiman's Legacy"); + banned.add("Survival of the Fittest"); + banned.add("Sustaining Spirit"); + banned.add("Sword of the Ages"); + banned.add("Sworn Defender"); + banned.add("Taiga"); + banned.add("Tainted Specter"); + banned.add("Taniwha"); + banned.add("Tawnos's Coffin"); + banned.add("Teeka's Dragon"); + banned.add("Teferi's Imp"); + banned.add("Teferi's Isle"); + banned.add("Teferi's Realm"); + banned.add("Telekinesis"); + banned.add("Telim'Tor"); + banned.add("Telim'Tor's Edict"); + banned.add("Tempest Efreet"); + banned.add("Temporal Aperture"); + banned.add("Tetsuo Umezawa"); + banned.add("Thawing Glaciers"); + banned.add("The Abyss"); + banned.add("The Tabernacle at Pendrell Vale"); + banned.add("Thelon's Curse"); + banned.add("Thelonite Monk"); + banned.add("Thought Lash"); + banned.add("Thran Tome"); + banned.add("Three Wishes"); + banned.add("Thrull Champion"); + banned.add("Thunder Spirit"); + banned.add("Tidal Control"); + banned.add("Timberline Ridge"); + banned.add("Time Spiral"); + banned.add("Time Vault"); + banned.add("Time Walk"); + banned.add("Timetwister"); + banned.add("Timetwister"); + banned.add("Timmerian Fiends"); + banned.add("Tinker"); + banned.add("Tithe"); + banned.add("Tolarian Academy"); + banned.add("Tolarian Entrancer"); + banned.add("Tolarian Serpent"); + banned.add("Tombstone Stairwell"); + banned.add("Tornado"); + banned.add("Torrent of Lava"); + banned.add("Tourach's Gate"); + banned.add("Tracker"); + banned.add("Trailblazer"); + banned.add("Transmute Artifact"); + banned.add("Treachery"); + banned.add("Treasure Cruise"); + banned.add("Triangle of War"); + banned.add("Tropical Island"); + banned.add("Tuknir Deathlock"); + banned.add("Tundra"); + banned.add("Two-Headed Giant of Foriys"); + banned.add("Typhoon"); + banned.add("Underground Sea"); + banned.add("Undiscovered Paradise"); + banned.add("Unexpected Potential"); + banned.add("Unfulfilled Desires"); + banned.add("Ur-Drago"); + banned.add("Urborg Justice"); + banned.add("Urborg Stalker"); + banned.add("Urza's Miter"); + banned.add("Vampiric Tutor"); + banned.add("Varchild's War-Riders"); + banned.add("Veldrane of Sengir"); + banned.add("Veldt"); + banned.add("Ventifact Bottle"); + banned.add("Vesuvan Doppelganger"); + banned.add("Veteran Bodyguard"); + banned.add("Viashivan Dragon"); + banned.add("Vodalian Knights"); + banned.add("Vodalian War Machine"); + banned.add("Volcanic Island"); + banned.add("Volrath's Shapeshifter"); + banned.add("Volrath's Stronghold"); + banned.add("Wall of Kelp"); + banned.add("Wandering Mage"); + banned.add("Warping Wurm"); + banned.add("Wave of Terror"); + banned.add("Weakstone"); + banned.add("Weatherseed Treefolk"); + banned.add("Well of Knowledge"); + banned.add("Wellspring"); + banned.add("Wheel of Fortune"); + banned.add("Willow Priestess"); + banned.add("Willow Satyr"); + banned.add("Windfall"); + banned.add("Winding Canyons"); + banned.add("Winter Sky"); + banned.add("Winter's Chill"); + banned.add("Winter's Night"); + banned.add("Wood Elemental"); + banned.add("Word of Command"); + banned.add("Worldknit"); + banned.add("Worms of the Earth"); + banned.add("Wormwood Treefolk"); + banned.add("Xanthic Statue"); + banned.add("Yare"); + banned.add("Yavimaya Hollow"); + banned.add("Yawgmoth's Bargain"); + banned.add("Yawgmoth's Will"); + banned.add("Zelyon Sword"); + banned.add("Zephid"); + banned.add("Zhalfirin Crusader"); + banned.add("Zirilan of the Claw"); + banned.add("Zuberi, Golden Feather"); + } +} diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 21e2db8e3fe..6aadb3d2ad9 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -110,6 +110,7 @@ + diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index 123ba8599f0..9b9598c07b4 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -107,6 +107,7 @@ + diff --git a/Mage.Sets/src/mage/sets/alarareborn/TaintedSigil.java b/Mage.Sets/src/mage/sets/alarareborn/TaintedSigil.java index 905f22ddacd..47da23ea1ad 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/TaintedSigil.java +++ b/Mage.Sets/src/mage/sets/alarareborn/TaintedSigil.java @@ -87,7 +87,7 @@ class AllPlayersLostLifeCount implements DynamicValue { PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get("PlayerLostLifeWatcher"); if (watcher != null) { int amountLifeLost = 0; - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(controllerId, game)) { amountLifeLost += watcher.getLiveLost(playerId); } return amountLifeLost; diff --git a/Mage.Sets/src/mage/sets/coldsnap/RuneSnag.java b/Mage.Sets/src/mage/sets/coldsnap/RuneSnag.java index 70bcf87ea59..31b4c09315a 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/RuneSnag.java +++ b/Mage.Sets/src/mage/sets/coldsnap/RuneSnag.java @@ -45,8 +45,9 @@ import mage.target.TargetSpell; * @author emerald000 */ public class RuneSnag extends CardImpl { - + private static final FilterCard filter = new FilterCard(); + static { filter.add(new NamePredicate("Rune Snag")); } @@ -55,7 +56,6 @@ public class RuneSnag extends CardImpl { super(ownerId, 46, "Rune Snag", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}"); this.expansionSetCode = "CSP"; - // Counter target spell unless its controller pays {2} plus an additional {2} for each card named Rune Snag in each graveyard. Effect effect = new CounterUnlessPaysEffect(new IntPlusDynamicValue(2, new MultipliedValue(new CardsInAllGraveyardsCount(filter), 2))); effect.setText("Counter target spell unless its controller pays {2} plus an additional {2} for each card named Rune Snag in each graveyard"); diff --git a/Mage.Sets/src/mage/sets/commander2013/CurseOfTheForsaken.java b/Mage.Sets/src/mage/sets/commander2013/CurseOfTheForsaken.java index 8011fafb75c..4d1b0660872 100644 --- a/Mage.Sets/src/mage/sets/commander2013/CurseOfTheForsaken.java +++ b/Mage.Sets/src/mage/sets/commander2013/CurseOfTheForsaken.java @@ -58,11 +58,10 @@ public class CurseOfTheForsaken extends CardImpl { this.subtype.add("Aura"); this.subtype.add("Curse"); - // Enchant player TargetPlayer auraTarget = new TargetPlayer(); this.getSpellAbility().addTarget(auraTarget); - this.getSpellAbility().addEffect(new AttachEffect(Outcome.GainLife)); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); // Whenever a creature attacks enchanted player, its controller gains 1 life. @@ -112,7 +111,7 @@ class CurseOfTheForsakenTriggeredAbility extends TriggeredAbilityImpl { if (enchantment != null && enchantment.getAttachedTo() != null && enchantment.getAttachedTo().equals(defender.getId())) { - for (Effect effect: this.getEffects()) { + for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } return true; diff --git a/Mage.Sets/src/mage/sets/commander2013/Stonecloaker.java b/Mage.Sets/src/mage/sets/commander2013/Stonecloaker.java index 92b4f50836f..d867cf82338 100644 --- a/Mage.Sets/src/mage/sets/commander2013/Stonecloaker.java +++ b/Mage.Sets/src/mage/sets/commander2013/Stonecloaker.java @@ -60,7 +60,7 @@ public class Stonecloaker extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // When Stonecloaker enters the battlefield, return a creature you control to its owner's hand. - Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(new FilterControlledCreaturePermanent()), true); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(new FilterControlledCreaturePermanent()), false); this.addAbility(ability); // When Stonecloaker enters the battlefield, exile target card from a graveyard. diff --git a/Mage.Sets/src/mage/sets/conspiracy/ExtractFromDarkness.java b/Mage.Sets/src/mage/sets/conspiracy/ExtractFromDarkness.java index 4fe08b08edc..ec1c37fda95 100644 --- a/Mage.Sets/src/mage/sets/conspiracy/ExtractFromDarkness.java +++ b/Mage.Sets/src/mage/sets/conspiracy/ExtractFromDarkness.java @@ -80,7 +80,7 @@ class ExtractFromDarknessMillEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { player.moveCards(player.getLibrary().getTopCards(game, 2), Zone.LIBRARY, Zone.GRAVEYARD, source, game); diff --git a/Mage.Sets/src/mage/sets/darkascension/CurseOfEchoes.java b/Mage.Sets/src/mage/sets/darkascension/CurseOfEchoes.java index ad3f964a8b2..dfee5dd7f9c 100644 --- a/Mage.Sets/src/mage/sets/darkascension/CurseOfEchoes.java +++ b/Mage.Sets/src/mage/sets/darkascension/CurseOfEchoes.java @@ -147,7 +147,7 @@ class CurseOfEchoesEffect extends OneShotEffect { Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source)); if (spell != null) { String chooseMessage = "Copy target spell? You may choose new targets for the copy."; - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { if (!playerId.equals(spell.getControllerId())) { Player player = game.getPlayer(playerId); if (player.chooseUse(Outcome.Copy, chooseMessage, source, game)) { diff --git a/Mage.Sets/src/mage/sets/exodus/Cataclysm.java b/Mage.Sets/src/mage/sets/exodus/Cataclysm.java index ac1df0bf079..5c7953f2a0b 100644 --- a/Mage.Sets/src/mage/sets/exodus/Cataclysm.java +++ b/Mage.Sets/src/mage/sets/exodus/Cataclysm.java @@ -86,7 +86,7 @@ class CataclysmEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { List chosen = new ArrayList<>(); - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); Target target1 = new TargetControlledPermanent(1, 1, new FilterControlledArtifactPermanent(), true); diff --git a/Mage.Sets/src/mage/sets/guildpact/BeastmastersMagemark.java b/Mage.Sets/src/mage/sets/guildpact/BeastmastersMagemark.java new file mode 100644 index 00000000000..51659bd9544 --- /dev/null +++ b/Mage.Sets/src/mage/sets/guildpact/BeastmastersMagemark.java @@ -0,0 +1,94 @@ +/* + * 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.sets.guildpact; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Markedagain + */ +public class BeastmastersMagemark extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); + static { + filter.add(new EnchantedPredicate()); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public BeastmastersMagemark(UUID ownerId) { + super(ownerId, 80, "Beastmaster's Magemark", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + this.expansionSetCode = "GPT"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Creatures you control that are enchanted get +1/+1. + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1,1, Duration.WhileOnBattlefield, filter, false)); + this.addAbility(ability); + // Whenever a creature you control that's enchanted becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. + BlockedCreatureCount value = new BlockedCreatureCount(); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +1/+1 until end of turn for each creature blocking it"); + this.addAbility(new BecomesBlockedAllTriggeredAbility(effect, false,filter,false)); + } + + public BeastmastersMagemark(final BeastmastersMagemark card) { + super(card); + } + + @Override + public BeastmastersMagemark copy() { + return new BeastmastersMagemark(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/guildpact/FencersMagemark.java b/Mage.Sets/src/mage/sets/guildpact/FencersMagemark.java new file mode 100644 index 00000000000..0889a07bcdd --- /dev/null +++ b/Mage.Sets/src/mage/sets/guildpact/FencersMagemark.java @@ -0,0 +1,90 @@ +/* + * 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.sets.guildpact; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Markedagain + */ +public class FencersMagemark extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); + static { + filter.add(new EnchantedPredicate()); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public FencersMagemark(UUID ownerId) { + super(ownerId, 65, "Fencer's Magemark", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.expansionSetCode = "GPT"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Creatures you control that are enchanted get +1/+1 and have first strike. + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1,1, Duration.WhileOnBattlefield, filter, false)); + Effect effect = new GainAbilityAllEffect(FirstStrikeAbility.getInstance(),Duration.WhileOnBattlefield,filter, " and have first strike"); + ability.addEffect(effect); + this.addAbility(ability); + } + + public FencersMagemark(final FencersMagemark card) { + super(card); + } + + @Override + public FencersMagemark copy() { + return new FencersMagemark(this); + } +} diff --git a/Mage.Sets/src/mage/sets/guildpact/GuardiansMagemark.java b/Mage.Sets/src/mage/sets/guildpact/GuardiansMagemark.java new file mode 100644 index 00000000000..39a1e80b938 --- /dev/null +++ b/Mage.Sets/src/mage/sets/guildpact/GuardiansMagemark.java @@ -0,0 +1,88 @@ +/* + * 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.sets.guildpact; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Markedagain + */ +public class GuardiansMagemark extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); + static { + filter.add(new EnchantedPredicate()); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public GuardiansMagemark(UUID ownerId) { + super(ownerId, 8, "Guardian's Magemark", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + this.expansionSetCode = "GPT"; + this.subtype.add("Aura"); + + // Flash + this.addAbility(FlashAbility.getInstance()); + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Creatures you control that are enchanted get +1/+1. + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1,1, Duration.WhileOnBattlefield, filter, false)); + this.addAbility(ability); + } + + public GuardiansMagemark(final GuardiansMagemark card) { + super(card); + } + + @Override + public GuardiansMagemark copy() { + return new GuardiansMagemark(this); + } +} diff --git a/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java b/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java new file mode 100644 index 00000000000..712648fca81 --- /dev/null +++ b/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java @@ -0,0 +1,92 @@ +/* + * 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.sets.guildpact; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Markedagain + */ +public class NecromancersMagemark extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); + static { + filter.add(new EnchantedPredicate()); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public NecromancersMagemark(UUID ownerId) { + super(ownerId, 53, "Necromancer's Magemark", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + this.expansionSetCode = "GPT"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Creatures you control that are enchanted get +1/+1. + ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1,1, Duration.WhileOnBattlefield, filter, false)); + this.addAbility(ability); + // If a creature you control that's enchanted would die, return it to its owner's hand instead. + Effect effect = new ReturnToHandSourceEffect(); + ability = new DiesCreatureTriggeredAbility(effect,false); + this.addAbility(ability); + } + + public NecromancersMagemark(final NecromancersMagemark card) { + super(card); + } + + @Override + public NecromancersMagemark copy() { + return new NecromancersMagemark(this); + } +} diff --git a/Mage.Sets/src/mage/sets/iceage/JohtullWurm.java b/Mage.Sets/src/mage/sets/iceage/JohtullWurm.java index 524fbde5197..d1fd3b5b7af 100644 --- a/Mage.Sets/src/mage/sets/iceage/JohtullWurm.java +++ b/Mage.Sets/src/mage/sets/iceage/JohtullWurm.java @@ -1,119 +1,71 @@ -/* - * 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.sets.iceage; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.BecomesBlockedTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.MultipliedValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.game.Game; -import mage.game.combat.CombatGroup; - -/** - * - * @author fireshoes - */ -public class JohtullWurm extends CardImpl { - - public JohtullWurm(UUID ownerId) { - super(ownerId, 138, "Johtull Wurm", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{5}{G}"); - this.expansionSetCode = "ICE"; - this.subtype.add("Wurm"); - this.power = new MageInt(6); - this.toughness = new MageInt(6); - - // Whenever Johtull Wurm becomes blocked, it gets -2/-1 until end of turn for each creature blocking it beyond the first. - this.addAbility(new JohtullWurmAbility()); - } - - public JohtullWurm(final JohtullWurm card) { - super(card); - } - - @Override - public JohtullWurm copy() { - return new JohtullWurm(this); - } -} - -class JohtullWurmAbility extends BecomesBlockedTriggeredAbility { - - public JohtullWurmAbility() { - super(null, false); - JohtullWurmValue toughnessValue = new JohtullWurmValue(); - DynamicValue powerValue = new MultipliedValue(toughnessValue, 2); - this.addEffect(new BoostSourceEffect(powerValue, toughnessValue, Duration.EndOfTurn)); - } - - public JohtullWurmAbility(final JohtullWurmAbility ability) { - super(ability); - } - - @Override - public JohtullWurmAbility copy() { - return new JohtullWurmAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} becomes blocked, it gets -2/-1 until end of turn for each creature blocking it beyond the first."; - } -} - -class JohtullWurmValue implements DynamicValue { - - @Override - public JohtullWurmValue copy() { - return new JohtullWurmValue(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - for(CombatGroup combatGroup : game.getCombat().getGroups()) { - if(combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { - int blockers = combatGroup.getBlockers().size(); - return blockers > 1 ? -(blockers - 1) : 0; - } - } - return 0; - } - - @Override - public String getMessage() { - return "-2/-1 until end of turn for each creature blocking it beyond the first"; - } -} - +/* + * 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.sets.iceage; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class JohtullWurm extends CardImpl { + + public JohtullWurm(UUID ownerId) { + super(ownerId, 138, "Johtull Wurm", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{5}{G}"); + this.expansionSetCode = "ICE"; + this.subtype.add("Wurm"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Whenever Johtull Wurm becomes blocked, it gets -2/-1 until end of turn for each creature blocking it beyond the first. + DynamicValue blockedCreatureCount = new BlockedCreatureCount("each creature blocking it beyond the first", true); + Effect effect = new BoostSourceEffect(new MultipliedValue(blockedCreatureCount, -2), new MultipliedValue(blockedCreatureCount, -1), Duration.EndOfTurn); + effect.setText("it gets -2/-1 until end of turn for each creature blocking it beyond the first"); + this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); + } + + public JohtullWurm(final JohtullWurm card) { + super(card); + } + + @Override + public JohtullWurm copy() { + return new JohtullWurm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/ElfhameSanctuary.java b/Mage.Sets/src/mage/sets/invasion/ElfhameSanctuary.java new file mode 100644 index 00000000000..00ff659c0b0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/ElfhameSanctuary.java @@ -0,0 +1,108 @@ +/* + * 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.sets.invasion; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterBasicLandCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author Markedagain + */ +public class ElfhameSanctuary extends CardImpl { + + public ElfhameSanctuary(UUID ownerId) { + super(ownerId, 185, "Elfhame Sanctuary", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + this.expansionSetCode = "INV"; + + // At the beginning of your upkeep, you may search your library for a basic land card, reveal that card, and put it into your hand. If you do, you skip your draw step this turn and shuffle your library. + Ability ability = new BeginningOfUpkeepTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterBasicLandCard())), TargetController.YOU, true); + ability.addEffect(new SkipDrawStepThisTurn()); + + this.addAbility(ability); + } + + public ElfhameSanctuary(final ElfhameSanctuary card) { + super(card); + } + + @Override + public ElfhameSanctuary copy() { + return new ElfhameSanctuary(this); + } +} + +class SkipDrawStepThisTurn extends ReplacementEffectImpl { + + public SkipDrawStepThisTurn() { + super(Duration.UntilYourNextTurn, Outcome.Neutral); + staticText = "Skip your draw step this turn"; + } + + public SkipDrawStepThisTurn(final SkipDrawStepThisTurn effect) { + super(effect); + } + + @Override + public SkipDrawStepThisTurn copy() { + return new SkipDrawStepThisTurn(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DRAW_STEP; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getPlayerId().equals(source.getControllerId()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/invasion/GlobalRuin.java b/Mage.Sets/src/mage/sets/invasion/GlobalRuin.java new file mode 100644 index 00000000000..635764fc927 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/GlobalRuin.java @@ -0,0 +1,111 @@ +/* + * 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.sets.invasion; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterLandPermanent; +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.common.TargetControlledPermanent; + +/** + * + * @author Markedagain + */ +public class GlobalRuin extends CardImpl { + + public GlobalRuin(UUID ownerId) { + super(ownerId, 18, "Global Ruin", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{W}"); + this.expansionSetCode = "INV"; + + // Each player chooses from the lands he or she controls a land of each basic land type, then sacrifices the rest. + this.getSpellAbility().addEffect(new GlobalRuinDestroyLandEffect()); + } + + public GlobalRuin(final GlobalRuin card) { + super(card); + } + + @Override + public GlobalRuin copy() { + return new GlobalRuin(this); + } +} + +class GlobalRuinDestroyLandEffect extends OneShotEffect { + + public GlobalRuinDestroyLandEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Each player chooses from the lands he or she controls a land of each basic land type, then sacrifices the rest"; + } + + public GlobalRuinDestroyLandEffect(final GlobalRuinDestroyLandEffect effect) { + super(effect); + } + + @Override + public GlobalRuinDestroyLandEffect copy() { + return new GlobalRuinDestroyLandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Set lands = new HashSet<>(); + + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + for (String landName : new String[]{"Forest", "Island", "Mountain", "Plains", "Swamp"}) { + FilterControlledLandPermanent filter = new FilterControlledLandPermanent(landName + " you control"); + filter.add(new SubtypePredicate(landName)); + Target target = new TargetControlledPermanent(1, 1, filter, true); + if (target.canChoose(player.getId(), game)) { + player.chooseTarget(outcome, target, source, game); + lands.add(target.getFirstTarget()); + } + } + } + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterLandPermanent(), game)){ + if (!lands.contains(permanent.getId())){ + permanent.sacrifice(permanent.getId(), game); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/SparringGolem.java b/Mage.Sets/src/mage/sets/invasion/SparringGolem.java index 9f9a2844949..98304b10f88 100644 --- a/Mage.Sets/src/mage/sets/invasion/SparringGolem.java +++ b/Mage.Sets/src/mage/sets/invasion/SparringGolem.java @@ -1,116 +1,69 @@ -/* - * 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.sets.invasion; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.BecomesBlockedTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.game.Game; -import mage.game.combat.CombatGroup; - -/** - * - * @author fireshoes - */ -public class SparringGolem extends CardImpl { - - public SparringGolem(UUID ownerId) { - super(ownerId, 312, "Sparring Golem", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); - this.expansionSetCode = "INV"; - this.subtype.add("Golem"); - this.power = new MageInt(2); - this.toughness = new MageInt(2); - - // Whenever Sparring Golem becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. - this.addAbility(new SparringGolemAbility()); - } - - public SparringGolem(final SparringGolem card) { - super(card); - } - - @Override - public SparringGolem copy() { - return new SparringGolem(this); - } -} - -class SparringGolemAbility extends BecomesBlockedTriggeredAbility { - - public SparringGolemAbility() { - super(null, false); - SparringGolemValue value = new SparringGolemValue(); - this.addEffect(new BoostSourceEffect(value, value, Duration.EndOfTurn)); - } - - public SparringGolemAbility(final SparringGolemAbility ability) { - super(ability); - } - - @Override - public SparringGolemAbility copy() { - return new SparringGolemAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} becomes blocked, it gets +1/+1 until end of turn for each creature blocking it."; - } -} - -class SparringGolemValue implements DynamicValue { - - @Override - public SparringGolemValue copy() { - return new SparringGolemValue(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - for(CombatGroup combatGroup : game.getCombat().getGroups()) { - if(combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { - int blockers = combatGroup.getBlockers().size(); - return blockers > 1 ? (blockers) : 0; - } - } - return 0; - } - - @Override - public String getMessage() { - return "+1/+1 until end of turn for each creature blocking it"; - } -} +/* + * 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.sets.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class SparringGolem extends CardImpl { + + public SparringGolem(UUID ownerId) { + super(ownerId, 312, "Sparring Golem", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + this.expansionSetCode = "INV"; + this.subtype.add("Golem"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Sparring Golem becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. + BlockedCreatureCount value = new BlockedCreatureCount(); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +1/+1 until end of turn for each creature blocking it"); + this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); + } + + public SparringGolem(final SparringGolem card) { + super(card); + } + + @Override + public SparringGolem copy() { + return new SparringGolem(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/legions/BerserkMurlodont.java b/Mage.Sets/src/mage/sets/legions/BerserkMurlodont.java index d0c38c0faec..dcddb71fa2d 100644 --- a/Mage.Sets/src/mage/sets/legions/BerserkMurlodont.java +++ b/Mage.Sets/src/mage/sets/legions/BerserkMurlodont.java @@ -1,67 +1,76 @@ -/* - * 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.sets.legions; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; - -/** - * - * @author fireshoes - */ -public class BerserkMurlodont extends CardImpl { - - public BerserkMurlodont(UUID ownerId) { - super(ownerId, 117, "Berserk Murlodont", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{G}"); - this.expansionSetCode = "LGN"; - this.subtype.add("Beast"); - this.power = new MageInt(3); - this.toughness = new MageInt(3); - - // Whenever a Beast becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. - Effect effect = new BoostSourceEffect(1, 1, Duration.EndOfTurn); - effect.setText("it gets +1/+1 until end of turn for each creature blocking it"); - this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(effect, false)); - } - - public BerserkMurlodont(final BerserkMurlodont card) { - super(card); - } - - @Override - public BerserkMurlodont copy() { - return new BerserkMurlodont(this); - } -} +/* + * 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.sets.legions; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedAllTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author Markedagain + */ +public class BerserkMurlodont extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a Beast"); + static { + filter.add(new SubtypePredicate("Beast")); + } + + public BerserkMurlodont(UUID ownerId) { + super(ownerId, 117, "Berserk Murlodont", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{G}"); + this.expansionSetCode = "LGN"; + this.subtype.add("Beast"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever a Beast becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. + BlockedCreatureCount value = new BlockedCreatureCount(); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +1/+1 until end of turn for each creature blocking it"); + this.addAbility(new BecomesBlockedAllTriggeredAbility(effect, false,filter,false)); + } + + public BerserkMurlodont(final BerserkMurlodont card) { + super(card); + } + + @Override + public BerserkMurlodont copy() { + return new BerserkMurlodont(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/ArbiterOfKnollridge.java b/Mage.Sets/src/mage/sets/lorwyn/ArbiterOfKnollridge.java index 146d923b0ee..95c7c0d61fd 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/ArbiterOfKnollridge.java +++ b/Mage.Sets/src/mage/sets/lorwyn/ArbiterOfKnollridge.java @@ -40,6 +40,7 @@ import mage.cards.CardImpl; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import mage.players.PlayerList; /** * @@ -85,7 +86,8 @@ class ArbiterOfKnollridgeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int maxLife = 0; - for (UUID pid : game.getPlayerList()) { + PlayerList playerList = game.getState().getPlayersInRange(source.getControllerId(), game); + for (UUID pid : playerList) { Player p = game.getPlayer(pid); if (p != null) { if (maxLife < p.getLife()) { @@ -93,7 +95,7 @@ class ArbiterOfKnollridgeEffect extends OneShotEffect { } } } - for (UUID pid : game.getPlayerList()) { + for (UUID pid : playerList) { Player p = game.getPlayer(pid); if (p != null) { p.setLife(maxLife, game); diff --git a/Mage.Sets/src/mage/sets/lorwyn/GlenElendraPranksters.java b/Mage.Sets/src/mage/sets/lorwyn/GlenElendraPranksters.java new file mode 100644 index 00000000000..770af5089c2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/GlenElendraPranksters.java @@ -0,0 +1,102 @@ +/* + * 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.sets.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author Markedagain + */ +public class GlenElendraPranksters extends CardImpl { + + public GlenElendraPranksters(UUID ownerId) { + super(ownerId, 67, "Glen Elendra Pranksters", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Faerie"); + this.subtype.add("Wizard"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever you cast a spell during an opponent's turn, you may return target creature you control to its owner's hand. + this.addAbility(new GlenElendraPrankstersTriggeredAbility()); + } + + public GlenElendraPranksters(final GlenElendraPranksters card) { + super(card); + } + + @Override + public GlenElendraPranksters copy() { + return new GlenElendraPranksters(this); + } +} +class GlenElendraPrankstersTriggeredAbility extends TriggeredAbilityImpl { + GlenElendraPrankstersTriggeredAbility() { + super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), true); + this.addTarget(new TargetControlledCreaturePermanent()); + } + + GlenElendraPrankstersTriggeredAbility(final GlenElendraPrankstersTriggeredAbility ability) { + super(ability); + } + + @Override + public GlenElendraPrankstersTriggeredAbility copy() { + return new GlenElendraPrankstersTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.controllerId) + && game.getOpponents(this.controllerId).contains(game.getActivePlayerId()); + } + + @Override + public String getRule() { + return "Whenever you cast a spell during an opponent's turn, " + super.getRule(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/magic2011/SerraAscendant.java b/Mage.Sets/src/mage/sets/magic2011/SerraAscendant.java index 6249ea6ee65..8acd2927c35 100644 --- a/Mage.Sets/src/mage/sets/magic2011/SerraAscendant.java +++ b/Mage.Sets/src/mage/sets/magic2011/SerraAscendant.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,22 +20,14 @@ * 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.sets.magic2011; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.SubLayer; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -43,6 +35,13 @@ import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -64,7 +63,7 @@ public class SerraAscendant extends CardImpl { // Lifelink (Damage dealt by this creature also causes you to gain that much life.) this.addAbility(LifelinkAbility.getInstance()); - + // As long as you have 30 or more life, Serra Ascendant gets +5/+5 and has flying. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SerraAscendantEffect())); } @@ -99,9 +98,9 @@ class SerraAscendantEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent creature = game.getPermanent(source.getSourceId()); - if (creature != null) { - Player player = game.getPlayer(creature.getControllerId()); - if (player != null && player.getLife() >= 30) { + Player controller = game.getPlayer(source.getControllerId()); + if (creature != null && controller != null) { + if (controller.getLife() >= 30) { switch (layer) { case PTChangingEffects_7: if (sublayer == SubLayer.ModifyPT_7c) { @@ -111,12 +110,13 @@ class SerraAscendantEffect extends ContinuousEffectImpl { break; case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - creature.addAbility(FlyingAbility.getInstance(), game); + creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); } break; } - return true; + } + return true; } return false; } @@ -128,7 +128,7 @@ class SerraAscendantEffect extends ContinuousEffectImpl { @Override public boolean hasLayer(Layer layer) { - return layer == Layer.AbilityAddingRemovingEffects_6 || layer == layer.PTChangingEffects_7; + return Layer.AbilityAddingRemovingEffects_6.equals(layer) || Layer.PTChangingEffects_7.equals(layer); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magic2013/Worldfire.java b/Mage.Sets/src/mage/sets/magic2013/Worldfire.java index 4ef69e58ec6..7a4fe173a8d 100644 --- a/Mage.Sets/src/mage/sets/magic2013/Worldfire.java +++ b/Mage.Sets/src/mage/sets/magic2013/Worldfire.java @@ -89,7 +89,7 @@ class WorldfireEffect extends OneShotEffect { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { permanent.moveToExile(id, "all permanents", id, game); } - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { for (UUID cid : player.getHand().copy()) { diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/BlockadeRunner.java b/Mage.Sets/src/mage/sets/mercadianmasques/BlockadeRunner.java new file mode 100644 index 00000000000..404dcdcea85 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/BlockadeRunner.java @@ -0,0 +1,68 @@ +/* + * 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.sets.mercadianmasques; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author djbrez + */ +public class BlockadeRunner extends CardImpl { + + public BlockadeRunner(UUID ownerId) { + super(ownerId, 60, "Blockade Runner", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Merfolk"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {U}: Blockade Runner is unblockable this turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, + new CantBeBlockedSourceEffect(Duration.EndOfTurn), + new ManaCostsImpl("{U}"))); + } + + public BlockadeRunner(final BlockadeRunner card) { + super(card); + } + + @Override + public BlockadeRunner copy() { + return new BlockadeRunner(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/DreadSpecter.java b/Mage.Sets/src/mage/sets/mirage/DreadSpecter.java new file mode 100644 index 00000000000..b9220585be3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/DreadSpecter.java @@ -0,0 +1,79 @@ +/* + * 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.sets.mirage; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.BlocksOrBecomesBlockedByCreatureTriggeredAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author djbrez + */ +public class DreadSpecter extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public DreadSpecter(UUID ownerId) { + super(ownerId, 17, "Dread Specter", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "MIR"; + this.subtype.add("Specter"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Dread Specter blocks or becomes blocked by a nonblack creature, destroy that creature at end of combat. + Effect effect = new CreateDelayedTriggeredAbilityEffect( + new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true); + effect.setText("destroy that creature at end of combat"); + this.addAbility(new BlocksOrBecomesBlockedByCreatureTriggeredAbility(effect, filter, false)); + } + + public DreadSpecter(final DreadSpecter card) { + super(card); + } + + @Override + public DreadSpecter copy() { + return new DreadSpecter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/JungleWurm.java b/Mage.Sets/src/mage/sets/mirage/JungleWurm.java index 0ad27034812..7a66ccdecad 100644 --- a/Mage.Sets/src/mage/sets/mirage/JungleWurm.java +++ b/Mage.Sets/src/mage/sets/mirage/JungleWurm.java @@ -1,119 +1,72 @@ -/* - * 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.sets.mirage; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.BecomesBlockedTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.game.Game; -import mage.game.combat.CombatGroup; -import mage.game.events.GameEvent; - -/** - * - * @author LoneFox - */ -public class JungleWurm extends CardImpl { - - public JungleWurm(UUID ownerId) { - super(ownerId, 122, "Jungle Wurm", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); - this.expansionSetCode = "MIR"; - this.subtype.add("Wurm"); - this.power = new MageInt(5); - this.toughness = new MageInt(5); - - // Whenever Jungle Wurm becomes blocked, it gets -1/-1 until end of turn for each creature blocking it beyond the first. - this.addAbility(new JungleWurmAbility()); - } - - public JungleWurm(final JungleWurm card) { - super(card); - } - - @Override - public JungleWurm copy() { - return new JungleWurm(this); - } -} - -class JungleWurmAbility extends BecomesBlockedTriggeredAbility { - - public JungleWurmAbility() { - super(null, false); - JungleWurmValue value = new JungleWurmValue(); - this.addEffect(new BoostSourceEffect(value, value, Duration.EndOfTurn)); - } - - public JungleWurmAbility(final JungleWurmAbility ability) { - super(ability); - } - - @Override - public JungleWurmAbility copy() { - return new JungleWurmAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} becomes blocked, it gets -1/-1 until end of turn for each creature blocking it beyond the first."; - } -} - -class JungleWurmValue implements DynamicValue { - - @Override - public JungleWurmValue copy() { - return new JungleWurmValue(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - int count = 0; - for(CombatGroup combatGroup : game.getCombat().getGroups()) { - if(combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { - int blockers = combatGroup.getBlockers().size(); - return blockers > 1 ? -(blockers - 1) : 0; - } - } - return 0; - } - - @Override - public String getMessage() { - return "-1/-1 until end of turn for each creature blocking it beyond the first"; - } -} - +/* + * 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.sets.mirage; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class JungleWurm extends CardImpl { + + public JungleWurm(UUID ownerId) { + super(ownerId, 122, "Jungle Wurm", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + this.expansionSetCode = "MIR"; + this.subtype.add("Wurm"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Whenever Jungle Wurm becomes blocked, it gets -1/-1 until end of turn for each creature blocking it beyond the first. + BlockedCreatureCount blockedCreatureCount = new BlockedCreatureCount("each creature blocking it beyond the first", true); + DynamicValue value = new MultipliedValue(blockedCreatureCount, -1); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets -1/-1 until end of turn for each creature blocking it beyond the first"); + this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); + } + + public JungleWurm(final JungleWurm card) { + super(card); + } + + @Override + public JungleWurm copy() { + return new JungleWurm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ninthedition/ElvishBerserker.java b/Mage.Sets/src/mage/sets/ninthedition/ElvishBerserker.java index b53ffa4298b..924d718d4cd 100644 --- a/Mage.Sets/src/mage/sets/ninthedition/ElvishBerserker.java +++ b/Mage.Sets/src/mage/sets/ninthedition/ElvishBerserker.java @@ -1,117 +1,70 @@ -/* - * 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.sets.ninthedition; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.BecomesBlockedTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.game.Game; -import mage.game.combat.CombatGroup; - -/** - * - * @author ilcartographer - */ -public class ElvishBerserker extends CardImpl { - - public ElvishBerserker(UUID ownerId) { - super(ownerId, 237, "Elvish Berserker", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}"); - this.expansionSetCode = "9ED"; - this.subtype.add("Elf"); - this.subtype.add("Berserker"); - this.power = new MageInt(1); - this.toughness = new MageInt(1); - - // Whenever Elvish Berserker becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. - this.addAbility(new ElvishBerserkerAbility()); - } - - public ElvishBerserker(final ElvishBerserker card) { - super(card); - } - - @Override - public ElvishBerserker copy() { - return new ElvishBerserker(this); - } -} - -class ElvishBerserkerAbility extends BecomesBlockedTriggeredAbility { - - public ElvishBerserkerAbility() { - super(null, false); - ElvishBerserkerValue value = new ElvishBerserkerValue(); - this.addEffect(new BoostSourceEffect(value, value, Duration.EndOfTurn)); - } - - public ElvishBerserkerAbility(final ElvishBerserkerAbility ability) { - super(ability); - } - - @Override - public ElvishBerserkerAbility copy() { - return new ElvishBerserkerAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} becomes blocked, it gets +1/+1 until end of turn for each creature blocking it."; - } -} - -class ElvishBerserkerValue implements DynamicValue { - - @Override - public ElvishBerserkerValue copy() { - return new ElvishBerserkerValue(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - for(CombatGroup combatGroup : game.getCombat().getGroups()) { - if(combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { - int blockers = combatGroup.getBlockers().size(); - return blockers > 1 ? (blockers) : 0; - } - } - return 0; - } - - @Override - public String getMessage() { - return "+1/+1 until end of turn for each creature blocking it"; - } -} +/* + * 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.sets.ninthedition; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author ilcartographer + */ +public class ElvishBerserker extends CardImpl { + + public ElvishBerserker(UUID ownerId) { + super(ownerId, 237, "Elvish Berserker", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}"); + this.expansionSetCode = "9ED"; + this.subtype.add("Elf"); + this.subtype.add("Berserker"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Elvish Berserker becomes blocked, it gets +1/+1 until end of turn for each creature blocking it. + BlockedCreatureCount value = new BlockedCreatureCount(); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +1/+1 until end of turn for each creature blocking it"); + this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); + } + + public ElvishBerserker(final ElvishBerserker card) { + super(card); + } + + @Override + public ElvishBerserker copy() { + return new ElvishBerserker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/odyssey/RabidElephant.java b/Mage.Sets/src/mage/sets/odyssey/RabidElephant.java index 4c496f27b80..7d4dac87c25 100644 --- a/Mage.Sets/src/mage/sets/odyssey/RabidElephant.java +++ b/Mage.Sets/src/mage/sets/odyssey/RabidElephant.java @@ -1,117 +1,72 @@ -/* - * 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.sets.odyssey; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.BecomesBlockedTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.game.Game; -import mage.game.combat.CombatGroup; - -/** - * - * @author LevelX2 - */ -public class RabidElephant extends CardImpl { - - public RabidElephant(UUID ownerId) { - super(ownerId, 263, "Rabid Elephant", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{G}"); - this.expansionSetCode = "ODY"; - this.subtype.add("Elephant"); - - this.power = new MageInt(3); - this.toughness = new MageInt(4); - - // Whenever Rabid Elephant becomes blocked, it gets +2/+2 until end of turn for each creature blocking it. - this.addAbility(new RabidElephantAbility()); - } - - public RabidElephant(final RabidElephant card) { - super(card); - } - - @Override - public RabidElephant copy() { - return new RabidElephant(this); - } -} - -class RabidElephantAbility extends BecomesBlockedTriggeredAbility { - - public RabidElephantAbility() { - super(null, false); - RabidElephantValue value = new RabidElephantValue(); - this.addEffect(new BoostSourceEffect(value, value, Duration.EndOfTurn)); - } - - public RabidElephantAbility(final RabidElephantAbility ability) { - super(ability); - } - - @Override - public RabidElephantAbility copy() { - return new RabidElephantAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} becomes blocked, it gets +2/+2 until end of turn for each creature blocking it."; - } -} - -class RabidElephantValue implements DynamicValue { - - @Override - public RabidElephantValue copy() { - return new RabidElephantValue(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - for(CombatGroup combatGroup : game.getCombat().getGroups()) { - if(combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { - int blockers = combatGroup.getBlockers().size(); - return blockers > 1 ? (blockers) * 2 : 0; - } - } - return 0; - } - - @Override - public String getMessage() { - return "+2/+2 until end of turn for each creature blocking it"; - } -} +/* + * 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.sets.odyssey; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class RabidElephant extends CardImpl { + + public RabidElephant(UUID ownerId) { + super(ownerId, 263, "Rabid Elephant", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{G}"); + this.expansionSetCode = "ODY"; + this.subtype.add("Elephant"); + + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Whenever Rabid Elephant becomes blocked, it gets +2/+2 until end of turn for each creature blocking it. + DynamicValue value = new MultipliedValue(new BlockedCreatureCount(),2); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +2/+2 until end of turn for each creature blocking it"); + this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); + } + + public RabidElephant(final RabidElephant card) { + super(card); + } + + @Override + public RabidElephant copy() { + return new RabidElephant(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/onslaught/WordsOfWind.java b/Mage.Sets/src/mage/sets/onslaught/WordsOfWind.java index 756f729d359..fae884fb83a 100644 --- a/Mage.Sets/src/mage/sets/onslaught/WordsOfWind.java +++ b/Mage.Sets/src/mage/sets/onslaught/WordsOfWind.java @@ -92,7 +92,7 @@ class WordsOfWindEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { game.informPlayers("Each player returns a permanent he or she controls to its owner's hand instead"); - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { TargetControlledPermanent target = new TargetControlledPermanent(); diff --git a/Mage.Sets/src/mage/sets/planechase/SyphonSoul.java b/Mage.Sets/src/mage/sets/planechase/SyphonSoul.java index e8906dabdaa..6b643e265cc 100644 --- a/Mage.Sets/src/mage/sets/planechase/SyphonSoul.java +++ b/Mage.Sets/src/mage/sets/planechase/SyphonSoul.java @@ -74,7 +74,7 @@ class SyphonSoulEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int damageDealt = 0; - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { if (!playerId.equals(source.getControllerId())) { damageDealt += game.getPlayer(playerId).damage(2, source.getSourceId(), game, false, true); } diff --git a/Mage.Sets/src/mage/sets/portalsecondage/RazorclawBear.java b/Mage.Sets/src/mage/sets/portalsecondage/RazorclawBear.java index f8746c1fa22..3fda93ee35a 100644 --- a/Mage.Sets/src/mage/sets/portalsecondage/RazorclawBear.java +++ b/Mage.Sets/src/mage/sets/portalsecondage/RazorclawBear.java @@ -52,7 +52,7 @@ public class RazorclawBear extends CardImpl { // Whenever Razorclaw Bear becomes blocked, it gets +2/+2 until end of turn. Effect effect = new BoostSourceEffect(2, 2, Duration.EndOfTurn); - effect.setText("it gets +2/+2 until end of turn for each creature blocking it"); + effect.setText("it gets +2/+2 until end of turn"); this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/PestilenceDemon.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/PestilenceDemon.java index 0256675d651..c34ee564b2a 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/PestilenceDemon.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/PestilenceDemon.java @@ -90,7 +90,7 @@ class PestilenceDemonEffect extends OneShotEffect { p.damage(1, source.getSourceId(), game, false, true); } } - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player p = game.getPlayer(playerId); if (p != null) { p.damage(1, source.getSourceId(), game, false, true); diff --git a/Mage.Sets/src/mage/sets/scourge/DecreeOfAnnihilation.java b/Mage.Sets/src/mage/sets/scourge/DecreeOfAnnihilation.java index 8f1efa909a3..6c92e5b9ee9 100644 --- a/Mage.Sets/src/mage/sets/scourge/DecreeOfAnnihilation.java +++ b/Mage.Sets/src/mage/sets/scourge/DecreeOfAnnihilation.java @@ -108,7 +108,7 @@ class DecreeOfAnnihilationEffect extends OneShotEffect { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { permanent.moveToExile(id, "all artifacts, creatures, and land", id, game); } - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { for (UUID cid : player.getHand().copy()) { diff --git a/Mage.Sets/src/mage/sets/stronghold/SpinedSliver.java b/Mage.Sets/src/mage/sets/stronghold/SpinedSliver.java index da10b8dc8f6..cf3f572246f 100644 --- a/Mage.Sets/src/mage/sets/stronghold/SpinedSliver.java +++ b/Mage.Sets/src/mage/sets/stronghold/SpinedSliver.java @@ -32,6 +32,8 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.cards.CardImpl; @@ -54,7 +56,6 @@ public class SpinedSliver extends CardImpl { filter.add(new SubtypePredicate("Sliver")); } - public SpinedSliver(UUID ownerId) { super(ownerId, 142, "Spined Sliver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{R}{G}"); this.expansionSetCode = "STH"; @@ -64,7 +65,10 @@ public class SpinedSliver extends CardImpl { this.toughness = new MageInt(2); // Whenever a Sliver becomes blocked, that Sliver gets +1/+1 until end of turn for each creature blocking it. - Ability ability = new BecomesBlockedByCreatureTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false); + BlockedCreatureCount value = new BlockedCreatureCount(); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +1/+1 until end of turn for each creature blocking it"); + Ability ability = new BecomesBlockedByCreatureTriggeredAbility(effect, false); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter, diff --git a/Mage.Sets/src/mage/sets/timespiral/KaervekTheMerciless.java b/Mage.Sets/src/mage/sets/timespiral/KaervekTheMerciless.java index 3264e6a9e19..fd737f8ec50 100644 --- a/Mage.Sets/src/mage/sets/timespiral/KaervekTheMerciless.java +++ b/Mage.Sets/src/mage/sets/timespiral/KaervekTheMerciless.java @@ -98,9 +98,9 @@ class KaervekTheMercilessEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - MageObject spellCast = game.getObject(targetPointer.getFirst(game, source)); + MageObject spellCast = game.getObject(getTargetPointer().getFirst(game, source)); if (spellCast instanceof Spell) { - int cost = ((Spell)spellCast).getConvertedManaCost(); + int cost = ((Spell) spellCast).getConvertedManaCost(); Player target = game.getPlayer(source.getFirstTarget()); if (target != null) { target.damage(cost, source.getSourceId(), game, false, true); @@ -108,7 +108,7 @@ class KaervekTheMercilessEffect extends OneShotEffect { } Permanent targetCreature = game.getPermanent(source.getFirstTarget()); if (targetCreature != null) { - targetCreature.damage(cost, source.getSourceId(), game, true, false); + targetCreature.damage(cost, source.getSourceId(), game, false, true); return true; } } diff --git a/Mage.Sets/src/mage/sets/timespiral/TemporalIsolation.java b/Mage.Sets/src/mage/sets/timespiral/TemporalIsolation.java index 804e68e1a8b..4f13fd224c1 100644 --- a/Mage.Sets/src/mage/sets/timespiral/TemporalIsolation.java +++ b/Mage.Sets/src/mage/sets/timespiral/TemporalIsolation.java @@ -57,7 +57,6 @@ public class TemporalIsolation extends CardImpl { this.expansionSetCode = "TSP"; this.subtype.add("Aura"); - // Flash this.addAbility(FlashAbility.getInstance()); // Enchant creature @@ -65,11 +64,11 @@ public class TemporalIsolation extends CardImpl { this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); - this.addAbility(ability); + this.addAbility(ability); // Enchanted creature has shadow. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ShadowAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield))); // Prevent all damage that would be dealt by enchanted creature. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PreventAllDamageByAttachedEffect(Duration.WhileOnBattlefield, "enchanted creature", false))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PreventAllDamageByAttachedEffect(Duration.WhileOnBattlefield, "enchanted creature", false))); } public TemporalIsolation(final TemporalIsolation card) { diff --git a/Mage.Sets/src/mage/sets/urzaslegacy/GangOfElk.java b/Mage.Sets/src/mage/sets/urzaslegacy/GangOfElk.java index ec2120547f7..c3ccea99283 100644 --- a/Mage.Sets/src/mage/sets/urzaslegacy/GangOfElk.java +++ b/Mage.Sets/src/mage/sets/urzaslegacy/GangOfElk.java @@ -29,17 +29,16 @@ package mage.sets.urzaslegacy; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BecomesBlockedTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.BlockedCreatureCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; -import mage.game.Game; -import mage.game.combat.CombatGroup; /** * @@ -57,7 +56,10 @@ public class GangOfElk extends CardImpl { this.toughness = new MageInt(4); // Whenever Gang of Elk becomes blocked, it gets +2/+2 until end of turn for each creature blocking it. - this.addAbility(new GangOfElkAbility()); + DynamicValue value = new MultipliedValue(new BlockedCreatureCount(), 2); + Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn); + effect.setText("it gets +2/+2 until end of turn for each creature blocking it"); + this.addAbility(new BecomesBlockedTriggeredAbility(effect, false)); } public GangOfElk(final GangOfElk card) { @@ -69,50 +71,3 @@ public class GangOfElk extends CardImpl { return new GangOfElk(this); } } - -class GangOfElkAbility extends BecomesBlockedTriggeredAbility { - - public GangOfElkAbility() { - super(null, false); - GangOfElkValue value = new GangOfElkValue(); - this.addEffect(new BoostSourceEffect(value, value, Duration.EndOfTurn)); - } - - public GangOfElkAbility(final GangOfElkAbility ability) { - super(ability); - } - - @Override - public GangOfElkAbility copy() { - return new GangOfElkAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} becomes blocked, it gets +2/+2 until end of turn for each creature blocking it."; - } -} - -class GangOfElkValue implements DynamicValue { - - @Override - public GangOfElkValue copy() { - return new GangOfElkValue(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - for(CombatGroup combatGroup : game.getCombat().getGroups()) { - if(combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { - int blockers = combatGroup.getBlockers().size(); - return blockers > 1 ? (blockers) * 2 : 0; - } - } - return 0; - } - - @Override - public String getMessage() { - return "+2/+2 until end of turn for each creature blocking it"; - } -} diff --git a/Mage.Sets/src/mage/sets/urzassaga/Whetstone.java b/Mage.Sets/src/mage/sets/urzassaga/Whetstone.java index 0dc9de8d86b..b513741ee9f 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Whetstone.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Whetstone.java @@ -80,7 +80,7 @@ class WhetstoneEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getPlayerList()) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { player.moveCards(player.getLibrary().getTopCards(game, 2), Zone.LIBRARY, Zone.GRAVEYARD, source, game); diff --git a/Mage.Sets/src/mage/sets/zendikar/WorldQueller.java b/Mage.Sets/src/mage/sets/zendikar/WorldQueller.java index d85879e1ff7..53cdea0dacc 100644 --- a/Mage.Sets/src/mage/sets/zendikar/WorldQueller.java +++ b/Mage.Sets/src/mage/sets/zendikar/WorldQueller.java @@ -45,7 +45,6 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.choices.Choice; import mage.choices.ChoiceImpl; -import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; @@ -115,12 +114,12 @@ class WorldQuellerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { List chosen = new ArrayList<>(); - Player you = game.getPlayer(source.getControllerId()); + Player player = game.getPlayer(source.getControllerId()); Permanent sourceCreature = game.getPermanent(source.getSourceId()); - if (you != null && sourceCreature != null) { + if (player != null && sourceCreature != null) { Choice choiceImpl = new ChoiceImpl(); choiceImpl.setChoices(choice); - while (you.canRespond() && !you.choose(Outcome.Neutral, choiceImpl, game)) {} + while (player.canRespond() && !player.choose(Outcome.Neutral, choiceImpl, game)) {} CardType type = null; String choosenType = choiceImpl.getChoice(); @@ -148,26 +147,11 @@ class WorldQuellerEffect extends OneShotEffect { TargetPermanent target = new TargetControlledPermanent(1, 1, filter, false); target.setNotTarget(true); - // you always go first - if (target.canChoose(you.getId(), game)) { - while (you.canRespond() && !target.isChosen() && target.canChoose(you.getId(), game)) { - you.choose(Outcome.Sacrifice, target, source.getSourceId(), game); - } - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null) { - chosen.add(permanent); - } - } - - target.clearChosen(); - - // opponents follow - for (UUID playerId : game.getPlayerList()) { - if (playerId != you.getId()) { - Player player = game.getPlayer(playerId); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player2 = game.getPlayer(playerId); if (target.canChoose(playerId, game)) { - while (!target.isChosen() && target.canChoose(playerId, game)) { - player.chooseTarget(Outcome.Sacrifice, target, source, game); + while (player2.canRespond() && !target.isChosen() && target.canChoose(playerId, game)) { + player2.chooseTarget(Outcome.Sacrifice, target, source, game); } Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { @@ -175,7 +159,6 @@ class WorldQuellerEffect extends OneShotEffect { } target.clearChosen(); } - } } // all chosen permanents are sacrificed together diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SurgeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SurgeTest.java index 171781717c0..a636fe4d5bc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SurgeTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SurgeTest.java @@ -70,17 +70,26 @@ public class SurgeTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Crush of Tentacles"); // {4}{U}{U} addCard(Zone.HAND, playerA, "Lightning Bolt"); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + + // Put a token onto the battlefield that's a copy of target creature you control. + // Flashback {5}{U}{U}(You may cast this card from your graveyard for its flashback cost. Then exile it.) + addCard(Zone.HAND, playerB, "Cackling Counterpart"); + addCard(Zone.BATTLEFIELD, playerB, "Island", 3); addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Cackling Counterpart", "Silvercoat Lion"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crush of Tentacles with surge"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); assertGraveyardCount(playerA, "Lightning Bolt", 1); + assertGraveyardCount(playerB, "Cackling Counterpart", 1); assertGraveyardCount(playerA, "Crush of Tentacles", 1); assertPermanentCount(playerA, "Octopus", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 0); assertHandCount(playerA, "Silvercoat Lion", 1); assertHandCount(playerB, "Silvercoat Lion", 1); assertPermanentCount(playerA, 7); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/prevention/PreventAttachedEffectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/prevention/PreventAttachedEffectTest.java new file mode 100644 index 00000000000..3cc1fec3c2f --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/prevention/PreventAttachedEffectTest.java @@ -0,0 +1,80 @@ +/* + * 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 org.mage.test.cards.prevention; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class PreventAttachedEffectTest extends CardTestPlayerBase { + + /** + * Kaervek the Merciless still deals damage with the triggered ability when + * enchanted with Temporal Isolation. + */ + @Test + public void testDamageToPlayerPrevented() { + // Whenever an opponent casts a spell, Kaervek the Merciless deals damage to target creature or player equal to that spell's converted mana cost. + addCard(Zone.BATTLEFIELD, playerA, "Kaervek the Merciless"); + // Flash + // Enchant creature + // Enchanted creature has shadow. + // Prevent all damage that would be dealt by enchanted creature. + addCard(Zone.HAND, playerA, "Temporal Isolation", 1); // {1}{W} + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); // {1}{W} + addCard(Zone.HAND, playerB, "Pillarfield Ox", 1); // {3}{W} + addCard(Zone.BATTLEFIELD, playerB, "Plains", 6); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Temporal Isolation", "Kaervek the Merciless"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); + addTarget(playerA, playerB); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pillarfield Ox"); + addTarget(playerA, "Silvercoat Lion"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Kaervek the Merciless", 1); + assertPermanentCount(playerA, "Temporal Isolation", 1); + + assertPermanentCount(playerB, "Silvercoat Lion", 1); + assertPermanentCount(playerB, "Pillarfield Ox", 1); + + assertLife(playerA, 20); + assertLife(playerB, 20); + } + +} 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 8618a73267d..588dd63444a 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 @@ -63,10 +63,12 @@ import mage.constants.SpellAbilityType; import mage.constants.Zone; import mage.counters.Counter; import mage.counters.Counters; +import mage.filter.Filter; import mage.filter.FilterPermanent; import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterCreatureForCombat; import mage.filter.common.FilterCreatureForCombatBlock; +import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.common.FilterPlaneswalkerPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.NamePredicate; @@ -99,6 +101,7 @@ import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInOpponentsGraveyard; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreaturePermanentAmount; import mage.target.common.TargetPermanentOrPlayer; import mage.util.MessageToClient; @@ -742,7 +745,23 @@ public class TestPlayer implements Player { if (target.getTargetController() != null && target.getAbilityController() != null) { abilityControllerId = target.getAbilityController(); } - if ((target instanceof TargetPermanent) || (target instanceof TargetPermanentOrPlayer)) { + if (target instanceof TargetPlayer || target instanceof TargetCreatureOrPlayer) { + for (String targetDefinition : targets) { + if (targetDefinition.startsWith("targetPlayer=")) { + String playerName = targetDefinition.substring(targetDefinition.indexOf("targetPlayer=") + 13); + for (Player player : game.getPlayers().values()) { + if (player.getName().equals(playerName) + && target.canTarget(computerPlayer.getId(), player.getId(), source, game)) { + target.add(player.getId(), game); + targets.remove(targetDefinition); + return true; + } + } + } + } + + } + if ((target instanceof TargetPermanent) || (target instanceof TargetPermanentOrPlayer) || (target instanceof TargetCreatureOrPlayer)) { for (String targetDefinition : targets) { String[] targetList = targetDefinition.split("\\^"); boolean targetFound = false; @@ -759,9 +778,13 @@ public class TestPlayer implements Player { targetName = targetName.substring(0, targetName.length() - 11); } } - for (Permanent permanent : game.getBattlefield().getAllActivePermanents((FilterPermanent) target.getFilter(), game)) { + Filter filter = target.getFilter(); + if (filter instanceof FilterCreatureOrPlayer) { + filter = ((FilterCreatureOrPlayer) filter).getCreatureFilter(); + } + for (Permanent permanent : game.getBattlefield().getAllActivePermanents((FilterPermanent) filter, game)) { if (permanent.getName().equals(targetName) || (permanent.getName() + "-" + permanent.getExpansionSetCode()).equals(targetName)) { - if (((TargetPermanent) target).canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) { + if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) { if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) { target.add(permanent.getId(), game); targetFound = true; @@ -770,6 +793,7 @@ public class TestPlayer implements Player { } } } + } if (targetFound) { targets.remove(targetDefinition); @@ -777,22 +801,7 @@ public class TestPlayer implements Player { } } } - if (target instanceof TargetPlayer) { - for (String targetDefinition : targets) { - if (targetDefinition.startsWith("targetPlayer=")) { - String playerName = targetDefinition.substring(targetDefinition.indexOf("targetPlayer=") + 13); - for (Player player : game.getPlayers().values()) { - if (player.getName().equals(playerName) - && ((TargetPlayer) target).canTarget(computerPlayer.getId(), player.getId(), source, game)) { - target.add(player.getId(), game); - targets.remove(targetDefinition); - return true; - } - } - } - } - } if (target instanceof TargetCardInHand) { for (String targetDefinition : targets) { String[] targetList = targetDefinition.split("\\^"); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/BlockedCreatureCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/BlockedCreatureCount.java new file mode 100644 index 00000000000..78ac659e793 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/BlockedCreatureCount.java @@ -0,0 +1,91 @@ +/* + * 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.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.game.Game; +import mage.game.combat.CombatGroup; + +/** + * + * @author Markedagain + */ +public class BlockedCreatureCount implements DynamicValue { + + private String message; + boolean beyondTheFirst; + + public BlockedCreatureCount() { + this("each creature blocking it"); + } + + public BlockedCreatureCount(String message) { + this(message, false); + } + + public BlockedCreatureCount(String message, boolean beyondTheFist) { + this.message = message; + } + + public BlockedCreatureCount(final BlockedCreatureCount dynamicValue) { + super(); + this.message = dynamicValue.message; + this.beyondTheFirst = dynamicValue.beyondTheFirst; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + for (CombatGroup combatGroup : game.getCombat().getGroups()) { + if (combatGroup.getAttackers().contains(sourceAbility.getSourceId())) { + int blockers = combatGroup.getBlockers().size(); + if (beyondTheFirst) { + blockers = blockers > 0 ? blockers - 1 : 0; + } + return blockers; + } + } + return 0; + } + + @Override + public BlockedCreatureCount copy() { + return new BlockedCreatureCount(this); + } + + @Override + public String getMessage() { + return message; + } + + @Override + public String toString() { + return "X"; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageByAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageByAttachedEffect.java index 9c39034d8b3..9911a2bc789 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageByAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PreventAllDamageByAttachedEffect.java @@ -25,7 +25,6 @@ * 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; @@ -39,13 +38,12 @@ import mage.game.permanent.Permanent; * * @author LevelX2 */ - public class PreventAllDamageByAttachedEffect extends PreventionEffectImpl { private final String attachedDescription; public PreventAllDamageByAttachedEffect(Duration duration, String attachedDescription, boolean onlyCombat) { - super(duration, Integer.MAX_VALUE, onlyCombat); + super(duration, Integer.MAX_VALUE, onlyCombat, false); this.attachedDescription = attachedDescription; staticText = setText(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromBattlefieldAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromBattlefieldAllEffect.java index 67977bfa6d2..403295e818d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromBattlefieldAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromBattlefieldAllEffect.java @@ -27,10 +27,11 @@ */ package mage.abilities.effects.common; +import java.util.HashSet; +import java.util.Set; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.Card; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterPermanent; @@ -61,11 +62,11 @@ public class ReturnToHandFromBattlefieldAllEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Cards cardsToHand = new CardsImpl(); + Set permanentsToHand = new HashSet<>(); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - cardsToHand.add(permanent); + permanentsToHand.add(permanent); } - controller.moveCards(cardsToHand, Zone.HAND, source, game); + controller.moveCards(permanentsToHand, Zone.HAND, source, game); return true; } return false; diff --git a/Mage/src/main/java/mage/cards/decks/Constructed.java b/Mage/src/main/java/mage/cards/decks/Constructed.java index c8c385e76d7..85cb94b9afa 100644 --- a/Mage/src/main/java/mage/cards/decks/Constructed.java +++ b/Mage/src/main/java/mage/cards/decks/Constructed.java @@ -108,14 +108,16 @@ public class Constructed extends DeckValidator { if (!rarities.isEmpty()) { for (Card card : deck.getCards()) { if (!rarities.contains(card.getRarity())) { - invalid.put(card.getName(), "Invalid rarity: " + card.getRarity()); - valid = false; + if( !legalRarity(card) ){ + valid = false; + } } } for (Card card : deck.getSideboard()) { if (!rarities.contains(card.getRarity())) { - invalid.put(card.getName(), "Invalid rarity: " + card.getRarity()); - valid = false; + if( !legalRarity(card) ){ + valid = false; + } } } } @@ -123,34 +125,14 @@ public class Constructed extends DeckValidator { if (!setCodes.isEmpty()) { for (Card card : deck.getCards()) { if (!setCodes.contains(card.getExpansionSetCode())) { - // check if card is legal if taken from other set - boolean legal = false; - List cardInfos = CardRepository.instance.findCards(card.getName()); - for (CardInfo cardInfo : cardInfos) { - if (setCodes.contains(cardInfo.getSetCode())) { - legal = true; - break; - } - } - if (!legal && !invalid.containsKey(card.getName())) { - invalid.put(card.getName(), "Invalid set: " + card.getExpansionSetCode()); + if( !legalSets(card) ){ valid = false; } } } for (Card card : deck.getSideboard()) { if (!setCodes.contains(card.getExpansionSetCode())) { - // check if card is legal if taken from other set - boolean legal = false; - List cardInfos = CardRepository.instance.findCards(card.getName()); - for (CardInfo cardInfo : cardInfos) { - if (setCodes.contains(cardInfo.getSetCode())) { - legal = true; - break; - } - } - if (!legal && !invalid.containsKey(card.getName())) { - invalid.put(card.getName(), "Invalid set: " + card.getExpansionSetCode()); + if( !legalSets(card) ){ valid = false; } } @@ -159,5 +141,46 @@ public class Constructed extends DeckValidator { logger.debug("DECK validate end: " + name + " deckname: " + deck.getName() + " invalids:" + invalid.size()); return valid; } + + /** + * Checks if the given card is legal in any of the given rarities + * @param card - the card to check + * @return Whether the card was printed at any of the given rarities. + */ + protected boolean legalRarity(Card card){ + // check if card is legal if taken from other set + boolean legal = false; + List cardInfos = CardRepository.instance.findCards(card.getName()); + for (CardInfo cardInfo : cardInfos) { + if (rarities.contains(cardInfo.getRarity())) { + legal = true; + break; + } + } + if (!legal && !invalid.containsKey(card.getName())) { + invalid.put(card.getName(), "Invalid rarity: " + card.getRarity()); + } + return legal; + } + /** + * Checks if the given card is legal in any of the given sets + * @param card - the card to check + * @return Whether the card was printed in any of this format's sets. + */ + protected boolean legalSets(Card card) { + // check if card is legal if taken from other set + boolean legal = false; + List cardInfos = CardRepository.instance.findCards(card.getName()); + for (CardInfo cardInfo : cardInfos) { + if (setCodes.contains(cardInfo.getSetCode())) { + legal = true; + break; + } + } + if (!legal && !invalid.containsKey(card.getName())) { + invalid.put(card.getName(), "Invalid set: " + card.getExpansionSetCode()); + } + return legal; + } }