From dff87b11637a45ffc1fc4dd88dae5a96e054816e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 11:08:45 -0400 Subject: [PATCH 1/8] Implemented Emissary of Sunrise --- .../src/mage/cards/e/EmissaryOfSunrise.java | 69 +++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + 2 files changed, 70 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java diff --git a/Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java b/Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.java new file mode 100644 index 0000000000..0587f17b36 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmissaryOfSunrise.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.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.keyword.ExploreSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author TheElk801 + */ +public class EmissaryOfSunrise extends CardImpl { + + public EmissaryOfSunrise(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // When Emissary of Sunrise enters the battlefield, it explores. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ExploreSourceEffect())); + } + + public EmissaryOfSunrise(final EmissaryOfSunrise card) { + super(card); + } + + @Override + public EmissaryOfSunrise copy() { + return new EmissaryOfSunrise(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 4af16f8659..9db95b74e6 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -79,6 +79,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Duress", 105, Rarity.COMMON, mage.cards.d.Duress.class)); cards.add(new SetCardInfo("Dusk Legion Dreadnought", 236, Rarity.UNCOMMON, mage.cards.d.DuskLegionDreadnought.class)); cards.add(new SetCardInfo("Duskborne Skymarcher", 9, Rarity.UNCOMMON, mage.cards.d.DuskborneSkymarcher.class)); + cards.add(new SetCardInfo("Emissary of Sunrise", 10, Rarity.UNCOMMON, mage.cards.e.EmissaryOfSunrise.class)); cards.add(new SetCardInfo("Emperor's Vanguard", 189, Rarity.RARE, mage.cards.e.EmperorsVanguard.class)); cards.add(new SetCardInfo("Entrancing Melody", 55, Rarity.RARE, mage.cards.e.EntrancingMelody.class)); cards.add(new SetCardInfo("Fathom Fleet Captain", 106, Rarity.RARE, mage.cards.f.FathomFleetCaptain.class)); From 68a42726a88a0fa4cca1ffe42850632c72689202 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 11:19:29 -0400 Subject: [PATCH 2/8] Implemented Shadowed Caravel, generalized explore triggers --- .../src/mage/cards/l/LurkingChupacabra.java | 46 +----------- .../src/mage/cards/s/ShadowedCaravel.java | 74 +++++++++++++++++++ .../src/mage/cards/w/WildgrowthWalker.java | 45 +---------- Mage.Sets/src/mage/sets/Ixalan.java | 1 + .../CreatureExploresTriggeredAbility.java | 43 +++++++++++ 5 files changed, 124 insertions(+), 85 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/s/ShadowedCaravel.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java diff --git a/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java b/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java index 6c011ea8f0..7f607f32f9 100644 --- a/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java +++ b/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java @@ -30,8 +30,7 @@ package mage.cards.l; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreatureExploresTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -39,12 +38,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -53,7 +48,7 @@ import mage.target.common.TargetCreaturePermanent; */ public class LurkingChupacabra extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); static { filter.add(new ControllerPredicate(TargetController.OPPONENT)); @@ -68,7 +63,7 @@ public class LurkingChupacabra extends CardImpl { this.toughness = new MageInt(3); // Whenever a creature you control explores, target creature an opponent controls gets -2/-2 until end of turn - Ability ability = new LurkingChupacabraTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); + Ability ability = new CreatureExploresTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); ability.addTarget(new TargetCreaturePermanent(filter)); } @@ -81,38 +76,3 @@ public class LurkingChupacabra extends CardImpl { return new LurkingChupacabra(this); } } - -class LurkingChupacabraTriggeredAbility extends TriggeredAbilityImpl { - - LurkingChupacabraTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false); - } - - LurkingChupacabraTriggeredAbility(final LurkingChupacabraTriggeredAbility effect) { - super(effect); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.EXPLORED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); - if (creature != null) { - return creature.getControllerId().equals(controllerId); - } - return false; - } - - @Override - public LurkingChupacabraTriggeredAbility copy() { - return new LurkingChupacabraTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever a creature you control explores, target creature an opponent controls gets -2/-2 until end of turn"; - } -} diff --git a/Mage.Sets/src/mage/cards/s/ShadowedCaravel.java b/Mage.Sets/src/mage/cards/s/ShadowedCaravel.java new file mode 100644 index 0000000000..ab340946d0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShadowedCaravel.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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreatureExploresTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.SubType; +import mage.abilities.keyword.CrewAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; + +/** + * + * @author TheElk801 + */ +public class ShadowedCaravel extends CardImpl { + + public ShadowedCaravel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever a creature you control explores, put a +1/+1 counter on Shadowed Caravel. + Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance()); + Ability ability = new CreatureExploresTriggeredAbility(effect); + this.addAbility(ability); + + // Crew 2 + this.addAbility(new CrewAbility(2)); + + } + + public ShadowedCaravel(final ShadowedCaravel card) { + super(card); + } + + @Override + public ShadowedCaravel copy() { + return new ShadowedCaravel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java b/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java index 8066b2dad3..7830ef9d03 100644 --- a/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java +++ b/Mage.Sets/src/mage/cards/w/WildgrowthWalker.java @@ -30,20 +30,15 @@ package mage.cards.w; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreatureExploresTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; /** * @@ -60,8 +55,9 @@ public class WildgrowthWalker extends CardImpl { // Whenever a creature you control explores, put a +1/+1 counter on Wildgrowth Walker and you gain 3 life. Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance()); - Ability ability = new WildgrowthWalkerTriggeredAbility(effect); + Ability ability = new CreatureExploresTriggeredAbility(effect); effect = new GainLifeEffect(3); + effect.setText("and you gain 3 life"); ability.addEffect(effect); this.addAbility(ability); } @@ -75,38 +71,3 @@ public class WildgrowthWalker extends CardImpl { return new WildgrowthWalker(this); } } - -class WildgrowthWalkerTriggeredAbility extends TriggeredAbilityImpl { - - WildgrowthWalkerTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false); - } - - WildgrowthWalkerTriggeredAbility(final WildgrowthWalkerTriggeredAbility effect) { - super(effect); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.EXPLORED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); - if (creature != null) { - return creature.getControllerId().equals(controllerId); - } - return false; - } - - @Override - public WildgrowthWalkerTriggeredAbility copy() { - return new WildgrowthWalkerTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever a creature you control explores, put a +1/+1 counter on {this} and you gain 3 life"; - } -} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 9db95b74e6..751beb6597 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -169,6 +169,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Search for Azcanta", 74, Rarity.RARE, mage.cards.s.SearchForAzcanta.class)); cards.add(new SetCardInfo("Sentinel Totem", 245, Rarity.UNCOMMON, mage.cards.s.SentinelTotem.class)); cards.add(new SetCardInfo("Settle the Wreckage", 34, Rarity.RARE, mage.cards.s.SettleTheWreckage.class)); + cards.add(new SetCardInfo("Shadowed Caravel", 246, Rarity.RARE, mage.cards.s.ShadowedCaravel.class)); cards.add(new SetCardInfo("Shapers of Nature", 228, Rarity.UNCOMMON, mage.cards.s.ShapersOfNature.class)); cards.add(new SetCardInfo("Shapers' Sanctuary", 206, Rarity.RARE, mage.cards.s.ShapersSanctuary.class)); cards.add(new SetCardInfo("Siren Stormtamer", 79, Rarity.UNCOMMON, mage.cards.s.SirenStormtamer.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java b/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java new file mode 100644 index 0000000000..e78b559cc4 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/CreatureExploresTriggeredAbility.java @@ -0,0 +1,43 @@ +package mage.abilities.effects.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +public class CreatureExploresTriggeredAbility extends TriggeredAbilityImpl { + + public CreatureExploresTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect, false); + } + + public CreatureExploresTriggeredAbility(final CreatureExploresTriggeredAbility effect) { + super(effect); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.EXPLORED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId()); + if (creature != null) { + return creature.getControllerId().equals(controllerId); + } + return false; + } + + @Override + public CreatureExploresTriggeredAbility copy() { + return new CreatureExploresTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever a creature you control explores, " + super.getRule(); + } +} From 73a8d64d5c58fd375ebfa7b52cecf741235a416e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 13:36:17 -0400 Subject: [PATCH 3/8] fixed Thraben Sentry --- Mage.Sets/src/mage/cards/t/ThrabenSentry.java | 13 +++---------- Mage.Sets/src/mage/sets/Ixalan.java | 1 + .../common/DiesCreatureTriggeredAbility.java | 11 ++++++----- Mage/src/main/java/mage/filter/StaticFilters.java | 2 +- .../common/FilterControlledCreaturePermanent.java | 10 ++++++---- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java index 335871c031..cf553d5504 100644 --- a/Mage.Sets/src/mage/cards/t/ThrabenSentry.java +++ b/Mage.Sets/src/mage/cards/t/ThrabenSentry.java @@ -37,22 +37,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.common.FilterControlledCreaturePermanent; /** * @author nantuko */ public class ThrabenSentry extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - - static { - filter.add(new AnotherPredicate()); - } public ThrabenSentry(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -66,7 +59,7 @@ public class ThrabenSentry extends CardImpl { // Whenever another creature you control dies, you may transform Thraben Sentry. this.addAbility(new TransformAbility()); - this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(true), true, filter)); + this.addAbility(new DiesCreatureTriggeredAbility(new TransformSourceEffect(true), true, new FilterControlledCreaturePermanent())); } public ThrabenSentry(final ThrabenSentry card) { diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 751beb6597..623026e62d 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -155,6 +155,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Ravenous Daggertooth", 202, Rarity.COMMON, mage.cards.r.RavenousDaggertooth.class)); cards.add(new SetCardInfo("Regisaur Alpha", 227, Rarity.RARE, mage.cards.r.RegisaurAlpha.class)); cards.add(new SetCardInfo("Revel in Riches", 117, Rarity.RARE, mage.cards.r.RevelInRiches.class)); + cards.add(new SetCardInfo("Rigging Runner", 157, Rarity.UNCOMMON, mage.cards.r.RiggingRunner.class)); cards.add(new SetCardInfo("Rile", 158, Rarity.COMMON, mage.cards.r.Rile.class)); cards.add(new SetCardInfo("Ripjaw Raptor", 203, Rarity.RARE, mage.cards.r.RipjawRaptor.class)); cards.add(new SetCardInfo("River Sneak", 70, Rarity.UNCOMMON, mage.cards.r.RiverSneak.class)); diff --git a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java index 6e160f7020..671945e5f9 100644 --- a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java @@ -3,6 +3,7 @@ package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; @@ -15,7 +16,7 @@ import mage.target.targetpointer.FixedTarget; */ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { - protected FilterCreaturePermanent filter; + protected FilterPermanent filter; private boolean setTargetPointer; public DiesCreatureTriggeredAbility(Effect effect, boolean optional) { @@ -34,15 +35,15 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { this.setTargetPointer = setTargetPointer; } - public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter) { + public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter) { this(effect, optional, filter, false); } - public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) { + public DiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) { this(Zone.BATTLEFIELD, effect, optional, filter, setTargetPointer); } - public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) { + public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) { super(zone, effect, optional); this.filter = filter; this.setTargetPointer = setTargetPointer; @@ -68,7 +69,7 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { - if (filter.match(zEvent.getTarget(), sourceId, controllerId, game)) { + if (filter.match(zEvent.getTarget(), sourceId, controllerId, game) && zEvent.getTarget().isCreature()) { if (setTargetPointer) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 620c7582d5..05a02cc488 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -41,7 +41,7 @@ public final class StaticFilters { public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT = new FilterControlledArtifactPermanent(); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT_OR_CREATURE = new FilterControlledPermanent("artifact or creature you control"); - public static final FilterControlledPermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control"); + public static final FilterPermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control"); public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_ANOTHER_CREATURE = new FilterControlledCreaturePermanent("another creature"); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_NON_LAND = new FilterControlledPermanent("nonland permanent"); public static final FilterLandPermanent FILTER_LAND = new FilterLandPermanent(); diff --git a/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java b/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java index f8fcd1a77c..a10d4b7b73 100644 --- a/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterControlledCreaturePermanent.java @@ -25,19 +25,21 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.filter.common; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; /** * * @author BetaSteward_at_googlemail.com */ -public class FilterControlledCreaturePermanent extends FilterControlledPermanent { +public class FilterControlledCreaturePermanent extends FilterPermanent { public FilterControlledCreaturePermanent() { this("creature you control"); @@ -46,8 +48,8 @@ public class FilterControlledCreaturePermanent extends FilterControlledPermanent public FilterControlledCreaturePermanent(String name) { super(name); this.add(new CardTypePredicate(CardType.CREATURE)); - } - + this.add(new ControllerPredicate(TargetController.YOU)); + } public FilterControlledCreaturePermanent(SubType subtype, String name) { super(name); From 4f4950b7ed6c6c231c1b5e010fc2764cb163cae2 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 13:52:58 -0400 Subject: [PATCH 4/8] Implemented Perilous Voyage --- .../src/mage/cards/p/PerilousVoyage.java | 107 ++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + Utils/mtg-cards-data.txt | 1 + 3 files changed, 109 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PerilousVoyage.java diff --git a/Mage.Sets/src/mage/cards/p/PerilousVoyage.java b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java new file mode 100644 index 0000000000..78313865e1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java @@ -0,0 +1,107 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author TheElk801 + */ +public class PerilousVoyage extends CardImpl { + + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent you don't control"); + + static { + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + } + + public PerilousVoyage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + // Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2. + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); + this.getSpellAbility().addEffect(new PerilousVoyageEffect()); + this.getSpellAbility().addTarget(new TargetPermanent()); + } + + public PerilousVoyage(final PerilousVoyage card) { + super(card); + } + + @Override + public PerilousVoyage copy() { + return new PerilousVoyage(this); + } +} + +class PerilousVoyageEffect extends OneShotEffect { + + PerilousVoyageEffect() { + super(Outcome.Benefit); + this.staticText = "Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2"; + } + + PerilousVoyageEffect(final PerilousVoyageEffect effect) { + super(effect); + } + + @Override + public PerilousVoyageEffect copy() { + return new PerilousVoyageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + boolean isLittle = permanent.getConvertedManaCost() < 3; + permanent.moveToZone(Zone.HAND, source.getSourceId(), game, true); + if (isLittle && player != null) { + player.scry(2, source, game); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 623026e62d..fdd7c29524 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -136,6 +136,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Opt", 65, Rarity.COMMON, mage.cards.o.Opt.class)); cards.add(new SetCardInfo("Otepec Huntmaster", 153, Rarity.UNCOMMON, mage.cards.o.OtepecHuntmaster.class)); cards.add(new SetCardInfo("Overflowing Insight", 64, Rarity.MYTHIC, mage.cards.o.OverflowingInsight.class)); + cards.add(new SetCardInfo("Perilous Voyage", 67, Rarity.UNCOMMON, mage.cards.p.PerilousVoyage.class)); cards.add(new SetCardInfo("Pillar of Origins", 241, Rarity.UNCOMMON, mage.cards.p.PillarOfOrigins.class)); cards.add(new SetCardInfo("Pirate's Cutlass", 242, Rarity.COMMON, mage.cards.p.PiratesCutlass.class)); cards.add(new SetCardInfo("Plains", 260, Rarity.LAND, mage.cards.basiclands.Plains.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 9d507cc389..dac7f4d4ab 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32364,6 +32364,7 @@ Kopala, Warden of Waves|Ixalan|61|R|{1}{U}{U}|Legendary Creature - Merfolk Wizar Lookout's Dispersal|Ixalan|62|U|{2}{U}|Instant|||Lookout's Dispersal costs {1} less to cast if you control a Pirate.$Counter target spell unless its controller pays {4}.| Overflowing Insight|Ixalan|64|M|{4}{U}{U}{U}|Sorcery|||Target player draws seven cards.| Opt|Ixalan|65|C|{U}|Instant|||Scry 1.$Draw a card.| +Perilous Voyage|Ixalan|67|U|{1}{U}|Instant|||Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2.| Prosperous Pirates|Ixalan|69|C|{4}{U}|Creature - Human Pirate|3|4|When Prosperous Pirates enters the battlefield, create two colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."| River Sneak|Ixalan|70|U|{1}{U}|Creature - Merfolk Warrior|1|1|River Sneak can't be blocked.$Whenever another Merfolk enters the battlefield under your control, River sneak gets +1/+1 until end of turn.| River's Rebuke|Ixalan|71|R|{4}{U}{U}|Sorcery|||Return all nonland permanents target player controls to their owner's hand.| From 9fa7729133779a89c6e5324f5eccf771ee46ba2e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 13:55:00 -0400 Subject: [PATCH 5/8] Implemented Perilous Voyage --- Mage.Sets/src/mage/cards/p/PerilousVoyage.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/PerilousVoyage.java b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java index 78313865e1..a20473e1ad 100644 --- a/Mage.Sets/src/mage/cards/p/PerilousVoyage.java +++ b/Mage.Sets/src/mage/cards/p/PerilousVoyage.java @@ -30,7 +30,6 @@ package mage.cards.p; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -60,9 +59,8 @@ public class PerilousVoyage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Return target nonland permanent you don't control to its owner's hand. If its converted mana cost was 2 or less, scry 2. - this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addEffect(new PerilousVoyageEffect()); - this.getSpellAbility().addTarget(new TargetPermanent()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } public PerilousVoyage(final PerilousVoyage card) { From ec9a198d0a4efb9b3c9d9efd5eee71f84a7b5632 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 14:20:20 -0400 Subject: [PATCH 6/8] Implemented Deathgorge Scavenger --- .../src/mage/cards/d/DeathgorgeScavenger.java | 109 ++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + 2 files changed, 110 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java diff --git a/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java b/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java new file mode 100644 index 0000000000..13b6ae13b3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java @@ -0,0 +1,109 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.Card; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author TheElk801 + */ +public class DeathgorgeScavenger extends CardImpl { + + public DeathgorgeScavenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever Deathgorge Scavenger enters the battlefield or attacks, you may exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, Deathgorge Scavenger gets +1/+1 until end of turn. + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DeathgorgeScavengerEffect(), true); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + } + + public DeathgorgeScavenger(final DeathgorgeScavenger card) { + super(card); + } + + @Override + public DeathgorgeScavenger copy() { + return new DeathgorgeScavenger(this); + } +} + +class DeathgorgeScavengerEffect extends OneShotEffect { + + public DeathgorgeScavengerEffect() { + super(Outcome.Benefit); + this.staticText = "exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, {this} gets +1/+1 until end of turn"; + } + + public DeathgorgeScavengerEffect(final DeathgorgeScavengerEffect effect) { + super(effect); + } + + @Override + public DeathgorgeScavengerEffect copy() { + return new DeathgorgeScavengerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && card != null) { + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true); + if (card.isCreature()) { + controller.gainLife(2, game); + } else { + new BoostSourceEffect(1, 1, Duration.EndOfTurn).apply(game, source); + } + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index fdd7c29524..9ca5f5b349 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -63,6 +63,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Deadeye Quartermaster", 50, Rarity.UNCOMMON, mage.cards.d.DeadeyeQuartermaster.class)); cards.add(new SetCardInfo("Deadeye Tormentor", 98, Rarity.COMMON, mage.cards.d.DeadeyeTormentor.class)); cards.add(new SetCardInfo("Deadeye Tracker", 99, Rarity.RARE, mage.cards.d.DeadeyeTracker.class)); + cards.add(new SetCardInfo("Deathgorge Scavenger", 184, Rarity.RARE, mage.cards.d.DeathgorgeScavenger.class)); cards.add(new SetCardInfo("Deathless Ancient", 100, Rarity.UNCOMMON, mage.cards.d.DeathlessAncient.class)); cards.add(new SetCardInfo("Deeproot Champion", 185, Rarity.RARE, mage.cards.d.DeeprootChampion.class)); cards.add(new SetCardInfo("Deeproot Waters", 51, Rarity.UNCOMMON, mage.cards.d.DeeprootWaters.class)); From 1cdc8d31778b65f7f039dbda8c746d7e4587569f Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 14:47:07 -0400 Subject: [PATCH 7/8] Implemented Field of Ruin --- Mage.Sets/src/mage/cards/f/FieldOfRuin.java | 134 ++++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + Utils/mtg-cards-data.txt | 1 + 3 files changed, 136 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FieldOfRuin.java diff --git a/Mage.Sets/src/mage/cards/f/FieldOfRuin.java b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java new file mode 100644 index 0000000000..45e3c514be --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FieldOfRuin.java @@ -0,0 +1,134 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author TheElk801 + */ +public class FieldOfRuin extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent("nonbasic land an opponent controls"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + filter.add(Predicates.not(new SupertypePredicate(SuperType.BASIC))); + } + + public FieldOfRuin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // {T}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {2}, {T}, Sacrifice Field of Ruin: Destroy target nonbasic land an opponent controls. Each player searches his or her library for a basic land card, puts it onto the battlefield, then shuffles his or her library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost()); + ability.addCost(new ManaCostsImpl("{2}")); + ability.addCost(new SacrificeSourceCost()); + ability.addEffect(new FieldOfRuinEffect()); + ability.addTarget(new TargetLandPermanent(filter)); + } + + public FieldOfRuin(final FieldOfRuin card) { + super(card); + } + + @Override + public FieldOfRuin copy() { + return new FieldOfRuin(this); + } +} + +class FieldOfRuinEffect extends OneShotEffect { + + FieldOfRuinEffect() { + super(Outcome.Benefit); + this.staticText = "Each player searches his or her library for a basic land card, puts it onto the battlefield, then shuffles his or her library."; + } + + FieldOfRuinEffect(final FieldOfRuinEffect effect) { + super(effect); + } + + @Override + public FieldOfRuinEffect copy() { + return new FieldOfRuinEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetCardInLibrary target = new TargetCardInLibrary(0, 1, StaticFilters.FILTER_BASIC_LAND_CARD); + if (player.searchLibrary(target, game)) { + for (UUID cardId : target.getTargets()) { + Card card = player.getLibrary().getCard(cardId, game); + if (card != null) { + card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), player.getId(), true); + } + + } + player.shuffleLibrary(source, game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index 9ca5f5b349..fd1e610dd8 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -86,6 +86,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Fathom Fleet Captain", 106, Rarity.RARE, mage.cards.f.FathomFleetCaptain.class)); cards.add(new SetCardInfo("Favorable Winds", 56, Rarity.UNCOMMON, mage.cards.f.FavorableWinds.class)); cards.add(new SetCardInfo("Fell Flagship", 238, Rarity.RARE, mage.cards.f.FellFlagship.class)); + cards.add(new SetCardInfo("Field of Ruin", 254, Rarity.UNCOMMON, mage.cards.f.FieldOfRuin.class)); cards.add(new SetCardInfo("Forest", 276, Rarity.LAND, mage.cards.basiclands.Forest.class)); cards.add(new SetCardInfo("Forest", 277, Rarity.LAND, mage.cards.basiclands.Forest.class)); cards.add(new SetCardInfo("Forest", 278, Rarity.LAND, mage.cards.basiclands.Forest.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index dac7f4d4ab..b375b744a0 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32372,6 +32372,7 @@ Azcanta, The Sunken Ruin|Ixalan|74b|R||Legendary Land|||(Transforms from Search Search for Azcanta|Ixalan|74a|R|{1}{U}|Legendary Enchantment|||| Siren Stormtamer|Ixalan|79|U|{U}|Creature - Siren Pirate Wizard|1|1|Flying${U}, Sacrifice Siren Stormtamer: Counter target spell or ability that targets you or a creature you control.| Spell Pierce|Ixalan|81|C|{U}|Instant|||Counter target noncreature spell unless its controller pays {2}.| +Spell Swindle|Ixalan|82|R|{3}{U}{U}|Instant|||Counter target spell. Create X colorless Treasure artifact tokens, where X is that spell's converted mana cost. They have "T, Sacrifice this artifact: Add one mana of any color to your mana pool."| Storm Fleet Aerialist|Ixalan|83|U|{1}{U}|Creature - Human Pirate|1|2|Flying$Raid - Storm Fleet Aerialist enters the battlefield with a +1/+1 counter on it if you attacked with a creature this turn.| Storm Fleet Spy|Ixalan|84|U|{2}{U}|Creature - Human Pirate|2|2|Raid - When Storm Fleet Spy enters the battlefield, if you attacked with a creature this turn, draw a card.| Arguel's Blood Fast|Ixalan|90a|R|{1}{B}|Legendary Enchantment|||{1}{B}, Pay 2 life: Draw a card.$At the beginning of your upkeep, if you have 5 or less life, you may transform Arguel's Blood Fast.| From 75ce112a5df025fe6769b2ba5cc06657464ffb73 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 14 Sep 2017 14:54:42 -0400 Subject: [PATCH 8/8] Implemented Spell Swindle --- Mage.Sets/src/mage/cards/s/SpellSwindle.java | 93 ++++++++++++++++++++ Mage.Sets/src/mage/sets/Ixalan.java | 1 + 2 files changed, 94 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SpellSwindle.java diff --git a/Mage.Sets/src/mage/cards/s/SpellSwindle.java b/Mage.Sets/src/mage/cards/s/SpellSwindle.java new file mode 100644 index 0000000000..6745cc8009 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpellSwindle.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.token.TreasureToken; +import mage.game.stack.StackObject; +import mage.target.TargetSpell; + +/** + * + * @author TheElk801 + */ +public class SpellSwindle extends CardImpl { + + public SpellSwindle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}"); + + // Counter target spell. Create X colorless Treasure artifact tokens, where X is that spell's converted mana cost. They have "T, Sacrifice this artifact: Add one mana of any color to your mana pool." + this.getSpellAbility().addTarget(new TargetSpell()); + this.getSpellAbility().addEffect(new SpellSwindleEffect()); + } + + public SpellSwindle(final SpellSwindle card) { + super(card); + } + + @Override + public SpellSwindle copy() { + return new SpellSwindle(this); + } +} + +class SpellSwindleEffect extends OneShotEffect { + + public SpellSwindleEffect() { + super(Outcome.Detriment); + staticText = "Counter target spell. Create X colorless Treasure artifact tokens, where X is that spell's converted mana cost. " + + "They have \"{T}, Sacrifice this artifact: Add one mana of any color to your mana pool"; + } + + public SpellSwindleEffect(final SpellSwindleEffect effect) { + super(effect); + } + + @Override + public SpellSwindleEffect copy() { + return new SpellSwindleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + StackObject stackObject = game.getStack().getStackObject(targetPointer.getFirst(game, source)); + if (stackObject != null) { + game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game); + return new CreateTokenEffect(new TreasureToken(), stackObject.getConvertedManaCost()).apply(game, source); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Ixalan.java b/Mage.Sets/src/mage/sets/Ixalan.java index fd1e610dd8..9395a410cd 100644 --- a/Mage.Sets/src/mage/sets/Ixalan.java +++ b/Mage.Sets/src/mage/sets/Ixalan.java @@ -185,6 +185,7 @@ public class Ixalan extends ExpansionSet { cards.add(new SetCardInfo("Snapping Sailback", 208, Rarity.UNCOMMON, mage.cards.s.SnappingSailback.class)); cards.add(new SetCardInfo("Sorcerous Spyglass", 248, Rarity.RARE, mage.cards.s.SorcerousSpyglass.class)); cards.add(new SetCardInfo("Spell Pierce", 81, Rarity.RARE, mage.cards.s.SpellPierce.class)); + cards.add(new SetCardInfo("Spell Swindle", 82, Rarity.RARE, mage.cards.s.SpellSwindle.class)); cards.add(new SetCardInfo("Spires of Orazca", 249, Rarity.RARE, mage.cards.s.SpiresOfOrazca.class)); cards.add(new SetCardInfo("Star of Extinction", 161, Rarity.MYTHIC, mage.cards.s.StarOfExtinction.class)); cards.add(new SetCardInfo("Stone Quarry", 289, Rarity.COMMON, mage.cards.s.StoneQuarry.class));