From f78d79e91429b5d5401c29b836c4a984bded0bc3 Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sat, 3 Sep 2016 23:35:32 -0400 Subject: [PATCH 01/26] Implement Tonic Peddler --- .../sets/mercadianmasques/TonicPeddler.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/TonicPeddler.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/TonicPeddler.java b/Mage.Sets/src/mage/sets/mercadianmasques/TonicPeddler.java new file mode 100644 index 00000000000..d2c6735619f --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/TonicPeddler.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mercadianmasques; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.GainLifeTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author Derpthemeus + */ +public class TonicPeddler extends CardImpl { + + public TonicPeddler(UUID ownerId) { + super(ownerId, 54, "Tonic Peddler", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Human"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {W}, {tap}, Discard a card: Target player gains 3 life. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeTargetEffect(3), new ManaCostsImpl("{W}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public TonicPeddler(final TonicPeddler card) { + super(card); + } + + @Override + public TonicPeddler copy() { + return new TonicPeddler(this); + } +} From dcf5a0593a08630680123fb6c78ec98db61bd837 Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sat, 3 Sep 2016 23:35:55 -0400 Subject: [PATCH 02/26] Implement Soothing Balm --- .../sets/mercadianmasques/SoothingBalm.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/SoothingBalm.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SoothingBalm.java b/Mage.Sets/src/mage/sets/mercadianmasques/SoothingBalm.java new file mode 100644 index 00000000000..e348c3cfd5e --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SoothingBalm.java @@ -0,0 +1,60 @@ +/* + * 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.abilities.effects.common.GainLifeTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetPlayer; + +/** + * + * @author Derpthemeus + */ +public class SoothingBalm extends CardImpl { + + public SoothingBalm(UUID ownerId) { + super(ownerId, 48, "Soothing Balm", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "MMQ"; + + // Target player gains 5 life. + this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().addEffect(new GainLifeTargetEffect(5)); + } + + public SoothingBalm(final SoothingBalm card) { + super(card); + } + + @Override + public SoothingBalm copy() { + return new SoothingBalm(this); + } +} From 0f66d41744f2e561d0693400f56efded5141ebf4 Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sat, 3 Sep 2016 23:36:48 -0400 Subject: [PATCH 03/26] Implement Rushwood Elemental --- .../mercadianmasques/RushwoodElemental.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/RushwoodElemental.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodElemental.java b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodElemental.java new file mode 100644 index 00000000000..4e16964b65d --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodElemental.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.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.counters.CounterType; + +/** + * + * @author Derpthemeus + */ +public class RushwoodElemental extends CardImpl { + + public RushwoodElemental(UUID ownerId) { + super(ownerId, 264, "Rushwood Elemental", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{G}{G}{G}{G}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Elemental"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + // At the beginning of your upkeep, you may put a +1/+1 counter on Rushwood Elemental. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, true)); + } + + public RushwoodElemental(final RushwoodElemental card) { + super(card); + } + + @Override + public RushwoodElemental copy() { + return new RushwoodElemental(this); + } +} From fb5087683f990123ae4549e5342b10b2254cca34 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 4 Sep 2016 22:34:43 +1000 Subject: [PATCH 04/26] spjspj - Implement new token source (mtg.onl) for downloading of tokens to tokenDescriptor format in TOK.zip --- .../card/dl/sources/CardImageSource.java | 2 + .../dl/sources/MagicCardsImageSource.java | 10 + .../card/dl/sources/MtgImageSource.java | 10 + .../dl/sources/MtgOnlTokensImageSource.java | 358 ++++++++++++++++++ .../dl/sources/MythicspoilerComSource.java | 10 + .../card/dl/sources/TokensMtgImageSource.java | 10 + .../dl/sources/WizardCardsImageSource.java | 10 + .../plugins/card/images/DownloadPictures.java | 75 +++- .../plugins/card/utils/CardImageUtils.java | 11 + 9 files changed, 481 insertions(+), 15 deletions(-) create mode 100644 Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java index b84f07cc1ad..5ac34ceb127 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java @@ -10,6 +10,8 @@ public interface CardImageSource { String generateURL(CardDownloadData card) throws Exception; String generateTokenUrl(CardDownloadData card) throws Exception; + String getNextHttpImageUrl(); + String getFileForHttpImage(String httpImageUrl); String getSourceName(); Float getAverageSize(); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java index 9b5f589a08e..df1ebc90cae 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java @@ -145,6 +145,16 @@ public class MagicCardsImageSource implements CardImageSource { } return instance; } + + @Override + public String getNextHttpImageUrl() { + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + return null; + } @Override public String generateURL(CardDownloadData card) throws Exception { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java index 1ff1f21c035..b7f77ac791b 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java @@ -54,6 +54,16 @@ public class MtgImageSource implements CardImageSource { public String getSourceName() { return "mtgimage.com"; } + + @Override + public String getNextHttpImageUrl() { + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + return null; + } @Override public String generateURL(CardDownloadData card) throws Exception { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java new file mode 100644 index 00000000000..f91179d0b4b --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java @@ -0,0 +1,358 @@ +/* + * 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.plugins.card.dl.sources; + +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import org.apache.log4j.Logger; +import org.mage.plugins.card.images.CardDownloadData; +import org.mage.plugins.card.images.DownloadPictures; + +/** + * + * @author spjspj + */ +public class MtgOnlTokensImageSource implements CardImageSource { + + private static final Logger logger = Logger.getLogger(MtgOnlTokensImageSource.class); + + private static CardImageSource instance = new MtgOnlTokensImageSource(); + + public static CardImageSource getInstance() { + if (instance == null) { + instance = new MtgOnlTokensImageSource(); + } + return instance; + } + + @Override + public String getSourceName() { + return "http://mtg.onl/token-list/tokens/"; + } + + @Override + public Float getAverageSize() { + return 26.7f; + } + + @Override + public String getNextHttpImageUrl() { + if (copyUrlToImage == null) { + setupLinks(); + } + + for (String key : copyUrlToImageDone.keySet()) { + if (copyUrlToImageDone.get(key) == false) { + copyUrlToImageDone.put(key, true); + return key; + } + } + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + if (httpImageUrl != null) { + return copyUrlToImage.get(httpImageUrl); + } + return null; + } + + @Override + public String generateURL(CardDownloadData card) throws Exception { + return null; + } + + HashMap copyUrlToImage = null; + HashMap copyImageToUrl = null; + HashMap copyUrlToImageDone = null; + + private void setupLinks() { + if (copyUrlToImage != null) { + return; + } + copyUrlToImage = new HashMap(); + copyImageToUrl = new HashMap(); + copyUrlToImageDone = new HashMap(); + copyUrlToImage.put("Angel_B_3_3.jpg", "ANGEL.B.ANGEL.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Angel_W_3_3.jpg", "ANGEL.W.ANGEL.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Angel_W_4_4.jpg", "ANGEL.W.ANGEL.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Ape_G_2_2.jpg", "APE.G.APE.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Ape_G_3_3.jpg", "APE.G.APE.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Ashaya_the_Awoken_World_G_4_4.jpg", "ASHAYATHEAWOKENWORLD.G.ELEMENTAL.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Assassin_B_1_1.jpg", "ASSASSIN.B.ASSASSIN.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Assembly-Worker_2_2.jpg", "ASSEMBLYWORKER..ASSEMBLYWORKER.ARTIFACTCREATURE.2.2.full.jpg"); + copyUrlToImage.put("Avatar_W_y_y.jpg", "AVATAR.W.AVATAR.CREATURE.S.S.full.jpg"); + copyUrlToImage.put("Bat_B_1_1.jpg", "BAT.B.BAT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Bat_B_1_2.jpg", "BAT.B.BAT.CREATURE.1.2.full.jpg"); + copyUrlToImage.put("Bear_G_2_2.jpg", "BEAR.G.BEAR.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Bear_G_4_4.jpg", "BEAR.G.BEAR.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Beast_B_3_3.jpg", "BEAST.B.BEAST.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Beast_G_3_3.jpg", "BEAST.G.BEAST.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Beast_G_2_2.jpg", "BEAST.G.BEAST.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Beast_G_4_4.jpg", "BEAST.G.BEAST.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Beast_G_5_5.jpg", "BEAST.G.BEAST.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Beast_RGW_8_8.jpg", "BEAST.WRG.BEAST.CREATURE.8.8.full.jpg"); + copyUrlToImage.put("Bird_Soldier_W_1_1.jpg", "BIRDSOLDIER.W.BIRD.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Bird_U_1_1.jpg", "BIRD.U.BIRD.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Bird_U_2_2.jpg", "BIRD.U.BIRD.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Bird_U_2_2_Enchantment.jpg", "BIRD.U.BIRD.ENCHANTMENTCREATURE.2.2.full.jpg"); + copyUrlToImage.put("Bird_WU_1_1.jpg", "BIRD.WU.BIRD.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Bird_W_1_1.jpg", "BIRD.W.BIRD.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Bird_W_3_3.jpg", "BIRD.W.BIRD.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Bird_W_3_4.jpg", "BIRD.W.BIRD.CREATURE.3.4.full.jpg"); + copyUrlToImage.put("Boar_G_2_2.jpg", "BOAR.G.BOAR.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Boar_G_3_3.jpg", "BOAR.G.BOAR.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Butterfly_G_1_1.jpg", "BUTTERFLY.G.INSECT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Camarid_U_1_1.jpg", "CAMARID.U.CAMARID.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Caribou_W_0_1.jpg", "CARIBOU.W.CARIBOU.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Carnivore_R_3_1.jpg", "CARNIVORE.R.BEAST.CREATURE.3.1.full.jpg"); + copyUrlToImage.put("Cat_B_2_1.jpg", "CAT.B.CAT.CREATURE.2.1.full.jpg"); + copyUrlToImage.put("Cat_G_1_1.jpg", "CAT.G.CAT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Cat_R_1_1.jpg", "CAT.R.CAT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Cat_Soldier_W_1_1.jpg", "CATSOLDIER.W.CATSOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Cat_W_2_2.jpg", "CAT.W.CAT.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Cat_Warrior_G_2_2.jpg", "CATWARRIOR.G.CATWARRIOR.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Centaur_G_3_3.jpg", "CENTAUR.G.CENTAUR.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Centaur_G_3_3_Enchantment.jpg", "CENTAUR.G.CENTAUR.ENCHANTMENTCREATURE.3.3.full.jpg"); + copyUrlToImage.put("Centaur_G_3_3_protection.jpg", "CENTAUR.G.CENTAUR.CREATURE.3.3a.full.jpg"); + copyUrlToImage.put("Citizen_W_1_1.jpg", "CITIZEN.W.CITIZEN.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Cleric_WB_1_1.jpg", "CLERIC.WB.CLERIC.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Cleric_W_2_1.jpg", "CLERIC.W.CLERIC.CREATUREENCHANTMENT.2.1.full.jpg"); + copyUrlToImage.put("Cloud_Sprite_U_1_1.jpg", "CLOUDSPRITE.U.FAERIE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Clue.jpg", "CLUE..CLUE.ARTIFACT.0.0.full.jpg"); + copyUrlToImage.put("Construct_1_1.jpg", "CONSTRUCT..CONSTRUCT.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Construct_6_12.jpg", "CONSTRUCT..CONSTRUCT.CREATUREARTIFACT.6.12.full.jpg"); + copyUrlToImage.put("Demon_B_5_5.jpg", "DEMON.B.DEMON.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Demon_B_y_y.jpg", "DEMON.B.DEMON.CREATURE.S.S.full.jpg"); + copyUrlToImage.put("Devil_R_1_1.jpg", "DEVIL.R.DEVIL.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Djinn_5_5.jpg", "DJINN..DJINN.ARTIFACTCREATURE.5.5.full.jpg"); + copyUrlToImage.put("Djinn_Monk_U_2_2.jpg", "DJINNMONK.U.DJINNMONK.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Dragon_RG_1_1.jpg", "DRAGON.RG.DRAGON.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Dragon_R_2_2.jpg", "DRAGON.R.DRAGON.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Dragon_R_4_4.jpg", "DRAGON.R.DRAGON.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Dragon_R_5_5.jpg", "DRAGON.R.DRAGON.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Dragon_R_6_6.jpg", "DRAGON.R.DRAGON.CREATURE.6.6.full.jpg"); + copyUrlToImage.put("Dragon_Spirit_U_5_5.jpg", "DRAGONSPIRIT.U.DRAGONSPIRIT.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Drake_UG_2_2.jpg", "DRAKE.UG.DRAKE.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Drake_U_2_2.jpg", "DRAKE.U.DRAKE.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Eldrazi_10_10.jpg", "ELDRAZI..ELDRAZI.CREATURE.10.10.full.jpg"); + copyUrlToImage.put("Eldrazi_Scion_1_1.jpg", "ELDRAZISCION..ELDRAZISCION.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Eldrazi_Spawn_0_1.jpg", "ELDRAZISPAWN..ELDRAZISPAWN.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Elemental_BR_5_5.jpg", "ELEMENTAL.BR.ELEMENTAL.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Elemental_GW_y_y.jpg", "ELEMENTAL.WG.ELEMENTAL.CREATURE.S.S.full.jpg"); + copyUrlToImage.put("Elemental_G_2_2.jpg", "ELEMENTAL.G.ELEMENTAL.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Elemental_G_4_4.jpg", "ELEMENTAL.G.ELEMENTAL.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Elemental_G_5_3.jpg", "ELEMENTAL.G.ELEMENTAL.CREATURE.5.3.full.jpg"); + copyUrlToImage.put("Elemental_G_7_7.jpg", "ELEMENTAL.G.ELEMENTAL.CREATURE.7.7.full.jpg"); + copyUrlToImage.put("Elemental_R_7_1.jpg", "ELEMENTAL.R.ELEMENTAL.CREATURE.7.1.full.jpg"); + copyUrlToImage.put("Elemental_Shaman_R_3_1.jpg", "ELEMENTALSHAMAN.R.ELEMENTALSHAMAN.CREATURE.3.1.full.jpg"); + copyUrlToImage.put("Elephant_G_3_3.jpg", "ELEPHANT.G.ELEPHANT.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Elf_Druid_G_1_1.jpg", "ELFDRUID.G.ELFDRUID.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Elf_G_1_1.jpg", "ELFWARRIOR.G.ELFWARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Elf_Warrior_GW_1_1.jpg", "ELFWARRIOR.WG.ELFWARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Elf_Warrior_G_1_1.jpg", "ELFWARRIOR.G.ELFWARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Faerie_Rogue_B_1_1.jpg", "FAERIEROGUE.B.FAERIEROGUE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Faerie_Rogue_UB_1_1.jpg", "FAERIEROGUE.UB.FAERIEROGUE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Faerie_U_1_1.jpg", "FAERIE.U.FAERIE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Festering_Goblin_B_1_1.jpg", "FESTERINGGOBLIN.B.ZOMBIEGOBLIN.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Fish_U_3_3.jpg", "FISH.U.FISH.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Frog_Lizard_G_3_3.jpg", "FROGLIZARD.G.FROGLIZARD.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Gargoyle_3_4.jpg", "GARGOYLE..GARGOYLE.CREATUREARTIFACT.3.4.full.jpg"); + copyUrlToImage.put("Germ_B_0_0.jpg", "GERM.B.GERM.CREATURE.0.0.full.jpg"); + copyUrlToImage.put("Giant_R_4_4.jpg", "GIANT.R.GIANT.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Giant_Warrior_RG_4_4.jpg", "GIANTWARRIOR.RG.GIANTWARRIOR.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Giant_Warrior_W_5_5.jpg", "GIANTWARRIOR.W.GIANTWARRIOR.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Gnome_1_1.jpg", "GNOME..GNOME.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Goat_W_0_1.jpg", "GOAT.W.GOAT.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Goblin_R_1_1.jpg", "GOBLIN.R.GOBLIN.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Goblin_R_2_1.jpg", "GOBLIN.R.GOBLIN.CREATURE.2.1.full.jpg"); + copyUrlToImage.put("Goblin_Rogue_B_1_1.jpg", "GOBLINROGUE.B.GOBLINROGUE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Goblin_Scout_R_1_1.jpg", "GOBLINSCOUT.R.GOBLINSCOUT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Goblin_Soldier_RW_1_1.jpg", "GOBLINSOLDIER.WR.GOBLINSOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Goblin_Warrior_RG_1_1.jpg", "GOBLINWARRIOR.RG.GOBLINWARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Gold_.jpg", "GOLD...ARTIFACT.0.0.full.jpg"); + copyUrlToImage.put("Goldmeadow_Harrier_W_1_1.jpg", "GOLDMEADOWHARRIER.W.KITHKINSOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Golem_3_3.jpg", "GOLEM..GOLEM.ARTIFACTCREATURE.3.3.full.jpg"); + copyUrlToImage.put("Golem_3_3_Enchantment.jpg", "GOLEM..GOLEM.ENCHANTMENTARTIFACTCREATURE.3.3.full.jpg"); + copyUrlToImage.put("Golem_9_9.jpg", "GOLEM..GOLEM.ARTIFACTCREATURE.9.9.full.jpg"); + copyUrlToImage.put("Graveborn_BR_3_1.jpg", "GRAVEBORN.BR.GRAVEBORN.CREATURE.3.1.full.jpg"); + copyUrlToImage.put("Griffin_W_2_2.jpg", "GRIFFIN.W.GRIFFIN.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Harpy_B_1_1.jpg", "HARPY.B.HARPY.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Hellion_R_4_4.jpg", "HELLION.R.HELLION.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Hippo_G_1_1.jpg", "HIPPO.G.HIPPO.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Homunculus_U_0_1.jpg", "HOMUNCULUS.U.HOMUNCULUS.CREATUREARTIFACT.0.1.full.jpg"); + copyUrlToImage.put("Homunculus_U_2_2.jpg", "HOMUNCULUS.U.HOMUNCULUS.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Hornet_1_1.jpg", "HORNET..INSECT.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Horror_B_4_4.jpg", "HORROR.B.HORROR.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Horror_B_X_X.jpg", "HORROR.B.HORROR.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Horror_UB_1_1.jpg", "HORROR.UB.HORROR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Horror_X_X.jpg", "HORROR..HORROR.ARTIFACTCREATURE.X.X.full.jpg"); + copyUrlToImage.put("Hound_G_1_1.jpg", "HOUND.G.HOUND.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Human_Cleric_WB_1_1.jpg", "HUMANCLERIC.WB.HUMANCLERIC.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Human_R_1_1.jpg", "HUMAN.R.HUMAN.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Human_Soldier_W_1_1.jpg", "HUMANSOLDIER.W.HUMANSOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Human_W_1_1.jpg", "HUMAN.W.HUMAN.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Hydra_G_X_X.jpg", "HYDRA.G.HYDRA.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Illusion_U_1_1.jpg", "ILLUSION.U.ILLUSION.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Illusion_U_2_2.jpg", "ILLUSION.U.ILLUSION.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Insect_G_1_1.jpg", "INSECT.G.INSECT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Insect_G_6_1.jpg", "INSECT.G.INSECT.CREATURE.6.1.full.jpg"); + copyUrlToImage.put("Kaldra_4_4.jpg", "KALDRA..AVATAR.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Kavu_B_3_3.jpg", "KAVU.B.KAVU.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Kelp_U_0_1.jpg", "KELP.U.PLANTWALL.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Kithkin_Soldier_W_1_1.jpg", "KITHKINSOLDIER.W.KITHKINSOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Knight_Ally_W_2_2.jpg", "KNIGHTALLY.W.KNIGHTALLY.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Knight_B_2_2.jpg", "KNIGHT.B.KNIGHT.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Knight_W_1_1.jpg", "KNIGHT.W.KNIGHT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Knight_W_2_2.jpg", "KNIGHT.W.KNIGHT.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Kobolds_of_Kher_Keep_R_0_1.jpg", "KOBOLDSOFKHERKEEP.R.KOBOLD.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Kor_Ally_W_1_1.jpg", "KORALLY.W.KORALLY.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Kor_Soldier_W_1_1.jpg", "KORSOLDIER.W.KORSOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Kraken_U_9_9.jpg", "KRAKEN.U.KRAKEN.CREATURE.9.9.full.jpg"); + copyUrlToImage.put("Landmine_.jpg", "LANDMINE...ARTIFACT.0.0.full.jpg"); + copyUrlToImage.put("Lightning_Ranger_R_5_1.jpg", "LIGHTNINGRAGER.R.ELEMENTAL.CREATURE.5.1.full.jpg"); + copyUrlToImage.put("Lizard_G_2_2.jpg", "LIZARD.G.LIZARD.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Llanowar_Elves_G_1_1.jpg", "LLANOWARELVES.G.ELFDRUID.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Marit_Lage_B_20_20.jpg", "MARITLAGE.B.AVATAR.CREATURE.20.20.full.jpg"); + copyUrlToImage.put("Merfolk_U_1_1.jpg", "MERFOLK.U.MERFOLK.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Merfolk_Wizard_U_1_1.jpg", "MERFOLKWIZARD.U.MERFOLKWIZARD.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Metallic_Sliver_1_1.jpg", "METALLICSLIVER..SLIVER.CREATUREARTIFACT.1.1.full.jpg"); + copyUrlToImage.put("Minion_B_1_1.jpg", "MINION.B.MINION.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Minion_B_X_X.jpg", "MINION.B.MINION.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Minor_Demon_BR_1_1.jpg", "MINORDEMON.BR.DEMON.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Minotaur_R_2_3.jpg", "MINOTAUR.R.MINOTAUR.CREATURE.2.3.full.jpg"); + copyUrlToImage.put("Monk_W_1_1.jpg", "MONK.W.MONK.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Myr_1_1.jpg", "MYR..MYR.CREATUREARTIFACT.1.1.full.jpg"); + copyUrlToImage.put("Octopus_U_8_8.jpg", "OCTOPUS.U.OCTOPUS.CREATURE.8.8.full.jpg"); + copyUrlToImage.put("Ogre_R_3_3.jpg", "OGRE.R.OGRE.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Ogre_R_4_4.jpg", "OGRE.R.OGRE.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Ooze_G_1_1.jpg", "OOZE.G.OOZE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Ooze_G_2_2.jpg", "OOZE.G.OOZE.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Ooze_G_3_3.jpg", "OOZE.G.OOZE.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Orb_U_X_X.jpg", "ORB.U.ORB.CREATURE.X.X.jpg.full.jpg"); + copyUrlToImage.put("Pegasus_W_1_1.jpg", "PEGASUS.W.PEGASUS.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Pentavite_1_1.jpg", "PENTAVITE..PENTAVITE.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Pest_0_1.jpg", "PEST..PEST.ARTIFACTCREATURE.0.1.full.jpg"); + copyUrlToImage.put("Pincher_2_2.jpg", "PINCHER..PINCHER.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Plant_G_0_1.jpg", "PLANT.G.PLANT.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Plant_G_1_1.jpg", "PLANT.G.PLANT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Rat_B_1_1.jpg", "RAT.B.RAT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Reflection_W_2_2.jpg", "REFLECTION.W.REFLECTION.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Rhino_G_4_4.jpg", "RHINO.G.RHINO.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Rukh_R_4_4.jpg", "BIRD.R.BIRD.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Sand_1_1.jpg", "SAND..SAND.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Sand_Warrior_RGW_1_1.jpg", "SANDWARRIOR.WRG.SANDWARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Saporling_G_1_1.jpg", "SAPROLING.G.SAPROLING.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Satyr_RG_2_2.jpg", "SATYR.RG.SATYR.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Serf_B_0_1.jpg", "SERF.B.SERF.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Shapeshifter_1_1.jpg", "SHAPESHIFTER..SHAPESHIFTER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Skeleton_B_1_1.jpg", "SKELETON.B.SKELETON.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Sliver_1_1.jpg", "SLIVER..SLIVER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Snake_1_1.jpg", "SNAKE..SNAKE.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Snake_B_1_1.jpg", "SNAKE.B.SNAKE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Snake_GB_1_1.jpg", "SNAKE.BG.SNAKE.ENCHANTMENTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Snake_GU_1_1.jpg", "SNAKE.UG.SNAKE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Snake_G_1_1.jpg", "SNAKE.G.SNAKE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Soldier_Ally_W_1_1.jpg", "SOLDIERALLY.W.SOLDIERALLY.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Soldier_RW_1_1.jpg", "SOLDIER.WR.SOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Soldier_R_1_1.jpg", "SOLDIER.R.SOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Soldier_W_1_1.jpg", "SOLDIER.W.SOLDIER.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Soldier_W_1_1_Enchantment.jpg", "SOLDIER.W.SOLDIER.ENCHANTMENTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Spark_Elemental_R_3_1.jpg", "SPARKELEMENTAL.R.ELEMENTAL.CREATURE.3.1.full.jpg"); + copyUrlToImage.put("Spawn_2_2.jpg", "SPAWN..SPAWN.ARTIFACTCREATURE.2.2.full.jpg"); + copyUrlToImage.put("Sphinx_U_4_4.jpg", "SPHINX.U.SPHINX.CREATURE.4.4.full.jpg"); + copyUrlToImage.put("Spider_B_2_4.jpg", "SPIDER.B.SPIDER.CREATURE.2.4.full.jpg"); + copyUrlToImage.put("Spider_G_1_2.jpg", "SPIDER.G.SPIDER.CREATURE.1.2.full.jpg"); + copyUrlToImage.put("Spider_G_1_3.jpg", "SPIDER.G.SPIDER.ENCHANTMENTCREATURE.1.3.full.jpg"); + copyUrlToImage.put("Spike_G_1_1.jpg", "SPIKE.G.SPIKE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Spirit_1_1.jpg", "SPIRIT..SPIRIT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Spirit_U_1_1.jpg", "SPIRIT.U.SPIRIT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Spirit_WB_1_1.jpg", "SPIRIT.WB.SPIRIT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Spirit_WB_y_y.jpg", "SPIRIT.WB.SPIRIT.ENCHANTMENTCREATURE.S.S.full.jpg"); + copyUrlToImage.put("Spirit_W_1_1.jpg", "SPIRIT.W.SPIRIT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Spirit_W_3_3.jpg", "SPIRIT.W.SPIRIT.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Spirit_Warror_BG_y_y.jpg", "SPIRITWARRIOR.BG.SPIRITWARRIOR.CREATURE.S.S.full.jpg"); + copyUrlToImage.put("Squid_U_1_1.jpg", "SQUID.U.SQUID.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Squirrel_G_1_1.jpg", "SQUIRREL.G.SQUIRREL.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Stoneforged_Blade_.jpg", "STONEFORGEDBLADE..EQUIPMENT.ARTIFACT.0.0.full.jpg"); + copyUrlToImage.put("Tetravite_1_1.jpg", "TETRAVITE..TETRAVITE.CREATUREARTIFACT.1.1.full.jpg"); + copyUrlToImage.put("Thopter_1_1.jpg", "THOPTER..THOPTER.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Thopter_U_1_1.jpg", "THOPTER.U.THOPTER.CREATUREARTIFACT.1.1.full.jpg"); + copyUrlToImage.put("Thrull_B_0_1.jpg", "THRULL.B.THRULL.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Thrull_B_1_1.jpg", "THRULL.B.THRULL.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Treefolk_G_X_X.jpg", "TREEFOLK.G.TREEFOLK.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Treefolk_Shaman_G_2_5.jpg", "TREEFOLKSHAMAN.G.TREEFOLKSHAMAN.CREATURE.2.5.full.jpg"); + copyUrlToImage.put("Treefolk_Warrior_G_y_y.jpg", "TREEFOLKWARRIOR.G.TREEFOLKWARRIOR.CREATURE.S.S.full.jpg"); + copyUrlToImage.put("Triskelavite_1_1.jpg", "TRISKELAVITE..TRISKELAVITE.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Tuktuk_the_Returned_5_5.jpg", "TUKTUKTHERETURNED..GOBLIN.ARTIFACTCREATURE.5.5.full.jpg"); + copyUrlToImage.put("Urami_B_5_5.jpg", "URAMI.B.DEMONSPIRIT.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Vampire_B_1_1.jpg", "VAMPIRE.B.VAMPIRE.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Vampire_B_2_2.jpg", "VAMPIRE.B.VAMPIRE.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Vampire_B_X_X.jpg", "VAMPIRE.B.VAMPIRE.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Vampire_Knight_B_1_1.jpg", "VAMPIREKNIGHT.B.VAMPIREKNIGHT.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Voja_GW_2_2.jpg", "VOJA.WG.WOLF.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Wall_U_5_5.jpg", "WALL.U.WALL.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Warrior_B_2_1.jpg", "WARRIOR.B.WARRIOR.CREATURE.2.1.full.jpg"); + copyUrlToImage.put("Warrior_R_1_1.jpg", "WARRIOR.R.WARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Warrior_W_1_1.jpg", "WARRIOR.W.WARRIOR.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Wasp_1_1.jpg", "WASP..INSECT.ARTIFACTCREATURE.1.1.full.jpg"); + copyUrlToImage.put("Weird_U_3_3.jpg", "WEIRD.U.WEIRD.CREATURE.3.3.full.jpg"); + copyUrlToImage.put("Whale_U_6_6.jpg", "WHALE.U.WHALE.CREATURE.6.6.full.jpg"); + copyUrlToImage.put("Wirefly_2_2.jpg", "WIREFLY..INSECT.ARTIFACTCREATURE.2.2.full.jpg"); + copyUrlToImage.put("Wolf_G_2_2.jpg", "WOLF.G.WOLF.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Wood_G_0_1.jpg", "WOOD.G.WALL.CREATURE.0.1.full.jpg"); + copyUrlToImage.put("Worm_BG_1_1.jpg", "WORM.BG.WORM.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Wurm_3_3.jpg", "WURM..WURM.ARTIFACTCREATURE.3.3.full.jpg"); + copyUrlToImage.put("Wurm_B_6_6.jpg", "WURM.B.WURM.CREATURE.6.6.full.jpg"); + copyUrlToImage.put("Wurm_G_6_6.jpg", "WURM.G.WURM.CREATURE.6.6.full.jpg"); + copyUrlToImage.put("Zombie_B_2_2.jpg", "ZOMBIE.B.ZOMBIE.CREATURE.2.2.full.jpg"); + copyUrlToImage.put("Zombie_B_2_2_Enchantment.jpg", "ZOMBIE.B.ZOMBIE.ENCHANTMENTCREATURE.2.2.full.jpg"); + copyUrlToImage.put("Zombie_B_5_5.jpg", "ZOMBIEGIANT.B.ZOMBIEGIANT.CREATURE.5.5.full.jpg"); + copyUrlToImage.put("Zombie_B_X_X.jpg", "ZOMBIE.B.ZOMBIE.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Zombie_Horror_B_X_X.jpg", "ZOMBIEHORROR.B.ZOMBIEHORROR.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Zombie_U_X_X.jpg", "ZOMBIE.U.ZOMBIE.CREATURE.X.X.full.jpg"); + copyUrlToImage.put("Zombie_Wizard_UB_1_1.jpg", "ZOMBIEWIZARD.BG.ZOMBIEWIZARD.CREATURE.1.1.full.jpg"); + copyUrlToImage.put("Zombie_Wizard_UB_1_1.jpg", "ZOMBIEWIZARD.UB.ZOMBIEWIZARD.CREATURE.1.1.full.jpg"); + + for (String key : copyUrlToImage.keySet()) { + copyUrlToImageDone.put(key, false); + copyImageToUrl.put(copyUrlToImage.get(key), key); + } + } + + @Override + public String generateTokenUrl(CardDownloadData card) throws IOException { + + if (copyUrlToImage == null) { + setupLinks(); + } + return null; + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index 7883eaecce5..11b1657c08d 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -234,4 +234,14 @@ public class MythicspoilerComSource implements CardImageSource { public Float getAverageSize() { return 50.0f; } + + @Override + public String getNextHttpImageUrl() { + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + return null; + } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java index 0761b05cb4e..089085660bc 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java @@ -66,6 +66,16 @@ public class TokensMtgImageSource implements CardImageSource { public Float getAverageSize() { return 26.7f; } + + @Override + public String getNextHttpImageUrl() { + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + return null; + } @Override public String generateURL(CardDownloadData card) throws Exception { 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 b00d7b5621e..d07ac10d8f2 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 @@ -260,6 +260,16 @@ public class WizardCardsImageSource implements CardImageSource { languageAliases.put("de", "German"); } + @Override + public String getNextHttpImageUrl() { + return null; + } + + @Override + public String getFileForHttpImage(String httpImageUrl) { + return null; + } + private Map getSetLinks(String cardSet) { ConcurrentHashMap setLinks = new ConcurrentHashMap<>(); ExecutorService executor = Executors.newFixedThreadPool(10); 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 339db215fea..2a4a1ca9f43 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 @@ -58,6 +58,7 @@ import net.java.truevfs.kernel.spec.FsSyncException; import org.apache.log4j.Logger; import org.mage.plugins.card.dl.sources.CardImageSource; import org.mage.plugins.card.dl.sources.MagicCardsImageSource; +import org.mage.plugins.card.dl.sources.MtgOnlTokensImageSource; import org.mage.plugins.card.dl.sources.MythicspoilerComSource; import org.mage.plugins.card.dl.sources.TokensMtgImageSource; import org.mage.plugins.card.dl.sources.WizardCardsImageSource; @@ -145,6 +146,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab "wizards.com", "mythicspoiler.com", "tokens.mtg.onl", //"mtgimage.com (HQ)", + "mtg.onl" //"mtgathering.ru HQ", //"mtgathering.ru MQ", //"mtgathering.ru LQ", @@ -172,6 +174,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab case 3: cardImageSource = TokensMtgImageSource.getInstance(); break; + case 4: + cardImageSource = MtgOnlTokensImageSource.getInstance(); + break; } int count = DownloadPictures.this.cards.size(); float mb = (count * cardImageSource.getAverageSize()) / 1024; @@ -239,7 +244,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab TFile file; for (CardInfo card : allCards) { if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) { - CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), + CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard()); file = new TFile(CardImageUtils.generateImagePath(url)); if (!file.exists()) { @@ -492,14 +497,29 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab url = cardImageSource.generateURL(card); } - if (url != null) { + if (url == null) { + String imageRef = cardImageSource.getNextHttpImageUrl(); + String fileName = cardImageSource.getFileForHttpImage(imageRef); + if (imageRef != null && fileName != null) { + imageRef = cardImageSource.getSourceName() + imageRef; + try { + URL imageUrl = new URL(imageRef); + + Runnable task = new DownloadTask(imageUrl, fileName, 1); + executor.execute(task); + } catch (Exception ex) { + } + } else { + if (card != null) { + logger.info("Card not available on " + cardImageSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ")"); + synchronized (sync) { + update(cardIndex + 1, cardsToDownload.size()); + } + } + } + } else if (url != null) { Runnable task = new DownloadTask(card, new URL(url), cardsToDownload.size()); executor.execute(task); - } else { - logger.info("Card not available on " + cardImageSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ")"); - synchronized (sync) { - update(cardIndex + 1, cardsToDownload.size()); - } } } catch (Exception ex) { @@ -535,11 +555,23 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private final CardDownloadData card; private final URL url; private final int count; + private final String actualFilename; + private boolean useSpecifiedPaths; public DownloadTask(CardDownloadData card, URL url, int count) { this.card = card; this.url = url; this.count = count; + this.actualFilename = ""; + useSpecifiedPaths = false; + } + + public DownloadTask(URL url, String actualFilename, int count) { + this.card = null; + this.url = url; + this.count = count; + this.actualFilename = actualFilename; + useSpecifiedPaths = true; } @Override @@ -549,9 +581,20 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab TFile outputFile = null; try { filePath.append(Constants.IO.imageBaseDir); - filePath.append(card.hashCode()).append(".").append(card.getName().replace(":", "").replace("//", "-")).append(".jpg"); - temporaryFile = new File(filePath.toString()); - String imagePath = CardImageUtils.generateImagePath(card); + if (!useSpecifiedPaths && card != null) { + filePath.append(card.hashCode()).append(".").append(card.getName().replace(":", "").replace("//", "-")).append(".jpg"); + temporaryFile = new File(filePath.toString()); + } + String imagePath; + if (useSpecifiedPaths) { + imagePath = CardImageUtils.getTokenBasePath(); // temporaryFile = plugins/images\NUM.jace, telepath unbound.jpg + imagePath += actualFilename; // imagePath = d:\xmage_images\ORI.zip\ORI\Jace,telepathunbound.jpg + String tmpFile = filePath + actualFilename + ".2"; + temporaryFile = new File(tmpFile.toString()); + } else { + imagePath = CardImageUtils.generateImagePath(card); + } + outputFile = new TFile(imagePath); if (!outputFile.exists()) { outputFile.getParentFile().mkdirs(); @@ -599,7 +642,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab out.flush(); out.close(); - if (card.isTwoFacedCard()) { + if (card != null && card.isTwoFacedCard()) { BufferedImage image = ImageIO.read(temporaryFile); if (image.getHeight() == 470) { BufferedImage renderedImage = new BufferedImage(265, 370, BufferedImage.TYPE_INT_RGB); @@ -620,11 +663,13 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab new TFile(temporaryFile).cp_rp(outputFile); } } else { - logger.warn("Image download for " + card.getName() - + (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "") - + "(" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString()); + if (card != null) { + logger.warn("Image download for " + card.getName() + + (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "") + + "(" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString()); + } if (logger.isDebugEnabled()) { // Shows the returned html from the request to the web server - logger.debug("Return ed HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream())); + logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream())); } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java index 8e69839c567..d527c659dcd 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java @@ -117,6 +117,17 @@ public class CardImageUtils { return buildPath(imagesDir, set); } } + + public static String getTokenBasePath() { + String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true"); + String imagesPath = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null); + + if (PreferencesDialog.isSaveImagesToZip()) { + return imagesPath + TFile.separator + "TOK" + ".zip" + TFile.separator; + } else { + return imagesPath + TFile.separator + "TOK" + TFile.separator; + } + } private static String getTokenDescriptorImagePath(CardDownloadData card) { String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true"); From 5e911ca63cd5748c7b0152961bfb3e5b98a9dbe1 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Sun, 4 Sep 2016 09:08:46 -0500 Subject: [PATCH 05/26] Updated image sources for upcoming sets. --- .../plugins/card/dl/sources/MagicCardsImageSource.java | 6 ++++++ .../plugins/card/dl/sources/WizardCardsImageSource.java | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java index 9b5f589a08e..b6e2663a7ad 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java @@ -18,7 +18,9 @@ public class MagicCardsImageSource implements CardImageSource { { put("10E", "tenth-edition"); put("AER", "aether-revolt"); + put("AKH", "amonkhet"); put("ALA", "shards-of-alara"); + put("ANB", "archenemy-nicol-bolas"); put("APAC", "asia-pacific-land-program"); put("APC", "player-rewards-2001"); put("ARB", "alara-reborn"); @@ -32,6 +34,7 @@ public class MagicCardsImageSource implements CardImageSource { put("C15", "commander-2015"); put("C16", "commander-2016"); put("CLASH", "clash-pack"); + put("CMA", "commander-anthology"); put("CMA", "commanders-arsenal"); put("CMD", "commander"); put("CN2", "conspiracy-take-the-crown"); @@ -60,6 +63,7 @@ public class MagicCardsImageSource implements CardImageSource { put("DDP", "duel-decks-zendikar-vs-eldrazi"); put("DDQ", "duel-decks-blessed-vs-cursed"); put("DDR", "duel-decks-nissa-vs-ob-nixilis"); + put("DDS", "duel-decks-mind-vs-might"); put("DGM", "dragons-maze"); put("DKA", "dark-ascension"); put("DRB", "from-the-vault-dragons"); @@ -76,6 +80,7 @@ public class MagicCardsImageSource implements CardImageSource { put("GRC", "wpngateway"); put("GTC", "gatecrash"); put("HOP", "planechase"); + put("HOU", "hour-of-devastation"); put("INV", "player-rewards-2001"); put("ISD", "innistrad"); put("JOU", "journey-into-nyx"); @@ -94,6 +99,7 @@ public class MagicCardsImageSource implements CardImageSource { put("MGDC", "magic-game-day-cards"); put("MLP", "launch-party"); put("MM2", "modern-masters-2015"); + put("MM3", "modern-masters-2017"); put("MMA", "modern-masters"); put("MOR", "morningtide"); put("MPRP", "magic-player-rewards"); 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 b00d7b5621e..9045412d25e 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 @@ -89,8 +89,10 @@ public class WizardCardsImageSource implements CardImageSource { setsAliases.put("8ED", "Eighth Edition"); setsAliases.put("9ED", "Ninth Edition"); setsAliases.put("AER", "Aether Revolt"); + setsAliases.put("AKH", "Amonkhet"); setsAliases.put("ALA", "Shards of Alara"); setsAliases.put("ALL", "Alliances"); + setsAliases.put("ANB", "Archenemy: Nicol Bolas"); setsAliases.put("APC", "Apocalypse"); setsAliases.put("ARB", "Alara Reborn"); setsAliases.put("ARC", "Archenemy"); @@ -107,6 +109,7 @@ public class WizardCardsImageSource implements CardImageSource { setsAliases.put("C14", "Commander 2014"); setsAliases.put("C15", "Commander 2015"); setsAliases.put("C16", "Commander 2016"); + setsAliases.put("CMA", "Commander Anthology"); setsAliases.put("CHK", "Champions of Kamigawa"); setsAliases.put("CHR", "Chronicles"); setsAliases.put("CMD", "Magic: The Gathering-Commander"); @@ -134,7 +137,8 @@ public class WizardCardsImageSource implements CardImageSource { setsAliases.put("DDO", "Duel Decks: Elspeth vs. Kiora"); setsAliases.put("DDP", "Duel Decks: Zendikar vs. Eldrazi"); setsAliases.put("DDQ", "Duel Decks: Blessed vs. Cursed"); - setsAliases.put("DDR", "Duel Decks: Nissa vs Ob Nixilis"); + setsAliases.put("DDR", "Duel Decks: Nissa vs. Ob Nixilis"); + setsAliases.put("DDS", "Duel Decks: Mind vs. Might"); setsAliases.put("DGM", "Dragon's Maze"); setsAliases.put("DIS", "Dissension"); setsAliases.put("DKA", "Dark Ascension"); @@ -159,6 +163,7 @@ public class WizardCardsImageSource implements CardImageSource { setsAliases.put("H09", "Premium Deck Series: Slivers"); setsAliases.put("HML", "Homelands"); setsAliases.put("HOP", "Planechase"); + setsAliases.put("HOU", "Hour of Devastation"); setsAliases.put("ICE", "Ice Age"); setsAliases.put("INV", "Invasion"); setsAliases.put("ISD", "Innistrad"); @@ -189,6 +194,7 @@ public class WizardCardsImageSource implements CardImageSource { setsAliases.put("MLP", "Launch Party"); setsAliases.put("MMA", "Modern Masters"); setsAliases.put("MM2", "Modern Masters 2015"); + setsAliases.put("MM3", "Modern Masters 2017"); setsAliases.put("MMQ", "Mercadian Masques"); setsAliases.put("MOR", "Morningtide"); setsAliases.put("MPRP", "Magic Player Rewards"); From 87fa8888529dabd23fc6c1db8409856c5b5f7549 Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sun, 4 Sep 2016 10:39:12 -0400 Subject: [PATCH 06/26] Fix return value of LivingArmorEffect --- Mage.Sets/src/mage/sets/chronicles/LivingArmor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/chronicles/LivingArmor.java b/Mage.Sets/src/mage/sets/chronicles/LivingArmor.java index 5567e3a84e1..eeb1f865534 100644 --- a/Mage.Sets/src/mage/sets/chronicles/LivingArmor.java +++ b/Mage.Sets/src/mage/sets/chronicles/LivingArmor.java @@ -91,6 +91,7 @@ public class LivingArmor extends CardImpl { if (creature != null) { int amount = creature.getConvertedManaCost(); creature.addCounters(new BoostCounter(0, 1, amount), game); + return true; } return false; } From 507ddd871125d0d31fdf88329eb68ea18bf226ee Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 4 Sep 2016 17:14:27 +0200 Subject: [PATCH 07/26] * Necromancer's Magemark - Fixed replacement effect that was coded as triggered ability. --- .../sets/guildpact/NecromancersMagemark.java | 80 ++++++++++++++++--- .../KalitasTraitorOfGhet.java | 8 +- .../replacement/KalitasTraitorOfGhetTest.java | 55 ++++++++++--- 3 files changed, 119 insertions(+), 24 deletions(-) diff --git a/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java b/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java index 3b1a1d62470..ee646a5cf31 100644 --- a/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java +++ b/Mage.Sets/src/mage/sets/guildpact/NecromancersMagemark.java @@ -29,11 +29,9 @@ 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.ReplacementEffectImpl; 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; @@ -46,6 +44,11 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -55,12 +58,13 @@ import mage.target.common.TargetCreaturePermanent; */ public class NecromancersMagemark extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control that are enchanted"); + 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"; @@ -72,13 +76,13 @@ public class NecromancersMagemark extends CardImpl { 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)); + 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); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NecromancersMagemarkEffect())); } public NecromancersMagemark(final NecromancersMagemark card) { @@ -90,3 +94,61 @@ public class NecromancersMagemark extends CardImpl { return new NecromancersMagemark(this); } } + +class NecromancersMagemarkEffect extends ReplacementEffectImpl { + + public NecromancersMagemarkEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If a creature you control that's enchanted would die, return it to its owner's hand instead"; + } + + public NecromancersMagemarkEffect(final NecromancersMagemarkEffect effect) { + super(effect); + } + + @Override + public NecromancersMagemarkEffect copy() { + return new NecromancersMagemarkEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (permanent != null) { + controller.moveCards(permanent, Zone.HAND, source, game); + return true; + } + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.ZONE_CHANGE); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone().equals(Zone.BATTLEFIELD) && zEvent.getToZone().equals(Zone.GRAVEYARD)) { + Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + for (UUID attachmentId : permanent.getAttachments()) { + Permanent attachment = game.getPermanentOrLKIBattlefield(attachmentId); + if (attachment != null && attachment.getSubtype(game).contains("Aura")) { + return true; + } + } + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/oathofthegatewatch/KalitasTraitorOfGhet.java b/Mage.Sets/src/mage/sets/oathofthegatewatch/KalitasTraitorOfGhet.java index 45033a33995..2e21ba1e903 100644 --- a/Mage.Sets/src/mage/sets/oathofthegatewatch/KalitasTraitorOfGhet.java +++ b/Mage.Sets/src/mage/sets/oathofthegatewatch/KalitasTraitorOfGhet.java @@ -63,7 +63,7 @@ import mage.target.common.TargetControlledCreaturePermanent; * @author fireshoes */ public class KalitasTraitorOfGhet extends CardImpl { - + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another Vampire or Zombie"); static { @@ -83,10 +83,10 @@ public class KalitasTraitorOfGhet extends CardImpl { // Lifelink this.addAbility(LifelinkAbility.getInstance()); - + // If a nontoken creature an opponent controls would die, instead exile that card and put a 2/2 black Zombie creature token onto the battlefield. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KalitasTraitorOfGhetEffect())); - + // {2}{B}, Sacrifice another Vampire or Zombie: Put two +1/+1 counters on Kalitas, Traitor of Ghet. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), new ManaCostsImpl("{2}{B}")); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); @@ -131,7 +131,7 @@ class KalitasTraitorOfGhetEffect extends ReplacementEffectImpl { if (((ZoneChangeEvent) event).getFromZone().equals(Zone.BATTLEFIELD)) { Permanent permanent = ((ZoneChangeEvent) event).getTarget(); if (permanent != null) { - controller.moveCardToExileWithInfo(permanent, null, null, source.getSourceId(), game, Zone.BATTLEFIELD, true); + controller.moveCards(permanent, Zone.EXILED, source, game); new CreateTokenEffect(new ZombieToken()).apply(game, source); return true; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/KalitasTraitorOfGhetTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/KalitasTraitorOfGhetTest.java index 5191c1ae612..427ab5bfb53 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/KalitasTraitorOfGhetTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/KalitasTraitorOfGhetTest.java @@ -15,41 +15,74 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public class KalitasTraitorOfGhetTest extends CardTestPlayerBase { - + /* * Reported bug: Damnation with Kalitas, Traitor of Ghet on my side and 3 opponent creatures, it only exiled 1 creature giving me only 1 zombie instead of 3. - */ + */ @Test public void testDamnation() { - + /* Kalitas, Traitor of Ghet {2}{B}{B} 3/4 lifelink - Legendary Vampire If a nontoken creature an opponent controls would die, instead exile that card and put a 2/2 black Zombie creature token onto the battlefield. - */ + */ addCard(Zone.BATTLEFIELD, playerA, "Kalitas, Traitor of Ghet", 1); /* Damnation {2}{B}{B} - Sorcery Destroy all creatures. They can't be regenerated. - */ + */ addCard(Zone.HAND, playerA, "Damnation", 1); - + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); - + addCard(Zone.BATTLEFIELD, playerB, "Bronze Sable", 1); addCard(Zone.BATTLEFIELD, playerB, "Wall of Roots", 1); addCard(Zone.BATTLEFIELD, playerB, "Sigiled Starfish", 1); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Damnation"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - + assertGraveyardCount(playerA, "Kalitas, Traitor of Ghet", 1); assertGraveyardCount(playerA, "Damnation", 1); assertExileCount("Bronze Sable", 1); assertExileCount("Wall of Roots", 1); - assertExileCount("Sigiled Starfish", 1); + assertExileCount("Sigiled Starfish", 1); assertGraveyardCount(playerB, 0); // all 3 creatures of playerB should be exiled not in graveyard - assertExileCount("Kalitas, Traitor of Ghet", 0); // player controlled, not opponent so not exiled + assertExileCount("Kalitas, Traitor of Ghet", 0); // player controlled, not opponent so not exiled assertPermanentCount(playerA, "Zombie", 3); // 3 tokens generated from exiling 3 opponent's creatures } + + @Test + public void testDamnationGraveyard() { + + /* + Kalitas, Traitor of Ghet {2}{B}{B} 3/4 lifelink - Legendary Vampire + If a nontoken creature an opponent controls would die, instead exile that card and put a 2/2 black Zombie creature token onto the battlefield. + */ + addCard(Zone.GRAVEYARD, playerA, "Kalitas, Traitor of Ghet", 1); + /* + Damnation {2}{B}{B} - Sorcery + Destroy all creatures. They can't be regenerated. + */ + addCard(Zone.HAND, playerA, "Damnation", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + + addCard(Zone.BATTLEFIELD, playerB, "Bronze Sable", 1); + addCard(Zone.BATTLEFIELD, playerB, "Wall of Roots", 1); + addCard(Zone.BATTLEFIELD, playerB, "Sigiled Starfish", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Damnation"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Kalitas, Traitor of Ghet", 1); + assertGraveyardCount(playerA, "Damnation", 1); + assertGraveyardCount(playerB, "Bronze Sable", 1); + assertGraveyardCount(playerB, "Wall of Roots", 1); + assertGraveyardCount(playerB, "Sigiled Starfish", 1); + assertPermanentCount(playerA, "Zombie", 0); // 3 tokens generated from exiling 3 opponent's creatures + } + } From 133f0434114b73a39d7915b930cd9b0c57f83324 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 4 Sep 2016 17:17:34 +0200 Subject: [PATCH 08/26] * Orcish Spy - Fixed that the activated ability did not work. --- Mage.Sets/src/mage/sets/fallenempires/OrcishSpy1.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy1.java b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy1.java index cc6aed47697..27f7b40f698 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy1.java +++ b/Mage.Sets/src/mage/sets/fallenempires/OrcishSpy1.java @@ -52,8 +52,8 @@ public class OrcishSpy1 extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // {tap}: Look at the top three cards of target player's library. - Ability ability = new SimpleActivatedAbility(Zone.LIBRARY, new LookLibraryTopCardTargetPlayerEffect(3), new TapSourceCost()); + // {T}: Look at the top three cards of target player's library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryTopCardTargetPlayerEffect(3), new TapSourceCost()); this.addAbility(ability); } From 3d19637e8565d75291adc8c4e9339e8a939d774d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 4 Sep 2016 17:41:33 +0200 Subject: [PATCH 09/26] Added test for Oracle of Dust activated ability. --- .../activated/PutToGraveyardTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutToGraveyardTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutToGraveyardTest.java index dbb7b582684..1c3ab43a882 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutToGraveyardTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/activated/PutToGraveyardTest.java @@ -72,4 +72,32 @@ public class PutToGraveyardTest extends CardTestPlayerBase { } + /** + * Oracle of Dust does not seem to actually move cards from exile into the + * opponent's graveyard, even though every other part of the ability works + * just fine. + */ + @Test + public void testExileToGraveyard2() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // Devoid + // {2}, Put a card an opponent owns from exile into that player's graveyard: Draw a card, then discard a card. + addCard(Zone.BATTLEFIELD, playerA, "Oracle of Dust", 1); // {4}{U} + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + // Exile target creature. Its controller gains life equal to its power. + addCard(Zone.HAND, playerA, "Swords to Plowshares"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swords to Plowshares", "Silvercoat Lion"); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Swords to Plowshares", 1); + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + assertGraveyardCount(playerA, 2); + + } } From ce7c3d99a18f82f35cf0848b77dbf51181579360 Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sun, 4 Sep 2016 11:55:11 -0400 Subject: [PATCH 10/26] Implement Run Wild --- .../src/mage/sets/onslaught/RunWild.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/onslaught/RunWild.java diff --git a/Mage.Sets/src/mage/sets/onslaught/RunWild.java b/Mage.Sets/src/mage/sets/onslaught/RunWild.java new file mode 100644 index 00000000000..6bb70643dd3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/RunWild.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.onslaught; + +import java.util.UUID; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Derpthemeus + */ +public class RunWild extends CardImpl { + + public RunWild(UUID ownerId) { + super(ownerId, 279, "Run Wild", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{G}"); + this.expansionSetCode = "ONS"; + + // Until end of turn, target creature gains trample and "{G}: Regenerate this creature." + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + Effect effect1 = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); + effect1.setText("Until end of turn, target creature gains trample"); + this.getSpellAbility().addEffect(effect1); + + Effect effect2 = new GainAbilityTargetEffect(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{G}")), Duration.EndOfTurn); + effect2.setText("and \"{G}: Regenerate this creature\""); + this.getSpellAbility().addEffect(effect2); + + } + + public RunWild(final RunWild card) { + super(card); + } + + @Override + public RunWild copy() { + return new RunWild(this); + } +} From 7803847f4bd9d0f3184c8741ae0060121e5803ce Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sun, 4 Sep 2016 11:55:30 -0400 Subject: [PATCH 11/26] Implement Iron Lance --- .../mage/sets/mercadianmasques/IronLance.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/IronLance.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/IronLance.java b/Mage.Sets/src/mage/sets/mercadianmasques/IronLance.java new file mode 100644 index 00000000000..d586a32cb16 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/IronLance.java @@ -0,0 +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.mercadianmasques; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Derpthemeus + */ +public class IronLance extends CardImpl { + + public IronLance(UUID ownerId) { + super(ownerId, 300, "Iron Lance", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "MMQ"; + + // {3}, {tap}: Target creature gains first strike until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{3}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public IronLance(final IronLance card) { + super(card); + } + + @Override + public IronLance copy() { + return new IronLance(this); + } +} From f8c1a46645326d0ae6e2f5868b14b68420305263 Mon Sep 17 00:00:00 2001 From: Matt Oslan Date: Sun, 4 Sep 2016 11:56:35 -0400 Subject: [PATCH 12/26] Implement The Brute --- .../src/mage/sets/fifthedition/TheBrute.java | 79 +++++++++++++++++++ .../src/mage/sets/fourthedition/TheBrute.java | 52 ++++++++++++ Mage.Sets/src/mage/sets/legends/TheBrute.java | 52 ++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fifthedition/TheBrute.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/TheBrute.java create mode 100644 Mage.Sets/src/mage/sets/legends/TheBrute.java diff --git a/Mage.Sets/src/mage/sets/fifthedition/TheBrute.java b/Mage.Sets/src/mage/sets/fifthedition/TheBrute.java new file mode 100644 index 00000000000..916f7865fe4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/TheBrute.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.fifthedition; + +import java.util.UUID; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.RegenerateAttachedEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Derpthemeus + */ +public class TheBrute extends CardImpl { + + public TheBrute(UUID ownerId) { + super(ownerId, 272, "The Brute", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + this.expansionSetCode = "5ED"; + this.subtype.add("Aura"); + + // Enchant creature + TargetCreaturePermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + EnchantAbility ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets +1/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 0))); + + // {R}{R}{R}: Regenerate enchanted creature. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateAttachedEffect(AttachmentType.AURA), new ManaCostsImpl("{R}{R}{R}"))); + } + + public TheBrute(final TheBrute card) { + super(card); + } + + @Override + public TheBrute copy() { + return new TheBrute(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/TheBrute.java b/Mage.Sets/src/mage/sets/fourthedition/TheBrute.java new file mode 100644 index 00000000000..ecded18c12c --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/TheBrute.java @@ -0,0 +1,52 @@ +/* + * 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.fourthedition; + +import java.util.UUID; + +/** + * + * @author Derpthemeus + */ +public class TheBrute extends mage.sets.fifthedition.TheBrute { + + public TheBrute(UUID ownerId) { + super(ownerId); + this.cardNumber = "244"; + this.expansionSetCode = "4ED"; + } + + public TheBrute(final TheBrute card) { + super(card); + } + + @Override + public TheBrute copy() { + return new TheBrute(this); + } +} diff --git a/Mage.Sets/src/mage/sets/legends/TheBrute.java b/Mage.Sets/src/mage/sets/legends/TheBrute.java new file mode 100644 index 00000000000..fda190f1ed7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/TheBrute.java @@ -0,0 +1,52 @@ +/* + * 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.legends; + +import java.util.UUID; + +/** + * + * @author Derpthemeus + */ +public class TheBrute extends mage.sets.fifthedition.TheBrute { + + public TheBrute(UUID ownerId) { + super(ownerId); + this.cardNumber = "164"; + this.expansionSetCode = "LEG"; + } + + public TheBrute(final TheBrute card) { + super(card); + } + + @Override + public TheBrute copy() { + return new TheBrute(this); + } +} From b9d29d3ebfbcc05f80b2f8e0d221843e44f2302e Mon Sep 17 00:00:00 2001 From: fireshoes Date: Sun, 4 Sep 2016 22:54:05 -0500 Subject: [PATCH 13/26] Added upcoming sets. [KLD] Updated mtg-cards-data.txt. Added some simple cards. --- .../plugins/card/dl/sources/GathererSets.java | 31 +++-- .../src/main/resources/card-pictures-tok.txt | 12 ++ .../src/main/resources/image.url.properties | 4 +- Mage.Sets/src/mage/sets/Amonkhet.java | 56 ++++++++ .../src/mage/sets/ArchenemyNicolBolas.java | 52 +++++++ .../src/mage/sets/CommanderAnthology.java | 50 +++++++ .../src/mage/sets/HourOfDevastation.java | 60 ++++++++ Mage.Sets/src/mage/sets/MindVsMight.java | 30 ++++ .../src/mage/sets/ModernMasters2017.java | 61 ++++++++ .../mage/sets/kaladesh/AEtherTradewinds.java | 52 +++++++ .../src/mage/sets/kaladesh/BloomingMarsh.java | 72 ++++++++++ .../mage/sets/kaladesh/BotanicalSanctum.java | 72 ++++++++++ .../sets/kaladesh/ConcealedCourtyard.java | 72 ++++++++++ .../src/mage/sets/kaladesh/CurioVendor.java | 58 ++++++++ .../mage/sets/kaladesh/FiligreeFamiliar.java | 68 +++++++++ .../mage/sets/kaladesh/FuriousReprisal.java | 60 ++++++++ .../mage/sets/kaladesh/InspiringVantage.java | 72 ++++++++++ .../src/mage/sets/kaladesh/InventorsFair.java | 131 ++++++++++++++++++ .../mage/sets/kaladesh/SkyshipStalker.java | 79 +++++++++++ .../mage/sets/kaladesh/SpirebluffCanal.java | 72 ++++++++++ .../mage/sets/kaladesh/TasseledDromedary.java | 58 ++++++++ .../sets/kaladesh/TerrorOfTheFairgrounds.java | 58 ++++++++ .../mage/sets/kaladesh/VerdurousGearhulk.java | 81 +++++++++++ .../src/mage/sets/kaladesh/Whirlermaker.java | 66 +++++++++ Utils/known-sets.txt | 6 + Utils/mtg-cards-data.txt | 41 +++++- Utils/mtg-sets-data.txt | 6 + 27 files changed, 1463 insertions(+), 17 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/Amonkhet.java create mode 100644 Mage.Sets/src/mage/sets/ArchenemyNicolBolas.java create mode 100644 Mage.Sets/src/mage/sets/CommanderAnthology.java create mode 100644 Mage.Sets/src/mage/sets/HourOfDevastation.java create mode 100644 Mage.Sets/src/mage/sets/MindVsMight.java create mode 100644 Mage.Sets/src/mage/sets/ModernMasters2017.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/AEtherTradewinds.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/BloomingMarsh.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/BotanicalSanctum.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/ConcealedCourtyard.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/CurioVendor.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/FiligreeFamiliar.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/FuriousReprisal.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/InspiringVantage.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/InventorsFair.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/SkyshipStalker.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/SpirebluffCanal.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/TasseledDromedary.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/TerrorOfTheFairgrounds.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/VerdurousGearhulk.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/Whirlermaker.java diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java index 6b0ae72f593..0908e7847ff 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java @@ -19,42 +19,45 @@ public class GathererSets implements Iterable { "ARN", "ATQ", "LEG", "DRK", "FEM", "HML", "ICE", "ALL", "CSP", "MIR", "VIS", "WTH", - "TMP", "STH", "EXO", + "TMP", "STH", "EXO", "USG", "ULG", "UDS", "MMQ", "NMS", "PCY", "INV", "PLS", "APC", "ODY", "TOR", "JUD", "ONS", "LGN", "SCG", - "MRD", "DST", "5DN", - "CHK", "BOK", "SOK", - "RAV", "GPT", "DIS", - "TSP", "TSB", "PLC", "FUT", - "LRW", "MOR", + "MRD", "DST", "5DN", + "CHK", "BOK", "SOK", + "RAV", "GPT", "DIS", + "TSP", "TSB", "PLC", "FUT", + "LRW", "MOR", "SHM", "EVE", "MED", "ME2", "ME3", "ME4", "POR", "PO2", "PTK", + "ARC", "W16"}; - + private static final String[] withMythics = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI", - "DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN", - "DD3", "DD3B", "DDO", "DDP", "DDQ", "DDR", + "ANB", + "DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN", + "DD3", "DD3B", "DDO", "DDP", "DDQ", "DDR", "DDS", "FVD", "FVE", "FVL", "FVR", "V12", "V13", "V14", "V15", "V16", "ALA", "CON", "ARB", - "ZEN", "WWK", "ROE", + "ZEN", "WWK", "ROE", "SOM", "MBS", "NPH", - "CMD", "C13", "C14", "C15", "C16", + "CMD", "C13", "C14", "C15", "C16", "CMA", "PC2", "PCA", - "ISD", "DKA", "AVR", + "ISD", "DKA", "AVR", "RTR", "GTC", "DGM", - "MMA", "MM2", "EMA", + "MMA", "MM2", "EMA", "MM3", "THS", "BNG", "JOU", "CNS", "CN2", "VMA", "TPR", "KTK", "FRF", "DTK", "BFZ", "EXP", "OGW", "SOI", "EMN", - "KLD", "AER" + "KLD", "AER", + "AKH", "HOU" }; private static final HashMap symbolsReplacements = new HashMap<>(); diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt index c4070acff32..876297a2fa1 100644 --- a/Mage.Client/src/main/resources/card-pictures-tok.txt +++ b/Mage.Client/src/main/resources/card-pictures-tok.txt @@ -1,3 +1,15 @@ +|Generate|TOK:CN2|Assassin|| +|Generate|TOK:CN2|Beast|| +|Generate|TOK:CN2|Construct|| +|Generate|TOK:CN2|Dragon|| +|Generate|TOK:CN2|Goblin|| +|Generate|TOK:CN2|Insect|| +|Generate|TOK:CN2|Lizard|| +|Generate|TOK:CN2|Soldier|1| +|Generate|TOK:CN2|Soldier|2| +|Generate|TOK:CN2|Spirit|| +|Generate|TOK:CN2|Zombie|| + |Generate|TOK:EMA|Carnivore|| |Generate|TOK:EMA|Dragon|| |Generate|TOK:EMA|Elemental|1| diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties index d2c8221207f..488610d0575 100644 --- a/Mage.Client/src/main/resources/image.url.properties +++ b/Mage.Client/src/main/resources/image.url.properties @@ -74,6 +74,6 @@ dd3evg=ddaevg dd3gvl=ddagvl dd3jvc=ddajvc # Remove setname as soon as the images can be downloaded -ignore.urls=TOK,AER,PCA,C16,V16,KLD,DDR,CN2 +ignore.urls=TOK,AER,PCA,C16,DDR,DDS,ANB,AKH,HOU,MM3 # sets ordered by release time (newest goes first) -token.lookup.order=DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC \ No newline at end of file +token.lookup.order=ANB,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Amonkhet.java b/Mage.Sets/src/mage/sets/Amonkhet.java new file mode 100644 index 00000000000..54841cbabd6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/Amonkhet.java @@ -0,0 +1,56 @@ +/* + * 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.sets; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * + * @author fireshoes + */ +public class Amonkhet extends ExpansionSet { + + private static final Amonkhet fINSTANCE = new Amonkhet(); + + public static Amonkhet getInstance() { + return fINSTANCE; + } + + private Amonkhet() { + super("Amonkhet", "AKH", "mage.sets.amonkhet", new GregorianCalendar(2017, 4, 28).getTime(), SetType.EXPANSION); + this.blockName = "Amonkhet"; + this.hasBoosters = true; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + } +} diff --git a/Mage.Sets/src/mage/sets/ArchenemyNicolBolas.java b/Mage.Sets/src/mage/sets/ArchenemyNicolBolas.java new file mode 100644 index 00000000000..32b25f34719 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ArchenemyNicolBolas.java @@ -0,0 +1,52 @@ +/* + * 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; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * + * @author LevelX2 + */ + +public class ArchenemyNicolBolas extends ExpansionSet { + + private static final ArchenemyNicolBolas fINSTANCE = new ArchenemyNicolBolas(); + + public static ArchenemyNicolBolas getInstance() { + return fINSTANCE; + } + + private ArchenemyNicolBolas() { + super("Archenemy: Nicol Bolas", "ANB", "mage.sets.archenemynicolbolas", new GregorianCalendar(2017, 6, 16).getTime(), SetType.SUPPLEMENTAL); + this.blockName = "Command Zone"; + } + +} diff --git a/Mage.Sets/src/mage/sets/CommanderAnthology.java b/Mage.Sets/src/mage/sets/CommanderAnthology.java new file mode 100644 index 00000000000..366a10550a8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/CommanderAnthology.java @@ -0,0 +1,50 @@ +/* + * 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.sets; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * + * @author fireshoes + */ +public class CommanderAnthology extends ExpansionSet { + private static final CommanderAnthology fINSTANCE = new CommanderAnthology(); + + public static CommanderAnthology getInstance() { + return fINSTANCE; + } + + private CommanderAnthology() { + super("Commander Anthology", "CMA", "mage.sets.commanderanthology", new GregorianCalendar(2017, 6, 9).getTime(), SetType.SUPPLEMENTAL); + this.blockName = "Commander Anthology"; + this.hasBasicLands = false; + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java new file mode 100644 index 00000000000..7a7aa88526a --- /dev/null +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -0,0 +1,60 @@ +/* +* 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; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * + * @author fireshoes + */ +public class HourOfDevastation extends ExpansionSet { + + private static final HourOfDevastation fINSTANCE = new HourOfDevastation(); + + public static HourOfDevastation getInstance() { + return fINSTANCE; + } + + private HourOfDevastation() { + super("Hour of Devastation", "HOU", "mage.sets.hourofdevastation", new GregorianCalendar(2017, 7, 14).getTime(), SetType.EXPANSION); + this.blockName = "Amonkhet"; + this.parentSet = Amonkhet.getInstance(); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + } + +} diff --git a/Mage.Sets/src/mage/sets/MindVsMight.java b/Mage.Sets/src/mage/sets/MindVsMight.java new file mode 100644 index 00000000000..86621da8366 --- /dev/null +++ b/Mage.Sets/src/mage/sets/MindVsMight.java @@ -0,0 +1,30 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package mage.sets; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * + * @author fireshoes + */ + +public class MindVsMight extends ExpansionSet { + private static final MindVsMight fINSTANCE = new MindVsMight(); + + public static MindVsMight getInstance() { + return fINSTANCE; + } + + private MindVsMight() { + super("Duel Decks: Mind vs. Might", "DDS", "mage.sets.mindvsmight", new GregorianCalendar(2017, 3, 31).getTime(), SetType.SUPPLEMENTAL); + this.blockName = "Duel Decks"; + this.hasBasicLands = false; + } +} diff --git a/Mage.Sets/src/mage/sets/ModernMasters2017.java b/Mage.Sets/src/mage/sets/ModernMasters2017.java new file mode 100644 index 00000000000..d87a19d9ada --- /dev/null +++ b/Mage.Sets/src/mage/sets/ModernMasters2017.java @@ -0,0 +1,61 @@ +/* +* 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; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + + + +/** + * + * @author fireshoes + */ +public class ModernMasters2017 extends ExpansionSet { + + private static final ModernMasters2017 fINSTANCE = new ModernMasters2017(); + + public static ModernMasters2017 getInstance() { + return fINSTANCE; + } + + private ModernMasters2017() { + super("Modern Masters 2017", "MM3", "mage.sets.modernmasters2017", new GregorianCalendar(2017, 3, 17).getTime(), SetType.SUPPLEMENTAL); + this.blockName = "Reprint"; + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + } + +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/AEtherTradewinds.java b/Mage.Sets/src/mage/sets/kaladesh/AEtherTradewinds.java new file mode 100644 index 00000000000..56f34e2858a --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/AEtherTradewinds.java @@ -0,0 +1,52 @@ +/* + * 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.kaladesh; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class AEtherTradewinds extends mage.sets.worldwake.AEtherTradewinds { + + public AEtherTradewinds(UUID ownerId) { + super(ownerId); + this.cardNumber = "38"; + this.expansionSetCode = "KLD"; + } + + public AEtherTradewinds(final AEtherTradewinds card) { + super(card); + } + + @Override + public AEtherTradewinds copy() { + return new AEtherTradewinds(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/BloomingMarsh.java b/Mage.Sets/src/mage/sets/kaladesh/BloomingMarsh.java new file mode 100644 index 00000000000..a68fc8868c2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/BloomingMarsh.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author fireshoes + */ +public class BloomingMarsh extends CardImpl { + + public BloomingMarsh(UUID ownerId) { + super(ownerId, 243, "Blooming Marsh", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "KLD"; + + // Blooming Marsh enters the battlefield tapped unless you control two or fewer other lands. + Condition controls = new InvertCondition(new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, 3)); + String abilityText = "tapped unless you control fewer than 3 lands"; + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new TapSourceEffect(), controls, abilityText), abilityText)); + + // {T}: Add {B} or {G} to your mana pool. + this.addAbility(new BlackManaAbility()); + this.addAbility(new GreenManaAbility()); + } + + public BloomingMarsh(final BloomingMarsh card) { + super(card); + } + + @Override + public BloomingMarsh copy() { + return new BloomingMarsh(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/BotanicalSanctum.java b/Mage.Sets/src/mage/sets/kaladesh/BotanicalSanctum.java new file mode 100644 index 00000000000..c7996830abe --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/BotanicalSanctum.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author fireshoes + */ +public class BotanicalSanctum extends CardImpl { + + public BotanicalSanctum(UUID ownerId) { + super(ownerId, 244, "Botanical Sanctum", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "KLD"; + + // Botanical Sanctum enters the battlefield tapped unless you control two or fewer other lands. + Condition controls = new InvertCondition(new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, 3)); + String abilityText = "tapped unless you control fewer than 3 lands"; + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new TapSourceEffect(), controls, abilityText), abilityText)); + + // {T}: Add {G} or {U} to your mana pool. + this.addAbility(new GreenManaAbility()); + this.addAbility(new BlueManaAbility()); + } + + public BotanicalSanctum(final BotanicalSanctum card) { + super(card); + } + + @Override + public BotanicalSanctum copy() { + return new BotanicalSanctum(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ConcealedCourtyard.java b/Mage.Sets/src/mage/sets/kaladesh/ConcealedCourtyard.java new file mode 100644 index 00000000000..e529c348873 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ConcealedCourtyard.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author fireshoes + */ +public class ConcealedCourtyard extends CardImpl { + + public ConcealedCourtyard(UUID ownerId) { + super(ownerId, 245, "Concealed Courtyard", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "KLD"; + + // Concealed Courtyard enters the battlefield tapped unless you control two or fewer other lands. + Condition controls = new InvertCondition(new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, 3)); + String abilityText = "tapped unless you control fewer than 3 lands"; + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new TapSourceEffect(), controls, abilityText), abilityText)); + + // {T}: Add {W} or {B} to your mana pool.this.addAbility(new BlackManaAbility()); + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlackManaAbility()); + } + + public ConcealedCourtyard(final ConcealedCourtyard card) { + super(card); + } + + @Override + public ConcealedCourtyard copy() { + return new ConcealedCourtyard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/CurioVendor.java b/Mage.Sets/src/mage/sets/kaladesh/CurioVendor.java new file mode 100644 index 00000000000..a72d7f3de88 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/CurioVendor.java @@ -0,0 +1,58 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class CurioVendor extends CardImpl { + + public CurioVendor(UUID ownerId) { + super(ownerId, 42, "Curio Vendor", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vedalken"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + } + + public CurioVendor(final CurioVendor card) { + super(card); + } + + @Override + public CurioVendor copy() { + return new CurioVendor(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/FiligreeFamiliar.java b/Mage.Sets/src/mage/sets/kaladesh/FiligreeFamiliar.java new file mode 100644 index 00000000000..d9371fd7deb --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/FiligreeFamiliar.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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class FiligreeFamiliar extends CardImpl { + + public FiligreeFamiliar(UUID ownerId) { + super(ownerId, 212, "Filigree Familiar", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Fox"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Filigree Familiar enters the battlefield, you gain 2 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2), false)); + + // When Filigree Familiar dies, draw a card. + this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); + } + + public FiligreeFamiliar(final FiligreeFamiliar card) { + super(card); + } + + @Override + public FiligreeFamiliar copy() { + return new FiligreeFamiliar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/FuriousReprisal.java b/Mage.Sets/src/mage/sets/kaladesh/FuriousReprisal.java new file mode 100644 index 00000000000..46b21d4b652 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/FuriousReprisal.java @@ -0,0 +1,60 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author fireshoes + */ +public class FuriousReprisal extends CardImpl { + + public FuriousReprisal(UUID ownerId) { + super(ownerId, 115, "Furious Reprisal", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}"); + this.expansionSetCode = "KLD"; + + // Furious Reprisal deals 2 damage to each of two target creatures and/or players. + this.getSpellAbility().addEffect(new DamageTargetEffect(2, true, "each of two target creatures and/or players")); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer(2, 2)); + } + + public FuriousReprisal(final FuriousReprisal card) { + super(card); + } + + @Override + public FuriousReprisal copy() { + return new FuriousReprisal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/InspiringVantage.java b/Mage.Sets/src/mage/sets/kaladesh/InspiringVantage.java new file mode 100644 index 00000000000..ec4a6dd9739 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/InspiringVantage.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.mana.RedManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author fireshoes + */ +public class InspiringVantage extends CardImpl { + + public InspiringVantage(UUID ownerId) { + super(ownerId, 246, "Inspiring Vantage", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "KLD"; + + // Inspiring Vantage enters the battlefield tapped unless you control two or fewer other lands. + Condition controls = new InvertCondition(new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, 3)); + String abilityText = "tapped unless you control fewer than 3 lands"; + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new TapSourceEffect(), controls, abilityText), abilityText)); + + // {T}: Add {R} or {W} to your mana pool. + this.addAbility(new RedManaAbility()); + this.addAbility(new WhiteManaAbility()); + } + + public InspiringVantage(final InspiringVantage card) { + super(card); + } + + @Override + public InspiringVantage copy() { + return new InspiringVantage(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/InventorsFair.java b/Mage.Sets/src/mage/sets/kaladesh/InventorsFair.java new file mode 100644 index 00000000000..f6d71f8644f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/InventorsFair.java @@ -0,0 +1,131 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.common.MetalcraftCondition; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author fireshoes + */ +public class InventorsFair extends CardImpl { + + private static final FilterCard filter = new FilterCard("artifact"); + + static { + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + } + + public InventorsFair(UUID ownerId) { + super(ownerId, 247, "Inventors' Fair", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "KLD"; + this.supertype.add("Legendary"); + + // At the beginning of your upkeep, if you control three or more artifacts, you gain 1 life. + this.addAbility(new InventorsFairAbility()); + + // {t}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {4}, {T}, Sacrifice Inventors' Fair: Search your library for an artifact card, reveal it, put it into your hand, then shuffle your library. + // Activate this ability only if you control threeor more artifacts. + Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(1, filter), true), + new GenericManaCost(4), MetalcraftCondition.getInstance()); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public InventorsFair(final InventorsFair card) { + super(card); + } + + @Override + public InventorsFair copy() { + return new InventorsFair(this); + } +} + +class InventorsFairAbility extends TriggeredAbilityImpl { + + private FilterArtifactPermanent filter = new FilterArtifactPermanent(); + + public InventorsFairAbility() { + super(Zone.BATTLEFIELD, new GainLifeEffect(1)); + } + + public InventorsFairAbility(final InventorsFairAbility ability) { + super(ability); + } + + @Override + public InventorsFairAbility copy() { + return new InventorsFairAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.UPKEEP_STEP_PRE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.controllerId); + } + + @Override + public boolean checkInterveningIfClause(Game game) { + return game.getBattlefield().countAll(filter, this.controllerId, game) >= 3; + } + + @Override + public String getRule() { + return "At the beginning of your upkeep, if you control three or more artifacts, you gain 1 life."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/kaladesh/SkyshipStalker.java b/Mage.Sets/src/mage/sets/kaladesh/SkyshipStalker.java new file mode 100644 index 00000000000..a32beadd004 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/SkyshipStalker.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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author fireshoes + */ +public class SkyshipStalker extends CardImpl { + + public SkyshipStalker(UUID ownerId) { + super(ownerId, 130, "Skyship Stalker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dragon"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {R}: Skyship Stalker gains +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + + // {R}: Skyship Stalker gains first strike until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + + // {R}: Skyship Stalker gains haste until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + } + + public SkyshipStalker(final SkyshipStalker card) { + super(card); + } + + @Override + public SkyshipStalker copy() { + return new SkyshipStalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/SpirebluffCanal.java b/Mage.Sets/src/mage/sets/kaladesh/SpirebluffCanal.java new file mode 100644 index 00000000000..5bb81b370a9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/SpirebluffCanal.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author fireshoes + */ +public class SpirebluffCanal extends CardImpl { + + public SpirebluffCanal(UUID ownerId) { + super(ownerId, 249, "Spirebluff Canal", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "KLD"; + + // Spirebluff Canal enters the battlefield tapped unless you control two or fewer other lands. + Condition controls = new InvertCondition(new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), PermanentsOnTheBattlefieldCondition.CountType.FEWER_THAN, 3)); + String abilityText = "tapped unless you control fewer than 3 lands"; + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new TapSourceEffect(), controls, abilityText), abilityText)); + + // {T}: Add {U} or {R} to your mana pool. + this.addAbility(new BlueManaAbility()); + this.addAbility(new RedManaAbility()); + } + + public SpirebluffCanal(final SpirebluffCanal card) { + super(card); + } + + @Override + public SpirebluffCanal copy() { + return new SpirebluffCanal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/TasseledDromedary.java b/Mage.Sets/src/mage/sets/kaladesh/TasseledDromedary.java new file mode 100644 index 00000000000..2124ff493a7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/TasseledDromedary.java @@ -0,0 +1,58 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class TasseledDromedary extends CardImpl { + + public TasseledDromedary(UUID ownerId) { + super(ownerId, 30, "Tasseled Dromedary", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Camel"); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + } + + public TasseledDromedary(final TasseledDromedary card) { + super(card); + } + + @Override + public TasseledDromedary copy() { + return new TasseledDromedary(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/TerrorOfTheFairgrounds.java b/Mage.Sets/src/mage/sets/kaladesh/TerrorOfTheFairgrounds.java new file mode 100644 index 00000000000..18bb3c5412a --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/TerrorOfTheFairgrounds.java @@ -0,0 +1,58 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class TerrorOfTheFairgrounds extends CardImpl { + + public TerrorOfTheFairgrounds(UUID ownerId) { + super(ownerId, 137, "Terror of the Fairgrounds", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Gremlin"); + this.power = new MageInt(5); + this.toughness = new MageInt(2); + } + + public TerrorOfTheFairgrounds(final TerrorOfTheFairgrounds card) { + super(card); + } + + @Override + public TerrorOfTheFairgrounds copy() { + return new TerrorOfTheFairgrounds(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/VerdurousGearhulk.java b/Mage.Sets/src/mage/sets/kaladesh/VerdurousGearhulk.java new file mode 100644 index 00000000000..ffaf13ea75c --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/VerdurousGearhulk.java @@ -0,0 +1,81 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.counter.DistributeCountersEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetCreaturePermanentAmount; + +/** + * + * @author fireshoes + */ +public class VerdurousGearhulk extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public VerdurousGearhulk(UUID ownerId) { + super(ownerId, 172, "Verdurous Gearhulk", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{G}{G}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Verdurous Gearhulk enters the battlefield, distribute four +1/+1 counters among any number of target creatures you control. + Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect(CounterType.P1P1, 4, false, "any number of target creatures you control"), false); + ability.addTarget(new TargetCreaturePermanentAmount(4, filter)); + this.addAbility(ability); + } + + public VerdurousGearhulk(final VerdurousGearhulk card) { + super(card); + } + + @Override + public VerdurousGearhulk copy() { + return new VerdurousGearhulk(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/Whirlermaker.java b/Mage.Sets/src/mage/sets/kaladesh/Whirlermaker.java new file mode 100644 index 00000000000..3b85a2bd9a2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/Whirlermaker.java @@ -0,0 +1,66 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.permanent.token.ThopterColorlessToken; + +/** + * + * @author fireshoes + */ +public class Whirlermaker extends CardImpl { + + public Whirlermaker(UUID ownerId) { + super(ownerId, 239, "Whirlermaker", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "KLD"; + + // {4}, {T}: Create a 1/1 colorless Thopter artifact creature token with flying. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken()), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public Whirlermaker(final Whirlermaker card) { + super(card); + } + + @Override + public Whirlermaker copy() { + return new Whirlermaker(this); + } +} diff --git a/Utils/known-sets.txt b/Utils/known-sets.txt index 58184c1efb1..103ed38be59 100644 --- a/Utils/known-sets.txt +++ b/Utils/known-sets.txt @@ -1,9 +1,11 @@ Aether Revolt|aetherrevolt| Alara Reborn|alarareborn| Alliances|alliances| +Amonkhet|amonkhet| Antiquities|antiquities| Apocalypse|apocalypse| Archenemy|archenemy| +Archenemy: Nicol Bolas|archenemynicolbolas| Arabian Nights|arabiannights| Arena League|arenaleague| Asia Pacific Land Program|asiapacificlandprogram| @@ -21,6 +23,7 @@ Commander 2013 Edition|commander2013| Commander 2014 Edition|commander2014| Commander 2015|commander2015| Commander 2016|commander2016| +Commander Anthology|commanderanthology| Commander's Arsenal|commandersarsenal| Conflux|conflux| Conspiracy: Take the Crown|conspiracytakethecrown| @@ -45,6 +48,7 @@ Duel Decks: Izzet vs. Golgari|izzetvsgolgari| Duel Decks: Jace vs. Chandra|jacevschandra| Duel Decks: Jace vs. Vraska|jacevsvraska| Duel Decks: Knights vs. Dragons|knightsvsdragons| +Duel Decks: Mind vs. Might|mindvsmight| Duel Decks: Nissa vs. Ob Nixilis|nissavsobnixilis| Duel Decks: Phyrexia vs. the Coalition|phyrexiavsthecoalition| Duel Decks: Sorin vs. Tibalt|sorinvstibalt| @@ -79,6 +83,7 @@ Gatecrash|gatecrash| Grand Prix|grandprix| Guildpact|guildpact| Homelands|homelands| +Hour of Devastation|hourofdevastation| Ice Age|iceage| Innistrad|innistrad| Invasion|invasion| @@ -114,6 +119,7 @@ Mirrodin Besieged|mirrodinbesieged| Mirrodin|mirrodin| Modern Masters|modernmasters| Modern Masters 2015|modernmasters2015| +Modern Masters 2017|modernmasters2017| Morningtide|morningtide| Nemesis|nemesis| New Phyrexia|newphyrexia| diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 3674c3a93d2..2f436e19372 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -29654,4 +29654,43 @@ Terrarion|Eldritch Moon|201|C|{1}|Artifact|||Terrarion enters the battlefield ta Thirsting Axe|Eldritch Moon|202|U|{3}|Artifact - Equipment|||Equipped creature gets +4/+0.$At the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it.$Equip {2}| Geier Reach Sanitarium|Eldritch Moon|203|R||Legendary Land|||{T}: Add {C} to your mana pool.${2}, {T}: Each player draws a card, then discards a card.| Hanweir Battlements|Eldritch Moon|204|R||Land|||{T}: Add {C} to your mana pool.${R},{T}: Target creature gains haste until end of turn.${3}{R}{R},{T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township.| -Nephalia Academy|Eldritch Moon|205|U||Land|||If a spell or ability an opponent controls causes you to discard a card, you may reveal that card and put it on top of your library instead of putting it anywhere else.${T}: Add {C} to your mana pool.| \ No newline at end of file +Nephalia Academy|Eldritch Moon|205|U||Land|||If a spell or ability an opponent controls causes you to discard a card, you may reveal that card and put it on top of your library instead of putting it anywhere else.${T}: Add {C} to your mana pool.| +Aetherstorm Roc|Kaladesh|3|R|{2}{W}{W}|Creature - Bird|3|3|Flying$Whenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E} (an energy counter).$Whenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 creature on it and tap up to one target creature defending player controls.| +Glint-Sleeve Artisan|Kaladesh|017|C|{2}{W}|Creature - Dwarf Artificer|2|2|Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Propeller Pioneer|Kaladesh|024|C|{3}{W}|Creature - Human Artificer|2|1|Flying$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Tasseled Dromedary|Kaladesh|30|C|{W}|Creature - Camel|0|4|| +Aether Tradewinds|Kaladesh|38|C|{2}{U}|Instant|||Return target permanent you control and target permanent you don't control to their owners' hands.| +Curio Vendor|Kaladesh|42|C|{1}{U}|Creature - Vedalken|2|1|| +Saheeli's Artistry|Kaladesh|62|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except that it's an artifact in addition to its other types.| +Demon of Shadowy Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Shadowy Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (one energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control. | +Die Young|Kaladesh|76|C|{1}{B}|Sorcery|||Choose target creature. You get {E}{E} (two energy counters), then you may pay any amount of {E}. The creature gets -1/-1 until end of turn for each {E} paid this way.| +Gonti, Lord of Luxury|Kaladesh|084|R|{2}{B}{B}|Legendary Creature - Aetherborn Rogue|2|3|Deathtouch$When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.| +Live Fast|Kaladesh|87|C|{2}{B}|Sorcery|||You draw two cards, lose 2 life, and gain {E}{E} (two energy counters).| +Furious Reprisal|Kaladesh|115|U|{3}{R}|Sorcery|||Furious Reprisal deals 2 damage to each of two target creatures and/or players.| +Skyship Stalker|Kaladesh|130|R|{2}{R}{R}|Creature - Dragon|3|3|Flying${R}: Skyship Stalker gains +1/+0 until end of turn.${R}: Skyship Stalker gains first strike until end of turn.${R}: Skyship Stalker gains haste until end of turn.| +Speedway Fanatic|Kaladesh|132|U|{1}{R}|Creature - Human Pilot|2|1|Haste$Whenever Speedway Fanatic crews a Vehicle, that Vehicle gains haste until end of turn.| +Start Your Engines|Kaladesh|135|U|{3}{R}|Sorcery|||Vehicles you control becomes artifact creatures until end of turn. Creatures you control get +2/+0 until end of turn.| +Territorial Devourer|Kaladesh|136|R|{3}{R}|Creature - Gremlin|2|2|Trample $Whenever you gain one or more {E} (energy counters), Territorial Devourer gets +2/+2 until end of turn.| +Terror of the Fairgrounds|Kaladesh|137|C|{3}{R}|Creature - Gremlin|5|2|| +Architect of the Untamed|Kaladesh|143|R|{2}{G}|Creature - Elf Artificer Druid|2|3|Whenever a land enters the battlefiend under your control, you get {E} (an energy counter).$Pay {E}{E}{E}{E}{E}{E}{E}{E}: Create a 6/6 colorless Beast artifact creature token.| +Cultivator of Blades|Kaladesh|151|R|{3}{G}{G}|Creature - Elf Artificer|1|1|Fabricate 2$Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power.| +Verdurous Gearhulk|Kaladesh|172|M|{3}{G}{G}|Artifact Creature - Construct|4|4|Trample$When Verdurous Gearhulk enters the battlefield, distribute four +1/+1 counters among any number of target creatures you control.| +Depala, Pilot Exemplar|Kaladesh|178|R|{1}{R}{W}|Legendary Creature - Dwarf Pilot|3|3|Other Dwarves you control get +1/+1.$Each Vehicle you control gets +1/+1 as long as it's a creature.$Whenever Depala, Pilot Exemplar becomes tapped, you may pay {X}. If you do, reveal the top X cards of your library, put all Dwarf and Vehicle cards from among them into your hand, then put the rest on the bottom of your library in a random order.| +Rashmi, Eternities Crafter|Kaladesh|184|M|{2}{G}{U}|Legendary Creature - Elf Druid|2|3|Whenever you cast your first spell each turn, reveal the top card of your library. If it's a nonland card with converted mana cost less than that spell's, you may cast it without paying its mana cost. If you don't cast the revealed card, put it into your hand. | +Saheeli Rai|Kaladesh|186|M|{1}{U}{R}|Planeswalker - Saheeli|3|+1: Scry 1. Saheeli Rai deals 1 damage to each opponent.$-2: Create a token that's a copy of target artifact or creature you control, except it's an artifact in addition to its other types. That token gains haste. Exile it at the beginning of the next end step.$-7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.| +Aetherworks Marvel|Kaladesh|193|M|{4}|Legendary Artifact|||Whenever a permanent you control is put into a graveyard, you get {E} (an energy counter).${T}, Pay {E}{E}{E}{E}{E}{E}: Look at the top six cards of your library. You may cast a card from among them without paying its mana cost. Put the rest on the bottom of your library in a random order.| +Filigree Familiar|Kaladesh|212|U|{3}|Artifact Creature - Fox|2|2|When Filigree Familiar enters the battlefield, you gain 2 life.$When Filigree Familiar dies, draw a card.| +Fleetwheel Cruiser|Kaladesh|214|R|{4}|Artifact - Vehicle|5|3|Trample, Haste $When Fleetwheel Cruiser enters the battlefield, it becomes an artifact creature until the end of turn.$Crew 2 (Tap any number of creatures you control with total power 2 or more: This Vehicle becomes an artifact creature until end of turn.)| +Ghirapur Orrery|Kaladesh|216|R|{4}|Artifact|||Each player may play an additional land on each of his or her turns.$At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.| +Ovalchase Dragster|Kaladesh|225|U|{4}|Artifact - Vehicle|6|1|Trample, haste$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| +Panharmonicon|Kaladesh|226|R|{4}|Artifact|||If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.| +Sky Skiff|Kaladesh|233|C|{2}|Artifact - Vehicle|2|3|Flying$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| +Skysovereign, Consul Flagship|Kaladesh|234|M|{5}|Legendary Artifact - Vehicle|6|5|Flying$Whenever Skysovereign, Consul Flagship enters the battlefield or attacks, it deals 3 damage to target creature or planeswalker an opponent controls.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| +Whirlermaker|Kaladesh|239|U|{3}|Artifact|||{4}, {T}: Create a 1/1 colorless Thopter artifact creature token with flying.| +Woodweaver's Puzzleknot|Kaladesh|240|C|{2}|Artifact|||When Woodweaver's Puzzleknot enters the battlefield, you gain 3 life and get {E}{E}{E} (three energy counters).${2}{G}, Sacrifice Woodweaver's Puzzleknot: You gain 3 life and get {E}{E}{E}.| +Blooming Marsh|Kaladesh|243|R||Land|||Blooming Marsh enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {B} or {G} to your mana pool.| +Botanical Sanctum|Kaladesh|244|R||Land|||Botanical Sanctum enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {G} or {U} to your mana pool.| +Concealed Courtyard|Kaladesh|245|R||Land|||Concealed Courtyard enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {W} or {B} to your mana pool.| +Inspiring Vantage|Kaladesh|246|R||Land|||Inspiring Vantage enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {R} or {W} to your mana pool.| +Inventors' Fair|Kaladesh|247|R||Legendary Land|||At the beginning of your upkeep, if you control three or more artifacts, you gain 1 life.${t}: Add {C} to your mana pool.${4}, {T}, Sacrifice Inventors' Fair: Search your library for an artifact card, reveal it, put it into your hand, then shuffle your library. Activate this ability only if you control threeor more artifacts.| +Spirebluff Canal|Kaladesh|249|R||Land|||Spirebluff Canal enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {U} or {R} to your mana pool.| \ No newline at end of file diff --git a/Utils/mtg-sets-data.txt b/Utils/mtg-sets-data.txt index 9e00c06571e..569d17ba79a 100644 --- a/Utils/mtg-sets-data.txt +++ b/Utils/mtg-sets-data.txt @@ -9,8 +9,10 @@ Seventh Edition|7ED| Eighth Edition|8ED| Ninth Edition|9ED| Aether Revolt|AER| +Amonkhet|AKH| Shards of Alara|ALA| Alliances|ALL| +Archenemy: Nicol Bolas|ANB| Asia Pacific Land Program|APAC| Apocalypse|APC| Alara Reborn|ARB| @@ -32,6 +34,7 @@ Commander 2016 Edition|C16| Champions of Kamigawa|CHK| Chronicles|CHR| Clash Pack|CLASH| +Commander Anthology|CMA| Commander's Arsenal|CMA| Conspiracy: Take the Crown|CN2| Conflux|CON| @@ -58,6 +61,7 @@ Duel Decks: Elspeth vs. Kiora|DDO| Duel Decks: Zendikar vs. Eldrazi|DDP| Duel Decks: Blessed vs. Cursed|DDQ| Duel Decks: Nissa vs. Ob Nixilis|DDR| +Duel Decks: Mind vs. Might|DDS| Duels of the Planeswalkers|DPA| Dragon's Maze|DGM| Dissension|DIS| @@ -86,6 +90,7 @@ Guru|GUR| Premium Deck Series: Slivers|H09| Homelands|HML| Planechase|HOP| +Hour of Devastation|HOU| Ice Age|ICE| Invasion|INV| Innistrad|ISD| @@ -117,6 +122,7 @@ Game Day|MGDC| Mirage|MIR| Launch Party|MLP| Modern Masters 2015|MM2| +Modern Masters 2017|MM3| Modern Masters|MMA| Mercadian Masques|MMQ| Morningtide|MOR| From f2cc8d4571f3b9fb1fb42af50edf42a9c9ab8556 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Sun, 4 Sep 2016 23:06:13 -0500 Subject: [PATCH 14/26] Removed Nissa vs Ob Nixilis from ignored images. --- Mage.Client/src/main/resources/image.url.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties index 488610d0575..91c4c9a3f44 100644 --- a/Mage.Client/src/main/resources/image.url.properties +++ b/Mage.Client/src/main/resources/image.url.properties @@ -74,6 +74,6 @@ dd3evg=ddaevg dd3gvl=ddagvl dd3jvc=ddajvc # Remove setname as soon as the images can be downloaded -ignore.urls=TOK,AER,PCA,C16,DDR,DDS,ANB,AKH,HOU,MM3 +ignore.urls=TOK,AER,PCA,C16,DDS,ANB,AKH,HOU,MM3 # sets ordered by release time (newest goes first) token.lookup.order=ANB,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC \ No newline at end of file From e2a479255a91c9fca9aa159cc1e12cb822f7c03c Mon Sep 17 00:00:00 2001 From: ingmargoudt Date: Mon, 5 Sep 2016 15:03:47 +0200 Subject: [PATCH 15/26] refactor : removed all instances of new Random() and replaced with RandomUtil for a ThreadLocal randomizer --- .../client/deck/generator/DeckGenerator.java | 13 ++--- .../deck/generator/DeckGeneratorPool.java | 6 +-- .../mage/client/dialog/AddLandDialog.java | 4 +- .../plugins/card/images/DownloadPictures.java | 4 +- Mage.Common/src/mage/utils/DeckBuilder.java | 3 +- .../src/mage/game/MomirDuel.java | 4 +- .../src/mage/player/ai/ComputerPlayer6.java | 4 +- .../java/mage/player/ai/ComputerPlayer.java | 15 ++---- .../mage/player/ai/SimulatedPlayerMCTS.java | 52 +++++++++---------- .../java/mage/server/util/SystemUtil.java | 4 +- .../src/mage/sets/ShadowsOverInnistrad.java | 7 +-- .../sets/bornofthegods/WhimsOfTheFates.java | 4 +- .../mage/sets/commander/RuhanOfTheFomori.java | 4 +- .../mage/sets/commander2014/RavingDead.java | 4 +- .../sets/darkascension/HauntedFengraf.java | 4 +- .../src/mage/sets/eldritchmoon/RideDown.java | 2 + .../sets/innistrad/CharmbreakerDevils.java | 4 +- .../src/mage/sets/innistrad/Ghoulraiser.java | 4 +- .../sets/innistrad/MoldgrafMonstrosity.java | 3 +- .../mage/sets/innistrad/WoodlandSleuth.java | 4 +- .../mage/sets/magic2010/CapriciousEfreet.java | 4 +- .../mage/sets/magic2012/Scrambleverse.java | 4 +- .../src/mage/sets/magic2014/MoltenBirth.java | 3 +- .../src/mage/sets/mirrodin/KrarksThumb.java | 3 +- .../sets/riseoftheeldrazi/SurrealMemoir.java | 4 +- .../src/mage/sets/scourge/GripOfChaos.java | 3 +- .../src/mage/sets/shadowmoor/WildSwing.java | 5 +- Mage/src/main/java/mage/cards/CardsImpl.java | 4 +- .../main/java/mage/cards/ExpansionSet.java | 22 ++++---- Mage/src/main/java/mage/cards/Sets.java | 4 +- .../cards/decks/importer/MWSDeckImporter.java | 3 +- .../mage/cards/repository/CardRepository.java | 4 +- Mage/src/main/java/mage/game/GameImpl.java | 4 +- .../main/java/mage/game/draft/DraftCube.java | 4 +- .../main/java/mage/game/draft/DraftImpl.java | 1 + .../main/java/mage/game/match/MatchImpl.java | 3 +- .../game/permanent/token/CentaurToken.java | 3 +- .../permanent/token/ClueArtifactToken.java | 5 +- .../permanent/token/EldraziScionToken.java | 5 +- .../permanent/token/EldraziSpawnToken.java | 3 +- .../game/permanent/token/SoldierToken.java | 3 +- .../token/ThopterColorlessToken.java | 3 +- .../java/mage/game/permanent/token/Token.java | 3 +- .../game/permanent/token/WarriorToken.java | 3 +- .../game/permanent/token/ZombieToken.java | 5 +- .../mage/game/tournament/TournamentImpl.java | 4 +- Mage/src/main/java/mage/players/Library.java | 4 +- .../main/java/mage/players/PlayerImpl.java | 4 +- .../src/main/java/mage/target/TargetImpl.java | 3 +- Mage/src/main/java/mage/util/RandomUtil.java | 28 ++++++++++ .../main/java/mage/util/TournamentUtil.java | 6 +-- 51 files changed, 173 insertions(+), 133 deletions(-) create mode 100644 Mage/src/main/java/mage/util/RandomUtil.java diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java index d2b959c1c74..97471ed50b7 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java @@ -44,6 +44,7 @@ import mage.client.util.sets.ConstructedFormats; import mage.constants.CardType; import mage.constants.ColoredManaSymbol; import mage.constants.Rarity; +import mage.util.RandomUtil; import mage.util.TournamentUtil; /** @@ -120,7 +121,6 @@ public class DeckGenerator { */ private static String getRandomColors(String selectedColors) { - Random random = new Random(); List availableColors = new ArrayList<>(); for (ColoredManaSymbol cms : ColoredManaSymbol.values()) { availableColors.add(cms.toString().charAt(0)); @@ -138,7 +138,7 @@ public class DeckGenerator { } } for (int i = 0; i < randomColors && !availableColors.isEmpty(); i++) { - int index = random.nextInt(availableColors.size()); + int index = RandomUtil.nextInt(availableColors.size()); generatedColors.append(availableColors.remove(index)); } return generatedColors.toString(); @@ -214,14 +214,13 @@ public class DeckGenerator { List cardPool = CardRepository.instance.findCards(criteria); int retrievedCount = cardPool.size(); List deckCMCs = genPool.getCMCsForSpellCount(spellCount); - Random random = new Random(); int count = 0; int reservesAdded = 0; boolean added; if (retrievedCount > 0 && retrievedCount >= spellCount) { int tries = 0; while (count < spellCount) { - Card card = cardPool.get(random.nextInt(retrievedCount)).getMockCard(); + Card card = cardPool.get(RandomUtil.nextInt(retrievedCount)).getMockCard(); if (genPool.isValidSpellCard(card)) { int cardCMC = card.getManaCost().convertedManaCost(); for (DeckGeneratorCMC.CMC deckCMC : deckCMCs) { @@ -278,10 +277,9 @@ public class DeckGenerator { if (!genPool.isMonoColoredDeck() && genDialog.useNonBasicLand()) { List landCards = genPool.filterLands(CardRepository.instance.findCards(criteria)); int allCount = landCards.size(); - Random random = new Random(); if (allCount > 0) { while (countNonBasic < landsCount / 2) { - Card card = landCards.get(random.nextInt(allCount)); + Card card = landCards.get(RandomUtil.nextInt(allCount)); if (genPool.isValidLandCard(card)) { Card addedCard = card.copy(); deckLands.add(addedCard); @@ -394,10 +392,9 @@ public class DeckGenerator { * @return a single basic land that produces the color needed. */ private static Card getBasicLand(ColoredManaSymbol color, Map> basicLands) { - Random random = new Random(); String landName = DeckGeneratorPool.getBasicLandName(color.toString()); List basicLandsInfo = basicLands.get(landName); - return basicLandsInfo.get(random.nextInt(basicLandsInfo.size() - 1)).getMockCard().copy(); + return basicLandsInfo.get(RandomUtil.nextInt(basicLandsInfo.size() - 1)).getMockCard().copy(); } } diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorPool.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorPool.java index 7c7ff556f18..b5dcd45edf7 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorPool.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorPool.java @@ -32,6 +32,7 @@ import mage.cards.Card; import mage.cards.decks.Deck; import mage.cards.repository.CardInfo; import mage.constants.ColoredManaSymbol; +import mage.util.RandomUtil; import java.util.*; @@ -390,7 +391,6 @@ public class DeckGeneratorPool */ private List getFixedSpells() { - Random random = new Random(); int spellSize = deckCards.size(); int nonLandSize = (deckSize - landCount); @@ -409,7 +409,7 @@ public class DeckGeneratorPool spellsToAdd.add(reserveSpells.get(i)); for (int i = spellsNeeded + 1; i < reserveSpells.size() - 1; i++) { - int j = random.nextInt(i); + int j = RandomUtil.nextInt(i); Card randomCard = reserveSpells.get(j); if (isValidSpellCard(randomCard) && j < spellsToAdd.size()) { spellsToAdd.set(j, randomCard); @@ -424,7 +424,7 @@ public class DeckGeneratorPool else if(spellSize > (deckSize - landCount)) { int spellsRemoved = (spellSize)-(deckSize-landCount); for(int i = 0; i < spellsRemoved; ++i) { - deckCards.remove(random.nextInt(deckCards.size())); + deckCards.remove(RandomUtil.nextInt(deckCards.size())); } } diff --git a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java index 9b25eea3712..5748b13cd47 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/AddLandDialog.java @@ -46,6 +46,7 @@ import mage.cards.repository.ExpansionRepository; import mage.client.MageFrame; import mage.client.constants.Constants.DeckEditorMode; import mage.constants.Rarity; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -118,7 +119,6 @@ public class AddLandDialog extends MageDialog { } private void addLands(String landName, int number) { - Random random = new Random(); String landSetName = (String) cbLandSet.getSelectedItem(); CardCriteria criteria = new CardCriteria(); @@ -142,7 +142,7 @@ public class AddLandDialog extends MageDialog { } for (int i = 0; i < number; i++) { - Card land = cards.get(random.nextInt(cards.size())).getMockCard(); + Card land = cards.get(RandomUtil.nextInt(cards.size())).getMockCard(); deck.getCards().add(land); } } 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 2a4a1ca9f43..3b6dccae029 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 @@ -51,6 +51,7 @@ import mage.client.constants.Constants; import mage.client.dialog.PreferencesDialog; import mage.client.util.sets.ConstructedFormats; import mage.remote.Connection; +import mage.util.RandomUtil; import net.java.truevfs.access.TFile; import net.java.truevfs.access.TFileOutputStream; import net.java.truevfs.access.TVFS; @@ -68,7 +69,6 @@ import org.mage.plugins.card.utils.CardImageUtils; public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable { private static final Logger logger = Logger.getLogger(DownloadPictures.class); - private static final Random rnd = new Random(); private JProgressBar bar; private final JOptionPane dlg; @@ -689,7 +689,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private void setUpConnection(URLConnection httpConn) { // images download from magiccards.info may not work with default 'User-Agent: Java/1.x.x' request header - switch (rnd.nextInt(3)) { + switch (RandomUtil.nextInt(3)) { // chrome case 0: httpConn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); diff --git a/Mage.Common/src/mage/utils/DeckBuilder.java b/Mage.Common/src/mage/utils/DeckBuilder.java index 025a73bd370..525049b4fdd 100644 --- a/Mage.Common/src/mage/utils/DeckBuilder.java +++ b/Mage.Common/src/mage/utils/DeckBuilder.java @@ -14,6 +14,7 @@ import mage.cards.decks.Deck; import mage.constants.CardType; import mage.constants.ColoredManaSymbol; import mage.interfaces.rate.RateCallback; +import mage.util.RandomUtil; /** * Builds deck from provided card pool. @@ -205,7 +206,7 @@ public class DeckBuilder { ColoredManaSymbol bestColor = null; //Default to a color in the allowed colors if (allowedColors != null && !allowedColors.isEmpty()) { - bestColor = allowedColors.get(new Random().nextInt(allowedColors.size())); + bestColor = allowedColors.get(RandomUtil.nextInt(allowedColors.size())); } int lowestRatio = Integer.MAX_VALUE; for (final ColoredManaSymbol color : ColoredManaSymbol.values()) { diff --git a/Mage.Server.Plugins/Mage.Game.MomirDuel/src/mage/game/MomirDuel.java b/Mage.Server.Plugins/Mage.Game.MomirDuel/src/mage/game/MomirDuel.java index 9d37e749ad4..b2dc9b0b79f 100644 --- a/Mage.Server.Plugins/Mage.Game.MomirDuel/src/mage/game/MomirDuel.java +++ b/Mage.Server.Plugins/Mage.Game.MomirDuel/src/mage/game/MomirDuel.java @@ -56,6 +56,7 @@ import mage.game.permanent.token.EmptyToken; import mage.game.turn.TurnMod; import mage.players.Player; import mage.util.CardUtil; +import mage.util.RandomUtil; /** * @@ -135,7 +136,6 @@ class MomirEmblem extends Emblem { class MomirEffect extends OneShotEffect { - private static final Random rnd = new Random(); public MomirEffect() { super(Outcome.PutCreatureInPlay); @@ -158,7 +158,7 @@ class MomirEffect extends OneShotEffect { CardCriteria criteria = new CardCriteria().types(CardType.CREATURE).convertedManaCost(value); List options = CardRepository.instance.findCards(criteria); if (options != null && !options.isEmpty()) { - Card card = options.get(rnd.nextInt(options.size())).getCard(); + Card card = options.get(RandomUtil.nextInt(options.size())).getCard(); EmptyToken token = new EmptyToken(); CardUtil.copyTo(token).from(card); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), false, false); diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index e816a8757de..39b02660605 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -104,6 +104,7 @@ import mage.players.Player; import mage.target.Target; import mage.target.TargetCard; import mage.target.Targets; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -128,7 +129,6 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { protected Set actionCache; private static final List optimizers = new ArrayList<>(); protected int lastLoggedTurn = 0; - Random random = new Random(); protected static final String BLANKS = "..............................................."; static { @@ -631,7 +631,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { if (depth == maxDepth && action instanceof PassAbility) { val = val - PASSIVITY_PENALTY; // passivity penalty } - if (val > alpha || (depth == maxDepth && val == alpha && random.nextBoolean())) { // Adding random for equal value to get change sometimes + if (val > alpha || (depth == maxDepth && val == alpha && RandomUtil.nextBoolean())) { // Adding random for equal value to get change sometimes alpha = val; bestNode = newNode; bestNode.setScore(val); diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 6264e603016..2bcae9b1ffd 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -138,10 +138,7 @@ import mage.target.common.TargetDiscard; import mage.target.common.TargetOpponent; import mage.target.common.TargetPermanentOrPlayer; import mage.target.common.TargetSpellOrPermanent; -import mage.util.Copier; -import mage.util.MessageToClient; -import mage.util.TournamentUtil; -import mage.util.TreeNode; +import mage.util.*; import org.apache.log4j.Logger; /** @@ -165,7 +162,6 @@ public class ComputerPlayer extends PlayerImpl implements Player { private transient List chosenColors; private transient ManaCost currentUnpaidMana; - private final Random random = new Random(); public ComputerPlayer(String name, RangeOfInfluence range) { super(name, range); @@ -1258,7 +1254,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) { log.debug("announceXMana"); //TODO: improve this - int value = new Random().nextInt(max + 1); + int value = RandomUtil.nextInt(max + 1); if (value < max) { value++; } @@ -1558,7 +1554,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { } //TODO: improve this if (min < max && min == 0) { - return new Random().nextInt(max + 1); + return RandomUtil.nextInt(max + 1); } return min; } @@ -1587,7 +1583,6 @@ public class ComputerPlayer extends PlayerImpl implements Player { } private static void addBasicLands(Deck deck, String landName, int number) { - Random random = new Random(); Set landSets = TournamentUtil.getLandSetCodeForDeckSets(deck.getExpansionSetCodes()); CardCriteria criteria = new CardCriteria(); @@ -1605,7 +1600,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { } for (int i = 0; i < number; i++) { - Card land = cards.get(random.nextInt(cards.size())).getCard(); + Card land = cards.get(RandomUtil.nextInt(cards.size())).getCard(); deck.getCards().add(land); } } @@ -2239,7 +2234,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { UUID randomOpponentId = game.getOpponents(abilityControllerId).iterator().next(); Set opponents = game.getOpponents(abilityControllerId); if (opponents.size() > 1) { - int rand = random.nextInt(opponents.size()); + int rand = RandomUtil.nextInt(opponents.size()); int count = 0; for (UUID currentId : opponents) { if (count == rand) { diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java index 60212a9ee18..8a315878f18 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java @@ -54,6 +54,7 @@ import mage.players.Player; import mage.target.Target; import mage.target.TargetAmount; import mage.target.TargetCard; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -65,7 +66,6 @@ import org.apache.log4j.Logger; public class SimulatedPlayerMCTS extends MCTSPlayer { private boolean isSimulatedPlayer; - private static Random rnd = new Random(); private int actionCount = 0; private static final Logger logger = Logger.getLogger(SimulatedPlayerMCTS.class); @@ -115,21 +115,21 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { if (playables.size() == 1) { ability = playables.get(0); } else { - ability = playables.get(rnd.nextInt(playables.size())); + ability = playables.get(RandomUtil.nextInt(playables.size())); } List options = getPlayableOptions(ability, game); if (!options.isEmpty()) { if (options.size() == 1) { ability = options.get(0); } else { - ability = options.get(rnd.nextInt(options.size())); + ability = options.get(RandomUtil.nextInt(options.size())); } } if (ability.getManaCosts().getVariableCosts().size() > 0) { int amount = getAvailableManaProducers(game).size() - ability.getManaCosts().convertedManaCost(); if (amount > 0) { ability = ability.copy(); - ability.getManaCostsToPay().add(new GenericManaCost(rnd.nextInt(amount))); + ability.getManaCostsToPay().add(new GenericManaCost(RandomUtil.nextInt(amount))); } } // check if ability kills player, if not then it's ok to play @@ -163,7 +163,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { if (options.size() == 1) { ability = options.get(0); } else { - ability = options.get(rnd.nextInt(options.size())); + ability = options.get(RandomUtil.nextInt(options.size())); } } if (ability.isUsesStack()) { @@ -192,7 +192,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { List attackersList = super.getAvailableAttackers(defenderId, game); //use binary digits to calculate powerset of attackers int powerElements = (int) Math.pow(2, attackersList.size()); - int value = rnd.nextInt(powerElements); + int value = RandomUtil.nextInt(powerElements); StringBuilder binary = new StringBuilder(); binary.append(Integer.toBinaryString(value)); while (binary.length() < attackersList.size()) { @@ -219,7 +219,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { List blockers = getAvailableBlockers(game); for (Permanent blocker : blockers) { - int check = rnd.nextInt(numGroups + 1); + int check = RandomUtil.nextInt(numGroups + 1); if (check < numGroups) { CombatGroup group = game.getCombat().getGroups().get(check); if (group.getAttackers().size() > 0) { @@ -245,7 +245,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { return true; } Iterator it = possibleTargets.iterator(); - int targetNum = rnd.nextInt(possibleTargets.size()); + int targetNum = RandomUtil.nextInt(possibleTargets.size()); UUID targetId = it.next(); for (int i = 0; i < targetNum; i++) { targetId = it.next(); @@ -260,7 +260,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { return false; } if (!target.isRequired(source)) { - if (rnd.nextInt(possibleTargets.size() + 1) == 0) { + if (RandomUtil.nextInt(possibleTargets.size() + 1) == 0) { return false; } } @@ -269,7 +269,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { return true; } Iterator it = possibleTargets.iterator(); - int targetNum = rnd.nextInt(possibleTargets.size()); + int targetNum = RandomUtil.nextInt(possibleTargets.size()); UUID targetId = it.next(); for (int i = 0; i < targetNum; i++) { targetId = it.next(); @@ -305,7 +305,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { return false; } Iterator it = possibleTargets.iterator(); - int targetNum = rnd.nextInt(possibleTargets.size()); + int targetNum = RandomUtil.nextInt(possibleTargets.size()); UUID targetId = it.next(); for (int i = 0; i < targetNum; i++) { targetId = it.next(); @@ -338,7 +338,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { return !target.isRequired(source); } if (!target.isRequired(source)) { - if (rnd.nextInt(possibleTargets.size() + 1) == 0) { + if (RandomUtil.nextInt(possibleTargets.size() + 1) == 0) { return false; } } @@ -347,24 +347,24 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { return true; } Iterator it = possibleTargets.iterator(); - int targetNum = rnd.nextInt(possibleTargets.size()); + int targetNum = RandomUtil.nextInt(possibleTargets.size()); UUID targetId = it.next(); for (int i = 0; i < targetNum; i++) { targetId = it.next(); } - target.addTarget(targetId, rnd.nextInt(target.getAmountRemaining()) + 1, source, game); + target.addTarget(targetId, RandomUtil.nextInt(target.getAmountRemaining()) + 1, source, game); return true; } @Override public boolean chooseMulligan(Game game) { - return rnd.nextBoolean(); + return RandomUtil.nextBoolean(); } @Override public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { if (this.isHuman()) { - return rnd.nextBoolean(); + return RandomUtil.nextBoolean(); } return super.chooseUse(outcome, message, source, game); } @@ -372,7 +372,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public boolean choosePile(Outcome outcome, String message, List pile1, List pile2, Game game) { if (this.isHuman()) { - return rnd.nextBoolean(); + return RandomUtil.nextBoolean(); } return super.choosePile(outcome, message, pile1, pile2, game); } @@ -382,7 +382,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { if (this.isHuman()) { Iterator it = choice.getChoices().iterator(); String sChoice = it.next(); - int choiceNum = rnd.nextInt(choice.getChoices().size()); + int choiceNum = RandomUtil.nextInt(choice.getChoices().size()); for (int i = 0; i < choiceNum; i++) { sChoice = it.next(); } @@ -395,7 +395,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public int chooseReplacementEffect(Map rEffects, Game game) { if (this.isHuman()) { - return rnd.nextInt(rEffects.size()); + return RandomUtil.nextInt(rEffects.size()); } return super.chooseReplacementEffect(rEffects, game); } @@ -403,7 +403,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { if (this.isHuman()) { - return abilities.get(rnd.nextInt(abilities.size())); + return abilities.get(RandomUtil.nextInt(abilities.size())); } return super.chooseTriggeredAbility(abilities, game); } @@ -416,7 +416,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { if (modes.size() == 1) { return mode; } - int modeNum = rnd.nextInt(modes.getAvailableModes(source, game).size()); + int modeNum = RandomUtil.nextInt(modes.getAvailableModes(source, game).size()); for (int i = 0; i < modeNum; i++) { mode = it.next(); } @@ -428,7 +428,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public UUID chooseAttackerOrder(List attackers, Game game) { if (this.isHuman()) { - return attackers.get(rnd.nextInt(attackers.size())).getId(); + return attackers.get(RandomUtil.nextInt(attackers.size())).getId(); } return super.chooseAttackerOrder(attackers, game); } @@ -436,7 +436,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup, List blockerOrder, Game game) { if (this.isHuman()) { - return blockers.get(rnd.nextInt(blockers.size())).getId(); + return blockers.get(RandomUtil.nextInt(blockers.size())).getId(); } return super.chooseBlockerOrder(blockers, combatGroup, blockerOrder, game); } @@ -452,8 +452,8 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { targetId = targets.get(0); amount = remainingDamage; } else { - targetId = targets.get(rnd.nextInt(targets.size())); - amount = rnd.nextInt(damage + 1); + targetId = targets.get(RandomUtil.nextInt(targets.size())); + amount = RandomUtil.nextInt(damage + 1); } Permanent permanent = game.getPermanent(targetId); if (permanent != null) { @@ -476,7 +476,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public int getAmount(int min, int max, String message, Game game) { if (this.isHuman()) { - return rnd.nextInt(max - min) + min; + return RandomUtil.nextInt(max - min) + min; } return super.getAmount(min, max, message, game); } diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 97f1f39eff7..7893fbca3d7 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -6,6 +6,7 @@ import mage.cards.repository.CardRepository; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import mage.util.RandomUtil; import java.io.File; import java.util.Date; @@ -95,10 +96,9 @@ public class SystemUtil { continue; } - Random random = new Random(); Set cardsToLoad = new HashSet<>(); for (int i = 0; i < amount; i++) { - CardInfo cardInfo = cards.get(random.nextInt(cards.size())); + CardInfo cardInfo = cards.get(RandomUtil.nextInt(cards.size())); Card card = cardInfo != null ? cardInfo.getCard() : null; if (card != null) { cardsToLoad.add(card); diff --git a/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java b/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java index c09a17e4511..12ea2756440 100644 --- a/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java +++ b/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java @@ -38,6 +38,7 @@ import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.Rarity; import mage.constants.SetType; +import mage.util.RandomUtil; /** * @@ -73,7 +74,7 @@ public class ShadowsOverInnistrad extends ExpansionSet { public void addDoubleFace(List booster) { for (int i = 0; i < numBoosterDoubleFaced; i++) { List doubleFacedCards; - if (rnd.nextInt(15) < 10) { + if (RandomUtil.nextInt(15) < 10) { doubleFacedCards = getDoubleFacedCardsByRarity(Rarity.COMMON); } else { doubleFacedCards = getDoubleFacedCardsByRarity(Rarity.UNCOMMON); @@ -99,14 +100,14 @@ public class ShadowsOverInnistrad extends ExpansionSet { @Override public int getNumberOfSpecialCommons() { // Then about an eighth of the packs will have a second double-faced card, which will be a rare or mythic rare. - return rnd.nextInt(8) == 0 ? 1 : 0; + return RandomUtil.nextInt(8) == 0 ? 1 : 0; } @Override public void addSpecialCommon(List booster, int number) { // number is here always 1 List doubleFacedCards; - if (rnd.nextInt(8) > 0) { + if (RandomUtil.nextInt(8) > 0) { doubleFacedCards = getDoubleFacedCardsByRarity(Rarity.RARE); } else { doubleFacedCards = getDoubleFacedCardsByRarity(Rarity.MYTHIC); diff --git a/Mage.Sets/src/mage/sets/bornofthegods/WhimsOfTheFates.java b/Mage.Sets/src/mage/sets/bornofthegods/WhimsOfTheFates.java index 36856182484..2d50e66ab17 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/WhimsOfTheFates.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/WhimsOfTheFates.java @@ -48,6 +48,7 @@ import mage.players.Player; import mage.players.PlayerList; import mage.target.Target; import mage.target.TargetPermanent; +import mage.util.RandomUtil; /** * @@ -76,7 +77,6 @@ public class WhimsOfTheFates extends CardImpl { class WhimsOfTheFateEffect extends OneShotEffect { - protected static Random rnd = new Random(); public WhimsOfTheFateEffect() { super(Outcome.Detriment); @@ -173,7 +173,7 @@ class WhimsOfTheFateEffect extends OneShotEffect { Player player = game.getPlayer(playerPiles.getKey()); if (player != null) { // decide which pile to sacrifice - int sacrificePile = rnd.nextInt(3) + 1; // random number from 1 - 3 + int sacrificePile = RandomUtil.nextInt(3) + 1; // random number from 1 - 3 game.informPlayers(new StringBuilder(player.getLogName()).append(" sacrifices pile number ").append(sacrificePile).toString()); for (UUID permanentId : playerPiles.getValue().get(sacrificePile)) { Permanent permanent = game.getPermanent(permanentId); diff --git a/Mage.Sets/src/mage/sets/commander/RuhanOfTheFomori.java b/Mage.Sets/src/mage/sets/commander/RuhanOfTheFomori.java index b215a1ba779..8e051a99611 100644 --- a/Mage.Sets/src/mage/sets/commander/RuhanOfTheFomori.java +++ b/Mage.Sets/src/mage/sets/commander/RuhanOfTheFomori.java @@ -47,6 +47,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import mage.util.RandomUtil; /** * @@ -98,10 +99,9 @@ class RuhanOfTheFomoriEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Random random = new Random(); List opponents = new ArrayList<>(); opponents.addAll(game.getOpponents(controller.getId())); - Player opponent = game.getPlayer(opponents.get(random.nextInt(opponents.size()))); + Player opponent = game.getPlayer(opponents.get(RandomUtil.nextInt(opponents.size()))); if (opponent != null) { ContinuousEffect effect = new AttacksIfAbleTargetPlayerSourceEffect(); effect.setTargetPointer(new FixedTarget(opponent.getId())); diff --git a/Mage.Sets/src/mage/sets/commander2014/RavingDead.java b/Mage.Sets/src/mage/sets/commander2014/RavingDead.java index a46544c436b..b4bcb686eb8 100644 --- a/Mage.Sets/src/mage/sets/commander2014/RavingDead.java +++ b/Mage.Sets/src/mage/sets/commander2014/RavingDead.java @@ -49,6 +49,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import mage.util.RandomUtil; /** * @@ -102,10 +103,9 @@ class RavingDeadEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Random random = new Random(); List opponents = new ArrayList<>(); opponents.addAll(game.getOpponents(controller.getId())); - Player opponent = game.getPlayer(opponents.get(random.nextInt(opponents.size()))); + Player opponent = game.getPlayer(opponents.get(RandomUtil.nextInt(opponents.size()))); if (opponent != null) { ContinuousEffect effect = new AttacksIfAbleTargetPlayerSourceEffect(); effect.setTargetPointer(new FixedTarget(opponent.getId())); diff --git a/Mage.Sets/src/mage/sets/darkascension/HauntedFengraf.java b/Mage.Sets/src/mage/sets/darkascension/HauntedFengraf.java index 80e8777b2ee..f1579c77358 100644 --- a/Mage.Sets/src/mage/sets/darkascension/HauntedFengraf.java +++ b/Mage.Sets/src/mage/sets/darkascension/HauntedFengraf.java @@ -46,6 +46,7 @@ import mage.cards.CardImpl; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -98,8 +99,7 @@ class HauntedFengrafEffect extends OneShotEffect { if (player != null) { Card[] cards = player.getGraveyard().getCards(new FilterCreatureCard(), game).toArray(new Card[0]); if (cards.length > 0) { - Random rnd = new Random(); - Card card = cards[rnd.nextInt(cards.length)]; + Card card = cards[RandomUtil.nextInt(cards.length)]; card.moveToZone(Zone.HAND, source.getSourceId(), game, true); game.informPlayers(card.getName() + " returned to the hand of " + player.getLogName()); return true; diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/RideDown.java b/Mage.Sets/src/mage/sets/eldritchmoon/RideDown.java index fabce419d10..3ac0e21d3d1 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/RideDown.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/RideDown.java @@ -27,6 +27,8 @@ */ package mage.sets.eldritchmoon; +import mage.sets.EldritchMoon; + import java.util.UUID; /** diff --git a/Mage.Sets/src/mage/sets/innistrad/CharmbreakerDevils.java b/Mage.Sets/src/mage/sets/innistrad/CharmbreakerDevils.java index 839dc8f3f55..25f5ff325e2 100644 --- a/Mage.Sets/src/mage/sets/innistrad/CharmbreakerDevils.java +++ b/Mage.Sets/src/mage/sets/innistrad/CharmbreakerDevils.java @@ -49,6 +49,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -114,8 +115,7 @@ class CharmbreakerDevilsEffect extends OneShotEffect { new CardTypePredicate(CardType.SORCERY))); Card[] cards = player.getGraveyard().getCards(filter, game).toArray(new Card[0]); if (cards.length > 0) { - Random rnd = new Random(); - Card card = cards[rnd.nextInt(cards.length)]; + Card card = cards[RandomUtil.nextInt(cards.length)]; card.moveToZone(Zone.HAND, source.getSourceId(), game, true); game.informPlayers(new StringBuilder("Charmbreaker Devils: ").append(card.getName()).append(" returned to the hand of ").append(player.getLogName()).toString()); return true; diff --git a/Mage.Sets/src/mage/sets/innistrad/Ghoulraiser.java b/Mage.Sets/src/mage/sets/innistrad/Ghoulraiser.java index a5cfba8f1e5..2ada4c0cb4d 100644 --- a/Mage.Sets/src/mage/sets/innistrad/Ghoulraiser.java +++ b/Mage.Sets/src/mage/sets/innistrad/Ghoulraiser.java @@ -43,6 +43,7 @@ import mage.filter.FilterCard; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -96,8 +97,7 @@ class GhoulraiserEffect extends OneShotEffect { filter.add(new SubtypePredicate("Zombie")); Card[] cards = player.getGraveyard().getCards(filter, game).toArray(new Card[0]); if (cards.length > 0) { - Random rnd = new Random(); - Card card = cards[rnd.nextInt(cards.length)]; + Card card = cards[RandomUtil.nextInt(cards.length)]; card.moveToZone(Zone.HAND, source.getSourceId(), game, true); game.informPlayers(card.getName() + "returned to the hand of" + player.getLogName()); return true; diff --git a/Mage.Sets/src/mage/sets/innistrad/MoldgrafMonstrosity.java b/Mage.Sets/src/mage/sets/innistrad/MoldgrafMonstrosity.java index 2e4d4db01d0..bc16b5b3c4d 100644 --- a/Mage.Sets/src/mage/sets/innistrad/MoldgrafMonstrosity.java +++ b/Mage.Sets/src/mage/sets/innistrad/MoldgrafMonstrosity.java @@ -45,6 +45,7 @@ import mage.cards.CardImpl; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -116,7 +117,7 @@ class MoldgrafMonstrosityEffect extends OneShotEffect { return null; } int i = 0; - int pick = new Random().nextInt(cards.size()); + int pick = RandomUtil.nextInt(cards.size()); for (Card card : cards) { if (i == pick) { return card; diff --git a/Mage.Sets/src/mage/sets/innistrad/WoodlandSleuth.java b/Mage.Sets/src/mage/sets/innistrad/WoodlandSleuth.java index 58bfb1279af..b956488b401 100644 --- a/Mage.Sets/src/mage/sets/innistrad/WoodlandSleuth.java +++ b/Mage.Sets/src/mage/sets/innistrad/WoodlandSleuth.java @@ -45,6 +45,7 @@ import mage.cards.CardImpl; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -101,8 +102,7 @@ class WoodlandSleuthEffect extends OneShotEffect { if (player != null) { Card[] cards = player.getGraveyard().getCards(new FilterCreatureCard(), game).toArray(new Card[0]); if (cards.length > 0) { - Random rnd = new Random(); - Card card = cards[rnd.nextInt(cards.length)]; + Card card = cards[RandomUtil.nextInt(cards.length)]; card.moveToZone(Zone.HAND, source.getSourceId(), game, true); game.informPlayers(card.getName() + " returned to the hand of " + player.getLogName()); return true; diff --git a/Mage.Sets/src/mage/sets/magic2010/CapriciousEfreet.java b/Mage.Sets/src/mage/sets/magic2010/CapriciousEfreet.java index 302de2ba8c7..df5050cd3ee 100644 --- a/Mage.Sets/src/mage/sets/magic2010/CapriciousEfreet.java +++ b/Mage.Sets/src/mage/sets/magic2010/CapriciousEfreet.java @@ -44,6 +44,7 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.util.RandomUtil; /** * @@ -115,8 +116,7 @@ class CapriciousEfreetEffect extends OneShotEffect { } if (!targetPermanents.isEmpty()) { - Random random = new Random(); - permanent = targetPermanents.get(random.nextInt(targetPermanents.size())); + permanent = targetPermanents.get(RandomUtil.nextInt(targetPermanents.size())); permanent.destroy(source.getSourceId(), game, false); return true; } diff --git a/Mage.Sets/src/mage/sets/magic2012/Scrambleverse.java b/Mage.Sets/src/mage/sets/magic2012/Scrambleverse.java index f3ba25b30d7..b83a8cfd601 100644 --- a/Mage.Sets/src/mage/sets/magic2012/Scrambleverse.java +++ b/Mage.Sets/src/mage/sets/magic2012/Scrambleverse.java @@ -43,6 +43,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.PlayerList; import mage.target.targetpointer.FixedTarget; +import mage.util.RandomUtil; /** * @@ -81,11 +82,10 @@ class ScrambleverseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Random random = new Random(); PlayerList players = game.getState().getPlayersInRange(source.getControllerId(), game); int count = players.size(); for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterNonlandPermanent(), source.getControllerId(), source.getSourceId(), game)) { - ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, players.get(random.nextInt(count))); + ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, players.get(RandomUtil.nextInt(count))); effect.setTargetPointer(new FixedTarget(permanent.getId())); game.addEffect(effect, source); permanent.untap(game); diff --git a/Mage.Sets/src/mage/sets/magic2014/MoltenBirth.java b/Mage.Sets/src/mage/sets/magic2014/MoltenBirth.java index ff8fc7e9bb4..df4221518d2 100644 --- a/Mage.Sets/src/mage/sets/magic2014/MoltenBirth.java +++ b/Mage.Sets/src/mage/sets/magic2014/MoltenBirth.java @@ -41,6 +41,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.token.Token; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -106,7 +107,7 @@ class ElementalToken extends Token { public ElementalToken() { super("Elemental", "1/1 red Elemental creature"); this.setOriginalExpansionSetCode("M14"); - this.setTokenType(new Random().nextInt(2) + 1); + this.setTokenType(RandomUtil.nextInt(2) + 1); cardType.add(CardType.CREATURE); color.setRed(true); subtype.add("Elemental"); diff --git a/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java b/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java index 68c7595f228..24b2f71d8d0 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java +++ b/Mage.Sets/src/mage/sets/mirrodin/KrarksThumb.java @@ -41,6 +41,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -83,7 +84,7 @@ class KrarksThumbEffect extends ReplacementEffectImpl { Player player = game.getPlayer(event.getPlayerId()); if (player != null) { // because second flip is ignored it may not be done by the player method - boolean secondCoinFlip = new Random().nextBoolean(); + boolean secondCoinFlip = RandomUtil.nextBoolean(); if (!game.isSimulation()) { game.informPlayers("[Flip a coin] " + player.getLogName() + (secondCoinFlip ? " won (head)." : " lost (tail).")); } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrealMemoir.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrealMemoir.java index cdc512d4cb0..9bd362867ef 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrealMemoir.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrealMemoir.java @@ -42,6 +42,7 @@ import mage.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -93,8 +94,7 @@ class SurrealMemoirEffect extends OneShotEffect { filter.add(new CardTypePredicate(CardType.INSTANT)); Card[] cards = player.getGraveyard().getCards(filter, game).toArray(new Card[0]); if (cards.length > 0) { - Random rnd = new Random(); - Card card = cards[rnd.nextInt(cards.length)]; + Card card = cards[RandomUtil.nextInt(cards.length)]; card.moveToZone(Zone.HAND, source.getSourceId(), game, true); game.informPlayers(card.getName() + "returned to the hand of" + player.getLogName()); return true; diff --git a/Mage.Sets/src/mage/sets/scourge/GripOfChaos.java b/Mage.Sets/src/mage/sets/scourge/GripOfChaos.java index 0f846931d02..4f7131948dc 100644 --- a/Mage.Sets/src/mage/sets/scourge/GripOfChaos.java +++ b/Mage.Sets/src/mage/sets/scourge/GripOfChaos.java @@ -47,6 +47,7 @@ import mage.game.events.GameEvent.EventType; import mage.game.stack.StackObject; import mage.target.Target; import mage.target.targetpointer.FixedTarget; +import mage.util.RandomUtil; /** * @@ -154,7 +155,7 @@ class GripOfChaosEffect extends OneShotEffect { Set possibleTargets = target.possibleTargets(source.getSourceId(), source.getControllerId(), game); if (possibleTargets.size() > 0) { int i = 0; - int rnd = new Random().nextInt(possibleTargets.size()); + int rnd = RandomUtil.nextInt(possibleTargets.size()); Iterator it = possibleTargets.iterator(); while (i < rnd) { it.next(); diff --git a/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java b/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java index 3b3c4ac10ae..a6e9ac57182 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java @@ -43,6 +43,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.TargetPermanent; +import mage.util.RandomUtil; /** * @@ -98,8 +99,8 @@ class WildSwingEffect extends OneShotEffect { if (!source.getTargets().isEmpty() && sourceObject != null) { Target target = source.getTargets().get(0); if (target != null && !target.getTargets().isEmpty()) { - Random rnd = new Random(); - Permanent targetPermanent = game.getPermanent(target.getTargets().get(rnd.nextInt(target.getTargets().size()))); + + Permanent targetPermanent = game.getPermanent(target.getTargets().get(RandomUtil.nextInt(target.getTargets().size()))); if (targetPermanent != null) { game.informPlayers(sourceObject.getLogName() + ": The randomly chosen target to destroy is " + targetPermanent.getLogName()); targetPermanent.destroy(source.getSourceId(), game, false); diff --git a/Mage/src/main/java/mage/cards/CardsImpl.java b/Mage/src/main/java/mage/cards/CardsImpl.java index 46eeb4984d6..9719114d329 100644 --- a/Mage/src/main/java/mage/cards/CardsImpl.java +++ b/Mage/src/main/java/mage/cards/CardsImpl.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.UUID; import mage.filter.FilterCard; import mage.game.Game; +import mage.util.RandomUtil; import mage.util.ThreadLocalStringBuilder; /** @@ -51,7 +52,6 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl private static final ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(200); - private static Random rnd = new Random(); private UUID ownerId; public CardsImpl() { @@ -114,7 +114,7 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl return null; } UUID[] cards = this.toArray(new UUID[this.size()]); - return game.getCard(cards[rnd.nextInt(cards.length)]); + return game.getCard(cards[RandomUtil.nextInt(cards.length)]); } @Override diff --git a/Mage/src/main/java/mage/cards/ExpansionSet.java b/Mage/src/main/java/mage/cards/ExpansionSet.java index a81f82ce04b..3b4e004d9c9 100644 --- a/Mage/src/main/java/mage/cards/ExpansionSet.java +++ b/Mage/src/main/java/mage/cards/ExpansionSet.java @@ -38,13 +38,13 @@ import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.Rarity; import mage.constants.SetType; +import mage.util.RandomUtil; /** * @author BetaSteward_at_googlemail.com */ public abstract class ExpansionSet implements Serializable { - protected static Random rnd = new Random(); protected String name; protected String code; @@ -136,7 +136,7 @@ public abstract class ExpansionSet implements Serializable { protected void addToBooster(List booster, List cards) { if (!cards.isEmpty()) { - CardInfo cardInfo = cards.remove(rnd.nextInt(cards.size())); + CardInfo cardInfo = cards.remove(RandomUtil.nextInt(cards.size())); if (cardInfo != null) { Card card = cardInfo.getCard(); if (card != null) { @@ -156,7 +156,7 @@ public abstract class ExpansionSet implements Serializable { List specialLands = getSpecialLand(); List basicLands = getCardsByRarity(Rarity.LAND); for (int i = 0; i < numBoosterLands; i++) { - if (ratioBoosterSpecialLand > 0 && rnd.nextInt(ratioBoosterSpecialLand) == 0 && specialLands != null) { + if (ratioBoosterSpecialLand > 0 && RandomUtil.nextInt(ratioBoosterSpecialLand) == 0 && specialLands != null) { addToBooster(booster, specialLands); } else { addToBooster(booster, basicLands); @@ -183,7 +183,7 @@ public abstract class ExpansionSet implements Serializable { List rares = getCardsByRarity(Rarity.RARE); List mythics = getCardsByRarity(Rarity.MYTHIC); for (int i = 0; i < numBoosterRare; i++) { - if (ratioBoosterMythic > 0 && rnd.nextInt(ratioBoosterMythic) == 0) { + if (ratioBoosterMythic > 0 && RandomUtil.nextInt(ratioBoosterMythic) == 0) { addToBooster(booster, mythics); } else { addToBooster(booster, rares); @@ -208,11 +208,11 @@ public abstract class ExpansionSet implements Serializable { for (int i = 0; i < numBoosterDoubleFaced; i++) { CardCriteria criteria = new CardCriteria(); criteria.setCodes(this.code).doubleFaced(true); - if (rnd.nextInt(15) < 10) { + if (RandomUtil.nextInt(15) < 10) { criteria.rarities(Rarity.COMMON); - } else if (rnd.nextInt(5) < 4) { + } else if (RandomUtil.nextInt(5) < 4) { criteria.rarities(Rarity.UNCOMMON); - } else if (rnd.nextInt(8) < 7) { + } else if (RandomUtil.nextInt(8) < 7) { criteria.rarities(Rarity.RARE); } else { criteria.rarities(Rarity.MYTHIC); @@ -265,7 +265,7 @@ public abstract class ExpansionSet implements Serializable { } if (specialCards > 0) { for (int i = 0; i < numBoosterSpecial; i++) { - if (rnd.nextInt(15) < 10) { + if (RandomUtil.nextInt(15) < 10) { if (specialCommon != null && !specialCommon.isEmpty()) { addToBooster(booster, specialCommon); } else { @@ -273,7 +273,7 @@ public abstract class ExpansionSet implements Serializable { } continue; } - if (rnd.nextInt(4) < 3) { + if (RandomUtil.nextInt(4) < 3) { if (specialUncommon != null && !specialUncommon.isEmpty()) { addToBooster(booster, specialUncommon); } else { @@ -281,7 +281,7 @@ public abstract class ExpansionSet implements Serializable { } continue; } - if (rnd.nextInt(8) < 7) { + if (RandomUtil.nextInt(8) < 7) { if (specialRare != null && !specialRare.isEmpty()) { addToBooster(booster, specialRare); } else { @@ -291,7 +291,7 @@ public abstract class ExpansionSet implements Serializable { } if (specialMythic != null && !specialMythic.isEmpty()) { if (specialBonus != null && !specialBonus.isEmpty()) { - if (rnd.nextInt(3) < 2) { + if (RandomUtil.nextInt(3) < 2) { addToBooster(booster, specialMythic); continue; } diff --git a/Mage/src/main/java/mage/cards/Sets.java b/Mage/src/main/java/mage/cards/Sets.java index 0ddb5a8828e..41b605973e8 100644 --- a/Mage/src/main/java/mage/cards/Sets.java +++ b/Mage/src/main/java/mage/cards/Sets.java @@ -45,6 +45,7 @@ import mage.constants.CardType; import mage.constants.ColoredManaSymbol; import mage.util.ClassScanner; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -55,7 +56,6 @@ public class Sets extends HashMap { private static final Logger logger = Logger.getLogger(Sets.class); private static final Sets fINSTANCE = new Sets(); - protected static Random rnd = new Random(); public static Sets getInstance() { return fINSTANCE; @@ -111,7 +111,7 @@ public class Sets extends HashMap { int tries = 0; List cardPool = new ArrayList<>(); while (count < cardsCount) { - CardInfo cardInfo = cards.get(rnd.nextInt(cards.size())); + CardInfo cardInfo = cards.get(RandomUtil.nextInt(cards.size())); Card card = cardInfo != null ? cardInfo.getCard() : null; if (card != null) { cardPool.add(card); diff --git a/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java index 7ee643ff02a..0f738099adf 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java @@ -34,6 +34,7 @@ import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.util.RandomUtil; /** * @@ -71,7 +72,7 @@ public class MWSDeckImporter extends DeckImporter { List cards = null; cards = CardRepository.instance.findCards(criteria); if (!cards.isEmpty()) { - cardInfo = cards.get(new Random().nextInt(cards.size())); + cardInfo = cards.get(RandomUtil.nextInt(cards.size())); } } if (cardInfo == null) { diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 448771998b8..278d9ea027c 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -48,6 +48,7 @@ import java.util.TreeSet; import java.util.concurrent.Callable; import mage.constants.CardType; import mage.constants.SetType; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -65,7 +66,6 @@ public enum CardRepository { // raise this if new cards were added to the server private static final long CARD_CONTENT_VERSION = 57; - private final Random random = new Random(); private Dao cardDao; private Set classNames; @@ -317,7 +317,7 @@ public enum CardRepository { public CardInfo findCard(String name) { List cards = findCards(name); if (!cards.isEmpty()) { - return cards.get(random.nextInt(cards.size())); + return cards.get(RandomUtil.nextInt(cards.size())); } return null; } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 2e3b7272147..16227b0073b 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -124,6 +124,7 @@ import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.util.GameLog; import mage.util.MessageToClient; +import mage.util.RandomUtil; import mage.util.functions.ApplyToPermanent; import mage.watchers.Watchers; import mage.watchers.common.BlockedAttackerWatcher; @@ -159,7 +160,6 @@ public abstract class GameImpl implements Game, Serializable { FILTER_LEGENDARY.add(new SupertypePredicate("Legendary")); } - private static Random rnd = new Random(); private transient Object customData; protected boolean simulation = false; @@ -1098,7 +1098,7 @@ public abstract class GameImpl implements Game, Serializable { UUID[] players = getPlayers().keySet().toArray(new UUID[0]); UUID playerId; while (!hasEnded()) { - playerId = players[rnd.nextInt(players.length)]; + playerId = players[RandomUtil.nextInt(players.length)]; Player player = getPlayer(playerId); if (player != null && player.isInGame()) { fireInformEvent(state.getPlayer(playerId).getLogName() + " won the toss"); diff --git a/Mage/src/main/java/mage/game/draft/DraftCube.java b/Mage/src/main/java/mage/game/draft/DraftCube.java index e5df9e66808..2e8fddc1096 100644 --- a/Mage/src/main/java/mage/game/draft/DraftCube.java +++ b/Mage/src/main/java/mage/game/draft/DraftCube.java @@ -34,6 +34,7 @@ import mage.cards.Card; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -71,7 +72,6 @@ public abstract class DraftCube { private static final Logger logger = Logger.getLogger(DraftCube.class); - private static final Random rnd = new Random(); private final String name; private final int boosterSize = 15; @@ -100,7 +100,7 @@ public abstract class DraftCube { boolean done = false; int notValid = 0; while (!done) { - int index = rnd.nextInt(leftCubeCards.size()); + int index = RandomUtil.nextInt(leftCubeCards.size()); CardIdentity cardId = leftCubeCards.get(index); leftCubeCards.remove(index); if (!cardId.getName().isEmpty()) { diff --git a/Mage/src/main/java/mage/game/draft/DraftImpl.java b/Mage/src/main/java/mage/game/draft/DraftImpl.java index babf5359bd4..f0a73ce0d90 100644 --- a/Mage/src/main/java/mage/game/draft/DraftImpl.java +++ b/Mage/src/main/java/mage/game/draft/DraftImpl.java @@ -121,6 +121,7 @@ public abstract class DraftImpl implements Draft { for(UUID playerId : players.keySet()) { table.add(playerId); } + table.setCurrent(currentId); } if (oldDraftPlayer.isPicking()) { diff --git a/Mage/src/main/java/mage/game/match/MatchImpl.java b/Mage/src/main/java/mage/game/match/MatchImpl.java index a864f1f5c6e..d3d4f1091a2 100644 --- a/Mage/src/main/java/mage/game/match/MatchImpl.java +++ b/Mage/src/main/java/mage/game/match/MatchImpl.java @@ -45,6 +45,7 @@ import mage.game.result.ResultProtos.MatchProto; import mage.game.result.ResultProtos.MatchQuitStatus; import mage.players.Player; import mage.util.DateFormat; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -243,7 +244,7 @@ public abstract class MatchImpl implements Match { } protected void shufflePlayers() { - Collections.shuffle(this.players, new Random()); + Collections.shuffle(this.players, RandomUtil.getRandom()); } @Override diff --git a/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java b/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java index 2517090bc60..222201ef11b 100644 --- a/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/CentaurToken.java @@ -31,6 +31,7 @@ package mage.game.permanent.token; import java.util.Random; import mage.constants.CardType; import mage.MageInt; +import mage.util.RandomUtil; /** * @@ -41,7 +42,7 @@ public class CentaurToken extends Token { public CentaurToken() { super("Centaur", "3/3 green Centaur creature token"); cardType.add(CardType.CREATURE); - setTokenType(new Random().nextInt(2) +1); // randomly take image 1 or 2 + setTokenType(RandomUtil.nextInt(2) +1); // randomly take image 1 or 2 color.setGreen(true); subtype.add("Centaur"); power = new MageInt(3); diff --git a/Mage/src/main/java/mage/game/permanent/token/ClueArtifactToken.java b/Mage/src/main/java/mage/game/permanent/token/ClueArtifactToken.java index d1e64b27f8d..0e2ffa5785c 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ClueArtifactToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ClueArtifactToken.java @@ -38,6 +38,7 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.constants.CardType; import mage.constants.Zone; +import mage.util.RandomUtil; /** * @@ -69,10 +70,10 @@ public class ClueArtifactToken extends Token { public void setExpansionSetCodeForImage(String code) { super.setExpansionSetCodeForImage(code); if (getOriginalExpansionSetCode().equals("SOI")) { - this.setTokenType(new Random().nextInt(6) + 1); // 6 different images + this.setTokenType(RandomUtil.nextInt(6) + 1); // 6 different images } if (getOriginalExpansionSetCode().equals("EDM")) { - this.setTokenType(new Random().nextInt(6) + 1); // 6 different images + this.setTokenType(RandomUtil.nextInt(6) + 1); // 6 different images } } diff --git a/Mage/src/main/java/mage/game/permanent/token/EldraziScionToken.java b/Mage/src/main/java/mage/game/permanent/token/EldraziScionToken.java index 7b347d7de52..c2564d3669c 100644 --- a/Mage/src/main/java/mage/game/permanent/token/EldraziScionToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/EldraziScionToken.java @@ -37,6 +37,7 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.mana.SimpleManaAbility; import mage.constants.CardType; import mage.constants.Zone; +import mage.util.RandomUtil; /** * @@ -65,10 +66,10 @@ public class EldraziScionToken extends Token { public void setExpansionSetCodeForImage(String code) { super.setExpansionSetCodeForImage(code); if (getOriginalExpansionSetCode().equals("BFZ")) { - this.setTokenType(new Random().nextInt(3) + 1); // 3 different images + this.setTokenType(RandomUtil.nextInt(3) + 1); // 3 different images } if (getOriginalExpansionSetCode().equals("OGW")) { - this.setTokenType(new Random().nextInt(6) + 1); // 6 different images + this.setTokenType(RandomUtil.nextInt(6) + 1); // 6 different images } } diff --git a/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java b/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java index 2ec29418c6f..43956bef299 100644 --- a/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java @@ -37,6 +37,7 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.mana.SimpleManaAbility; import mage.constants.CardType; import mage.constants.Zone; +import mage.util.RandomUtil; /** * @@ -61,6 +62,6 @@ public class EldraziSpawnToken extends Token { availableImageSetCodes = tokenImageSets; // Get one of the three possible token images - this.setTokenType(new Random().nextInt(3) + 1); + this.setTokenType(RandomUtil.nextInt(3) + 1); } } \ No newline at end of file diff --git a/Mage/src/main/java/mage/game/permanent/token/SoldierToken.java b/Mage/src/main/java/mage/game/permanent/token/SoldierToken.java index 8ce18a7b7a6..ede064baf26 100644 --- a/Mage/src/main/java/mage/game/permanent/token/SoldierToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/SoldierToken.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Random; import mage.MageInt; import mage.constants.CardType; +import mage.util.RandomUtil; /** * @@ -62,7 +63,7 @@ public class SoldierToken extends Token { public void setExpansionSetCodeForImage(String code) { super.setExpansionSetCodeForImage(code); if (getOriginalExpansionSetCode().equals("THS")) { - this.setTokenType(new Random().nextInt(2) + 1); + this.setTokenType(RandomUtil.nextInt(2) + 1); } } diff --git a/Mage/src/main/java/mage/game/permanent/token/ThopterColorlessToken.java b/Mage/src/main/java/mage/game/permanent/token/ThopterColorlessToken.java index 695be8d1115..3e488568038 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ThopterColorlessToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ThopterColorlessToken.java @@ -34,6 +34,7 @@ import java.util.Random; import mage.MageInt; import mage.abilities.keyword.FlyingAbility; import mage.constants.CardType; +import mage.util.RandomUtil; /** * @@ -63,7 +64,7 @@ public class ThopterColorlessToken extends Token { public void setExpansionSetCodeForImage(String code) { super.setExpansionSetCodeForImage(code); if (getOriginalExpansionSetCode().equals("ORI")) { - this.setTokenType(new Random().nextInt(2) + 1); + this.setTokenType(RandomUtil.nextInt(2) + 1); } } diff --git a/Mage/src/main/java/mage/game/permanent/token/Token.java b/Mage/src/main/java/mage/game/permanent/token/Token.java index 84dfc613676..012f07187f5 100644 --- a/Mage/src/main/java/mage/game/permanent/token/Token.java +++ b/Mage/src/main/java/mage/game/permanent/token/Token.java @@ -46,6 +46,7 @@ import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; import mage.players.Player; +import mage.util.RandomUtil; public class Token extends MageObjectImpl { @@ -290,7 +291,7 @@ public class Token extends MageObjectImpl { // we should not set random set if appropriate set is already used if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty() || !availableImageSetCodes.contains(getOriginalExpansionSetCode())) { - setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size()))); + setOriginalExpansionSetCode(availableImageSetCodes.get(RandomUtil.nextInt(availableImageSetCodes.size()))); } } } else { diff --git a/Mage/src/main/java/mage/game/permanent/token/WarriorToken.java b/Mage/src/main/java/mage/game/permanent/token/WarriorToken.java index 5ddc1c3aa21..6a34f22d336 100644 --- a/Mage/src/main/java/mage/game/permanent/token/WarriorToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/WarriorToken.java @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.Random; import mage.MageInt; import mage.constants.CardType; +import mage.util.RandomUtil; /** * @@ -62,7 +63,7 @@ public class WarriorToken extends Token { public void setExpansionSetCodeForImage(String code) { super.setExpansionSetCodeForImage(code); if (getOriginalExpansionSetCode().equals("KTK")) { - this.setTokenType(new Random().nextInt(2) + 1); + this.setTokenType(RandomUtil.nextInt(2) + 1); } } } diff --git a/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java b/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java index fec1a2d90cd..8da3f8ad3d5 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ZombieToken.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Random; import mage.MageInt; import mage.constants.CardType; +import mage.util.RandomUtil; /** * @@ -61,13 +62,13 @@ public class ZombieToken extends Token { public void setExpansionSetCodeForImage(String code) { super.setExpansionSetCodeForImage(code); if (getOriginalExpansionSetCode().equals("ISD")) { - this.setTokenType(new Random().nextInt(3) + 1); + this.setTokenType(RandomUtil.nextInt(3) + 1); } if (getOriginalExpansionSetCode().equals("C14")) { this.setTokenType(2); } if (getOriginalExpansionSetCode().equals("EMN")) { - this.setTokenType(new Random().nextInt(4) + 1); + this.setTokenType(RandomUtil.nextInt(4) + 1); } } diff --git a/Mage/src/main/java/mage/game/tournament/TournamentImpl.java b/Mage/src/main/java/mage/game/tournament/TournamentImpl.java index ae2fea34ce7..ebc7faf589c 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentImpl.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentImpl.java @@ -57,6 +57,7 @@ import mage.game.result.ResultProtos.MatchQuitStatus; import mage.game.result.ResultProtos.TourneyProto; import mage.game.result.ResultProtos.TourneyRoundProto; import mage.players.Player; +import mage.util.RandomUtil; import org.apache.log4j.Logger; /** @@ -68,7 +69,6 @@ public abstract class TournamentImpl implements Tournament { protected UUID id = UUID.randomUUID(); protected List rounds = new CopyOnWriteArrayList<>(); protected Map players = new HashMap<>(); - protected static Random rnd = new Random(); protected String matchName; protected TournamentOptions options; protected TournamentType tournamentType; @@ -217,7 +217,7 @@ public abstract class TournamentImpl implements Tournament { private TournamentPlayer getNextAvailablePlayer(List roundPlayers, List playerWithByes) { TournamentPlayer nextPlayer; if (playerWithByes.isEmpty()) { - int i = rnd.nextInt(roundPlayers.size()); + int i = RandomUtil.nextInt(roundPlayers.size()); nextPlayer = roundPlayers.get(i); roundPlayers.remove(i); } else { // prefer players with byes to pair diff --git a/Mage/src/main/java/mage/players/Library.java b/Mage/src/main/java/mage/players/Library.java index 94db01427e3..157a986bba6 100644 --- a/Mage/src/main/java/mage/players/Library.java +++ b/Mage/src/main/java/mage/players/Library.java @@ -45,6 +45,7 @@ import mage.cards.Card; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; +import mage.util.RandomUtil; /** * @@ -52,7 +53,6 @@ import mage.game.Game; */ public class Library implements Serializable { - private static Random rnd = new Random(); private boolean emptyDraw; private final Deque library = new ArrayDeque<>(); @@ -76,7 +76,7 @@ public class Library implements Serializable { public void shuffle() { UUID[] shuffled = library.toArray(new UUID[0]); for (int n = shuffled.length - 1; n > 0; n--) { - int r = rnd.nextInt(n); + int r = RandomUtil.nextInt(n); UUID temp = shuffled[n]; shuffled[n] = shuffled[r]; shuffled[r] = temp; diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index d921af4bd41..12e72769ca2 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -135,13 +135,13 @@ import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetDiscard; import mage.util.CardUtil; import mage.util.GameLog; +import mage.util.RandomUtil; import org.apache.log4j.Logger; public abstract class PlayerImpl implements Player, Serializable { private static final Logger logger = Logger.getLogger(PlayerImpl.class); - private static Random rnd = new Random(); private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); /** @@ -2329,7 +2329,7 @@ public abstract class PlayerImpl implements Player, Serializable { */ @Override public boolean flipCoin(Game game, ArrayList appliedEffects) { - boolean result = rnd.nextBoolean(); + boolean result = RandomUtil.nextBoolean(); if (!game.isSimulation()) { game.informPlayers("[Flip a coin] " + getLogName() + (result ? " won (head)." : " lost (tail).")); } diff --git a/Mage/src/main/java/mage/target/TargetImpl.java b/Mage/src/main/java/mage/target/TargetImpl.java index 6a9a4113c53..f3452954ebb 100644 --- a/Mage/src/main/java/mage/target/TargetImpl.java +++ b/Mage/src/main/java/mage/target/TargetImpl.java @@ -47,6 +47,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import mage.util.RandomUtil; /** * @@ -322,7 +323,7 @@ public abstract class TargetImpl implements Target { Set possibleTargets = possibleTargets(source.getSourceId(), playerId, game); if (possibleTargets.size() > 0) { int i = 0; - int rnd = new Random().nextInt(possibleTargets.size()); + int rnd = RandomUtil.nextInt(possibleTargets.size()); Iterator it = possibleTargets.iterator(); while (i < rnd) { it.next(); diff --git a/Mage/src/main/java/mage/util/RandomUtil.java b/Mage/src/main/java/mage/util/RandomUtil.java new file mode 100644 index 00000000000..2721d4e0e83 --- /dev/null +++ b/Mage/src/main/java/mage/util/RandomUtil.java @@ -0,0 +1,28 @@ +package mage.util; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +/** + * Created by IGOUDT on 5-9-2016. + */ +public class RandomUtil { + + private static ThreadLocalRandom random = ThreadLocalRandom.current(); + + public static Random getRandom(){ + return random; + } + + public static int nextInt(){ + return random.nextInt(); + } + + public static int nextInt(int max){ + return random.nextInt(max); + } + + public static boolean nextBoolean() { + return random.nextBoolean(); + } +} diff --git a/Mage/src/main/java/mage/util/TournamentUtil.java b/Mage/src/main/java/mage/util/TournamentUtil.java index 5e5c825525f..c4f8ab2d1ec 100644 --- a/Mage/src/main/java/mage/util/TournamentUtil.java +++ b/Mage/src/main/java/mage/util/TournamentUtil.java @@ -61,10 +61,9 @@ public class TournamentUtil { if (landSetCodes.isEmpty()) { // if sets have no basic lands and also it has no parent or parent has no lands get last set with lands // select a set with basic lands by random - Random generator = new Random(); List basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate(); if (basicLandSets.size() > 0) { - landSetCodes.add(basicLandSets.get(generator.nextInt(basicLandSets.size())).getCode()); + landSetCodes.add(basicLandSets.get(RandomUtil.nextInt(basicLandSets.size())).getCode()); } } @@ -75,7 +74,6 @@ public class TournamentUtil { } public static List getLands(String landName, int number, Set landSets) { - Random random = new Random(); CardCriteria criteria = new CardCriteria(); if (!landSets.isEmpty()) { criteria.setCodes(landSets.toArray(new String[landSets.size()])); @@ -85,7 +83,7 @@ public class TournamentUtil { List cards = new ArrayList<>(); if (!lands.isEmpty()) { for (int i = 0; i < number; i++) { - Card land = lands.get(random.nextInt(lands.size())).getCard(); + Card land = lands.get(RandomUtil.nextInt(lands.size())).getCard(); cards.add(land); } } From f6d06c895e2051039584b4edebf35b2bea7aec30 Mon Sep 17 00:00:00 2001 From: spjspj Date: Tue, 6 Sep 2016 01:41:04 +1000 Subject: [PATCH 16/26] spjspj - Slight fix for colours of tokens --- Mage.Sets/src/mage/sets/alarareborn/LichLordOfUnx.java | 2 +- Mage.Sets/src/mage/sets/dragonsoftarkir/SkywiseTeachings.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/alarareborn/LichLordOfUnx.java b/Mage.Sets/src/mage/sets/alarareborn/LichLordOfUnx.java index 2591a8c73a6..39c4b722232 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/LichLordOfUnx.java +++ b/Mage.Sets/src/mage/sets/alarareborn/LichLordOfUnx.java @@ -94,7 +94,7 @@ class ZombieWizardToken extends Token { ZombieWizardToken() { super("Zombie Wizard", "a 1/1 blue and black Zombie Wizard creature token"); cardType.add(CardType.CREATURE); - color.setGreen(true); + color.setBlue(true); color.setBlack(true); subtype.add("Zombie"); subtype.add("Wizard"); diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/SkywiseTeachings.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/SkywiseTeachings.java index 00514f19f76..90d47cd2d66 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/SkywiseTeachings.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/SkywiseTeachings.java @@ -78,7 +78,7 @@ class SkywiseTeachingsToken extends Token { SkywiseTeachingsToken() { super("Djinn Monk", "a 2/2 blue Djinn Monk creature token with flying"); cardType.add(CardType.CREATURE); - color.setRed(true); + color.setBlue(true); this.subtype.add("Djinn"); this.subtype.add("Monk"); power = new MageInt(2); From d70f424d1bd81c86b9bf544dd2e9398a2a43eb16 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Tue, 6 Sep 2016 00:27:44 -0500 Subject: [PATCH 17/26] [KLD] Added 9/5 spoilers to mtg-cards-data.txt and implemented a few cards. --- .../sets/kaladesh/CataclysmicGearhulk.java | 188 ++++++++++++++++++ .../mage/sets/kaladesh/FortuitousFind.java | 73 +++++++ .../src/mage/sets/kaladesh/GhirapurGuide.java | 80 ++++++++ .../sets/kaladesh/MasterTrinketcrafter.java | 83 ++++++++ .../mage/sets/kaladesh/MorbidCuriosity.java | 75 +++++++ .../sets/kaladesh/OvalchaseDaredevil.java | 75 +++++++ .../mage/sets/kaladesh/WispweaverAngel.java | 149 ++++++++++++++ .../mage/game/permanent/token/ServoToken.java | 72 +++++++ Utils/mtg-cards-data.txt | 28 ++- 9 files changed, 820 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/CataclysmicGearhulk.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/FortuitousFind.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/GhirapurGuide.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/MasterTrinketcrafter.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/MorbidCuriosity.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/OvalchaseDaredevil.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/WispweaverAngel.java create mode 100644 Mage/src/main/java/mage/game/permanent/token/ServoToken.java diff --git a/Mage.Sets/src/mage/sets/kaladesh/CataclysmicGearhulk.java b/Mage.Sets/src/mage/sets/kaladesh/CataclysmicGearhulk.java new file mode 100644 index 00000000000..f824160fb64 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/CataclysmicGearhulk.java @@ -0,0 +1,188 @@ +/* + * 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.kaladesh; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledEnchantmentPermanent; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author fireshoes + */ +public class CataclysmicGearhulk extends CardImpl { + + public CataclysmicGearhulk(UUID ownerId) { + super(ownerId, 9, "Cataclysmic Gearhulk", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Construct"); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // When Cataclysmic Gearhulk enters the battlefield, each player chooses from among the non-land permanents he or she controls an artifact, a creature, + // an enchantment, and a planeswalker, then sacrifices the rest. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CataclysmicGearhulkEffect(), false)); + } + + public CataclysmicGearhulk(final CataclysmicGearhulk card) { + super(card); + } + + @Override + public CataclysmicGearhulk copy() { + return new CataclysmicGearhulk(this); + } +} + +class CataclysmicGearhulkEffect extends OneShotEffect { + + private static final FilterControlledArtifactPermanent filterArtifact = new FilterControlledArtifactPermanent("artifact"); + private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent("creature"); + private static final FilterControlledEnchantmentPermanent filterEnchantment = new FilterControlledEnchantmentPermanent("enchantment"); + private static final FilterControlledPlaneswalkerPermanent filterPlaneswalker = new FilterControlledPlaneswalkerPermanent("planeswalker"); + + static { + filterArtifact.add(Predicates.and( + new CardTypePredicate(CardType.ARTIFACT), + Predicates.not(new CardTypePredicate(CardType.LAND)))); + filterCreature.add(Predicates.and( + new CardTypePredicate(CardType.CREATURE), + Predicates.not(new CardTypePredicate(CardType.LAND)))); + filterEnchantment.add(Predicates.and( + new CardTypePredicate(CardType.ENCHANTMENT), + Predicates.not(new CardTypePredicate(CardType.LAND)))); + filterPlaneswalker.add(Predicates.and( + new CardTypePredicate(CardType.PLANESWALKER), + Predicates.not(new CardTypePredicate(CardType.LAND)))); + } + + public CataclysmicGearhulkEffect() { + super(Outcome.DestroyPermanent); + staticText = "Each player chooses from among the non-land permanents he or she controls an artifact, a creature, an enchantment, and a planeswalker, " + + "then sacrifices the rest"; + } + + public CataclysmicGearhulkEffect(CataclysmicGearhulkEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + List chosen = new ArrayList<>(); + + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + + Target target1 = new TargetControlledPermanent(1, 1, filterArtifact, true); + Target target2 = new TargetControlledPermanent(1, 1, filterCreature, true); + Target target3 = new TargetControlledPermanent(1, 1, filterEnchantment, true); + Target target4 = new TargetControlledPermanent(1, 1, filterPlaneswalker, true); + + if (target1.canChoose(player.getId(), game)) { + while (player.canRespond() && !target1.isChosen() && target1.canChoose(player.getId(), game)) { + player.chooseTarget(Outcome.Benefit, target1, source, game); + } + Permanent artifact = game.getPermanent(target1.getFirstTarget()); + if (artifact != null) { + chosen.add(artifact); + } + target1.clearChosen(); + } + + if (target2.canChoose(player.getId(), game)) { + while (player.canRespond() && !target2.isChosen() && target2.canChoose(player.getId(), game)) { + player.chooseTarget(Outcome.Benefit, target2, source, game); + } + Permanent creature = game.getPermanent(target2.getFirstTarget()); + if (creature != null) { + chosen.add(creature); + } + target2.clearChosen(); + } + + if (target3.canChoose(player.getId(), game)) { + while (player.canRespond() && !target3.isChosen() && target3.canChoose(player.getId(), game)) { + player.chooseTarget(Outcome.Benefit, target3, source, game); + } + Permanent enchantment = game.getPermanent(target3.getFirstTarget()); + if (enchantment != null) { + chosen.add(enchantment); + } + target3.clearChosen(); + } + + if (target4.canChoose(player.getId(), game)) { + while (player.canRespond() && !target4.isChosen() && target4.canChoose(player.getId(), game)) { + player.chooseTarget(Outcome.Benefit, target4, source, game); + } + Permanent planeswalker = game.getPermanent(target4.getFirstTarget()); + if (planeswalker != null) { + chosen.add(planeswalker); + } + target4.clearChosen(); + } + + } + + for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + if (!chosen.contains(permanent) && !permanent.getCardType().contains(CardType.LAND)) { + permanent.sacrifice(source.getSourceId(), game); + } + } + return true; + } + + @Override + public CataclysmicGearhulkEffect copy() { + return new CataclysmicGearhulkEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/FortuitousFind.java b/Mage.Sets/src/mage/sets/kaladesh/FortuitousFind.java new file mode 100644 index 00000000000..37baf104b80 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/FortuitousFind.java @@ -0,0 +1,73 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterArtifactCard; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author fireshoes + */ +public class FortuitousFind extends CardImpl { + + public FortuitousFind(UUID ownerId) { + super(ownerId, 81, "Fortuitous Find", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); + this.expansionSetCode = "KLD"; + + // Choose one or both — + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(2); + + // Return target artifact card from your graveyard to your hand.; + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard"))); + + // or Return target creature card from your graveyard to your hand. + Mode mode = new Mode(); + mode.getEffects().add(new ReturnToHandTargetEffect()); + mode.getTargets().add(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card from your graveyard"))); + this.getSpellAbility().addMode(mode); + } + + public FortuitousFind(final FortuitousFind card) { + super(card); + } + + @Override + public FortuitousFind copy() { + return new FortuitousFind(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/GhirapurGuide.java b/Mage.Sets/src/mage/sets/kaladesh/GhirapurGuide.java new file mode 100644 index 00000000000..83ebd692142 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/GhirapurGuide.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 mage.sets.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantBeBlockedByAllTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class GhirapurGuide extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 2 or less"); + + static { + filter.add(new PowerPredicate(Filter.ComparisonType.LessThan, 3)); + } + + public GhirapurGuide(UUID ownerId) { + super(ownerId, 156, "Ghirapur Guide", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Elf"); + this.subtype.add("Scout"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // {2}{G}: Target creature you control can't be blocked by creatures with power 2 or less this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedByAllTargetEffect(filter, Duration.EndOfTurn), new ManaCostsImpl("{2}{G}")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public GhirapurGuide(final GhirapurGuide card) { + super(card); + } + + @Override + public GhirapurGuide copy() { + return new GhirapurGuide(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/MasterTrinketcrafter.java b/Mage.Sets/src/mage/sets/kaladesh/MasterTrinketcrafter.java new file mode 100644 index 00000000000..80c494d83cd --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/MasterTrinketcrafter.java @@ -0,0 +1,83 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.permanent.token.ServoToken; + +/** + * + * @author fireshoes + */ +public class MasterTrinketcrafter extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Servo and Thopter creatures"); + + static { + filter.add(Predicates.or(new SubtypePredicate("Servo"), + new SubtypePredicate("Thopter"))); + } + + public MasterTrinketcrafter(UUID ownerId) { + super(ownerId, 21, "Master Trinketcrafter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dwarf"); + this.subtype.add("Artificer"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Servo and Thopter creatures you control get +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, false))); + + // {3}{W}: Create a 1/1 colorless Servo artifact creature token. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ServoToken(), 1), new ManaCostsImpl("{3}{W}"))); + } + + public MasterTrinketcrafter(final MasterTrinketcrafter card) { + super(card); + } + + @Override + public MasterTrinketcrafter copy() { + return new MasterTrinketcrafter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/MorbidCuriosity.java b/Mage.Sets/src/mage/sets/kaladesh/MorbidCuriosity.java new file mode 100644 index 00000000000..209127ad5f0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/MorbidCuriosity.java @@ -0,0 +1,75 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.dynamicvalue.common.SacrificeCostConvertedMana; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author fireshoes + */ +public class MorbidCuriosity extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or creature"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE))); + } + + public MorbidCuriosity(UUID ownerId) { + super(ownerId, 94, "Morbid Curiosity", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{B}{B}"); + this.expansionSetCode = "KLD"; + + // As an additional cost to cast Morbid Curiosity, sacrifice an artifact or creature. + this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + + // Draw cards equal to the converted mana cost of the sacrificed permanent. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new SacrificeCostConvertedMana("permanent"))); + } + + public MorbidCuriosity(final MorbidCuriosity card) { + super(card); + } + + @Override + public MorbidCuriosity copy() { + return new MorbidCuriosity(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/OvalchaseDaredevil.java b/Mage.Sets/src/mage/sets/kaladesh/OvalchaseDaredevil.java new file mode 100644 index 00000000000..6cc24a4583e --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/OvalchaseDaredevil.java @@ -0,0 +1,75 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author fireshoes + */ +public class OvalchaseDaredevil extends CardImpl { + + private static final FilterPermanent filter = new FilterArtifactPermanent("an artifact"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public OvalchaseDaredevil(UUID ownerId) { + super(ownerId, 97, "Ovalchase Daredevil", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Human"); + this.subtype.add("Pilot"); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // Whenever an artifact enters the battlefield under your control, you may return Ovalchase Daredevil from your graveyard to your hand. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.GRAVEYARD, new ReturnToHandSourceEffect(), filter, true)); + } + + public OvalchaseDaredevil(final OvalchaseDaredevil card) { + super(card); + } + + @Override + public OvalchaseDaredevil copy() { + return new OvalchaseDaredevil(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/WispweaverAngel.java b/Mage.Sets/src/mage/sets/kaladesh/WispweaverAngel.java new file mode 100644 index 00000000000..89fc10225b2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/WispweaverAngel.java @@ -0,0 +1,149 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetForSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.cards.MeldCard; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.util.CardUtil; + +/** + * + * @author fireshoes + */ +public class WispweaverAngel extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another creature you control"); + + static { + filter.add(new AnotherPredicate()); + } + + public WispweaverAngel(UUID ownerId) { + super(ownerId, 35, "Wispweaver Angel", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Angel"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control. + Effect effect = new ExileTargetForSourceEffect(); + effect.setApplyEffectsAfter(); + Ability ability = new EntersBattlefieldTriggeredAbility(effect, true); + ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false)); + ability.addEffect(new WispweaverAngelEffect()); + this.addAbility(ability); + } + + public WispweaverAngel(final WispweaverAngel card) { + super(card); + } + + @Override + public WispweaverAngel copy() { + return new WispweaverAngel(this); + } +} + +class WispweaverAngelEffect extends OneShotEffect { + + WispweaverAngelEffect() { + super(Outcome.Benefit); + staticText = "return that card to the battlefield under its owner's control"; + } + + WispweaverAngelEffect(final WispweaverAngelEffect effect) { + super(effect); + } + + @Override + public WispweaverAngelEffect copy() { + return new WispweaverAngelEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Cards cardsToBattlefield = new CardsImpl(); + UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + if (exileZoneId != null) { + ExileZone exileZone = game.getExile().getExileZone(exileZoneId); + if (exileZone != null) { + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + if (exileZone.contains(targetId)) { + cardsToBattlefield.add(targetId); + } + else { + Card card = game.getCard(targetId); + if (card != null && card instanceof MeldCard) { + MeldCard meldCard = (MeldCard) card; + Card topCard = meldCard.getTopHalfCard(); + Card bottomCard = meldCard.getBottomHalfCard(); + if (topCard.getZoneChangeCounter(game) == meldCard.getTopLastZoneChangeCounter() && exileZone.contains(topCard.getId())) { + cardsToBattlefield.add(topCard); + } + if (bottomCard.getZoneChangeCounter(game) == meldCard.getBottomLastZoneChangeCounter() && exileZone.contains(bottomCard.getId())) { + cardsToBattlefield.add(bottomCard); + } + } + } + } + } + } + if (!cardsToBattlefield.isEmpty()) { + controller.moveCards(cardsToBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null); + } + return true; + } + return false; + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/ServoToken.java b/Mage/src/main/java/mage/game/permanent/token/ServoToken.java new file mode 100644 index 00000000000..f06d83d33c4 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/ServoToken.java @@ -0,0 +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.game.permanent.token; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import mage.MageInt; +import mage.constants.CardType; + +/** + * + * @author fireshoes + */ +public class ServoToken extends Token { + + final static private List tokenImageSets = new ArrayList<>(); + + static { + tokenImageSets.addAll(Arrays.asList("KLD")); + } + + public ServoToken() { + super("Servo", "1/1 colorless Servo artifact creature token"); + availableImageSetCodes = tokenImageSets; + cardType.add(CardType.ARTIFACT); + cardType.add(CardType.CREATURE); + subtype.add("Servo"); + power = new MageInt(1); + toughness = new MageInt(1); + } + + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + } + + public ServoToken(final ServoToken token) { + super(token); + } + + @Override + public ServoToken copy() { + return new ServoToken(this); + } + +} diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 2f436e19372..fd8abfa68be 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -29655,33 +29655,55 @@ Thirsting Axe|Eldritch Moon|202|U|{3}|Artifact - Equipment|||Equipped creature g Geier Reach Sanitarium|Eldritch Moon|203|R||Legendary Land|||{T}: Add {C} to your mana pool.${2}, {T}: Each player draws a card, then discards a card.| Hanweir Battlements|Eldritch Moon|204|R||Land|||{T}: Add {C} to your mana pool.${R},{T}: Target creature gains haste until end of turn.${3}{R}{R},{T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township.| Nephalia Academy|Eldritch Moon|205|U||Land|||If a spell or ability an opponent controls causes you to discard a card, you may reveal that card and put it on top of your library instead of putting it anywhere else.${T}: Add {C} to your mana pool.| +Aerial Responder|Kaladesh|2|U|{1}{W}{W}|Creature - Dwarf Soldier|2|3|Flying, vigilance, lifelink| Aetherstorm Roc|Kaladesh|3|R|{2}{W}{W}|Creature - Bird|3|3|Flying$Whenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E} (an energy counter).$Whenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 creature on it and tap up to one target creature defending player controls.| -Glint-Sleeve Artisan|Kaladesh|017|C|{2}{W}|Creature - Dwarf Artificer|2|2|Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| -Propeller Pioneer|Kaladesh|024|C|{3}{W}|Creature - Human Artificer|2|1|Flying$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Cataclysmic Gearhulk|Kaladesh|9|M|{3}{W}{W}|Artifact Creature - Construct|4|5|Vigilance$When Cataclysmic Gearhulk enters the battlefield, each player chooses from among the non-land permanents he or she controls an artifact, a creature, an enchantment, and a planeswalker, then sacrifices the rest.| +Glint-Sleeve Artisan|Kaladesh|17|C|{2}{W}|Creature - Dwarf Artificer|2|2|Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| +Master Trinketcrafter|Kaladesh|21|R|{2}{W}|Creature - Dwarf Artificer|3|2|Servo and Thopter creatures you control get +1/+1.${3}{W}: Create a 1/1 colorless Servo artifact creature token.| +Propeller Pioneer|Kaladesh|24|C|{3}{W}|Creature - Human Artificer|2|1|Flying$Fabricate 1 (When this creature enters the battlefield, put a +1/+1 counter on it or create a 1/1 colorless Servo artifact creature token.)| Tasseled Dromedary|Kaladesh|30|C|{W}|Creature - Camel|0|4|| +Wispweaver Angel|Kaladesh|35|U|{4}{W}{W}|Creature - Angel|4|4|Flying$When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control.| Aether Tradewinds|Kaladesh|38|C|{2}{U}|Instant|||Return target permanent you control and target permanent you don't control to their owners' hands.| +Ceremonious Rejection|Kaladesh|40|U|{U}|Instant|||Counter target colorless spell.| Curio Vendor|Kaladesh|42|C|{1}{U}|Creature - Vedalken|2|1|| +Metallurgic Summonings|Kaladesh|56|M|{3}{U}{U}|Enchantment|||Whenever you cast an instant or sorcery spell, create an X/X colorless Construct artifact creature token, where X is that spell's converted mana cost.${3}{U}{U}, Exile Metallurgic Summons: Return all instant and sorcery cards from your graveyard to your hand. Activate this ability only if you control six or more artifacts.| Saheeli's Artistry|Kaladesh|62|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except that it's an artifact in addition to its other types.| Demon of Shadowy Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Shadowy Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (one energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control. | Die Young|Kaladesh|76|C|{1}{B}|Sorcery|||Choose target creature. You get {E}{E} (two energy counters), then you may pay any amount of {E}. The creature gets -1/-1 until end of turn for each {E} paid this way.| -Gonti, Lord of Luxury|Kaladesh|084|R|{2}{B}{B}|Legendary Creature - Aetherborn Rogue|2|3|Deathtouch$When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.| +Essence Extraction|Kaladesh|80|U|{1}{B}{B}|Instant|||Essence Extraction deals 3 damage to target creature and you gain 3 life.| +Fortuitous Find|Kaladesh|81|C|{2}{B}|Sorcery|||Choose one or both — Return target artifact card from your graveyard to your hand.; or Return target creature card from your graveyard to your hand.| +Gonti, Lord of Luxury|Kaladesh|84|R|{2}{B}{B}|Legendary Creature - Aetherborn Rogue|2|3|Deathtouch$When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.| Live Fast|Kaladesh|87|C|{2}{B}|Sorcery|||You draw two cards, lose 2 life, and gain {E}{E} (two energy counters).| +Morbid Curiosity|Kaladesh|94|U|{1}{B}{B}|Sorcery|||As an additional cost to cast Morbid Curiosity, sacrifice an artifact or creature.$Draw cards equal to the converted mana cost of the sacrificed permanent.| +Ovalchase Daredevil|Kaladesh|97|U|{3}{B}|Creature - Human Pilot|4|2|Whenever an artifact enters the battlefield under your control, you may return Ovalchase Daredevil from your graveyard to your hand.| +Chandra, Torch of Defiance|Kaladesh|110|M|{2}{R}{R}|Planeswalker - Chandra|||+1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent.$+1: Add {R}{R} to your mana pool.$-3: Chandra, Torch of Defiance deals 4 damage to target creature.$-7: You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player."| Furious Reprisal|Kaladesh|115|U|{3}{R}|Sorcery|||Furious Reprisal deals 2 damage to each of two target creatures and/or players.| +Harnessed Lightning|Kaladesh|117|U|{1}{R}|Instant|||Choose target creature. You get {E}{E}{E} (three energy counters), then you may pay any amount of {E}. Harnessed Lightning deals that much damage to that creature.| +Pia Nalaar|Kaladesh|124|R|{2}{R}|Legendary Creature - Human Artificer|2|2|When Pia Nalaar enters the battlefield, create a 1/1 colorless Thopter artifact creature token with flying.${1}{R}: Target artifact creature gets +1/+0 until end of turn.${1}, Sacrifice an artifact: Target creature can't block this turn.| Skyship Stalker|Kaladesh|130|R|{2}{R}{R}|Creature - Dragon|3|3|Flying${R}: Skyship Stalker gains +1/+0 until end of turn.${R}: Skyship Stalker gains first strike until end of turn.${R}: Skyship Stalker gains haste until end of turn.| Speedway Fanatic|Kaladesh|132|U|{1}{R}|Creature - Human Pilot|2|1|Haste$Whenever Speedway Fanatic crews a Vehicle, that Vehicle gains haste until end of turn.| Start Your Engines|Kaladesh|135|U|{3}{R}|Sorcery|||Vehicles you control becomes artifact creatures until end of turn. Creatures you control get +2/+0 until end of turn.| Territorial Devourer|Kaladesh|136|R|{3}{R}|Creature - Gremlin|2|2|Trample $Whenever you gain one or more {E} (energy counters), Territorial Devourer gets +2/+2 until end of turn.| Terror of the Fairgrounds|Kaladesh|137|C|{3}{R}|Creature - Gremlin|5|2|| +Arborback Stomper|Kaladesh|142|U|{3}{G}{G}|Creature - Beast|5|4|Trample$When Arborback Stomper enters the battlefield, you gain 5 life.| Architect of the Untamed|Kaladesh|143|R|{2}{G}|Creature - Elf Artificer Druid|2|3|Whenever a land enters the battlefiend under your control, you get {E} (an energy counter).$Pay {E}{E}{E}{E}{E}{E}{E}{E}: Create a 6/6 colorless Beast artifact creature token.| +Armorcraft Judge|Kaladesh|144|U|{3}{G}|Creature - Elf Artificer|3|3|When Armorcraft Judge enters the battlefield, draw a card for each creature you control with a +1/+1 counter on it.| Cultivator of Blades|Kaladesh|151|R|{3}{G}{G}|Creature - Elf Artificer|1|1|Fabricate 2$Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power.| +Ghirapur Guide|Kaladesh|156|U|{2}{G}|Creature - Elf Scout|3|2|{2}{G}: Target creature you control can't be blocked by creatures with power 2 or less this turn.| +Larger Than Life|Kaladesh|160|C|{1}{G}|Sorcery|||Target creature gets +4/+4 and gains trample until end of turn.| +Longtusk Cub|Kaladesh|161|U|{1}{G}|Creature - Cat|2|2|Whenever Longtusk Cub deals combat damage to a player, you get {E}{E} (two energy counters).$Pay {E}{E}: Put a +1/+1 counter on Longtusk Cub.| Verdurous Gearhulk|Kaladesh|172|M|{3}{G}{G}|Artifact Creature - Construct|4|4|Trample$When Verdurous Gearhulk enters the battlefield, distribute four +1/+1 counters among any number of target creatures you control.| Depala, Pilot Exemplar|Kaladesh|178|R|{1}{R}{W}|Legendary Creature - Dwarf Pilot|3|3|Other Dwarves you control get +1/+1.$Each Vehicle you control gets +1/+1 as long as it's a creature.$Whenever Depala, Pilot Exemplar becomes tapped, you may pay {X}. If you do, reveal the top X cards of your library, put all Dwarf and Vehicle cards from among them into your hand, then put the rest on the bottom of your library in a random order.| Rashmi, Eternities Crafter|Kaladesh|184|M|{2}{G}{U}|Legendary Creature - Elf Druid|2|3|Whenever you cast your first spell each turn, reveal the top card of your library. If it's a nonland card with converted mana cost less than that spell's, you may cast it without paying its mana cost. If you don't cast the revealed card, put it into your hand. | Saheeli Rai|Kaladesh|186|M|{1}{U}{R}|Planeswalker - Saheeli|3|+1: Scry 1. Saheeli Rai deals 1 damage to each opponent.$-2: Create a token that's a copy of target artifact or creature you control, except it's an artifact in addition to its other types. That token gains haste. Exile it at the beginning of the next end step.$-7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.| +Voltaic Brawler|Kaladesh|189|U|{R}{G}|Creature - Human Warrior|3|2|When Voltaic Brawler enters the battlefield, you get {E}{E} (two energy counters).$Whenever Voltaic Brawler attacks, you may pay {E}. If you do, it gets +1/+1 and gains trample until end of turn.| Aetherworks Marvel|Kaladesh|193|M|{4}|Legendary Artifact|||Whenever a permanent you control is put into a graveyard, you get {E} (an energy counter).${T}, Pay {E}{E}{E}{E}{E}{E}: Look at the top six cards of your library. You may cast a card from among them without paying its mana cost. Put the rest on the bottom of your library in a random order.| +Bomat Bazaar Barge|Kaladesh|198|U|{4}|Artifact - Vehicle|5|5|When Bomat Bazaar Barge enters the battlefield, draw a card.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| +Demolition Stomper|Kaladesh|206|U|{6}|Artifact - Vehicle|10|7|Demolition Stomper can't be blocked by creature with power 2 or less.$Crew 5 (Tap any number of creatures you control with total power 5 or more: This Vehicle becomes an artifact creature until end of turn.)| Filigree Familiar|Kaladesh|212|U|{3}|Artifact Creature - Fox|2|2|When Filigree Familiar enters the battlefield, you gain 2 life.$When Filigree Familiar dies, draw a card.| Fleetwheel Cruiser|Kaladesh|214|R|{4}|Artifact - Vehicle|5|3|Trample, Haste $When Fleetwheel Cruiser enters the battlefield, it becomes an artifact creature until the end of turn.$Crew 2 (Tap any number of creatures you control with total power 2 or more: This Vehicle becomes an artifact creature until end of turn.)| Ghirapur Orrery|Kaladesh|216|R|{4}|Artifact|||Each player may play an additional land on each of his or her turns.$At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.| +Inventor's Goggles|Kaladesh|218|C|{1}|Artifact - Equipment|||Equipped creature gets +1/+2.$Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it.$Equip {2} ({2}: Attach to target creature you control. Equip only as a sorcery)| Ovalchase Dragster|Kaladesh|225|U|{4}|Artifact - Vehicle|6|1|Trample, haste$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| Panharmonicon|Kaladesh|226|R|{4}|Artifact|||If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.| Sky Skiff|Kaladesh|233|C|{2}|Artifact - Vehicle|2|3|Flying$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| From bc0f53973d11c983087d235757639254a24c64ce Mon Sep 17 00:00:00 2001 From: emerald000 Date: Tue, 6 Sep 2016 02:07:59 -0400 Subject: [PATCH 18/26] Added an easier way to put custom text on buttons in a chooseUse prompt. --- .../java/mage/player/ai/ComputerPlayer.java | 5 ++--- .../src/mage/player/human/HumanPlayer.java | 22 +++++++++++++------ .../commander2015/DawnbreakReclaimer.java | 13 ++++++----- .../mage/sets/eldritchmoon/FortunesFavor.java | 4 +--- .../RemorselessPunishment.java | 15 +++++-------- .../java/org/mage/test/player/TestPlayer.java | 9 ++++---- .../java/org/mage/test/stub/PlayerStub.java | 3 +-- Mage/src/main/java/mage/game/GameImpl.java | 5 +---- Mage/src/main/java/mage/players/Player.java | 3 +-- 9 files changed, 38 insertions(+), 41 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 2bcae9b1ffd..0d1a60d29dd 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -42,7 +42,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; import java.util.Set; import java.util.TreeMap; import java.util.UUID; @@ -1272,11 +1271,11 @@ public class ComputerPlayer extends PlayerImpl implements Player { @Override public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { - return this.chooseUse(outcome, new MessageToClient(message), source, game); + return this.chooseUse(outcome, message, null, null, null, source, game); } @Override - public boolean chooseUse(Outcome outcome, MessageToClient message, Ability source, Game game) { + public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { log.debug("chooseUse: " + outcome.isGood()); // Be proactive! Always use abilities, the evaluation function will decide if it's good or not // Otherwise some abilities won't be used by AI like LoseTargetEffect that has "bad" outcome diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index d5c1e37d4e7..7d619864c53 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -177,17 +177,25 @@ public class HumanPlayer extends PlayerImpl { @Override public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { - return this.chooseUse(outcome, new MessageToClient(message), source, game); + return this.chooseUse(outcome, message, null, null, null, source, game); } @Override - public boolean chooseUse(Outcome outcome, MessageToClient message, Ability source, Game game) { + public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { + MessageToClient messageToClient = new MessageToClient(message, secondMessage); + Map options = new HashMap<>(2); + if (trueText != null) { + options.put("UI.left.btn.text", trueText); + } + if (falseText != null) { + options.put("UI.right.btn.text", falseText); + } if (source != null) { - Boolean answer = requestAutoAnswerId.get(source.getOriginalId() + "#" + message.getMessage()); + Boolean answer = requestAutoAnswerId.get(source.getOriginalId() + "#" + message); if (answer != null) { return answer; } else { - answer = requestAutoAnswerText.get(message.getMessage()); + answer = requestAutoAnswerText.get(message); if (answer != null) { return answer; } @@ -195,10 +203,10 @@ public class HumanPlayer extends PlayerImpl { } updateGameStatePriority("chooseUse", game); do { - if (message.getSecondMessage() == null) { - message.setSecondMessage(getRelatedObjectName(source, game)); + if (messageToClient.getSecondMessage() == null) { + messageToClient.setSecondMessage(getRelatedObjectName(source, game)); } - game.fireAskPlayerEvent(playerId, message, source); + game.fireAskPlayerEvent(playerId, messageToClient, source, options); waitForResponse(game); } while (response.getBoolean() == null && !abort); if (!abort) { diff --git a/Mage.Sets/src/mage/sets/commander2015/DawnbreakReclaimer.java b/Mage.Sets/src/mage/sets/commander2015/DawnbreakReclaimer.java index a548203590f..8ea80002417 100644 --- a/Mage.Sets/src/mage/sets/commander2015/DawnbreakReclaimer.java +++ b/Mage.Sets/src/mage/sets/commander2015/DawnbreakReclaimer.java @@ -50,7 +50,6 @@ import mage.players.Player; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInOpponentsGraveyard; import mage.target.common.TargetOpponent; -import mage.util.MessageToClient; /** * @@ -157,10 +156,14 @@ class DawnbreakReclaimerEffect extends OneShotEffect { cards.add(controllerCreatureCard); } if (!cards.isEmpty()) { - MessageToClient message = new MessageToClient("Return those cards to the battlefield under their owners' control?", - "Opponent's creature card: " + (cardOpponentGraveyard == null ? "none" : cardOpponentGraveyard.getLogName()) - + ", your creature card: " + (controllerCreatureCard == null ? "none" : controllerCreatureCard.getLogName())); - if (controller.chooseUse(outcome, message, source, game)) { + if (controller.chooseUse( + outcome, + "Return those cards to the battlefield under their owners' control?", + "Opponent's creature card: " + (cardOpponentGraveyard == null ? "none" : cardOpponentGraveyard.getLogName()) + ", your creature card: " + (controllerCreatureCard == null ? "none" : controllerCreatureCard.getLogName()), + null, + null, + source, + game)) { controller.moveCards(cards, Zone.BATTLEFIELD, source, game, false, false, true, null); } } diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/FortunesFavor.java b/Mage.Sets/src/mage/sets/eldritchmoon/FortunesFavor.java index bbae839ff03..148f580515b 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/FortunesFavor.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/FortunesFavor.java @@ -43,7 +43,6 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; -import mage.util.MessageToClient; /** * @@ -102,8 +101,7 @@ class FortunesFavorEffect extends OneShotEffect { cards.removeAll(target.getTargets()); controller.revealCards(sourceObject.getIdName() + " - cards in face-up pile", cards, game); game.informPlayers(targetOpponent.getLogName() + " puts " + faceDownPile.size() + " card(s) into the face-down pile"); - MessageToClient message = new MessageToClient("Put the face-down pile into your hand?", "(If you say yes, the face-up pile goes to the graveyard.)"); - if (controller.chooseUse(outcome, message, source, game)) { + if (controller.chooseUse(outcome, "Choose a pile to put in your hand.", null, "Face-down", "Face-up", source, game)) { controller.moveCards(faceDownPile, Zone.HAND, source, game); controller.moveCards(cards, Zone.GRAVEYARD, source, game); } else { diff --git a/Mage.Sets/src/mage/sets/oathofthegatewatch/RemorselessPunishment.java b/Mage.Sets/src/mage/sets/oathofthegatewatch/RemorselessPunishment.java index f7deb418094..e96dafa9322 100644 --- a/Mage.Sets/src/mage/sets/oathofthegatewatch/RemorselessPunishment.java +++ b/Mage.Sets/src/mage/sets/oathofthegatewatch/RemorselessPunishment.java @@ -42,7 +42,6 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetOpponent; -import mage.util.MessageToClient; /** * @@ -95,26 +94,22 @@ class RemorselessPunishmentEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); if (opponent != null) { - handleBaseEffect(game, source, opponent, 1); - handleBaseEffect(game, source, opponent, 2); + handleBaseEffect(game, source, opponent, "1st"); + handleBaseEffect(game, source, opponent, "2nd"); return true; } return false; } - private void handleBaseEffect(Game game, Ability source, Player opponent, int iteration) { + private void handleBaseEffect(Game game, Ability source, Player opponent, String iteration) { if (opponent.getHand().size() > 1) { - MessageToClient mtc = new MessageToClient("Discards two cards to prevent to lose 5 life?", - "If you want to sacrifice a creature or planeswalker instead click \"No\". (Iteration " + iteration + ")"); - if (opponent.chooseUse(outcome, mtc, source, game)) { + if (opponent.chooseUse(outcome, "Choose your " + iteration + " punishment.", null, "Discard two cards", "Choose another option", source, game)) { opponent.discard(2, false, source, game); return; } } if (game.getBattlefield().contains(filter, opponent.getId(), 1, game)) { - MessageToClient mtc = new MessageToClient("Sacrifice a creature or planeswalker?", - "If you don't sacrifice a creature or planeswalker, you lose 5 life instead. (Iteration " + iteration + ")"); - if (opponent.chooseUse(outcome, mtc, source, game)) { + if (opponent.chooseUse(outcome, "Choose your " + iteration + " punishment.", null, "Sacrifice a creature or planeswalker", "Lose 5 life", source, game)) { TargetPermanent target = new TargetPermanent(1, 1, filter, true); if (target.choose(Outcome.Sacrifice, opponent.getId(), source.getId(), game)) { for (UUID targetId : target.getTargets()) { 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 62e89e3e74f..5ede5fff409 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 @@ -104,7 +104,6 @@ import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreaturePermanentAmount; import mage.target.common.TargetPermanentOrPlayer; -import mage.util.MessageToClient; import org.junit.Ignore; /** @@ -976,12 +975,12 @@ public class TestPlayer implements Player { @Override public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { - return this.chooseUse(outcome, new MessageToClient(message), source, game); + return this.chooseUse(outcome, message, null, null, null, source, game); } @Override - public boolean chooseUse(Outcome outcome, MessageToClient message, Ability source, Game game) { - if (message.getMessage().equals("Scry 1?")) { + public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { + if (message.equals("Scry 1?")) { return false; } if (!choices.isEmpty()) { @@ -994,7 +993,7 @@ public class TestPlayer implements Player { return true; } } - return computerPlayer.chooseUse(outcome, message, source, game); + return computerPlayer.chooseUse(outcome, message, secondMessage, trueText, falseText, source, game); } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java index dbc17018ca1..81023463bab 100644 --- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java +++ b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java @@ -79,7 +79,6 @@ import mage.target.Target; import mage.target.TargetAmount; import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; -import mage.util.MessageToClient; /** * @@ -849,7 +848,7 @@ public class PlayerStub implements Player { } @Override - public boolean chooseUse(Outcome outcome, MessageToClient message, Ability source, Game game) { + public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { return false; } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 16227b0073b..f020c0e1e14 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -40,7 +40,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; import java.util.Set; import java.util.Stack; import java.util.UUID; @@ -1010,9 +1009,7 @@ public abstract class GameImpl implements Game, Serializable { for (UUID playerId : state.getPlayerList(startingPlayerId)) { Player player = getPlayer(playerId); if (player != null && player.getHand().size() < startingHandSize) { - if (player.chooseUse(Outcome.Benefit, new MessageToClient("Scry 1?", "Look at the top card of your library. You may put that card on the bottom of your library."), null, this)) { - player.scry(1, null, this); - } + player.scry(1, null, this); } } getState().setChoosingPlayerId(null); diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index f476c8c5a3f..9f28389214b 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -78,7 +78,6 @@ import mage.target.TargetAmount; import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; import mage.util.Copyable; -import mage.util.MessageToClient; /** * @@ -486,7 +485,7 @@ public interface Player extends MageItem, Copyable { boolean chooseUse(Outcome outcome, String message, Ability source, Game game); - boolean chooseUse(Outcome outcome, MessageToClient message, Ability source, Game game); + boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game); boolean choose(Outcome outcome, Choice choice, Game game); From 90a55eddb725e2e48db14e46d29c6fa1f595291c Mon Sep 17 00:00:00 2001 From: emerald000 Date: Tue, 6 Sep 2016 02:26:55 -0400 Subject: [PATCH 19/26] [KLD] Implemented Fabricate. Added 3 cards using it. --- .../sets/kaladesh/CultivatorOfBlades.java | 72 +++++++++++ .../sets/kaladesh/GlintSleeveArtisan.java | 63 +++++++++ .../mage/sets/kaladesh/PropellerPioneer.java | 66 ++++++++++ .../abilities/keyword/FabricateAbility.java | 122 ++++++++++++++++++ Utils/keywords.txt | 1 + 5 files changed, 324 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/CultivatorOfBlades.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/GlintSleeveArtisan.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/PropellerPioneer.java create mode 100644 Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java diff --git a/Mage.Sets/src/mage/sets/kaladesh/CultivatorOfBlades.java b/Mage.Sets/src/mage/sets/kaladesh/CultivatorOfBlades.java new file mode 100644 index 00000000000..c8d21c2fc21 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/CultivatorOfBlades.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FabricateAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterAttackingCreature; + +/** + * + * @author emerald000 + */ +public class CultivatorOfBlades extends CardImpl { + + public CultivatorOfBlades(UUID ownerId) { + super(ownerId, 151, "Cultivator of Blades", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Elf"); + this.subtype.add("Artificer"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Fabricate 2 + this.addAbility(new FabricateAbility(2)); + + // Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power. + this.addAbility(new AttacksTriggeredAbility(new BoostControlledEffect(new SourcePermanentPowerCount(), new SourcePermanentPowerCount(), Duration.EndOfTurn, new FilterAttackingCreature(), true, true), + true, "Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power.")); + } + + public CultivatorOfBlades(final CultivatorOfBlades card) { + super(card); + } + + @Override + public CultivatorOfBlades copy() { + return new CultivatorOfBlades(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/GlintSleeveArtisan.java b/Mage.Sets/src/mage/sets/kaladesh/GlintSleeveArtisan.java new file mode 100644 index 00000000000..2808f822d58 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/GlintSleeveArtisan.java @@ -0,0 +1,63 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.FabricateAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class GlintSleeveArtisan extends CardImpl { + + public GlintSleeveArtisan(UUID ownerId) { + super(ownerId, 017, "Glint-Sleeve Artisan", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Dwarf"); + this.subtype.add("Artificer"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Fabricate 1 + this.addAbility(new FabricateAbility(1)); + } + + public GlintSleeveArtisan(final GlintSleeveArtisan card) { + super(card); + } + + @Override + public GlintSleeveArtisan copy() { + return new GlintSleeveArtisan(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/PropellerPioneer.java b/Mage.Sets/src/mage/sets/kaladesh/PropellerPioneer.java new file mode 100644 index 00000000000..ad7d41fb3ab --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/PropellerPioneer.java @@ -0,0 +1,66 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.FabricateAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class PropellerPioneer extends CardImpl { + + public PropellerPioneer(UUID ownerId) { + super(ownerId, 24, "Propeller Pioneer", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{W}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Human"); + this.subtype.add("Artificer"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Fabricate 1 + this.addAbility(new FabricateAbility(1)); + } + + public PropellerPioneer(final PropellerPioneer card) { + super(card); + } + + @Override + public PropellerPioneer copy() { + return new PropellerPioneer(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java b/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java new file mode 100644 index 00000000000..b1e2cb84ca3 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java @@ -0,0 +1,122 @@ +/* + * 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.keyword; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * If you would draw a card, instead you may put exactly X cards from the top of your library into your graveyard. If + * you do, return this card from your graveyard to your hand. Otherwise, draw a card. + * + * @author North + */ +public class FabricateAbility extends EntersBattlefieldTriggeredAbility { + + public FabricateAbility(int value) { + super(new FabricateEffect(value), false, true); + } + + public FabricateAbility(final FabricateAbility ability) { + super(ability); + } + + @Override + public FabricateAbility copy() { + return new FabricateAbility(this); + } +} + +class FabricateEffect extends OneShotEffect { + + private final int value; + + FabricateEffect(int value) { + super(Outcome.Benefit); + this.value = value; + this.staticText = "Fabricate " + value + + " (When this creature enters the battlefield, put " + CardUtil.numberToText(value, "a") + " +1/+1 counter" + (value > 1 ? "s" : "") + + " on it or create " + CardUtil.numberToText(value, "a") + " 1/1 colorless Servo artifact creature token" + (value > 1 ? "s" : "") + ".)"; + } + + FabricateEffect(final FabricateEffect effect) { + super(effect); + this.value = effect.value; + } + + @Override + public FabricateEffect copy() { + return new FabricateEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (sourceObject != null && controller.chooseUse( + Outcome.BoostCreature, + "Fabricate " + value, + null, + "Put " + CardUtil.numberToText(value, "a") + " +1/+1 counter" + (value > 1 ? "s" : ""), + "Create " + CardUtil.numberToText(value, "a") + " 1/1 token" + (value > 1 ? "s" : ""), + source, + game)) { + ((Card) sourceObject).addCounters(CounterType.P1P1.createInstance(value), game); + } + else { + new ServoToken().putOntoBattlefield(value, game, source.getSourceId(), controller.getId()); + } + return true; + } + return false; + } +} + +class ServoToken extends Token { + + ServoToken() { + super("Servo", "1/1 colorless Servo artifact creature token"); + cardType.add(CardType.ARTIFACT); + cardType.add(CardType.CREATURE); + subtype.add("Servo"); + power = new MageInt(1); + toughness = new MageInt(1); + } +} diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 98fbf9c9791..6a173144c7c 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -20,6 +20,7 @@ Evoke|card, manaString| Exalted|new| Exploit|new| Extort|new| +Fabricate|number| Fear|instance| First strike|instance| Flanking|new| From 5c5d6365d853d337984ec7b743dd50dba11d8b04 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Tue, 6 Sep 2016 03:18:47 -0400 Subject: [PATCH 20/26] [KLD] Implemented Crew. Added 2 cards using it. --- .../mage/sets/kaladesh/BomatBazaarBarge.java | 67 +++++++++ .../src/mage/sets/kaladesh/SkySkiff.java | 65 +++++++++ .../continuous/AddCardTypeSourceEffect.java | 91 +++++++++++++ .../mage/abilities/keyword/CrewAbility.java | 127 ++++++++++++++++++ .../abilities/keyword/FabricateAbility.java | 5 +- Utils/keywords.txt | 1 + 6 files changed, 352 insertions(+), 4 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/BomatBazaarBarge.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/SkySkiff.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java create mode 100644 Mage/src/main/java/mage/abilities/keyword/CrewAbility.java diff --git a/Mage.Sets/src/mage/sets/kaladesh/BomatBazaarBarge.java b/Mage.Sets/src/mage/sets/kaladesh/BomatBazaarBarge.java new file mode 100644 index 00000000000..00c661d6842 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/BomatBazaarBarge.java @@ -0,0 +1,67 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.CrewAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class BomatBazaarBarge extends CardImpl { + + public BomatBazaarBarge(UUID ownerId) { + super(ownerId, 198, "Bomat Bazaar Barge", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vehicle"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // When Bomat Bazaar Barge enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); + + // Crew 3 + this.addAbility(new CrewAbility(3)); + } + + public BomatBazaarBarge(final BomatBazaarBarge card) { + super(card); + } + + @Override + public BomatBazaarBarge copy() { + return new BomatBazaarBarge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/SkySkiff.java b/Mage.Sets/src/mage/sets/kaladesh/SkySkiff.java new file mode 100644 index 00000000000..991162669e2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/SkySkiff.java @@ -0,0 +1,65 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class SkySkiff extends CardImpl { + + public SkySkiff(UUID ownerId) { + super(ownerId, 233, "Sky Skiff", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Vehicle"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Crew 1 + this.addAbility(new CrewAbility(1)); + } + + public SkySkiff(final SkySkiff card) { + super(card); + } + + @Override + public SkySkiff copy() { + return new SkySkiff(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.java new file mode 100644 index 00000000000..fa695f368f2 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardTypeSourceEffect.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.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.CardType; +import mage.constants.DependencyType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author emerald000 + */ +public class AddCardTypeSourceEffect extends ContinuousEffectImpl { + + private final CardType addedCardType; + + public AddCardTypeSourceEffect(CardType addedCardType, Duration duration) { + super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + this.addedCardType = addedCardType; + if (addedCardType.equals(CardType.ENCHANTMENT)) { + dependencyTypes.add(DependencyType.EnchantmentAddingRemoving); + } + } + + public AddCardTypeSourceEffect(final AddCardTypeSourceEffect effect) { + super(effect); + this.addedCardType = effect.addedCardType; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if (!permanent.getCardType().contains(addedCardType)) { + permanent.getCardType().add(addedCardType); + } + return true; + } + else if (this.getDuration().equals(Duration.Custom)) { + this.discard(); + } + return false; + } + + @Override + public AddCardTypeSourceEffect copy() { + return new AddCardTypeSourceEffect(this); + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + StringBuilder sb = new StringBuilder(); + sb.append("{this} becomes ").append(addedCardType.toString()).append(" in addition to its other types until end of turn"); + return sb.toString(); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java new file mode 100644 index 00000000000..65215877da9 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -0,0 +1,127 @@ +/* + * 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.keyword; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * @author emerald000 + */ +public class CrewAbility extends SimpleActivatedAbility { + + private final int value; + + public CrewAbility(int value) { + super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(CardType.ARTIFACT, Duration.EndOfTurn), new CrewCost(value)); + this.addEffect(new AddCardTypeSourceEffect(CardType.CREATURE, Duration.EndOfTurn)); + this.value = value; + } + + public CrewAbility(final CrewAbility ability) { + super(ability); + this.value = ability.value; + } + + @Override + public CrewAbility copy() { + return new CrewAbility(this); + } + + @Override + public String getRule() { + return "Crew " + value + " (Tap any number of creatures you control with total power " + value + " or more: This Vehicle becomes an artifact creature until end of turn.)"; + } +} + +class CrewCost extends CostImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + private final int value; + + CrewCost(int value) { + this.value = value; + } + + CrewCost(final CrewCost cost) { + super(cost); + this.value = cost.value; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { + int sumPower = 0; + for (UUID targetId : target.getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.tap(game)) { + sumPower += permanent.getPower().getValue(); + } + } + paid = sumPower >= value; + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + int sumPower = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) { + sumPower += permanent.getPower().getValue(); + if (sumPower >= value) { + return true; + } + } + return false; + } + + @Override + public CrewCost copy() { + return new CrewCost(this); + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java b/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java index b1e2cb84ca3..d60250a2ffe 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FabricateAbility.java @@ -42,10 +42,7 @@ import mage.players.Player; import mage.util.CardUtil; /** - * If you would draw a card, instead you may put exactly X cards from the top of your library into your graveyard. If - * you do, return this card from your graveyard to your hand. Otherwise, draw a card. - * - * @author North + * @author emerald000 */ public class FabricateAbility extends EntersBattlefieldTriggeredAbility { diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 6a173144c7c..c931be48ba2 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -5,6 +5,7 @@ Bloodthirst|number| Bushido|number| Convoke|new| Cascade|new| +Crew|number| Cumulative upkeep|cost| Cycling|cost| Dash|card, manaString| From 32fd2536247a936df491cc6558d4ad98c180e068 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Tue, 6 Sep 2016 11:06:02 -0500 Subject: [PATCH 21/26] [KLD] Added 9/6 spoilers to mtg-cards-data.txt. --- Utils/mtg-cards-data.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index fd8abfa68be..3a7d9e12a4e 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -29668,7 +29668,8 @@ Ceremonious Rejection|Kaladesh|40|U|{U}|Instant|||Counter target colorless spell Curio Vendor|Kaladesh|42|C|{1}{U}|Creature - Vedalken|2|1|| Metallurgic Summonings|Kaladesh|56|M|{3}{U}{U}|Enchantment|||Whenever you cast an instant or sorcery spell, create an X/X colorless Construct artifact creature token, where X is that spell's converted mana cost.${3}{U}{U}, Exile Metallurgic Summons: Return all instant and sorcery cards from your graveyard to your hand. Activate this ability only if you control six or more artifacts.| Saheeli's Artistry|Kaladesh|62|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except that it's an artifact in addition to its other types.| -Demon of Shadowy Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Shadowy Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (one energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control. | +Torrential Gearhulk|Kaladesh|67|M|{4}{U}{U}|Artifact Creature - Construct|5|6|Flash$When Torrential Gearhulk enters the battlefield, you may cast target instant card from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead.| +Demon of Dark Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Dark Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (an energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control.| Die Young|Kaladesh|76|C|{1}{B}|Sorcery|||Choose target creature. You get {E}{E} (two energy counters), then you may pay any amount of {E}. The creature gets -1/-1 until end of turn for each {E} paid this way.| Essence Extraction|Kaladesh|80|U|{1}{B}{B}|Instant|||Essence Extraction deals 3 damage to target creature and you gain 3 life.| Fortuitous Find|Kaladesh|81|C|{2}{B}|Sorcery|||Choose one or both — Return target artifact card from your graveyard to your hand.; or Return target creature card from your graveyard to your hand.| @@ -29679,6 +29680,8 @@ Ovalchase Daredevil|Kaladesh|97|U|{3}{B}|Creature - Human Pilot|4|2|Whenever an Chandra, Torch of Defiance|Kaladesh|110|M|{2}{R}{R}|Planeswalker - Chandra|||+1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent.$+1: Add {R}{R} to your mana pool.$-3: Chandra, Torch of Defiance deals 4 damage to target creature.$-7: You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player."| Furious Reprisal|Kaladesh|115|U|{3}{R}|Sorcery|||Furious Reprisal deals 2 damage to each of two target creatures and/or players.| Harnessed Lightning|Kaladesh|117|U|{1}{R}|Instant|||Choose target creature. You get {E}{E}{E} (three energy counters), then you may pay any amount of {E}. Harnessed Lightning deals that much damage to that creature.| +Lathnu Hellion|Kaladesh|121|R|{2}{R}|Creature - Hellion|4|4|Haste$When Lathnu Hellion enters the battlefield, you get {E}{E} (two energy counters).$At the beginning of your end step, sacrifice Lathnu Hellion unless you pay {E}{E}.| +Madcap Experiment|Kaladesh|122|R|{3}{R}|Sorcery|||Reveal cards from the top of your library until you reveal an artifact card. Put that card onto the battlefield and the rest on the bottom of your library in a random order. Madcap Experiment deals damage to you equal to the number of cards revealed this way.| Pia Nalaar|Kaladesh|124|R|{2}{R}|Legendary Creature - Human Artificer|2|2|When Pia Nalaar enters the battlefield, create a 1/1 colorless Thopter artifact creature token with flying.${1}{R}: Target artifact creature gets +1/+0 until end of turn.${1}, Sacrifice an artifact: Target creature can't block this turn.| Skyship Stalker|Kaladesh|130|R|{2}{R}{R}|Creature - Dragon|3|3|Flying${R}: Skyship Stalker gains +1/+0 until end of turn.${R}: Skyship Stalker gains first strike until end of turn.${R}: Skyship Stalker gains haste until end of turn.| Speedway Fanatic|Kaladesh|132|U|{1}{R}|Creature - Human Pilot|2|1|Haste$Whenever Speedway Fanatic crews a Vehicle, that Vehicle gains haste until end of turn.| @@ -29692,14 +29695,18 @@ Cultivator of Blades|Kaladesh|151|R|{3}{G}{G}|Creature - Elf Artificer|1|1|Fabri Ghirapur Guide|Kaladesh|156|U|{2}{G}|Creature - Elf Scout|3|2|{2}{G}: Target creature you control can't be blocked by creatures with power 2 or less this turn.| Larger Than Life|Kaladesh|160|C|{1}{G}|Sorcery|||Target creature gets +4/+4 and gains trample until end of turn.| Longtusk Cub|Kaladesh|161|U|{1}{G}|Creature - Cat|2|2|Whenever Longtusk Cub deals combat damage to a player, you get {E}{E} (two energy counters).$Pay {E}{E}: Put a +1/+1 counter on Longtusk Cub.| +Nissa, Vital Force|Kaladesh|163|M|{3}{G}{G}|Planeswalker - Nissa|||+1: Untap target land you control. Until your next turn, it becomes a 5/5 Elemental creature with haste. It's still a land.$-3: Return target permanent card from your graveyard to your hand.$-6: You get an emblem with "Whenever a land enters the battlefield under your control, you may draw a card."| Verdurous Gearhulk|Kaladesh|172|M|{3}{G}{G}|Artifact Creature - Construct|4|4|Trample$When Verdurous Gearhulk enters the battlefield, distribute four +1/+1 counters among any number of target creatures you control.| Depala, Pilot Exemplar|Kaladesh|178|R|{1}{R}{W}|Legendary Creature - Dwarf Pilot|3|3|Other Dwarves you control get +1/+1.$Each Vehicle you control gets +1/+1 as long as it's a creature.$Whenever Depala, Pilot Exemplar becomes tapped, you may pay {X}. If you do, reveal the top X cards of your library, put all Dwarf and Vehicle cards from among them into your hand, then put the rest on the bottom of your library in a random order.| Rashmi, Eternities Crafter|Kaladesh|184|M|{2}{G}{U}|Legendary Creature - Elf Druid|2|3|Whenever you cast your first spell each turn, reveal the top card of your library. If it's a nonland card with converted mana cost less than that spell's, you may cast it without paying its mana cost. If you don't cast the revealed card, put it into your hand. | Saheeli Rai|Kaladesh|186|M|{1}{U}{R}|Planeswalker - Saheeli|3|+1: Scry 1. Saheeli Rai deals 1 damage to each opponent.$-2: Create a token that's a copy of target artifact or creature you control, except it's an artifact in addition to its other types. That token gains haste. Exile it at the beginning of the next end step.$-7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.| Voltaic Brawler|Kaladesh|189|U|{R}{G}|Creature - Human Warrior|3|2|When Voltaic Brawler enters the battlefield, you get {E}{E} (two energy counters).$Whenever Voltaic Brawler attacks, you may pay {E}. If you do, it gets +1/+1 and gains trample until end of turn.| Aetherworks Marvel|Kaladesh|193|M|{4}|Legendary Artifact|||Whenever a permanent you control is put into a graveyard, you get {E} (an energy counter).${T}, Pay {E}{E}{E}{E}{E}{E}: Look at the top six cards of your library. You may cast a card from among them without paying its mana cost. Put the rest on the bottom of your library in a random order.| +Animation Module|Kaladesh|194|R|{1}|Artifact|||Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token.${3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind.| Bomat Bazaar Barge|Kaladesh|198|U|{4}|Artifact - Vehicle|5|5|When Bomat Bazaar Barge enters the battlefield, draw a card.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| +Decoction Module|Kaladesh|205|U|{2}|Artifact|||Whenever a creature enters the battlefield under your control, you get {E} (an energy counter).${4}, {T}: Return target creature you control to its owner's hand.| Demolition Stomper|Kaladesh|206|U|{6}|Artifact - Vehicle|10|7|Demolition Stomper can't be blocked by creature with power 2 or less.$Crew 5 (Tap any number of creatures you control with total power 5 or more: This Vehicle becomes an artifact creature until end of turn.)| +Fabrication Module|Kaladesh|211|U|{3}|Artifact|||Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.${4}, {T}: You get {E}.| Filigree Familiar|Kaladesh|212|U|{3}|Artifact Creature - Fox|2|2|When Filigree Familiar enters the battlefield, you gain 2 life.$When Filigree Familiar dies, draw a card.| Fleetwheel Cruiser|Kaladesh|214|R|{4}|Artifact - Vehicle|5|3|Trample, Haste $When Fleetwheel Cruiser enters the battlefield, it becomes an artifact creature until the end of turn.$Crew 2 (Tap any number of creatures you control with total power 2 or more: This Vehicle becomes an artifact creature until end of turn.)| Ghirapur Orrery|Kaladesh|216|R|{4}|Artifact|||Each player may play an additional land on each of his or her turns.$At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.| @@ -29715,4 +29722,6 @@ Botanical Sanctum|Kaladesh|244|R||Land|||Botanical Sanctum enters the battlefiel Concealed Courtyard|Kaladesh|245|R||Land|||Concealed Courtyard enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {W} or {B} to your mana pool.| Inspiring Vantage|Kaladesh|246|R||Land|||Inspiring Vantage enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {R} or {W} to your mana pool.| Inventors' Fair|Kaladesh|247|R||Legendary Land|||At the beginning of your upkeep, if you control three or more artifacts, you gain 1 life.${t}: Add {C} to your mana pool.${4}, {T}, Sacrifice Inventors' Fair: Search your library for an artifact card, reveal it, put it into your hand, then shuffle your library. Activate this ability only if you control threeor more artifacts.| -Spirebluff Canal|Kaladesh|249|R||Land|||Spirebluff Canal enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {U} or {R} to your mana pool.| \ No newline at end of file +Spirebluff Canal|Kaladesh|249|R||Land|||Spirebluff Canal enters the battlefield tapped unless you control two or fewer other lands.${T}: Add {U} or {R} to your mana pool.| +Chandra, Pyrogenius|Kaladesh|265|M|{4}{R}{R}|Planeswalker - Chandra|||+2: Chandra, Pyrogenius deals 2 damage to each opponent.$-3: Chandra, Pyrogenius deals 4 damage to target creature.$-10: Chandra, Pyrogenius deals 6 damage to target player and each creature he or she controls.| +Nissa, Nature's Artisan|Kaladesh|270|M|{4}{G}{G}|Planeswalker - Nissa|||+3: You gain 3 life.$-4: Reveal the top two cards of your library. Put all land cards from among them onto the battlefield and the rest into your hand.$-12: Creatures you control get +5/+5 and gain trample until end of turn.| \ No newline at end of file From f67cb21f2a1e6b2d6b8cbcdc5aed98e7312e2540 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Tue, 6 Sep 2016 22:15:33 -0500 Subject: [PATCH 22/26] [KLD] Implemented Chandra, Torch of Defiance; Chandra, Pyrogenius; Nissa, Nature's Artisan; and Nissa, Vital Force. --- Mage.Sets/src/mage/sets/Kaladesh.java | 6 + .../mage/sets/kaladesh/ChandraPyrogenius.java | 85 ++++++++++ .../sets/kaladesh/ChandraTorchOfDefiance.java | 146 ++++++++++++++++++ .../sets/kaladesh/NissaNaturesArtisan.java | 131 ++++++++++++++++ .../mage/sets/kaladesh/NissaVitalForce.java | 123 +++++++++++++++ 5 files changed, 491 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/ChandraPyrogenius.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/NissaNaturesArtisan.java create mode 100644 Mage.Sets/src/mage/sets/kaladesh/NissaVitalForce.java diff --git a/Mage.Sets/src/mage/sets/Kaladesh.java b/Mage.Sets/src/mage/sets/Kaladesh.java index 4a398155c5d..c2240aecd93 100644 --- a/Mage.Sets/src/mage/sets/Kaladesh.java +++ b/Mage.Sets/src/mage/sets/Kaladesh.java @@ -58,5 +58,11 @@ public class Kaladesh extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; + /* There are additional cards, numbered 265–270, that don't appear in Kaladesh + booster packs. These are new cards that are exclusive in the Planeswalker + Decks supplemental product, which are replacing Intro Packs. + These additional cards have a Kaladesh expansion symbol and are legal in all + formats in which Kaladesh is legal. */ + this.maxCardNumberInBooster = 264; } } diff --git a/Mage.Sets/src/mage/sets/kaladesh/ChandraPyrogenius.java b/Mage.Sets/src/mage/sets/kaladesh/ChandraPyrogenius.java new file mode 100644 index 00000000000..3348d3a9e29 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ChandraPyrogenius.java @@ -0,0 +1,85 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effects; +import mage.abilities.effects.common.DamageAllControlledTargetEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class ChandraPyrogenius extends CardImpl { + + public ChandraPyrogenius(UUID ownerId) { + super(ownerId, 265, "Chandra, Pyrogenius", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{R}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Chandra"); + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +2: Chandra, Pyrogenius deals 2 damage to each opponent. + this.addAbility(new LoyaltyAbility(new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT), 2)); + + // -3: Chandra, Pyrogenius deals 4 damage to target creature. + LoyaltyAbility ability = new LoyaltyAbility(new DamageTargetEffect(4), -3); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // -10: Chandra, Pyrogenius deals 6 damage to target player and each creature he or she controls. + Effects effects = new Effects(); + effects.add(new DamageTargetEffect(6)); + effects.add(new DamageAllControlledTargetEffect(6, new FilterCreaturePermanent())); + ability = new LoyaltyAbility(effects, -10); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public ChandraPyrogenius(final ChandraPyrogenius card) { + super(card); + } + + @Override + public ChandraPyrogenius copy() { + return new ChandraPyrogenius(this); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java b/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java new file mode 100644 index 00000000000..de7e35c3a1f --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java @@ -0,0 +1,146 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.players.Library; +import mage.players.Player; +import mage.target.common.TargetCreatureOrPlayer; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class ChandraTorchOfDefiance extends CardImpl { + + public ChandraTorchOfDefiance(UUID ownerId) { + super(ownerId, 110, "Chandra, Torch of Defiance", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{R}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Chandra"); + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent. + LoyaltyAbility ability = new LoyaltyAbility(new ChandraTorchOfDefianceEffect(), 1); + this.addAbility(ability); + + // +1: Add {R}{R} to your mana pool. + this.addAbility(new LoyaltyAbility(new BasicManaEffect(Mana.RedMana(2)), +1)); + + // -3: Chandra, Torch of Defiance deals 4 damage to target creature. + ability = new LoyaltyAbility(new DamageTargetEffect(4), -3); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // -7: You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new ChandraTorchOfDefianceEmblem()), -6)); + } + + public ChandraTorchOfDefiance(final ChandraTorchOfDefiance card) { + super(card); + } + + @Override + public ChandraTorchOfDefiance copy() { + return new ChandraTorchOfDefiance(this); + } +} + +class ChandraTorchOfDefianceEffect extends OneShotEffect { + + public ChandraTorchOfDefianceEffect() { + super(Outcome.Detriment); + this.staticText = "Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent"; + } + + public ChandraTorchOfDefianceEffect(final ChandraTorchOfDefianceEffect effect) { + super(effect); + } + + @Override + public ChandraTorchOfDefianceEffect copy() { + return new ChandraTorchOfDefianceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null && controller.getLibrary().size() > 0) { + Library library = controller.getLibrary(); + Card card = library.removeFromTop(game); + if (card != null) { + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + if (controller.chooseUse(Outcome.Benefit, "Cast the card?", source, game)) { + controller.cast(card.getSpellAbility(), game, false); + } else { + new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT).apply(game, source); + } + } + return true; + } + return false; + } +} + +class ChandraTorchOfDefianceEmblem extends Emblem { + + // You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player." + public ChandraTorchOfDefianceEmblem() { + this.setName("Emblem - Chandra, Torch of Defiance"); + Effect effect = new DamageTargetEffect(5); + effect.setText("this emblem deals 5 damage to target creature or player"); + Ability ability = new SpellCastControllerTriggeredAbility(Zone.COMMAND, effect, new FilterSpell("a spell"), false, false); + ability.addTarget(new TargetCreatureOrPlayer()); + getAbilities().add(ability); + } +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/NissaNaturesArtisan.java b/Mage.Sets/src/mage/sets/kaladesh/NissaNaturesArtisan.java new file mode 100644 index 00000000000..aff47101d86 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/NissaNaturesArtisan.java @@ -0,0 +1,131 @@ +/* + * 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.kaladesh; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterLandCard; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class NissaNaturesArtisan extends CardImpl { + + public NissaNaturesArtisan(UUID ownerId) { + super(ownerId, 270, "Nissa, Nature's Artisan", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{4}{G}{G}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Nissa"); + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +3: You gain 3 life. + this.addAbility(new LoyaltyAbility(new GainLifeEffect(3), 3)); + + // -4: Reveal the top two cards of your library. Put all land cards from among them onto the battlefield and the rest into your hand. + this.addAbility(new LoyaltyAbility(new NissaNaturesArtisanEffect(), -4)); + + // -12: Creatures you control get +5/+5 and gain trample until end of turn. + Effect effect = new BoostControlledEffect(5, 5, Duration.EndOfTurn); + effect.setText("Creature you control get +5/+5"); + LoyaltyAbility ability = new LoyaltyAbility(effect, -12); + ability.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn)); + this.addAbility(ability); + } + + public NissaNaturesArtisan(final NissaNaturesArtisan card) { + super(card); + } + + @Override + public NissaNaturesArtisan copy() { + return new NissaNaturesArtisan(this); + } +} + +class NissaNaturesArtisanEffect extends OneShotEffect { + + public NissaNaturesArtisanEffect() { + super(Outcome.PutCardInPlay); + staticText = "Reveal the top two cards of your library. Put all land cards from among them onto the battlefield and the rest into your hand"; + } + + public NissaNaturesArtisanEffect(final NissaNaturesArtisanEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || sourceObject == null) { + return false; + } + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, 2)); + if (cards.size() > 0) { + controller.revealCards(sourceObject.getIdName(), cards, game); + Set toBattlefield = new LinkedHashSet<>(); + for (Card card : cards.getCards(new FilterLandCard(), source.getSourceId(), source.getControllerId(), game)) { + cards.remove(card); + toBattlefield.add(card); + } + controller.moveCards(toBattlefield, Zone.BATTLEFIELD, source, game, false, false, true, null); + controller.moveCards(cards, Zone.HAND, source, game); + } + return true; + } + + @Override + public NissaNaturesArtisanEffect copy() { + return new NissaNaturesArtisanEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/kaladesh/NissaVitalForce.java b/Mage.Sets/src/mage/sets/kaladesh/NissaVitalForce.java new file mode 100644 index 00000000000..79311297da3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/NissaVitalForce.java @@ -0,0 +1,123 @@ +/* + * 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.kaladesh; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.common.FilterPermanentCard; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.command.Emblem; +import mage.game.permanent.token.Token; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author fireshoes + */ +public class NissaVitalForce extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent("land you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public NissaVitalForce(UUID ownerId) { + super(ownerId, 163, "Nissa, Vital Force", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{3}{G}{G}"); + this.expansionSetCode = "KLD"; + this.subtype.add("Nissa"); + + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(5)); + + // +1: Untap target land you control. Until your next turn, it becomes a 5/5 Elemental creature with haste. It's still a land. + LoyaltyAbility ability = new LoyaltyAbility(new UntapTargetEffect(), 1); + ability.addEffect(new BecomesCreatureTargetEffect(new NissaVitalForceToken(), false, true, Duration.UntilYourNextTurn)); + ability.addTarget(new TargetLandPermanent(filter)); + this.addAbility(ability); + + // -3: Return target permanent card from your graveyard to your hand. + ability = new LoyaltyAbility(new ReturnToHandTargetEffect(), -3); + ability.addTarget(new TargetCardInYourGraveyard(new FilterPermanentCard("permanent card from your graveyard"))); + this.addAbility(ability); + + // -6: You get an emblem with "Whenever a land enters the battlefield under your control, you may draw a card." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new NissaVitalForceEmblem()), -6)); + } + + public NissaVitalForce(final NissaVitalForce card) { + super(card); + } + + @Override + public NissaVitalForce copy() { + return new NissaVitalForce(this); + } +} + +class NissaVitalForceToken extends Token { + + public NissaVitalForceToken() { + super("", "5/5 Elemental creature with haste"); + this.cardType.add(CardType.CREATURE); + + this.subtype.add("Elemental"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + this.addAbility(HasteAbility.getInstance()); + } +} + +class NissaVitalForceEmblem extends Emblem { + + // You get an emblem with "Whenever a land enters the battlefield under your control, you may draw a card." + public NissaVitalForceEmblem() { + this.setName("Emblem - Nissa, Vital Force"); + Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.COMMAND, new DrawCardSourceControllerEffect(1), new FilterControlledLandPermanent("a land"), + true, null, true); + getAbilities().add(ability); + } +} From df2782fdb687164910013ce3229e3cff67a3f1f7 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Wed, 7 Sep 2016 01:07:21 -0400 Subject: [PATCH 23/26] [KLD] Basic implementation of energy counters. Added Woodweaver's Puzzleknot. Better display of energy counters would be preferred. --- .../java/mage/client/game/PlayerPanelExt.java | 12 +-- Mage.Common/src/mage/view/PlayerView.java | 16 ++-- .../sets/kaladesh/WoodweaversPuzzleknot.java | 76 ++++++++++++++++++ .../GetEnergyCountersControllerEffect.java | 77 +++++++++++++++++++ .../main/java/mage/counters/CounterType.java | 1 + 5 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index 1eced8ee837..7f454e5269c 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -77,13 +77,14 @@ import static mage.constants.Constants.DEFAULT_AVATAR_ID; import static mage.constants.Constants.MAX_AVATAR_ID; import static mage.constants.Constants.MIN_AVATAR_ID; import mage.constants.ManaType; +import mage.counters.Counter; +import mage.counters.CounterType; import mage.remote.Session; import mage.utils.timer.PriorityTimer; +import mage.view.CardView; import mage.view.ManaPoolView; import mage.view.PlayerView; import org.mage.card.arcane.ManaSymbols; -import mage.players.Player; -import mage.view.CardView; /** * Enhanced player pane. @@ -191,7 +192,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { changedFontLife = false; } lifeLabel.setText(Integer.toString(playerLife)); - poisonLabel.setText(Integer.toString(player.getPoison())); + poisonLabel.setText(Integer.toString(player.getCounters().getCount(CounterType.POISON))); handLabel.setText(Integer.toString(player.getHandCount())); int libraryCards = player.getLibraryCount(); if (libraryCards > 99) { @@ -330,9 +331,10 @@ public class PlayerPanelExt extends javax.swing.JPanel { } // Extend tooltip StringBuilder tooltipText = new StringBuilder(basicTooltipText); - if (player.getExperience() > 0) { - tooltipText.append("
Experience counters: ").append(player.getExperience()); + for (Counter counter : player.getCounters().values()) { + tooltipText.append("
").append(counter.getName()).append(" counters: ").append(counter.getCount()); } + avatar.setToolTipText(tooltipText.toString()); avatar.repaint(); diff --git a/Mage.Common/src/mage/view/PlayerView.java b/Mage.Common/src/mage/view/PlayerView.java index 76b72d8fc18..d64d2cb41e5 100644 --- a/Mage.Common/src/mage/view/PlayerView.java +++ b/Mage.Common/src/mage/view/PlayerView.java @@ -36,7 +36,7 @@ import java.util.Map; import java.util.UUID; import mage.cards.Card; import mage.constants.CardType; -import mage.counters.CounterType; +import mage.counters.Counters; import mage.game.ExileZone; import mage.game.Game; import mage.game.GameState; @@ -58,8 +58,7 @@ public class PlayerView implements Serializable { private final UUID playerId; private final String name; private final int life; - private final int poison; - private final int experience; + private final Counters counters; private final int wins; private final int winsNeeded; private final long deckHashCode; @@ -90,8 +89,7 @@ public class PlayerView implements Serializable { this.playerId = player.getId(); this.name = player.getName(); this.life = player.getLife(); - this.poison = player.getCounters().getCount(CounterType.POISON); - this.experience = player.getCounters().getCount(CounterType.EXPERIENCE); + this.counters = player.getCounters(); this.wins = player.getMatchPlayer().getWins(); this.winsNeeded = player.getMatchPlayer().getWinsNeeded(); // If match ended immediately before, deck can be set to null so check is necessarry here @@ -195,12 +193,8 @@ public class PlayerView implements Serializable { return this.life; } - public int getPoison() { - return this.poison; - } - - public int getExperience() { - return this.experience; + public Counters getCounters() { + return this.counters; } public int getLibraryCount() { diff --git a/Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java b/Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java new file mode 100644 index 00000000000..5428d34b7b3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java @@ -0,0 +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.kaladesh; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author emerald000 + */ +public class WoodweaversPuzzleknot extends CardImpl { + + public WoodweaversPuzzleknot(UUID ownerId) { + super(ownerId, 240, "Woodweaver's Puzzleknot", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "KLD"; + + // When Woodweaver's Puzzleknot enters the battlefield, you gain 3 life and get {E}{E}{E}. + Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)); + Effect effect = new GetEnergyCountersControllerEffect(3); + effect.setText("and get {E}{E}{E}"); + ability.addEffect(effect); + this.addAbility(ability); + + // {2}{G}, Sacrifice Woodweaver's Puzzleknot: You gain 3 life and get {E}{E}{E}. + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(3), new ManaCostsImpl<>("{2}{G}")); + ability.addCost(new SacrificeSourceCost()); + ability.addEffect(effect); + this.addAbility(ability); + } + + public WoodweaversPuzzleknot(final WoodweaversPuzzleknot card) { + super(card); + } + + @Override + public WoodweaversPuzzleknot copy() { + return new WoodweaversPuzzleknot(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java new file mode 100644 index 00000000000..faa2598939b --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common.counter; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * @author emerald000 + */ +public class GetEnergyCountersControllerEffect extends OneShotEffect { + + private final int value; + + public GetEnergyCountersControllerEffect(int value) { + super(Outcome.Benefit); + this.value = value; + setText(); + } + + public GetEnergyCountersControllerEffect(final GetEnergyCountersControllerEffect effect) { + super(effect); + this.value = effect.value; + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + return player.addCounters(CounterType.ENERGY.createInstance(value), game); + } + return false; + } + + private void setText() { + this.staticText = "you get "; + for (int i = 0; i < value; i++) { + this.staticText += "{E}"; + } + this.staticText += " (" + CardUtil.numberToText(value, "an") + " energy counter" + (value > 1 ? "s" : "") + ")"; + } + + @Override + public GetEnergyCountersControllerEffect copy() { + return new GetEnergyCountersControllerEffect(this); + } +} diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 4d41db4ee0c..6e1817559e4 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -54,6 +54,7 @@ public enum CounterType { DIVINITY("divinity"), DOOM("doom"), ELIXIR("elixir"), + ENERGY("energy"), EON("eon"), EXPERIENCE("experience"), EYEBALL("eyeball"), From 8342d03ac9abfecc7b5573e82447e653acdf959b Mon Sep 17 00:00:00 2001 From: spjspj Date: Wed, 7 Sep 2016 21:52:52 +1000 Subject: [PATCH 24/26] spjspj - Set Token Descriptor --- Mage.Common/src/mage/view/CardView.java | 3 ++- Mage/src/main/java/mage/cards/CardImpl.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 18ef48839e9..8451015e895 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -475,7 +475,8 @@ public class CardView extends SimpleCardView { this.manaCost = token.getManaCost().getSymbols(); this.rarity = Rarity.NA; this.type = token.getTokenType(); - this.tokenSetCode = token.getOriginalExpansionSetCode(); + this.tokenDescriptor = token.getTokenDescriptor(); + this.tokenSetCode = token.getOriginalExpansionSetCode(); } protected final void setTargets(Targets targets) { diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index ebe0e0aa52c..556b51a827a 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -142,6 +142,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { ownerId = card.ownerId; cardNumber = card.cardNumber; expansionSetCode = card.expansionSetCode; + tokenDescriptor = card.tokenDescriptor; rarity = card.rarity; canTransform = card.canTransform; From 72b13214e61646069e150339f79ced8191c38998 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Wed, 7 Sep 2016 10:59:51 -0500 Subject: [PATCH 25/26] [KLD] Updated mtg-cards-data.txt with 9/7 spoilers. --- .../src/mage/sets/kaladesh/ChandraTorchOfDefiance.java | 2 +- Utils/mtg-cards-data.txt | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java b/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java index de7e35c3a1f..08da58f4ba6 100644 --- a/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java +++ b/Mage.Sets/src/mage/sets/kaladesh/ChandraTorchOfDefiance.java @@ -120,7 +120,7 @@ class ChandraTorchOfDefianceEffect extends OneShotEffect { Card card = library.removeFromTop(game); if (card != null) { controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); - if (controller.chooseUse(Outcome.Benefit, "Cast the card?", source, game)) { + if (controller.chooseUse(Outcome.Benefit, "Cast the card? (You still pay the costs)", source, game) && !card.getCardType().contains(CardType.LAND)) { controller.cast(card.getSpellAbility(), game, false); } else { new DamagePlayersEffect(Outcome.Damage, new StaticValue(2), TargetController.OPPONENT).apply(game, source); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 3a7d9e12a4e..d770dbac957 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -29667,6 +29667,7 @@ Aether Tradewinds|Kaladesh|38|C|{2}{U}|Instant|||Return target permanent you con Ceremonious Rejection|Kaladesh|40|U|{U}|Instant|||Counter target colorless spell.| Curio Vendor|Kaladesh|42|C|{1}{U}|Creature - Vedalken|2|1|| Metallurgic Summonings|Kaladesh|56|M|{3}{U}{U}|Enchantment|||Whenever you cast an instant or sorcery spell, create an X/X colorless Construct artifact creature token, where X is that spell's converted mana cost.${3}{U}{U}, Exile Metallurgic Summons: Return all instant and sorcery cards from your graveyard to your hand. Activate this ability only if you control six or more artifacts.| +Paradoxical Outcome|Kaladesh|60|R|{3}{U}|Instant|||Return any number of target nonland, nontoken permanents you control to their owners' hands. Draw a card for each card return to your hand this way.| Saheeli's Artistry|Kaladesh|62|R|{4}{U}{U}|Sorcery|||Choose one or both —$• Create a token that's a copy of target artifact.$• Create a token that's a copy of target creature, except that it's an artifact in addition to its other types.| Torrential Gearhulk|Kaladesh|67|M|{4}{U}{U}|Artifact Creature - Construct|5|6|Flash$When Torrential Gearhulk enters the battlefield, you may cast target instant card from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead.| Demon of Dark Schemes|Kaladesh|73|M|{3}{B}{B}{B}|Creature - Demon|5|5|Flying$When Demon of Dark Schemes enters the battlefield, all other creatures get -2/-2 until end of turn.$Whenever another creature dies, you get {E} (an energy counter).${2}{B}, Pay {E}{E}{E}{E}: Put target creature card from a graveyard onto the battlefiend tapped under your control.| @@ -29676,6 +29677,7 @@ Fortuitous Find|Kaladesh|81|C|{2}{B}|Sorcery|||Choose one or both — Return Gonti, Lord of Luxury|Kaladesh|84|R|{2}{B}{B}|Legendary Creature - Aetherborn Rogue|2|3|Deathtouch$When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.| Live Fast|Kaladesh|87|C|{2}{B}|Sorcery|||You draw two cards, lose 2 life, and gain {E}{E} (two energy counters).| Morbid Curiosity|Kaladesh|94|U|{1}{B}{B}|Sorcery|||As an additional cost to cast Morbid Curiosity, sacrifice an artifact or creature.$Draw cards equal to the converted mana cost of the sacrificed permanent.| +Noxious Gearhulk|Kaladesh|96|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When Noxious Gearhulk enters the battlefield, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.| Ovalchase Daredevil|Kaladesh|97|U|{3}{B}|Creature - Human Pilot|4|2|Whenever an artifact enters the battlefield under your control, you may return Ovalchase Daredevil from your graveyard to your hand.| Chandra, Torch of Defiance|Kaladesh|110|M|{2}{R}{R}|Planeswalker - Chandra|||+1: Exile the top card of your library. You may cast that card. If you don't, Chandra, Torch of Defiance deals 2 damage to each opponent.$+1: Add {R}{R} to your mana pool.$-3: Chandra, Torch of Defiance deals 4 damage to target creature.$-7: You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to target creature or player."| Furious Reprisal|Kaladesh|115|U|{3}{R}|Sorcery|||Furious Reprisal deals 2 damage to each of two target creatures and/or players.| @@ -29691,6 +29693,7 @@ Terror of the Fairgrounds|Kaladesh|137|C|{3}{R}|Creature - Gremlin|5|2|| Arborback Stomper|Kaladesh|142|U|{3}{G}{G}|Creature - Beast|5|4|Trample$When Arborback Stomper enters the battlefield, you gain 5 life.| Architect of the Untamed|Kaladesh|143|R|{2}{G}|Creature - Elf Artificer Druid|2|3|Whenever a land enters the battlefiend under your control, you get {E} (an energy counter).$Pay {E}{E}{E}{E}{E}{E}{E}{E}: Create a 6/6 colorless Beast artifact creature token.| Armorcraft Judge|Kaladesh|144|U|{3}{G}|Creature - Elf Artificer|3|3|When Armorcraft Judge enters the battlefield, draw a card for each creature you control with a +1/+1 counter on it.| +Bristling Hydra|Kaladesh|147|R|{2}{G}{G}|Creature - Hydra|4|3|When Bristling Hydra enters the battlefield, you get {E}{E}{E} (three energy counters).$Pay {E}{E}{E}: Put a +1/+1 count on Bristling Hydra. It gains hexproof until end of turn.| Cultivator of Blades|Kaladesh|151|R|{3}{G}{G}|Creature - Elf Artificer|1|1|Fabricate 2$Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power.| Ghirapur Guide|Kaladesh|156|U|{2}{G}|Creature - Elf Scout|3|2|{2}{G}: Target creature you control can't be blocked by creatures with power 2 or less this turn.| Larger Than Life|Kaladesh|160|C|{1}{G}|Sorcery|||Target creature gets +4/+4 and gains trample until end of turn.| @@ -29701,16 +29704,21 @@ Depala, Pilot Exemplar|Kaladesh|178|R|{1}{R}{W}|Legendary Creature - Dwarf Pilot Rashmi, Eternities Crafter|Kaladesh|184|M|{2}{G}{U}|Legendary Creature - Elf Druid|2|3|Whenever you cast your first spell each turn, reveal the top card of your library. If it's a nonland card with converted mana cost less than that spell's, you may cast it without paying its mana cost. If you don't cast the revealed card, put it into your hand. | Saheeli Rai|Kaladesh|186|M|{1}{U}{R}|Planeswalker - Saheeli|3|+1: Scry 1. Saheeli Rai deals 1 damage to each opponent.$-2: Create a token that's a copy of target artifact or creature you control, except it's an artifact in addition to its other types. That token gains haste. Exile it at the beginning of the next end step.$-7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.| Voltaic Brawler|Kaladesh|189|U|{R}{G}|Creature - Human Warrior|3|2|When Voltaic Brawler enters the battlefield, you get {E}{E} (two energy counters).$Whenever Voltaic Brawler attacks, you may pay {E}. If you do, it gets +1/+1 and gains trample until end of turn.| +Aetherflux Reservoir|Kaladesh|192|R|{4}|Artifact|||Whenever you cast a spell, you gain 1 life for each spell you've cast this turn.$Pay 50 life: Aetherflux Reservoir deals 50 damage to target creature or player.| Aetherworks Marvel|Kaladesh|193|M|{4}|Legendary Artifact|||Whenever a permanent you control is put into a graveyard, you get {E} (an energy counter).${T}, Pay {E}{E}{E}{E}{E}{E}: Look at the top six cards of your library. You may cast a card from among them without paying its mana cost. Put the rest on the bottom of your library in a random order.| Animation Module|Kaladesh|194|R|{1}|Artifact|||Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token.${3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind.| Bomat Bazaar Barge|Kaladesh|198|U|{4}|Artifact - Vehicle|5|5|When Bomat Bazaar Barge enters the battlefield, draw a card.$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)| +Cogworker's Puzzleknot|Kaladesh|201|C|{2}|Artifact|||When Cogworker's Puzzleknot enters the battlefield, create a 1/1 colorless Servo artifact creature token.${1}{W}, Sacrifice Cogworker's Puzzleknot: Create a 1/1 colorless Servo artifact creature token.| Decoction Module|Kaladesh|205|U|{2}|Artifact|||Whenever a creature enters the battlefield under your control, you get {E} (an energy counter).${4}, {T}: Return target creature you control to its owner's hand.| Demolition Stomper|Kaladesh|206|U|{6}|Artifact - Vehicle|10|7|Demolition Stomper can't be blocked by creature with power 2 or less.$Crew 5 (Tap any number of creatures you control with total power 5 or more: This Vehicle becomes an artifact creature until end of turn.)| Fabrication Module|Kaladesh|211|U|{3}|Artifact|||Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.${4}, {T}: You get {E}.| Filigree Familiar|Kaladesh|212|U|{3}|Artifact Creature - Fox|2|2|When Filigree Familiar enters the battlefield, you gain 2 life.$When Filigree Familiar dies, draw a card.| +Fireforger's Puzzleknot|Kaladesh|213|C|{2}|Artifact|||When Fireforger's Puzzleknot enters the battlefield, it deals 1 damage to target creature or player.${2}{R}, Sacrifice Fireforger's Puzzleknot: It deals 1 damage to target creature or player.| Fleetwheel Cruiser|Kaladesh|214|R|{4}|Artifact - Vehicle|5|3|Trample, Haste $When Fleetwheel Cruiser enters the battlefield, it becomes an artifact creature until the end of turn.$Crew 2 (Tap any number of creatures you control with total power 2 or more: This Vehicle becomes an artifact creature until end of turn.)| Ghirapur Orrery|Kaladesh|216|R|{4}|Artifact|||Each player may play an additional land on each of his or her turns.$At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.| +Glassblower's Puzzleknot|Kaladesh|217|C|{2}|Artifact|||When Glassblower's Puzzleknot enters the battlefield, scry 2, then you get {E}{E}. (You get two energy counters. To scry 2, look at the top two cards of you library, then put any number of them on the bottom of your library and the rest on top in any order.)${2}{U}, Sacrifice Glassblower's Puzzleknot: Scry 2, then you get {E}{E}.| Inventor's Goggles|Kaladesh|218|C|{1}|Artifact - Equipment|||Equipped creature gets +1/+2.$Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it.$Equip {2} ({2}: Attach to target creature you control. Equip only as a sorcery)| +Metalspinner's Puzzleknot|Kaladesh|221|C|{2}|Artifact|||When Metalspinner's Puzzleknot enters the battlefield, you draw a card and you lose 1 life.${2}{B}, Sacrifice Metalspinner's Puzzleknot: You draw a card and you lose 1 life.| Ovalchase Dragster|Kaladesh|225|U|{4}|Artifact - Vehicle|6|1|Trample, haste$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| Panharmonicon|Kaladesh|226|R|{4}|Artifact|||If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.| Sky Skiff|Kaladesh|233|C|{2}|Artifact - Vehicle|2|3|Flying$Crew 1 (Tap any number of creatures you control with total power 1 or more: This Vehicle becomes an artifact creature until end of turn.)| From 8375af12f2a1f737d8c79c21f8ff841cd8016862 Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 8 Sep 2016 12:38:19 +1000 Subject: [PATCH 26/26] spjspj - Implement Fountain Watch --- .../sets/mercadianmasques/FountainWatch.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/FountainWatch.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/FountainWatch.java b/Mage.Sets/src/mage/sets/mercadianmasques/FountainWatch.java new file mode 100644 index 00000000000..9ee1ecb1f21 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/FountainWatch.java @@ -0,0 +1,78 @@ +/* + * 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.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.ShroudAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; + +/** + * + * @author spjspj + */ +public class FountainWatch extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Artifacts and Enchantments"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.ENCHANTMENT))); + } + + public FountainWatch(UUID ownerId) { + super(ownerId, 19, "Fountain Watch", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Artifacts and enchantments you control have shroud. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(ShroudAbility.getInstance(), Duration.WhileOnBattlefield, filter, false))); + } + + public FountainWatch(final FountainWatch card) { + super(card); + } + + @Override + public FountainWatch copy() { + return new FountainWatch(this); + } +}